Skip to content

Commit

Permalink
#1401 - compare directly after uploading the bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
petmongrels committed Jan 2, 2025
1 parent 1bfe59b commit 000cb83
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 138 deletions.
48 changes: 48 additions & 0 deletions src/adminApp/service/CompareMetadataService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import _ from "lodash";
import httpClient from "../../common/utils/httpClient";

export const CHANGE_TYPE = {
ADDED: "added",
REMOVED: "removed",
MODIFIED: "modified",
NO_MODIFICATION: "noModification"
};

const isNoModification = function(obj) {
if (!_.isObject(obj)) return false;
if (obj.changeType === CHANGE_TYPE.NO_MODIFICATION) return true;
return _.some(obj, value => isNoModification(value));
};

const filterForms = function(data) {
const filteredData = _.reduce(
data,
(acc, formData, formName) => {
if (!isNoModification(formData) && formName !== "formMappings.json") {
acc[formName] = formData;
}
return acc;
},
{}
);

return _.reduce(
filteredData,
(acc, formData, formName) => {
acc[formName] = formData;
return acc;
},
{}
);
};

class CompareMetadataService {
static async compare(file) {
const formData = new FormData();
formData.append("incumbentBundle", file);
const response = await httpClient.post("/web/bundle/findChanges", formData);
return filterForms(response.data);
}
}

export default CompareMetadataService;
27 changes: 22 additions & 5 deletions src/upload/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { LocationHierarchy } from "./LocationHierarchy";
import Typography from "@material-ui/core/Typography";
import { Box } from "@material-ui/core";
import MetadataDiff from "./MetadataDiff";
import CompareMetadataService from "../adminApp/service/CompareMetadataService";

