Skip to content

Commit

Permalink
avniproject/avni-product#1531 | WIP: Introduce locationHierarchy sele…
Browse files Browse the repository at this point in the history
…ction for Locations Upload / Sample download
  • Loading branch information
himeshr committed May 30, 2024
1 parent 8c5478f commit 527b313
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 117 deletions.
162 changes: 63 additions & 99 deletions src/upload/Dashboard.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import { filter, get, isEmpty, isNil, concat } from "lodash";
import _, { concat, get, isEmpty, isNil } from "lodash";
import Status from "./Status";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import { makeStyles } from "@material-ui/core/styles";
import CloudDownload from "@material-ui/icons/CloudDownload";
import Button from "@material-ui/core/Button";
import FileUpload from "../common/components/FileUpload";
import { staticTypesWithStaticDownload, staticTypesWithDynamicDownload } from "./Types";
import { staticTypesWithDynamicDownload, staticTypesWithStaticDownload } from "./Types";
import api from "./api";
import DropDown from "../common/components/DropDown";
import { getStatuses, getUploadTypes } from "./reducers";
Expand All @@ -19,7 +19,10 @@ import { DocumentationContainer } from "../common/components/DocumentationContai
import Checkbox from "@material-ui/core/Checkbox";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { LocationModes } from "./LocationModes";
import _ from "lodash";
import Tooltip from "@material-ui/core/Tooltip";
import { LocationHierarchy } from "./LocationHierarchy";
import Typography from "@material-ui/core/Typography";
import { Box } from "@material-ui/core";

