Skip to content

Commit

Permalink
Merge 63958bd into bf75f21
Browse files Browse the repository at this point in the history
  • Loading branch information
ifirmawan committed Jan 5, 2024
2 parents bf75f21 + 63958bd commit cebcc79
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 41 deletions.
6 changes: 5 additions & 1 deletion backend/api/v1/v1_profile/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,11 @@ def list(self, request, *args, **kwargs):
def export_administrations_template(request: Request, version):
attributes = clean_array_param(
request.query_params.get('attributes', ''), maybe_int)
filepath = generate_excel(cast(SystemUser, request.user), attributes)
level = request.query_params.get('level', None)
prefilled = request.query_params.get('prefilled', False)
filepath = generate_excel(
cast(SystemUser, request.user), attributes, level, prefilled
)
filename = filepath.split("/")[-1].replace(" ", "-")
with open(filepath, 'rb') as template_file:
response = HttpResponse(
Expand Down
45 changes: 41 additions & 4 deletions backend/utils/administration_upload_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@
from django.utils import timezone

import pandas as pd
from api.v1.v1_profile.models import Levels, AdministrationAttribute
from api.v1.v1_profile.models import (
Levels,
AdministrationAttribute,
Administration
)

from api.v1.v1_users.models import SystemUser


def generate_excel(user: SystemUser, attributes: List[int] = []):
def generate_excel(
user: SystemUser,
attributes: List[int] = [],
level: int = None,
prefilled: bool = False,
):
directory = 'tmp/administrations-template'
os.makedirs(directory, exist_ok=True)
filename = (
Expand All @@ -18,11 +27,16 @@ def generate_excel(user: SystemUser, attributes: List[int] = []):
filepath = f"./{directory}/{filename}"
if os.path.exists(filepath):
os.remove(filepath)
generate_template(filepath, attributes)
generate_template(filepath, attributes, level, prefilled)
return filepath


def generate_template(filepath, attributes: List[int] = []):
def generate_template(
filepath,
attributes: List[int] = [],
level: int = None,
prefilled: bool = False
):
level_headers = [
f'{lvl.id}|{lvl.name}' for lvl
in Levels.objects.order_by('level').all()]
Expand All @@ -48,6 +62,29 @@ def generate_template(filepath, attributes: List[int] = []):
})
for col_num, value in enumerate(data.columns.values):
worksheet.write(0, col_num, value, header_format)
# get administrations list when level is exists
if level and prefilled:
administrations = Administration.objects\
.filter(level_id__lte=level).all()
for adx, adm in enumerate(administrations):
find_col = next((
lx for lx, lvl in enumerate(level_headers)
if str(adm.level_id) in lvl
), -1)
if find_col >= 0:
worksheet.write(adx + 1, find_col, adm.name)
if adm.path:
adm_parents = [
list(
filter(lambda item: item.id == int(p), administrations)
)
for p in list(filter(
lambda path: path, adm.path.split(".")
))
]
for parent_col, pl in enumerate(adm_parents):
[parent] = pl
worksheet.write(adx + 1, parent_col, parent.name)
writer.save()


Expand Down
3 changes: 3 additions & 0 deletions frontend/src/lib/ui-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,9 @@ const uiText = {
endOfListLabel: "End of List",
addMewOrg: "Add new organization",
searchPlaceholder: "Search...",
bulkUploadAttr: "Attributes",
bulkUploadAttrPlaceholder: "Select Attributes...",
bulkUploadCheckboxPrefilled: "Prefilled administrative list",
},

de: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
Select,
Upload,
Result,
Form,
Checkbox,
} from "antd";
import { FileTextFilled } from "@ant-design/icons";
import { Breadcrumbs, DescriptionPanel } from "../../components";
Expand Down Expand Up @@ -37,7 +39,7 @@ const UploadAdministrationData = () => {
const [selectedAttributes, setSelectedAttributes] = useState([]);
const { notify } = useNotification();
const navigate = useNavigate();
const { language } = store.useState((s) => s);
const { language, levels } = store.useState((s) => s);
const { active: activeLang } = language;

const text = useMemo(() => {
Expand Down Expand Up @@ -130,17 +132,19 @@ const UploadAdministrationData = () => {
setSelectedAttributes(e);
};

const downloadTemplate = () => {
const downloadTemplate = ({ level, prefilled }) => {
setLoading(true);
const query = {
attributes: selectedAttributes,
level,
prefilled,
};
const queryURL = "?" + new URLSearchParams(query).toString();
const apiURL = `export/administrations-template${queryURL}`;
api
.get(
`export/administrations-template?attributes=${selectedAttributes.join(
","
)}`,
{
responseType: "blob",
}
)
.get(apiURL, {
responseType: "blob",
})
.then((res) => {
const contentDispositionHeader = res.headers["content-disposition"];
const filename = regExpFilename.exec(contentDispositionHeader)?.groups
Expand Down Expand Up @@ -221,30 +225,59 @@ const UploadAdministrationData = () => {
style={{ padding: 0, minHeight: "40vh" }}
bodyStyle={{ padding: 0 }}
>
<Space align="center" size={32}>
<img src="/assets/data-download.svg" />
<p>{text.templateDownloadHint}</p>
<Select
placeholder="Select Attributes..."
className="multiple-select-box"
onChange={handleAttributeChange}
mode="multiple"
allowClear
>
{attributes.map((f, fI) => (
<Option key={fI} value={f.id}>
{f.name}
</Option>
))}
</Select>
<Button
loading={loading}
type="primary"
onClick={downloadTemplate}
shape="round"
<Space direction="vertical">
<Space align="center" size={32}>
<img src="/assets/data-download.svg" />
<p>{text.templateDownloadHint}</p>
</Space>
<Form
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
onFinish={downloadTemplate}
>
{text.download}
</Button>
<Form.Item label={text.admLevel} name="level">
<Select
placeholder={text.selectLevel}
fieldNames={{ value: "id", label: "name" }}
options={levels}
allowClear
/>
</Form.Item>
<Form.Item label={text.bulkUploadAttr} name="attributes">
<Select
placeholder={text.bulkUploadAttrPlaceholder}
className="multiple-select-box"
onChange={handleAttributeChange}
mode="multiple"
allowClear
>
{attributes.map((f, fI) => (
<Option key={fI} value={f.id}>
{f.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item
name="prefilled"
valuePropName="checked"
wrapperCol={{ offset: 6, span: 18 }}
>
<Checkbox>{text.bulkUploadCheckboxPrefilled}</Checkbox>
</Form.Item>
<Row justify="center" align="middle">
<Col span={18} offset={6}>
<Button
loading={loading}
type="primary"
htmlType="submit"
shape="round"
>
{text.download}
</Button>
</Col>
</Row>
</Form>
</Space>
<Space align="center" size={32}>
<img src="/assets/data-upload.svg" />
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/pages/upload-administration-data/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
}
.ant-card-body > .ant-space:first-child {
border-bottom: solid #d7dbec 1px;
padding-left: 0;
.ant-form {
width: 50%;
margin: 0 auto;
}
}
.ant-card-body
> .ant-space:nth-child(2)
Expand All @@ -35,9 +40,6 @@
margin-bottom: 16px;
}
}
.multiple-select-box {
width: 13rem;
}
}
}
}

0 comments on commit cebcc79

Please sign in to comment.