Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0cb1fa4
Added complaint changes
Bhavya-egov Aug 4, 2025
3cd151a
FEATURE/HCMPRE-2947 : Cancel Campign UI Integration (#2964)
Swathi-eGov Aug 6, 2025
45c5ffe
Merge branch 'master' into console-V0.5
Swathi-eGov Aug 6, 2025
230df89
Fixed Syntax Issue
Swathi-eGov Aug 6, 2025
6e9194d
Merge branch 'master' into console-V0.5
Swathi-eGov Aug 6, 2025
ad486aa
Merge branch 'master' into console-V0.5
Swathi-eGov Aug 6, 2025
a0cc3f4
Merge branch 'master' into console-V0.5
NabeelAyubee Aug 6, 2025
ff44c55
Merge branch 'master' into console-V0.5
Swathi-eGov Aug 8, 2025
2bcee17
Merge branch 'master' into console-V0.5
Swathi-eGov Aug 8, 2025
3f516d6
FEATURE/HCMPRE-2958 : Added dependency field changes (#2980)
Swathi-eGov Aug 8, 2025
747151d
Merge branch 'master' into console-V0.5
Swathi-eGov Aug 8, 2025
c671b13
Fixed Compile issues
Ramkrishna-egov Aug 11, 2025
d3672b5
GIT-2888:: Fetaures/Properties changes and HRMS Fixes (#2959)
Ramkrishna-egov Aug 11, 2025
5272fef
Fixed Acxknowledgement page rendering and Accept visibilityCondition …
Ramkrishna-egov Aug 12, 2025
4ffc60e
Added complaint components
Ramkrishna-egov Aug 13, 2025
4bdcd7b
Added autro fill condition to field properties
Ramkrishna-egov Aug 13, 2025
218abb2
Updated Complaint Inbox Template name
Ramkrishna-egov Aug 18, 2025
468c4e9
Fixed FormConfig update issue
Ramkrishna-egov Aug 18, 2025
f42593c
Updated conditionalNavigationKey in Form Config to acept empty array …
Ramkrishna-egov Aug 18, 2025
218a4ae
migrating 0.4 fixes (#3024)
nabeelmd-eGov Aug 22, 2025
046c25a
Updated Template renderer Case mismatch for template name
Ramkrishna-egov Aug 25, 2025
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 @@ -137,7 +137,7 @@ const getFieldType = (field) => {
return "text";
case "number":
return "number";
case "textarea":
case "textArea":
return "textarea";
case "time":
return "time";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";


const ViewDetailComponent = ({ headingName, desc, buttonLabel, navLink , type , icon , disabled,isDraftCampaign }) => {
const { t } = useTranslation();
const history = useHistory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState, useMemo, Fragment, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { useLocation, useHistory } from "react-router-dom";
import { Wrapper } from "./SelectingBoundaryComponent";
import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader,Chip } from "@egovernments/digit-ui-components";
import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader, PopUp, Button, Chip } from "@egovernments/digit-ui-components";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

CardText used but not imported — will crash at runtime

You render inside PopUp, but it isn’t imported. Either import CardText or replace it with the already-imported TextBlock.

Apply this minimal fix:

-import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader, PopUp, Button, Chip } from "@egovernments/digit-ui-components";
+import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader, PopUp, Button, Chip, CardText } from "@egovernments/digit-ui-components";
📝 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
import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader, PopUp, Button, Chip } from "@egovernments/digit-ui-components";
-import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader, PopUp, Button, Chip } from "@egovernments/digit-ui-components";
+import { AlertCard, Stepper, TextBlock, Tag, Card, HeaderComponent, Loader, PopUp, Button, Chip, CardText } from "@egovernments/digit-ui-components";
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/SelectingBoundariesDuplicate.js
around line 5, the JSX renders <CardText> but CardText is not imported causing a
runtime crash; replace any <CardText> usage with the already-imported TextBlock
(or alternatively add CardText to the named import list from
"@egovernments/digit-ui-components") so the component reference matches an
imported symbol.

import { CONSOLE_MDMS_MODULENAME } from "../Module";
import TagComponent from "./TagComponent";