const useStyles = makeStyles(theme => ({
root: {},
Expand All @@ -44,6 +45,14 @@ const useStyles = makeStyles(theme => ({
}
}));

class ReviewStatusStatus {
constructor(loading, response, error) {
this.loading = loading;
this.response = response;
this.error = error;
}
}

const isMetadataDiffReviewEnabled = true;
const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(), userRoles }) => {
const classes = useStyles();
Expand All @@ -54,7 +63,7 @@ const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(
const [mode, setMode] = React.useState("CREATE");
const [hierarchy, setHierarchy] = React.useState();
const [configuredHierarchies, setConfiguredHierarchies] = React.useState([]);
const [reviewMode, setReviewMode] = React.useState(false);
const [reviewStatus, setReviewStatus] = React.useState(null);

const selectFile = (content, userfile) => setFile(userfile);
const getUploadTypeCode = name =>
Expand Down Expand Up @@ -115,12 +124,20 @@ const Dashboard = ({ getStatuses, getUploadTypes, uploadTypes = new UploadTypes(
(uploadType === "Locations" && isEmpty(mode)) ||
(uploadType === "Locations" && mode === "CREATE" && isEmpty(hierarchy));

const handleReviewClick = () => {
setReviewMode(true);
const handleReviewClick = async () => {
try {
CompareMetadataService.compare(file).then(filteredData => {
setReviewStatus(new ReviewStatusStatus(false, filteredData, null));
});
setReviewStatus(new ReviewStatusStatus(true, null, null));
} catch (err) {
setReviewStatus(new ReviewStatusStatus(true, null, "An error occurred while comparing metadata."));
console.error(err);
}
};

if (reviewMode) {
return <MetadataDiff />;
if (reviewStatus) {
return <MetadataDiff loading={reviewStatus.loading} response={reviewStatus.response} error={reviewStatus.error} />;
}

return (
Expand Down
157 changes: 24 additions & 133 deletions src/upload/MetadataDiff.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,11 @@ import React, { useState } from "react";
import { Button, Typography, Paper, Grid, CircularProgress, MenuItem, FormControl, Select, InputLabel } from "@material-ui/core";
import httpClient from "common/utils/httpClient";
import _ from "lodash";
import { CHANGE_TYPE } from "../adminApp/service/CompareMetadataService";

const MetadataDiff = () => {
const [file1, setFile1] = useState(null);
const [file2, setFile2] = useState(null);
const [response, setResponse] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const MetadataDiff = ({ response, error, loading }) => {
const [selectedForm, setSelectedForm] = useState("");

const CHANGE_TYPE = {
ADDED: "added",
REMOVED: "removed",
MODIFIED: "modified",
NO_MODIFICATION: "noModification"
};

const formLabels = {
"Missing Files in PROD ZIP": "Removed from Old Metadata",
"Missing Files in UAT ZIP": "Newly Added Metadata"
Expand All @@ -26,70 +15,6 @@ const MetadataDiff = () => {
const getDisplayLabel = formKey => formLabels[formKey] || formKey;
const isValueChanged = value => _.isObject(value) && !_.isNil(value.oldValue) && !_.isNil(value.newValue);

const handleFileChange = (event, fileNumber) => {
const file = event.target.files[0];
if (fileNumber === 1) {
setFile1(file);
} else if (fileNumber === 2) {
setFile2(file);
}
};

const isNoModification = obj => {
if (!_.isObject(obj)) return false;
if (obj.changeType === CHANGE_TYPE.NO_MODIFICATION) return true;
return _.some(obj, value => isNoModification(value));
};

const filterForms = data => {
const filteredData = _.reduce(
data,
(acc, formData, formName) => {
if (!isNoModification(formData) && formName !== "formMappings.json") {
acc[formName] = formData;
}
return acc;
},
{}
);

return _.reduce(
filteredData,
(acc, formData, formName) => {
acc[formName] = formData;
return acc;
},
{}
);
};

const handleSubmit = async () => {
if (_.isNil(file1) || _.isNil(file2)) {
setError("Please select both files.");
return;
}

const formData = new FormData();
formData.append("file1", file1);
formData.append("file2", file2);

setLoading(true);
setResponse(null);
setError(null);

try {
const response = await httpClient.post("/api/compare-metadata", formData);
const filteredData = filterForms(response.data);
setResponse(filteredData);
setSelectedForm("");
} catch (err) {
setError("An error occurred while comparing metadata.");
console.error(err);
} finally {
setLoading(false);
}
};

const handleFormChange = event => {
const selectedKey = event.target.value;
setSelectedForm(selectedKey);
Expand All @@ -108,7 +33,7 @@ const MetadataDiff = () => {
}
};

const renderJsonWithColor = (data, indent = 0, parentChangeType = null) => {
const JsonWithColor = ({ data, indent = 0, parentChangeType = null }) => {
if (!_.isObject(data)) {
return <span style={{ fontSize: "18px" }}>{String(data)}</span>;
}
Expand All @@ -121,54 +46,58 @@ const MetadataDiff = () => {
if (key === "changeType" || key === "dataType") return null;

if (isValueChanged(value)) {
return renderChangedValue(key, value, indent);
return <ChangedValue key={key} value={value} indent={indent} />;
}

if (_.isArray(value)) {
return renderArray(key, value, indent, changeType);
return <Array key={key} array={value} indent={indent} changeType={changeType} />;
}

if (_.isObject(value)) {
return renderNestedObject(key, value, indent, changeType);
return <NestedObject key={key} obj={value} indent={indent} changeType={changeType} />;
}

return renderKeyValue(key, value, changeType);
return <KeyValue key={key} value={value} changeType={changeType} />;
})}
</div>
);
};

const renderChangedValue = (key, value, indent) => (
const ChangedValue = ({ key, value, indent }) => (
<div key={key} style={{ marginBottom: 10 }}>
<strong style={{ color: "orange", fontSize: "18px" }}>{key}:</strong>
<div style={{ color: getColor(CHANGE_TYPE.REMOVED), marginLeft: 20 }}>
<strong>oldValue:</strong> {renderJsonWithColor(value.oldValue, indent + 20, CHANGE_TYPE.REMOVED)}
<strong>oldValue:</strong>
<JsonWithColor item={value.oldValue} indent={indent + 20} changeType={CHANGE_TYPE.REMOVED} />
</div>
<div style={{ color: getColor(CHANGE_TYPE.ADDED), marginLeft: 20 }}>
<strong>newValue:</strong> {renderJsonWithColor(value.newValue, indent + 20, CHANGE_TYPE.ADDED)}
<strong>newValue:</strong>
<JsonWithColor item={value.newValue} indent={indent + 20} changeType={CHANGE_TYPE.ADDED} />
</div>
</div>
);

const renderArray = (key, array, indent, changeType) => (
const Array = ({ key, array, indent, changeType }) => (
<div key={key} style={{ marginBottom: 20 }}>
<strong style={{ color: getColor(changeType), fontSize: "18px" }}>{key}:</strong>
{_.map(array, (item, index) => (
<div key={index} style={{ marginLeft: 20 }}>
{renderJsonWithColor(item, indent + 20, item.changeType || changeType)}
<JsonWithColor item={item} indent={indent + 20} changeType={item.changeType || changeType} />
</div>
))}
</div>
);

const renderNestedObject = (key, obj, indent, changeType) => (
const NestedObject = ({ key, obj, indent, changeType }) => (
<div key={key} style={{ marginBottom: 10 }}>
<strong style={{ color: getColor(changeType), fontSize: "18px" }}>{key}:</strong>
<div style={{ marginLeft: 20 }}>{renderJsonWithColor(obj, indent + 20, obj.changeType || changeType)}</div>
<div style={{ marginLeft: 20 }}>
<JsonWithColor item={obj} indent={indent + 20} changeType={obj.changeType || changeType} />
</div>
</div>
);

const renderKeyValue = (key, value, changeType) => (
const KeyValue = ({ key, value, changeType }) => (
<div key={key} style={{ marginBottom: 20 }}>
<strong style={{ color: getColor(changeType), fontSize: "18px" }}>{key}:</strong>
<div style={{ color: getColor(changeType), marginLeft: 20 }}>{String(value)}</div>
Expand All @@ -183,48 +112,6 @@ const MetadataDiff = () => {
</Typography>
</div>
<Grid container spacing={3}>
<Grid item xs={12} md={6} style={{ display: "flex", justifyContent: "flex-start" }}>
<input
accept=".zip"
type="file"
onChange={e => handleFileChange(e, 1)}
style={{
display: "block",
marginBottom: 50,
width: "150%",
padding: "20px",
fontSize: "20px",
cursor: "pointer"
}}
/>
</Grid>
<Grid item xs={12} md={6} style={{ display: "flex", justifyContent: "center" }}>
<input
accept=".zip"
type="file"
onChange={e => handleFileChange(e, 2)}
style={{
display: "block",
marginBottom: 50,
width: "150%",
padding: "20px",
fontSize: "20px",
cursor: "pointer",
transform: "translateX(-70%)"
}}
/>
</Grid>
<Grid item xs={12}>
<Button
variant="contained"
color="primary"
onClick={handleSubmit}
disabled={loading}
style={{ marginTop: "-80px", marginLeft: "20px", fontSize: "18px" }}
>
Compare Metadata
</Button>
</Grid>
<Grid item xs={12}>
{loading && <CircularProgress />}
{error && <Typography color="error">{error}</Typography>}
Expand All @@ -247,7 +134,11 @@ const MetadataDiff = () => {
})}
</Select>
</FormControl>
{selectedForm && response[selectedForm] && <div style={{ marginTop: 20 }}>{renderJsonWithColor(response[selectedForm])}</div>}
{selectedForm && response[selectedForm] && (
<div style={{ marginTop: 20 }}>
<JsonWithColor data={response[selectedForm]} />
</div>
)}
</>
)}
</Grid>
Expand Down

0 comments on commit 000cb83

Please sign in to comment.