const useStyles = makeStyles(theme => ({
root: {},
Expand All @@ -38,20 +41,15 @@ const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(
const [file, setFile] = React.useState();
const [autoApprove, setAutoApprove] = React.useState(false);
const [mode, setMode] = React.useState("relaxed");
const [hierarchy, setHierarchy] = React.useState();
const [configuredHierarchies, setConfiguredHierarchies] = React.useState([]);

const selectFile = (content, userfile) => setFile(userfile);
const getUploadTypeCode = name =>
staticTypesWithStaticDownload.getCode(name) ||
staticTypesWithDynamicDownload.getCode(name) ||
uploadTypes.getCode(name);
staticTypesWithStaticDownload.getCode(name) || staticTypesWithDynamicDownload.getCode(name) || uploadTypes.getCode(name);

const uploadFile = async () => {
const [ok, error] = await api.bulkUpload(
getUploadTypeCode(uploadType),
file,
autoApprove,
mode
);
const [ok, error] = await api.bulkUpload(getUploadTypeCode(uploadType), file, autoApprove, mode);
if (!ok && error) {
alert(error);
}
Expand All @@ -67,11 +65,7 @@ const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(
if (staticTypesWithStaticDownload.getCode(entityForDownload)) {
await api.downloadSample(staticTypesWithStaticDownload.getCode(entityForDownload));
} else if (
!_.isUndefined(
(uploadType =
uploadTypes.getCode(entityForDownload) ||
staticTypesWithDynamicDownload.getCode(entityForDownload))
)
!_.isUndefined((uploadType = uploadTypes.getCode(entityForDownload) || staticTypesWithDynamicDownload.getCode(entityForDownload)))
) {
await api.downloadDynamicSample(uploadType);
}
Expand All @@ -80,25 +74,17 @@ const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(

React.useEffect(() => {
getUploadTypes();
api.fetchLocationHierarchies().then(json => setConfiguredHierarchies(JSON.parse(json)));
}, []);

const uploadOptions = () =>
concat(
staticTypesWithStaticDownload.names,
staticTypesWithDynamicDownload.names,
uploadTypes.names
);

const downloadOptions = () =>
filter(
uploadOptions(),
({ name }) => name !== staticTypesWithStaticDownload.getName("metadataZip")
);
const uploadAndDownloadOptions = () =>
concat(staticTypesWithStaticDownload.names, staticTypesWithDynamicDownload.names, uploadTypes.names);

const dropdownHandler = option => {
setAutoApprove(false);
setMode("relaxed");
setUploadType(option);
option !== staticTypesWithStaticDownload.getName("metadataZip") && setEntityForDownload(option);
};

return (
Expand All @@ -107,84 +93,62 @@ const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(
<Grid item xs={12} style={{ minWidth: 1200, maxWidth: 1400 }}>
<Paper className={classes.uploadDownloadSection}>
<DocumentationContainer filename={"Upload.md"}>
<Grid container>
<Grid item xs={12} sm={6}>
<Grid container item>
Upload
<Grid container item spacing={2}>
<Grid container item>
Upload
</Grid>
<Grid container item>
<Grid container item direction="column" justifyContent="center" alignItems="flex-start" xs={12} sm={6} spacing={2}>
<DropDown name="Type" value={uploadType} onChange={dropdownHandler} options={uploadAndDownloadOptions()} />
<Tooltip title="Download Sample file for selected Upload type" placement="bottom-start" arrow>
<Button color="primary" onClick={downloadSampleFile} disabled={isEmpty(entityForDownload)}>
<CloudDownload disabled={isEmpty(entityForDownload)} />
<span style={{ marginLeft: "1em" }}>Download Sample</span>
</Button>
</Tooltip>
</Grid>
<Grid container item spacing={2}>
<Grid container item xs={12} sm={3}>
<DropDown
name="Type"
value={uploadType}
onChange={dropdownHandler}
options={uploadOptions()}
/>
<Grid container item direction="column" justifyContent="center" alignItems="flex-start" xs={12} sm={6} spacing={2}>
<Grid item>
<FileUpload canSelect={!isEmpty(uploadType)} canUpload={!isNil(file)} onSelect={selectFile} onUpload={uploadFile} />
</Grid>
<Grid
container
item
direction="column"
justifyContent="center"
alignItems="flex-start"
xs={12}
sm={9}
spacing={2}
>
<Grid item>
<FileUpload
canSelect={!isEmpty(uploadType)}
canUpload={!isNil(file)}
onSelect={selectFile}
onUpload={uploadFile}
/>
</Grid>
<Grid item>Selected File: {get(file, "name", "")}</Grid>
<Grid item>
<span style={{ marginLeft: "1em" }}>Selected File: {get(file, "name", "")}</span>
</Grid>
</Grid>
</Grid>
<Grid item xs={12} sm={6}>
<Grid container item>
Download Sample
</Grid>
<Grid
item
container
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<DropDown
name="Type"
value={entityForDownload}
onChange={setEntityForDownload}
options={downloadOptions()}
</Grid>
<Grid container>
<Grid container item>
{uploadTypes.isApprovalEnabled(uploadType) && (
<FormControlLabel
control={
<Checkbox
checked={autoApprove}
onChange={event => setAutoApprove(event.target.checked)}
name="autoApprove"
color="primary"
/>
}
label={"Approve automatically"}
/>
<Button
color="primary"
onClick={downloadSampleFile}
disabled={isEmpty(entityForDownload)}
>
<CloudDownload disabled={isEmpty(entityForDownload)} />
{" Download"}
</Button>
</Grid>
)}
</Grid>
<Grid container item>
{uploadType === "Locations" && <LocationModes mode={mode} setMode={setMode} />}
</Grid>
<Grid container item>
{uploadType === "Locations" && mode === "relaxed" && configuredHierarchies && configuredHierarchies.length > 0 && (
<LocationHierarchy hierarchy={hierarchy} setHierarchy={setHierarchy} configuredHierarchies={configuredHierarchies} />
)}
{uploadType === "Locations" && mode === "relaxed" && (!configuredHierarchies || configuredHierarchies.length === 0) && (
<Box>
<Typography color="error" display="block" gutterBottom>
Invalid or missing Location Hierarchy.
</Typography>
</Box>
)}
</Grid>
</Grid>
{uploadTypes.isApprovalEnabled(uploadType) && (
<FormControlLabel
control={
<Checkbox
checked={autoApprove}
onChange={event => setAutoApprove(event.target.checked)}
name="autoApprove"
color="primary"
/>
}
label={"Approve automatically"}
/>
)}
{uploadType === "Locations" && <LocationModes mode={mode} setMode={setMode} />}
</DocumentationContainer>
</Paper>
</Grid>
Expand Down
35 changes: 35 additions & 0 deletions src/upload/LocationHierarchy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import FormControl from "@material-ui/core/FormControl";
import FormLabel from "@material-ui/core/FormLabel";
import RadioGroup from "@material-ui/core/RadioGroup";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Radio from "@material-ui/core/Radio";
import _ from "lodash";

export const LocationHierarchy = ({ hierarchy, setHierarchy, configuredHierarchies }) => {
const handleChange = event => {
setHierarchy(event.target.value);
};

return (
<FormControl component="fieldset" style={{ marginTop: "20px" }}>
<FormLabel component="legend">Select Location Hierarchy</FormLabel>
<RadioGroup
aria-label="hierarchy"
name="hierarchy1"
value={hierarchy || _.get(configuredHierarchies[0], "value")}
onChange={handleChange}
>
{configuredHierarchies.map(hierarchicalValue => (
<FormControlLabel
disabled={configuredHierarchies.length <= 1}
key={hierarchicalValue.value}
value={hierarchicalValue.value}
control={<Radio color="primary" />}
label={hierarchicalValue.label}
/>
))}
</RadioGroup>
</FormControl>
);
};
25 changes: 12 additions & 13 deletions src/upload/LocationModes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import FormLabel from "@material-ui/core/FormLabel";
import RadioGroup from "@material-ui/core/RadioGroup";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Radio from "@material-ui/core/Radio";
import Tooltip from "@material-ui/core/Tooltip";

export const LocationModes = ({ mode, setMode }) => {
const handleChange = event => {
Expand All @@ -13,19 +14,17 @@ export const LocationModes = ({ mode, setMode }) => {
return (
<FormControl component="fieldset" style={{ marginTop: "20px" }}>
<FormLabel component="legend">Select Mode</FormLabel>
<RadioGroup
row
aria-label="mode"
name="mode1"
value={mode || "relaxed"}
onChange={handleChange}
>
<FormControlLabel value="relaxed" control={<Radio color="primary" />} label="Create" />
<FormControlLabel
value="strict"
control={<Radio color="primary" />}
label="Edit + Create"
/>
<RadioGroup row aria-label="mode" name="mode1" value={mode || "relaxed"} onChange={handleChange}>
<Tooltip title="Create new locations" placement="bottom-start" arrow>
<div>
<FormControlLabel value="relaxed" control={<Radio color="primary" />} label="Create" />
</div>
</Tooltip>
<Tooltip title="Edit locations' name, parent, GPS co-ordinates or properties" placement="bottom-start" arrow>
<div>
<FormControlLabel value="strict" control={<Radio color="primary" />} label="Edit" />
</div>
</Tooltip>
</RadioGroup>
</FormControl>
);
Expand Down
13 changes: 8 additions & 5 deletions src/upload/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { get } from "lodash";

export default {
fetchUploadJobStatuses: (params = {}) => {
return http
.fetchJson(http.withParams("/import/status", { size: 5, ...params }))
.then(r => r.json);
return http.fetchJson(http.withParams("/import/status", { size: 5, ...params })).then(r => r.json);
},
bulkUpload: (type, file, autoApprove, locationUploadMode) =>
http
Expand All @@ -17,11 +15,16 @@ export default {
fetchUploadTypes: () => {
return http.fetchJson(http.withParams("/web/importTypes")).then(r => r.json);
},
fetchLocationHierarchies: () => {
return http
.fetchJson(http.withParams("/web/locationHierarchies"))
.then(r => r.json)
.catch(r => "[]");
},
async downloadSample(type) {
const file = await fetch(`/bulkuploads/sample/${type}.csv`);
const content = await file.text();
files.download(`sample-${type}.csv`, content);
},
downloadDynamicSample: type =>
http.downloadFile(`/web/importSample?uploadType=${type}`, `sample-${type}.csv`)
downloadDynamicSample: type => http.downloadFile(`/web/importSample?uploadType=${type}`, `sample-${type}.csv`)
};

0 comments on commit 527b313

Please sign in to comment.