Expand Down Expand Up @@ -78,7 +78,7 @@ const SelectingBoundariesDuplicate = ({ onSelect, formData, ...props }) => {
},
};

const { data: campaignData, isFetching } = Digit.Hooks.useCustomAPIHook(reqCriteria);
const { data: campaignData, isFetching } = Digit.Hooks.useCustomAPIHook(reqCriteria);

Comment on lines +81 to 82
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)

Hook result aliasing: remove unused isFetching or use for loader

You destructure isFetching but never use it. Either wire it into your loading state or drop it to keep the file clean.

🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/SelectingBoundariesDuplicate.js
around lines 81-82, the hook result destructures isFetching but it is never
used; either remove isFetching from the destructuring to avoid an unused
variable, or wire it into the component's loading state (e.g., show a
loader/spinner or an early return while isFetching is true and only render the
main UI when false); update imports/props as needed to pass the loading flag to
children or to render a loading indicator and ensure no lint warnings remain.

useEffect(() => {
onSelect("boundaryType", { selectedData: selectedData, boundaryData: boundaryOptions, updateBoundary: !restrictSelection });
Expand Down Expand Up @@ -107,9 +107,9 @@ const SelectingBoundariesDuplicate = ({ onSelect, formData, ...props }) => {
setBoundaryOptions(sessionData?.boundaryData || {});
}
setTimeout(() => setIsLoading(false), 10);
}, [props?.props?.sessionData?.HCM_CAMPAIGN_SELECTING_BOUNDARY_DATA?.boundaryType , campaignData]);
}, [props?.props?.sessionData?.HCM_CAMPAIGN_SELECTING_BOUNDARY_DATA?.boundaryType, campaignData]);

