Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hierarchy #1647

Merged
merged 3 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export const UICustomizations = {
});
return res;
}
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider enhancing the delay utility function.

The delay function could be improved for better maintainability and reusability.

-const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
+/**
+ * Creates a Promise that resolves after the specified delay
+ * @param {number} ms - The delay duration in milliseconds
+ * @returns {Promise<void>}
+ */
+const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

Consider moving this utility function to a shared utilities file for reuse across the application.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
/**
* Creates a Promise that resolves after the specified delay
* @param {number} ms - The delay duration in milliseconds
* @returns {Promise<void>}
*/
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
🧰 Tools
🪛 Biome

[error] 215-215: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


⚠️ Potential issue

Fix switch case declaration scope.

The delay function is declared within a switch case, which could lead to scoping issues.

Move the declaration outside the switch statement:

+const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
+
 switch (key) {
   case "ACTION":
     const tenantId = Digit.ULBService.getCurrentTenantId();
     const generateFile = async () => {
       // ...
     }
-    const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
     const generateTemplate = async () => {
       // ...
     }
     // ...
 }

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 Biome

[error] 215-215: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

const generateTemplate = async () => {
const res = await Digit.CustomService.getResponse({
url: `/project-factory/v1/data/_download`,
Expand All @@ -228,6 +229,7 @@ export const UICustomizations = {
}
const downloadExcelTemplate = async () => {
const res = await generateFile();
await delay(2000);
const resFile = await generateTemplate();
if (resFile && resFile?.GeneratedResource?.[0]?.fileStoreid) {
// Splitting filename before .xlsx or .xls
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Card, Loader } from "@egovernments/digit-ui-components";
import { Button } from "@egovernments/digit-ui-components";
import { Button, Toast } from "@egovernments/digit-ui-components";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
Expand All @@ -9,16 +9,21 @@ const config = {
defaultHierarchyType: "DEFAULTBOUNDARY",
hierarchyType: "DEMOONCONSOLE",
};
// const [config, setConfig] = useState({defaultHierarchyType: "DEFAULTBOUNDARY",
// hierarchyType: "DEMOONCONSOLE"});
Comment on lines +12 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove commented-out code to improve code cleanliness

The commented-out code appears to be unnecessary. Removing it can help keep the codebase clean and maintainable.


const Boundary = () => {
const { t } = useTranslation();
const tenantId = Digit.ULBService.getCurrentTenantId();
const searchParams = new URLSearchParams(location.search);
const defaultHierarchyType = config?.defaultHierarchyType || searchParams.get("defaultHierarchyType");
const hierarchyType = config?.hierarchyType || searchParams.get("hierarchyType");
const [defaultHierarchyType, setDefaultHierarchyType] = useState(config?.defaultHierarchyType || searchParams.get("defaultHierarchyType"));
const [hierarchyType, setHierarchyType] = useState(config?.hierarchyType || searchParams.get("hierarchyType"));
Comment on lines +19 to +20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify optional chaining for the config object

Since config is always defined in this scope, you can remove the optional chaining config?. to simplify the code.

Apply this diff:

-const [defaultHierarchyType, setDefaultHierarchyType] = useState(config?.defaultHierarchyType || searchParams.get("defaultHierarchyType"));
+const [defaultHierarchyType, setDefaultHierarchyType] = useState(config.defaultHierarchyType || searchParams.get("defaultHierarchyType"));

-const [hierarchyType, setHierarchyType] = useState(config?.hierarchyType || searchParams.get("hierarchyType"));
+const [hierarchyType, setHierarchyType] = useState(config.hierarchyType || searchParams.get("hierarchyType"));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [defaultHierarchyType, setDefaultHierarchyType] = useState(config?.defaultHierarchyType || searchParams.get("defaultHierarchyType"));
const [hierarchyType, setHierarchyType] = useState(config?.hierarchyType || searchParams.get("hierarchyType"));
const [defaultHierarchyType, setDefaultHierarchyType] = useState(config.defaultHierarchyType || searchParams.get("defaultHierarchyType"));
const [hierarchyType, setHierarchyType] = useState(config.hierarchyType || searchParams.get("hierarchyType"));


const [showPopUp, setShowPopUp] = useState(false);
const [geoPodeData, setGeoPodeData] = useState(false);
const history = useHistory();
const mdms_context_path = window?.globalConfigs?.getConfig("MDMS_V2_CONTEXT_PATH") || "mdms-v2";

const reqCriteriaResource = {
url: `/boundary-service/boundary-hierarchy-definition/_search`,
body: {
Expand All @@ -29,11 +34,118 @@ const Boundary = () => {
hierarchyType: defaultHierarchyType,
},
},

};
const { isLoading, data, isFetching } = Digit.Hooks.useCustomAPIHook(reqCriteriaResource);
const rc = {
url: `/${mdms_context_path}/v2/_search`,
body: {
MdmsCriteria: {
tenantId: tenantId,
schemaCode: "HCM-ADMIN-CONSOLE.HierarchySchema",
},
},
changeQueryName: "SCHEMA_SEARCH",
};
const { isLoading1, data: mdms, isFetching1 } = Digit.Hooks.useCustomAPIHook(rc);
const user = Digit.UserService.getUser();
const user_name = user?.info?.userName;

const rc1 = {
url: `/health-hrms/employees/_search`,
body: {
},
params: {
tenantId: tenantId,
codes: user_name,
sortOrder: "ASC"

},
changeQueryName: user_name,
}
const { isLoading2, data:Employees, isFetching2 } = Digit.Hooks.useCustomAPIHook(rc1);

const [authorized, setAuthorized] = useState(false);

const getHierarchyTypes = React.useCallback((dataArray, campaign) => {
return dataArray
.filter(item => item.data.type === campaign)
.map(item => item.data.hierarchytype)[0];
}, []);

// Separate useEffect for authorization check and hierarchy type updates
useEffect(() => {
if (data?.BoundaryHierarchy && data?.BoundaryHierarchy.length > 0) setGeoPodeData(true);
if (!Employees?.Employees?.[0]?.assignments?.[0]?.department || !mdms) return;

const dep = Employees.Employees[0].assignments[0].department;
const arrayOfHier = mdms.mdms;

if (dep === null) {
setAuthorized(true);
return;
}

const searchForDepInCampaign = (dataArray, dep) => {
return dataArray.some(
(item) => item.data.type === "campaign" && item.data.department.includes(dep)
);
};

const result = searchForDepInCampaign(arrayOfHier, dep);

if (result) {
setAuthorized(true);

// Get both hierarchy types at once to avoid multiple state updates
const newHierarchyTypes = getHierarchyTypes(arrayOfHier, "campaign");
const newDefHierarchyTypes = getHierarchyTypes(arrayOfHier, "default");

// Only update if values have changed
if (JSON.stringify(hierarchyType) !== JSON.stringify(newHierarchyTypes)) {
setHierarchyType(newHierarchyTypes);
Comment on lines +104 to +105
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use direct comparison for hierarchy types instead of JSON.stringify

When comparing hierarchyType and newHierarchyTypes, using JSON.stringify may be unnecessary if they are strings or simple types. Consider using direct comparison for better performance.

Apply this diff:

-if (JSON.stringify(hierarchyType) !== JSON.stringify(newHierarchyTypes)) {
+if (hierarchyType !== newHierarchyTypes) {

Similarly, for defaultHierarchyType:

-if (JSON.stringify(defaultHierarchyType) !== JSON.stringify(newDefHierarchyTypes)) {
+if (defaultHierarchyType !== newDefHierarchyTypes) {

Committable suggestion was skipped due to low confidence.

callGenerate(newHierarchyTypes);
// generateFile().catch(error => {
// console.error("Failed to generate file:", error);
// });
}

if (JSON.stringify(defaultHierarchyType) !== JSON.stringify(newDefHierarchyTypes)) {
setDefaultHierarchyType(newDefHierarchyTypes);
}
} else {
setAuthorized(false);
}
}, [Employees, mdms, getHierarchyTypes]);


const generateFile = async(hierarchyType)=>{
const res = await Digit.CustomService.getResponse({
url: `/project-factory/v1/data/_generate`,
body: {
},
params: {
tenantId: tenantId,
type: "boundaryManagement",
forceUpdate: true,
hierarchyType: hierarchyType,
campaignId: "default"
}
});
return res;
}
const callGenerate =async(hierarchyType)=>{
const res = await generateFile(hierarchyType)
return res;

}

useEffect(() => {
if (data?.BoundaryHierarchy && data?.BoundaryHierarchy.length > 0)
{
setGeoPodeData(true);
}
}, [data]);


const [direct, setDirect] = useState(false);
const [directView, setDirectView] = useState(false);
Expand Down Expand Up @@ -65,7 +177,7 @@ const Boundary = () => {

const callGeoPode = (val) => {
history.push(
`/${window.contextPath}/employee/campaign/geopode?defaultHierarchyType=${defaultHierarchyType}&hierarchyType=${hierarchyType}&newHierarchy=${val}`,
`/${window.contextPath}/employee/campaign/boundary/geopode?defaultHierarchyType=${defaultHierarchyType}&hierarchyType=${hierarchyType}&newHierarchy=${val}`,
{ data: data }
);
};
Expand All @@ -78,39 +190,57 @@ const Boundary = () => {
{ data: data }
);
};

const [toast, setToast] = useState(false);

if (isFetching) return <Loader />;
return (
<React.Fragment>
<BoundaryPopup showPopUp={showPopUp} setShowPopUp={setShowPopUp} callGeoPode={callGeoPode} geoPodeData={geoPodeData} />

{toast &&
<Toast label={t("USER_NOT_AUTHORISED")} type={"error"} onClose={() => setToast(false)} />}
<Card type={"primary"} variant={"viewcard"} className={"example-view-card"}>
<div style={{ fontWeight: 700, fontSize: "2.5rem" }}>{t("BOUNDARY_DATA_MANAGEMENT")}</div>
<div style={{ height: "2rem" }}></div>
<div style={{ display: "flex", justifyContent: "space-between", width: "100%" }}>
<Button
type={"button"}
size={"large"}
// isDisabled={!authorized}
variation={"secondary"}
label={t("CREATE_NEW_BOUNDARY_DATA")}
onClick={() => {
if (direct && geoPodeData) {
if(authorized)
{
if (direct) {
callDirectView();
} else {
setShowPopUp(true);
}
}
else{
setToast(true);

}
Comment on lines +209 to +224
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure consistent handling of authorized checks and isDisabled properties

To improve user experience and code consistency, consider re-enabling the isDisabled={!authorized} property for the "Create New Boundary Data" button and removing the authorized check from the onClick handler. This prevents unauthorized users from interacting with the button.

Apply this diff:

-// isDisabled={!authorized}
+isDisabled={!authorized}

...

onClick={() => {
-  if(authorized)
-  {
     if (direct) {
       callDirectView();
     } else {
       setShowPopUp(true);
     }
-  }
-  else{
-    setToast(true);
-  }
}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// isDisabled={!authorized}
variation={"secondary"}
label={t("CREATE_NEW_BOUNDARY_DATA")}
onClick={() => {
if (direct && geoPodeData) {
if(authorized)
{
if (direct) {
callDirectView();
} else {
setShowPopUp(true);
}
}
else{
setToast(true);
}
isDisabled={!authorized}
variation={"secondary"}
label={t("CREATE_NEW_BOUNDARY_DATA")}
onClick={() => {
if (direct) {
callDirectView();
} else {
setShowPopUp(true);
}
}}

}}
style={{ width: "38rem", height: "5rem" }}
textStyles={{ fontSize: "1.5rem" }}
/>
<Button
type={"button"}
size={"large"}
isDisabled={!directView}
isDisabled={!directView && !authorized}
variation={"secondary"}
label={t("EDIT_BOUNDARY_DATA")}
onClick={() => {
// setShowPopUp(false);
callDirectView();
if(authorized)
{
callDirectView();
}
else{
setToast(true);
}
Comment on lines +232 to +243
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Align isDisabled property with authorized state for the "Edit Boundary Data" button

For consistency, adjust the isDisabled property and simplify the onClick handler by relying on the button's disabled state.

Apply this diff:

-isDisabled={!directView && !authorized}
+isDisabled={!authorized}

...

onClick={() => {
-  if(authorized)
-  {
     callDirectView();
-  }
-  else{
-    setToast(true);
-  }
}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isDisabled={!directView && !authorized}
variation={"secondary"}
label={t("EDIT_BOUNDARY_DATA")}
onClick={() => {
// setShowPopUp(false);
callDirectView();
if(authorized)
{
callDirectView();
}
else{
setToast(true);
}
isDisabled={!authorized}
variation={"secondary"}
label={t("EDIT_BOUNDARY_DATA")}
onClick={() => {
// setShowPopUp(false);
callDirectView();

}}
style={{ width: "38rem", height: "5rem" }}
textStyles={{ fontSize: "1.5rem" }}
Expand Down
Loading