useEffect(() => {
useEffect(() => {
if (
props?.props?.sessionData?.HCM_CAMPAIGN_UPLOAD_BOUNDARY_DATA?.uploadBoundary?.uploadedFile?.length > 0 ||
props?.props?.sessionData?.HCM_CAMPAIGN_UPLOAD_FACILITY_DATA?.uploadFacility?.uploadedFile?.length > 0 ||
Expand Down Expand Up @@ -138,6 +138,32 @@ const SelectingBoundariesDuplicate = ({ onSelect, formData, ...props }) => {
// window.dispatchEvent(new Event("checking"));
// }, [key]);

const Template = {
url: "/project-factory/v1/project-type/cancel-campaign",
body: {
CampaignDetails: {
tenantId: tenantId,
campaignId: queryParams?.id,
}
},
};
const mutation = Digit.Hooks.useCustomAPIMutationHook(Template);

const handleCancelClick = async () => {
await mutation.mutate(
{},
{
onSuccess: async (result) => {
history.push(`/${window?.contextPath}/employee/campaign/my-campaign-new`)
},
onError: (error, result) => {
const errorCode = error?.response?.data?.Errors?.[0]?.code;
console.error(errorCode);
},
}
);
};

const checkDataPresent = ({ action }) => {
if (action === false) {
setShowPopUp(false);
Expand Down Expand Up @@ -191,7 +217,7 @@ const SelectingBoundariesDuplicate = ({ onSelect, formData, ...props }) => {
<TagComponent campaignName={campaignName} />
{
isDraftCampaign ? (
<div className="digit-tag-container" style={{margin:"0rem"}}>
<div className="digit-tag-container" style={{ margin: "0rem" }}>
<Chip text={`${t(`CANCEL_CAMPAIGN`)}`} onClick={handleCancelClick} hideClose={false} />
</div>
) : null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ const AppConfigurationParentRedesign = ({
parentDispatch={parentDispatch}
AppConfigMdmsData={AppConfigMdmsData}
localeModule={localeModule}
parentState={parentState}
pageTag={`${t("CMN_PAGE")} ${currentStep} / ${stepper?.length}`}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ const reducer = (state = initialState, action, updateLocalization) => {

const MODULE_CONSTANTS = "HCM-ADMIN-CONSOLE";

function AppConfigurationWrapper({ screenConfig, localeModule, pageTag }) {
function AppConfigurationWrapper({ screenConfig, localeModule, pageTag,parentState }) {
const queryClient = useQueryClient();
const { locState, addMissingKey, updateLocalization, onSubmit, back, showBack, parentDispatch } = useAppLocalisationContext();
const [state, dispatch] = useReducer((state, action) => reducer(state, action, updateLocalization), initialState);
Expand Down Expand Up @@ -395,7 +395,7 @@ function AppConfigurationWrapper({ screenConfig, localeModule, pageTag }) {
for (let i = 0; i < headerFields.length; i++) {
if (headerFields[i]?.jsonPath === "ScreenHeading") {
const fieldItem = headerFields[i];
const value = locS?.find((i) => i?.code === fieldItem?.value)?.[cL] || null;
const value = (locS ||[])?.find((i) => i?.code === fieldItem?.value)?.[cL] || null;
if (!value || value.trim() === "") {
return { type: "error", value: `${t("HEADER_FIELD_EMPTY_ERROR")}` };
}
Expand Down Expand Up @@ -633,7 +633,7 @@ function AppConfigurationWrapper({ screenConfig, localeModule, pageTag }) {
})
}
/>
<DrawerFieldComposer />
<DrawerFieldComposer parentState={parentState} screenConfig={screenConfig} selectedField={state?.drawerField}/>
</>
) : (
<DndProvider backend={HTML5Backend}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const locReducer = (state = initialState, action) => {

const MODULE_CONSTANTS = "HCM-ADMIN-CONSOLE";
//TODO @nabeel @jagan move this component to ui-component repo & clean up
function AppLocalisationWrapperDev({ onSubmit, localeModule, screenConfig, back, showBack, parentDispatch, ...props }) {
function AppLocalisationWrapperDev({ onSubmit, localeModule, screenConfig, back, showBack, parentDispatch, parentState,...props }) {
if (!localeModule) {
return <Loader />;
}
Expand Down Expand Up @@ -129,7 +129,7 @@ function AppLocalisationWrapperDev({ onSubmit, localeModule, screenConfig, back,
localeModule,
}}
>
<AppConfigurationWrapper pageTag={props?.pageTag} screenConfig={screenConfig} localeModule={localeModule} />
<AppConfigurationWrapper pageTag={props?.pageTag} screenConfig={screenConfig} localeModule={localeModule} parentState={parentState}/>
</AppLocalisationContext.Provider>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import React, { useEffect, useState, Fragment, useMemo } from "react";
import { Dropdown, Card, FieldV1, LabelFieldPair, TextInput } from "@egovernments/digit-ui-components";

function DependentFieldsWrapper({ t, parentState, onExpressionChange, screenConfig, selectedFieldItem }) {

// List of possible operators
const OPERATORS = ['!==', '>=', '<=', '==', '>', '<']
.sort((a, b) => b.length - a.length);
/**
* Parses an expression like "A.B==C" and extracts A, B, operator, C
*/
function parseExpression(expression = "") {
for (const operator of OPERATORS) {
const idx = expression.indexOf(operator);
if (idx !== -1) {
const [field, value] = [
expression.slice(0, idx),
expression.slice(idx + operator.length)
];
const [selectedPage, selectedField] = field.split(".");
return {
selectedPage: { code: selectedPage, name: selectedPage } || "",
selectedField: { code: selectedField, name: selectedField } || "",
comparisonType: { code: operator, name: operator },
fieldValue: value || ""
};
}
}
// Fallback: if no operator found
return {
selectedPage: {},
selectedField: {},
comparisonType: {},
fieldValue: ""
};
}
Comment on lines +12 to +36
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parsing of field path with nested dots; split only on the first dot.

Current field.split(".") drops deeper segments in jsonPath (e.g., page.a.b.c becomes page/a). Split at the first dot to preserve the full field path.

Apply:

-                const [selectedPage, selectedField] = field.split(".");
-                return {
-                    selectedPage: { code: selectedPage, name: selectedPage } || "",
-                    selectedField: { code: selectedField, name: selectedField } || "",
+                const dotIdx = field.indexOf(".");
+                const pagePart = dotIdx >= 0 ? field.slice(0, dotIdx) : field;
+                const fieldPart = dotIdx >= 0 ? field.slice(dotIdx + 1) : "";
+                return {
+                    selectedPage: pagePart ? { code: pagePart, name: pagePart } : {},
+                    selectedField: fieldPart ? { code: fieldPart, name: fieldPart } : {},
                     comparisonType: { code: operator, name: operator },
                     fieldValue: value || ""
                 };
📝 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
function parseExpression(expression = "") {
for (const operator of OPERATORS) {
const idx = expression.indexOf(operator);
if (idx !== -1) {
const [field, value] = [
expression.slice(0, idx),
expression.slice(idx + operator.length)
];
const [selectedPage, selectedField] = field.split(".");
return {
selectedPage: { code: selectedPage, name: selectedPage } || "",
selectedField: { code: selectedField, name: selectedField } || "",
comparisonType: { code: operator, name: operator },
fieldValue: value || ""
};
}
}
// Fallback: if no operator found
return {
selectedPage: {},
selectedField: {},
comparisonType: {},
fieldValue: ""
};
}
function parseExpression(expression = "") {
for (const operator of OPERATORS) {
const idx = expression.indexOf(operator);
if (idx !== -1) {
const [field, value] = [
expression.slice(0, idx),
expression.slice(idx + operator.length)
];
const dotIdx = field.indexOf(".");
const pagePart = dotIdx >= 0 ? field.slice(0, dotIdx) : field;
const fieldPart = dotIdx >= 0 ? field.slice(dotIdx + 1) : "";
return {
selectedPage: pagePart ? { code: pagePart, name: pagePart } : {},
selectedField: fieldPart ? { code: fieldPart, name: fieldPart } : {},
comparisonType: { code: operator, name: operator },
fieldValue: value || ""
};
}
}
// Fallback: if no operator found
return {
selectedPage: {},
selectedField: {},
comparisonType: {},
fieldValue: ""
};
}
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
between lines 12 and 36, the parseExpression function incorrectly splits the
field string on every dot, losing nested path segments. Modify the split logic
to split only on the first dot, extracting the selectedPage as the substring
before the first dot and selectedField as the remainder after it, preserving the
full nested field path.


const currentExpressionFromConfig = selectedFieldItem?.visibilityCondition?.expression;

const parsed = parseExpression(currentExpressionFromConfig);

// State initialization
const [selectedPage, setSelectedPage] = useState(parsed.selectedPage);
const [selectedField, setSelectedField] = useState(parsed.selectedField);
const [comparisonType, setComparisonType] = useState(parsed.comparisonType);
const [fieldValue, setFieldValue] = useState(parsed.fieldValue);
const currentPage = screenConfig?.[0]?.name;
const currentTemplate = parentState?.currentTemplate;

const pageOptions = useMemo(() => {
const currentIndex = currentTemplate.findIndex((p) => p.name === currentPage);
return currentTemplate.slice(0, currentIndex + 1).map((p) => ({
code: p.name,
name: p.name,
}));
}, [currentTemplate, currentPage]);
Comment on lines +50 to +56
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against undefined currentTemplate to prevent runtime errors.

If parentState.currentTemplate is undefined, .findIndex()/.slice() will throw. Default to an empty array.

Apply:

-    const pageOptions = useMemo(() => {
-        const currentIndex = currentTemplate.findIndex((p) => p.name === currentPage);
-        return currentTemplate.slice(0, currentIndex + 1).map((p) => ({
+    const pageOptions = useMemo(() => {
+        const template = Array.isArray(currentTemplate) ? currentTemplate : [];
+        const currentIndex = template.findIndex((p) => p.name === currentPage);
+        return template.slice(0, currentIndex + 1).map((p) => ({
             code: p.name,
             name: p.name,
         }));
-    }, [currentTemplate, currentPage]);
+    }, [currentTemplate, currentPage]);
📝 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 pageOptions = useMemo(() => {
const currentIndex = currentTemplate.findIndex((p) => p.name === currentPage);
return currentTemplate.slice(0, currentIndex + 1).map((p) => ({
code: p.name,
name: p.name,
}));
}, [currentTemplate, currentPage]);
const pageOptions = useMemo(() => {
const template = Array.isArray(currentTemplate) ? currentTemplate : [];
const currentIndex = template.findIndex((p) => p.name === currentPage);
return template.slice(0, currentIndex + 1).map((p) => ({
code: p.name,
name: p.name,
}));
}, [currentTemplate, currentPage]);
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
around lines 50 to 56, the code uses currentTemplate without checking if it is
undefined, which can cause runtime errors when calling findIndex or slice. Fix
this by defaulting currentTemplate to an empty array if it is undefined before
using it in useMemo, ensuring safe calls to findIndex and slice.


const fieldOptions = useMemo(() => {
const pageObj = currentTemplate.find((p) => p.name === selectedPage?.code)?.cards?.[0];
if (!pageObj) return [];
return pageObj.fields.map((f) => ({
code: f.jsonPath,
name: f.jsonPath,
format: f.format,
enums: f.dropDownOptions || [],
}));
}, [parentState?.currentTemplate, selectedPage?.code]);
Comment on lines +58 to +67
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Also null-safe fieldOptions and align useMemo deps with referenced vars.

Use the local currentTemplate (null-safe) and avoid errors when page is not found.

Apply:

-    const fieldOptions = useMemo(() => {
-        const pageObj = currentTemplate.find((p) => p.name === selectedPage?.code)?.cards?.[0];
+    const fieldOptions = useMemo(() => {
+        const template = Array.isArray(currentTemplate) ? currentTemplate : [];
+        const pageObj = template.find((p) => p.name === selectedPage?.code)?.cards?.[0];
         if (!pageObj) return [];
         return pageObj.fields.map((f) => ({
             code: f.jsonPath,
             name: f.jsonPath,
             format: f.format,
             enums: f.dropDownOptions || [],
         }));
-    }, [parentState?.currentTemplate, selectedPage?.code]);
+    }, [currentTemplate, selectedPage?.code]);
📝 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 fieldOptions = useMemo(() => {
const pageObj = currentTemplate.find((p) => p.name === selectedPage?.code)?.cards?.[0];
if (!pageObj) return [];
return pageObj.fields.map((f) => ({
code: f.jsonPath,
name: f.jsonPath,
format: f.format,
enums: f.dropDownOptions || [],
}));
}, [parentState?.currentTemplate, selectedPage?.code]);
const fieldOptions = useMemo(() => {
const template = Array.isArray(currentTemplate) ? currentTemplate : [];
const pageObj = template.find((p) => p.name === selectedPage?.code)?.cards?.[0];
if (!pageObj) return [];
return pageObj.fields.map((f) => ({
code: f.jsonPath,
name: f.jsonPath,
format: f.format,
enums: f.dropDownOptions || [],
}));
}, [currentTemplate, selectedPage?.code]);
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
around lines 58 to 67, the useMemo hook references parentState?.currentTemplate
in dependencies but uses local currentTemplate variable inside, which can cause
stale values or errors. Fix this by updating the dependency array to include
currentTemplate instead of parentState?.currentTemplate, and add null checks to
ensure currentTemplate and selectedPage are valid before accessing their
properties to prevent runtime errors when pageObj is not found.


const selectedFieldObj = fieldOptions.find((f) => f.code === selectedField);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix selected field lookup; compare against selectedField.code.

selectedField is an object; comparing to it directly fails.

Apply:

-    const selectedFieldObj = fieldOptions.find((f) => f.code === selectedField);
+    const selectedFieldObj = fieldOptions.find((f) => f.code === selectedField?.code);
📝 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 selectedFieldObj = fieldOptions.find((f) => f.code === selectedField);
const selectedFieldObj = fieldOptions.find((f) => f.code === selectedField?.code);
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
at line 69, the code compares fieldOptions' code to selectedField directly, but
selectedField is an object. Fix this by comparing fieldOptions' code to
selectedField.code instead to correctly find the matching field object.


useEffect(() => {
if (selectedPage?.code && selectedField?.code && comparisonType?.code && fieldValue !== "") {
const expression = `${selectedPage?.code}.${selectedField?.code}${comparisonType?.code}${fieldValue}`;
onExpressionChange?.(expression);
}
}, [selectedPage?.code, selectedField?.code, comparisonType?.code, fieldValue, onExpressionChange]);

return (
<Card type="secondary">
<LabelFieldPair vertical={true} removeMargin={true}>
<p style={{ margin: "0px" }}>{t("HCM_SELECT_PAGE")}</p>
<div className="digit-field" style={{ width: "100%" }}>
<Dropdown
option={pageOptions}
optionKey="code"
name="pageSelect"
t={t}
select={(e) => {
setSelectedPage(e);
setSelectedField({});
}}
selected={selectedPage}
/>
</div>
</LabelFieldPair>
<LabelFieldPair vertical={true} removeMargin={true}>
<p style={{ margin: "0px" }}>{t("HCM_SELECT_FIELD")}</p>
<div className="digit-field" style={{ width: "100%" }}>
<Dropdown
option={fieldOptions}
optionKey="code"
name="fieldSelect"
t={t}
select={(e) => {
setSelectedField(e);
setFieldValue("");
}}
selected={selectedField}
disabled={!selectedPage?.code}
/>
</div>
</LabelFieldPair>
<LabelFieldPair vertical={true} removeMargin={true}>
<p style={{ margin: "0px" }}>{t("HCM_COMPARISION_TYPE")}</p>
<div className="digit-field" style={{ width: "100%" }}>
<Dropdown
option={[
{ code: "==", name: "equals to" },
{ code: "!==", name: "not equals to" },
{ code: ">=", name: "greater than or equals to" },
{ code: "<=", name: "less than or equals to" },
{ code: ">", name: "greater than" },
{ code: "<", name: "less than" },
]}
optionKey="code"
name="comparisonSelect"
t={t}
select={(e) => setComparisonType(e)}
disabled={!selectedField?.code}
selected={comparisonType}
/>
Comment on lines +117 to +131
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)

Optional: localize operator labels.

Operator names are hardcoded in English. Consider using translation keys for consistency.

Example:

-    { code: "==", name: "equals to" },
+    { code: "==", name: t("HCM_EQUALS_TO") },
📝 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
option={[
{ code: "==", name: "equals to" },
{ code: "!==", name: "not equals to" },
{ code: ">=", name: "greater than or equals to" },
{ code: "<=", name: "less than or equals to" },
{ code: ">", name: "greater than" },
{ code: "<", name: "less than" },
]}
optionKey="code"
name="comparisonSelect"
t={t}
select={(e) => setComparisonType(e)}
disabled={!selectedField?.code}
selected={comparisonType}
/>
option={[
- { code: "==", name: "equals to" },
+ { code: "==", name: t("HCM_EQUALS_TO") },
{ code: "!==", name: "not equals to" },
{ code: ">=", name: "greater than or equals to" },
{ code: "<=", name: "less than or equals to" },
{ code: ">", name: "greater than" },
{ code: "<", name: "less than" },
]}
optionKey="code"
name="comparisonSelect"
t={t}
select={(e) => setComparisonType(e)}
disabled={!selectedField?.code}
selected={comparisonType}
/>
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
around lines 117 to 131, the operator labels are hardcoded in English, which
affects localization consistency. Replace the hardcoded operator names with
translation keys using the provided translation function 't' to enable proper
localization of these labels.

</div>
</LabelFieldPair>
<LabelFieldPair vertical={true} removeMargin={true}>
<p style={{ margin: "0px" }}>{t("HCM_SELECT_VALUE")}</p>
<div className="digit-field" style={{ width: "100%" }}>
{selectedFieldObj && selectedFieldObj.format === "dropdown" ? (
<Dropdown
label={t("Select Value")}
option={selectedFieldObj.enums.map((en) => ({
code: en.code,
name: en.name,
}))}
optionKey="code"
name="valueSelect"
t={t}
select={(e) => setFieldValue(e.code)}
disabled={!selectedField?.code}
selected={fieldValue}
/>
) : (
Comment on lines +137 to +151
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Pass an object as selected to Dropdown; string breaks selection highlighting.

Your other Dropdown usages pass an object. Use the selected enum object for consistency.

Apply:

-                        <Dropdown
+                        <Dropdown
                             label={t("Select Value")}
                             option={selectedFieldObj.enums.map((en) => ({
                                 code: en.code,
                                 name: en.name,
                             }))}
                             optionKey="code"
                             name="valueSelect"
                             t={t}
-                            select={(e) => setFieldValue(e.code)}
+                            select={(e) => setFieldValue(e.code)}
                             disabled={!selectedField?.code}
-                            selected={fieldValue}
+                            selected={selectedFieldObj.enums.find((en) => en.code === fieldValue) || {}}
                         />
📝 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
{selectedFieldObj && selectedFieldObj.format === "dropdown" ? (
<Dropdown
label={t("Select Value")}
option={selectedFieldObj.enums.map((en) => ({
code: en.code,
name: en.name,
}))}
optionKey="code"
name="valueSelect"
t={t}
select={(e) => setFieldValue(e.code)}
disabled={!selectedField?.code}
selected={fieldValue}
/>
) : (
{selectedFieldObj && selectedFieldObj.format === "dropdown" ? (
<Dropdown
label={t("Select Value")}
option={selectedFieldObj.enums.map((en) => ({
code: en.code,
name: en.name,
}))}
optionKey="code"
name="valueSelect"
t={t}
select={(e) => setFieldValue(e.code)}
disabled={!selectedField?.code}
selected={selectedFieldObj.enums.find((en) => en.code === fieldValue) || {}}
/>
) : (
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
between lines 137 and 151, the Dropdown component's selected prop is currently
set to a string (fieldValue), which breaks selection highlighting. To fix this,
pass the entire selected enum object from selectedFieldObj.enums that matches
fieldValue instead of just the string code, ensuring consistency with other
Dropdown usages that expect an object for the selected prop.

<TextInput
type="text"
populators={{ name: "fieldValue" }}
placeholder={t("Enter value")}
value={fieldValue}
onChange={(event) => setFieldValue(event.target.value)}
disabled={!selectedField?.code}
/>
)}
</div>
</LabelFieldPair>
</Card>
);
}

export default React.memo(DependentFieldsWrapper);
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const whenToShow = (panelItem, drawerState) => {
}
};

const RenderField = ({ state, panelItem, drawerState, setDrawerState, updateLocalization, AppScreenLocalisationConfig }) => {
const RenderField = ({ state, panelItem, drawerState, setDrawerState, updateLocalization, AppScreenLocalisationConfig,parentState,handleExpressionChange,screenConfig ,selectedField}) => {
const { t } = useTranslation();
const isLocalisable = AppScreenLocalisationConfig?.fields
?.find((i) => i.fieldType === drawerState?.appType)
Expand Down Expand Up @@ -166,6 +166,10 @@ const RenderField = ({ state, panelItem, drawerState, setDrawerState, updateLoca
drawerState={drawerState}
AppScreenLocalisationConfig={AppScreenLocalisationConfig}
disabled={drawerState?.hidden}
parentState={parentState}
handleExpressionChange={handleExpressionChange}
screenConfig={screenConfig}
selectedField={selectedField}
/>
))
: null}
Expand Down Expand Up @@ -381,7 +385,7 @@ const RenderField = ({ state, panelItem, drawerState, setDrawerState, updateLoca
}
};

function DrawerFieldComposer() {
function DrawerFieldComposer({parentState,screenConfig,selectedField}) {
const { t } = useTranslation();
const { locState, updateLocalization, AppScreenLocalisationConfig } = useAppLocalisationContext();
const { state, dispatch } = useAppConfigContext();
Expand All @@ -404,6 +408,19 @@ function DrawerFieldComposer() {
return state?.MASTER_DATA?.DrawerPanelConfig?.filter((i) => i.tab === activeTab).sort((a, b) => a.order - b.order);
}, [state?.MASTER_DATA?.drawerField, tabs]);

const handleExpressionChange = (expressionString) => {
if (drawerState.visibilityCondition?.expression !== expressionString) {
setDrawerState(prev => ({
...prev,
visibilityCondition: {
...prev.visibilityCondition,
expression: expressionString
}
}));
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent crash when visibilityCondition is undefined.

Spreading prev.visibilityCondition throws if it’s undefined. Default it to {}.

Apply:

   const handleExpressionChange = (expressionString) => {
     if (drawerState.visibilityCondition?.expression !== expressionString) {
       setDrawerState(prev => ({
         ...prev,
         visibilityCondition: {
-          ...prev.visibilityCondition,
+          ...(prev.visibilityCondition || {}),
           expression: expressionString
         }
       }));
     }
   };
📝 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 handleExpressionChange = (expressionString) => {
if (drawerState.visibilityCondition?.expression !== expressionString) {
setDrawerState(prev => ({
...prev,
visibilityCondition: {
...prev.visibilityCondition,
expression: expressionString
}
}));
}
};
const handleExpressionChange = (expressionString) => {
if (drawerState.visibilityCondition?.expression !== expressionString) {
setDrawerState(prev => ({
...prev,
visibilityCondition: {
...(prev.visibilityCondition || {}),
expression: expressionString
}
}));
}
};
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
around lines 411 to 421, the code spreads prev.visibilityCondition without
checking if it is undefined, which can cause a crash. To fix this, default
prev.visibilityCondition to an empty object {} when spreading it inside
setDrawerState to prevent errors when it is undefined.



useEffect(() => {
if (state?.drawerField) {
setDrawerState(state?.drawerField);
Expand Down Expand Up @@ -476,6 +493,10 @@ function DrawerFieldComposer() {
state={state}
updateLocalization={updateLocalization}
AppScreenLocalisationConfig={AppScreenLocalisationConfig}
parentState={parentState}
handleExpressionChange={handleExpressionChange}
screenConfig={screenConfig}
selectedField={selectedField}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AppLocalisationWrapper, Loader, useCustomT } from "@egovernments/digit-
//development mode
import AppPreview from "../../../components/AppPreview";

function ImpelComponentWrapper({ variant, screenConfig, submit, back, showBack, parentDispatch, localeModule, pageTag, ...props }) {
function ImpelComponentWrapper({ variant, screenConfig, submit, back, showBack, parentDispatch, localeModule, pageTag, parentState,...props }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Prop added to wrapper signature looks fine; ensure all callers are updated.

Adding parentState here is consistent with the redesign. Verify upstream callers pass it everywhere to avoid undefined access downstream.

Run to find all ImpelComponentWrapper usages and verify parentState is passed:


🏁 Script executed:

#!/bin/bash
rg -n "ImpelComponentWrapper" -A3 -B1

Length of output: 3324


Missing parentState Prop in ImpelComponentWrapper Call

The only caller of ImpelComponentWrapper in
AppConfigurationParentLayer.js (around line 473) isn’t passing the newly added parentState prop. This will lead to undefined downstream. Please update the invocation:

<ImpelComponentWrapper
   variant={variant}
   screenConfig={currentScreen}
   submit={submit}
+  parentState={parentState}
   back={back}
   showBack={showBack}
   parentDispatch={parentDispatch}
   localeModule={localeModule}
   pageTag={pageTag}
   {...props}
/>

• File: packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
• Location: around line 473

Ensure any other usages (if added later) also include parentState.

📝 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
function ImpelComponentWrapper({ variant, screenConfig, submit, back, showBack, parentDispatch, localeModule, pageTag, parentState,...props }) {
<ImpelComponentWrapper
variant={variant}
screenConfig={currentScreen}
submit={submit}
parentState={parentState}
back={back}
showBack={showBack}
parentDispatch={parentDispatch}
localeModule={localeModule}
pageTag={pageTag}
{...props}
/>
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
around line 473, the call to ImpelComponentWrapper is missing the newly added
parentState prop. Update the invocation of ImpelComponentWrapper to include the
parentState prop by passing the appropriate parentState value from the current
component's state or props. Also, verify any other usages of
ImpelComponentWrapper to ensure they include the parentState prop to avoid
undefined errors downstream.

const MODULE_CONSTANTS = "HCM-ADMIN-CONSOLE";
const searchParams = new URLSearchParams(location.search);
const fieldMasterName = searchParams.get("fieldType");
Expand Down Expand Up @@ -186,6 +186,7 @@ function ImpelComponentWrapper({ variant, screenConfig, submit, back, showBack,
// parentDispatch={parentDispatch}
// localeModule={localeModule}
// pageTag={pageTag}
// parentState={parentState}
// />
// );
// }
Expand All @@ -199,6 +200,7 @@ function ImpelComponentWrapper({ variant, screenConfig, submit, back, showBack,
parentDispatch={parentDispatch}
localeModule={localeModule}
pageTag={pageTag}
parentState={parentState}
>
<AppPreview />
</AppLocalisationWrapper>
Expand Down
Loading
Loading