From 34bba7f6d33b811e36541cb90c9834d1a83b4462 Mon Sep 17 00:00:00 2001 From: rachana-egov Date: Mon, 11 Nov 2024 18:09:34 +0530 Subject: [PATCH 1/2] fixed boundary selection dropdown issue --- .../src/components/MultiSelectDropdown.js | 101 ++++-- .../components/SelectingBoundaryComponent.js | 340 +++++++++--------- 2 files changed, 236 insertions(+), 205 deletions(-) diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/MultiSelectDropdown.js b/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/MultiSelectDropdown.js index f38487a0974..39d627298ca 100644 --- a/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/MultiSelectDropdown.js +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/MultiSelectDropdown.js @@ -55,7 +55,7 @@ const primaryIconColor = Colors.lightTheme.primary[1]; const dividerColor = Colors.lightTheme.generic.divider; const background = Colors.lightTheme.paper.secondary; -const Wrapper = ({ boundaryOptions, setShowPopUp, alreadyQueuedSelectedState, onSelect, popUpOption ,hierarchyType ,frozenData , frozenType }) => { +const Wrapper = ({ boundaryOptions, setShowPopUp, alreadyQueuedSelectedState, onSelect, popUpOption, hierarchyType, frozenData, frozenType, onClose }) => { const [dummySelected, setDummySelected] = useState(alreadyQueuedSelectedState); const boundaryType = alreadyQueuedSelectedState.find((item) => item.propsData[1] !== null)?.propsData[1]?.type; const { t } = useTranslation(); @@ -124,6 +124,7 @@ const Wrapper = ({ boundaryOptions, setShowPopUp, alreadyQueuedSelectedState, on onClick={() => { const selectedPropsData = dummySelected.map((item) => item.propsData); onSelect(selectedPropsData); + onClose(selectedPropsData); setShowPopUp(false); }} />, @@ -135,7 +136,7 @@ const Wrapper = ({ boundaryOptions, setShowPopUp, alreadyQueuedSelectedState, on > - {t((hierarchyType + "_" + boundaryType).toUpperCase())} + {t((hierarchyType + "_" + boundaryType).toUpperCase())} *
@@ -192,7 +193,7 @@ const Wrapper = ({ boundaryOptions, setShowPopUp, alreadyQueuedSelectedState, on }, {}) ).map(([parent, items]) => (
-
{t(parent)}
+
{t(parent)}
{items.map((value, index) => { const translatedText = t(value.code); @@ -250,6 +251,7 @@ const MultiSelectDropdown = ({ optionsKey, selected = [], onSelect, + onClose, defaultLabel = "", defaultUnit = "", props, @@ -268,7 +270,7 @@ const MultiSelectDropdown = ({ popUpOption, hierarchyType, frozenType, - isSearchable=false, + isSearchable = false, }) => { const [active, setActive] = useState(false); const [searchQuery, setSearchQuery] = useState(); @@ -307,7 +309,15 @@ const MultiSelectDropdown = ({ newState.map((e) => e.propsData), getCategorySelectAllState(), props - ); // Update the form state here + ); + if (onClose && !active) { + onClose( + newState.map((e) => e.propsData), + getCategorySelectAllState(), + props + ); + } + // Update the form state here return newState; case "REPLACE_COMPLETE_STATE": return action.payload; @@ -344,6 +354,14 @@ const MultiSelectDropdown = ({ getCategorySelectAllState(), props ); + if (onClose) { + onClose( + alreadyQueuedSelectedState?.map((e) => e.propsData), + getCategorySelectAllState(), + props + ); + } + } }, [active]); @@ -351,7 +369,7 @@ const MultiSelectDropdown = ({ const initialCategorySelectedState = options.reduce((acc, category) => { if (category.options) { var filteredCategoryOptions = category?.options; - if(searchQuery?.length>0){ + if (searchQuery?.length > 0) { filteredCategoryOptions = category?.options?.filter((option) => t(option?.code)?.toLowerCase()?.includes(searchQuery?.toLowerCase())); } acc[category.code] = filteredCategoryOptions.every((option) => @@ -419,17 +437,17 @@ const MultiSelectDropdown = ({ const filtOptns = searchQuery?.length > 0 ? options?.filter( - (option) => - t(option[optionsKey] && typeof option[optionsKey] == "string" && option[optionsKey].toUpperCase()) - .toLowerCase() - .indexOf(searchQuery.toLowerCase()) >= 0 - ) + (option) => + t(option[optionsKey] && typeof option[optionsKey] == "string" && option[optionsKey].toUpperCase()) + .toLowerCase() + .indexOf(searchQuery.toLowerCase()) >= 0 + ) : options; useEffect(() => { setOptionIndex(0); }, [searchQuery]); - + function onSearch(e) { setSearchQuery(e.target.value); } @@ -460,13 +478,14 @@ const MultiSelectDropdown = ({ } }); } else { + const isChecked = arguments[0].target.checked; isChecked ? dispatch({ type: "ADD_TO_SELECTED_EVENT_QUEUE", payload: arguments }) : dispatch({ - type: "REMOVE_FROM_SELECTED_EVENT_QUEUE", - payload: arguments, - }); + type: "REMOVE_FROM_SELECTED_EVENT_QUEUE", + payload: arguments, + }); } onSelect( alreadyQueuedSelectedState?.map((e) => e.propsData), @@ -486,6 +505,9 @@ const MultiSelectDropdown = ({ const handleClearAll = () => { dispatch({ type: "REPLACE_COMPLETE_STATE", payload: [] }); onSelect([], getCategorySelectAllState(), props); + if (onClose) { + onClose([], getCategorySelectAllState(), props); + } }; const openPopUp = (alreadyQueuedSelectedState) => { @@ -501,17 +523,17 @@ const MultiSelectDropdown = ({ const payload = variant === "nestedmultiselect" ? flattenedOptions - .filter((option) => !option.options) - .map((option) => ({ - code: option.code, - name: option.name, - propsData: [null, option], - })) - : options.map((option) => ({ + .filter((option) => !option.options) + .map((option) => ({ code: option.code, name: option.name, propsData: [null, option], - })); + })) + : options.map((option) => ({ + code: option.code, + name: option.name, + propsData: [null, option], + })); dispatch({ type: "REPLACE_COMPLETE_STATE", payload: payload, @@ -634,9 +656,9 @@ const MultiSelectDropdown = ({ } }; const filteredOptions = searchQuery?.length > 0 - ? options?.map((option) => { + ? options?.map((option) => { if (option?.options && option.options.length > 0) { - const matchingNestedOptions = option.options.filter((nestedOption) => + const matchingNestedOptions = option.options.filter((nestedOption) => t(nestedOption.code).toLowerCase().includes(searchQuery.toLowerCase()) ); if (matchingNestedOptions.length > 0) { @@ -653,7 +675,7 @@ const MultiSelectDropdown = ({ return null; }).filter(Boolean) - : options; + : options; const parentOptionsWithChildren = filteredOptions.filter((option) => option.options && option.options.length > 0); @@ -728,11 +750,9 @@ const MultiSelectDropdown = ({ return (
selectedOption.code === option.code) ? "checked" : "" - } ${index === optionIndex && !alreadyQueuedSelectedState.find((selectedOption) => selectedOption.code === option.code) ? "keyChange" : ""}${ - isFrozen ? "frozen" : "" - }`} + className={`digit-multiselectdropodwn-menuitem ${variant ? variant : ""} ${alreadyQueuedSelectedState.find((selectedOption) => selectedOption.code === option.code) ? "checked" : "" + } ${index === optionIndex && !alreadyQueuedSelectedState.find((selectedOption) => selectedOption.code === option.code) ? "keyChange" : ""}${isFrozen ? "frozen" : "" + }`} onMouseDown={() => setIsActive(true)} onMouseUp={() => setIsActive(false)} onMouseLeave={() => setIsActive(false)} @@ -839,9 +859,8 @@ const MultiSelectDropdown = ({ style={props?.style} >
0 - ? `${alreadyQueuedSelectedState.length} ${defaultUnit} Selected` - : defaultLabel} + ? `${alreadyQueuedSelectedState.length} ${defaultUnit} Selected` + : defaultLabel}

)} @@ -908,8 +927,12 @@ const MultiSelectDropdown = ({ variant === "treemultiselect" ? () => onSelectToAddToQueue([value]) : isPropsNeeded - ? (e) => onSelectToAddToQueue(e, value, props) - : (e) => onSelectToAddToQueue(e, value) + ? (e) => onSelectToAddToQueue(e, value, props) + : (e) => { + + onSelectToAddToQueue(e, value); + } + } hideClose={isClose} className="multiselectdropdown-tag" @@ -930,6 +953,7 @@ const MultiSelectDropdown = ({ setShowPopUp={setShowPopUp} alreadyQueuedSelectedState={alreadyQueuedSelectedState} onSelect={onSelect} + onClose={onClose} popUpOption={popUpOption} hierarchyType={hierarchyType} frozenData={frozenData} @@ -973,6 +997,7 @@ MultiSelectDropdown.propTypes = { optionsKey: PropTypes.string.isRequired, selected: PropTypes.array, onSelect: PropTypes.func.isRequired, + onClose: PropTypes.func, defaultLabel: PropTypes.string, defaultUnit: PropTypes.string, props: PropTypes.object, diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/SelectingBoundaryComponent.js b/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/SelectingBoundaryComponent.js index 9f8e0d29ded..72f54417d90 100644 --- a/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/SelectingBoundaryComponent.js +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/SelectingBoundaryComponent.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect, Fragment, useRef , useMemo } from "react"; +import React, { useState, useEffect, Fragment, useRef, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { Card, CardHeader, Header, CardText } from "@egovernments/digit-ui-react-components"; import { LabelFieldPair, CardLabel } from "@egovernments/digit-ui-components"; @@ -6,7 +6,7 @@ import { LabelFieldPair, CardLabel } from "@egovernments/digit-ui-components"; import MultiSelectDropdown from "./MultiSelectDropdown"; import { value } from "jsonpath"; import { Dropdown } from "@egovernments/digit-ui-components"; -import { Loader , PopUp, Button } from "@egovernments/digit-ui-components"; +import { Loader, PopUp, Button } from "@egovernments/digit-ui-components"; import { merge } from "lodash"; // const frozenData = [ @@ -101,7 +101,7 @@ const Wrapper = ({ boundaryOptionsPage={boundaryOptions} data={hierarchyData} isMultiSelect={isMultiSelect} - restrictSelectionPage = {restrictSelection} + restrictSelectionPage={restrictSelection} > ); }; @@ -127,7 +127,7 @@ const SelectingBoundaryComponent = ({ const [showPopUp, setShowPopUp] = useState(false); const timerRef = useRef(null); const [parentRoot, setParentRoot] = useState(selectedData?.find((item) => item?.isRoot === true)?.type || {}); - const [restrictSelection , setRestrictSelection] = useState(restrictSelectionPage); + const [restrictSelection, setRestrictSelection] = useState(restrictSelectionPage); useEffect(() => { @@ -205,7 +205,7 @@ const SelectingBoundaryComponent = ({ }; useEffect(() => { - + setSelectedData(selectedData1); if (selectedData1?.find((item) => item?.isRoot === true)?.type) { setParentRoot(selectedData1?.find((item) => item?.isRoot === true)?.type); @@ -220,7 +220,7 @@ const SelectingBoundaryComponent = ({ if (isBoundaryDataValid && hierarchy && selectedData1?.length > 0) { updateBoundaryOptions(selectedData1, boundaryData, hierarchy); } - }, [hierarchy , isBoundaryDataValid ]); + }, [hierarchy, isBoundaryDataValid]); function createHierarchyStructure(hierarchy) { const hierarchyStructure = {}; @@ -272,7 +272,7 @@ const SelectingBoundaryComponent = ({ function handleBoundaryChange(data, boundary) { if ( - restrictSelection + restrictSelection ) { setShowPopUp(true); return; @@ -335,16 +335,16 @@ const SelectingBoundaryComponent = ({ } } else { // const mergedData = [...(selectedData || []).filter((item) => item?.type !== newBoundaryType), ...transformedRes]; - + let mergedData = []; if (frozenData?.length > 0) { - const mergedFrozenData = [ - ...(selectedData || []).filter((item) => item?.type !== newBoundaryType), - ...transformedRes, - ]; - const frozenCodes = new Set(frozenData.map((item) => item.code)); - const mergedCodes = new Set(mergedFrozenData.map((item) => item.code)); - mergedData = [...mergedFrozenData, ...frozenData.filter((frozenItem) => !mergedCodes.has(frozenItem.code))]; + const mergedFrozenData = [ + ...(selectedData || []).filter((item) => item?.type !== newBoundaryType), + ...transformedRes, + ]; + const frozenCodes = new Set(frozenData.map((item) => item.code)); + const mergedCodes = new Set(mergedFrozenData.map((item) => item.code)); + mergedData = [...mergedFrozenData, ...frozenData.filter((frozenItem) => !mergedCodes.has(frozenItem.code))]; } else if (!frozenData || frozenData?.length === 0) { mergedData = [...(selectedData || []).filter((item) => item?.type !== newBoundaryType), ...transformedRes]; } @@ -422,7 +422,7 @@ const SelectingBoundaryComponent = ({ timerRef.current = setTimeout(() => { onSelect({ selectedData: selectedData, boundaryOptions: boundaryOptions, restrictSelection: restrictSelection }); }, 1); - }, [selectedData, boundaryOptions , restrictSelection]); + }, [selectedData, boundaryOptions, restrictSelection]); const checkDataPresent = ({ action }) => { if (action === false) { @@ -444,163 +444,169 @@ const SelectingBoundaryComponent = ({
{isMultiSelect ? hierarchy?.BoundaryHierarchy?.[0]?.boundaryHierarchy - .filter((boundary, index, array) => { - // Find the index of the lowest hierarchy - const lowestIndex = array.findIndex((b) => b.boundaryType === lowest); - // Include only those boundaries that are above or equal to the lowest hierarchy - return index <= lowestIndex; - }) - .map((boundary) => { - const frozenCount = frozenData?.filter((frozenItem) => frozenItem?.type === boundary.boundaryType).length; - - // Find the count of boundaryType in boundaryOptions - const optionsCount = Object.entries(boundaryOptions) - .filter(([key]) => key.startsWith(boundary.boundaryType)) - .flatMap(([key, value]) => Object.entries(value || {})).length; - - // Disable dropdown if counts match - const isDisabled = frozenCount === optionsCount; - - return boundary?.parentBoundaryType == null ? ( - - - {t((hierarchyType + "_" + boundary?.boundaryType).toUpperCase())} - * - -
- key.startsWith(boundary.boundaryType)) - .flatMap( - ([key, value]) => - Object.entries(value || {}).map(([subkey, item]) => ({ - code: subkey, - name: subkey, - type: boundary.boundaryType, - })) || [] - )} - onSelect={(value) => { - handleBoundaryChange(value, boundary); - }} - selected={selectedData?.filter((item) => item?.type === boundary?.boundaryType) || []} - optionsKey={"code"} - disabled={isDisabled} - hierarchyType={hierarchyType} - config={{ - isDropdownWithChip: true, - chipKey: "code", - }} - frozenData={frozenData} - frozenType={frozenType} - isSearchable={true} - /> -
-
- ) : ( - - - {t((hierarchyType + "_" + boundary?.boundaryType).toUpperCase())} - * - -
- key.startsWith(boundary.boundaryType)) - .flatMap(([key, value]) => - Object.entries(value || {}) - .filter(([subkey, item]) => { - const itemCode = item?.split(".")?.[0]; - if (frozenData?.length > 0) { - const isFrozen = frozenData.some((frozenOption) => { - return ( - frozenOption.code === subkey && frozenOption.type === boundary.boundaryType - // frozenOption.code === ${t(itemCode)}.${t(subkey)} && - // frozenOption.boundaryType === boundary.boundaryType - ); - }); - return frozenType === "filter" ? !isFrozen : true; // Filter or include based on frozenType - } - return true; - }) - .map(([subkey, item]) => ({ - code: item?.split(".")?.[0], - name: item?.split(".")?.[0], - options: - [ - { - code: subkey, - name: subkey, - type: boundary.boundaryType, - parent: `${item?.split(".")?.[0]}`, - }, - ] || [], - })) - )} - onSelect={(value) => { - handleBoundaryChange(value, boundary); - }} - selected={selectedData?.filter((item) => item?.type === boundary?.boundaryType) || []} - optionsKey={"code"} - disabled={isDisabled} - restrictSelection={restrictSelection} - config={{ - isDropdownWithChip: true, - chipKey: "code", - numberOfChips: 4, - }} - hierarchyType={hierarchyType} - addCategorySelectAllCheck={true} - addSelectAllCheck={true} - variant="nestedmultiselect" - frozenData={frozenData} - frozenType={frozenType} - // frozenData={frozenType === "frozen" ? frozenData : []} - popUpOption={boundaryOptions} - isSearchable={true} - /> -
-
- ); - }) - : hierarchy?.BoundaryHierarchy?.[0]?.boundaryHierarchy - .filter((boundary, index, array) => { - // Find the index of the lowest hierarchy - const lowestIndex = array.findIndex((b) => b.boundaryType === lowest); - // Include only those boundaries that are above or equal to the lowest hierarchy - return index <= lowestIndex; - }) - .map((boundary) => ( + .filter((boundary, index, array) => { + // Find the index of the lowest hierarchy + const lowestIndex = array.findIndex((b) => b.boundaryType === lowest); + // Include only those boundaries that are above or equal to the lowest hierarchy + return index <= lowestIndex; + }) + .map((boundary) => { + const frozenCount = frozenData?.filter((frozenItem) => frozenItem?.type === boundary.boundaryType).length; + + // Find the count of boundaryType in boundaryOptions + const optionsCount = Object.entries(boundaryOptions) + .filter(([key]) => key.startsWith(boundary.boundaryType)) + .flatMap(([key, value]) => Object.entries(value || {})).length; + + // Disable dropdown if counts match + const isDisabled = frozenCount === optionsCount; + + return boundary?.parentBoundaryType == null ? ( + + + {t((hierarchyType + "_" + boundary?.boundaryType).toUpperCase())} + * + +
+ key.startsWith(boundary.boundaryType)) + .flatMap( + ([key, value]) => + Object.entries(value || {}).map(([subkey, item]) => ({ + code: subkey, + name: subkey, + type: boundary.boundaryType, + })) || [] + )} + onSelect={(value) => { + // handleBoundaryChange(value, boundary); + }} + onClose={(value) => { + handleBoundaryChange(value, boundary); + }} + selected={selectedData?.filter((item) => item?.type === boundary?.boundaryType) || []} + optionsKey={"code"} + disabled={isDisabled} + hierarchyType={hierarchyType} + config={{ + isDropdownWithChip: true, + chipKey: "code", + }} + frozenData={frozenData} + frozenType={frozenType} + isSearchable={true} + /> +
+
+ ) : ( {t((hierarchyType + "_" + boundary?.boundaryType).toUpperCase())} * - key.startsWith(boundary.boundaryType)) - .flatMap( - ([key, value]) => - Object.entries(value || {}).map(([subkey, item]) => ({ - code: item?.split(".")?.[0], - name: subkey, - type: boundary.boundaryType, - })) || [] - )} - select={(value) => { - handleBoundaryChange(value, boundary); - }} - selected={selectedData?.filter((item) => item?.type === boundary?.boundaryType)?.[0] || {}} - optionKey={"code"} - restrictSelection={restrictSelection} - /> +
+ key.startsWith(boundary.boundaryType)) + .flatMap(([key, value]) => + Object.entries(value || {}) + .filter(([subkey, item]) => { + const itemCode = item?.split(".")?.[0]; + if (frozenData?.length > 0) { + const isFrozen = frozenData.some((frozenOption) => { + return ( + frozenOption.code === subkey && frozenOption.type === boundary.boundaryType + // frozenOption.code === ${t(itemCode)}.${t(subkey)} && + // frozenOption.boundaryType === boundary.boundaryType + ); + }); + return frozenType === "filter" ? !isFrozen : true; // Filter or include based on frozenType + } + return true; + }) + .map(([subkey, item]) => ({ + code: item?.split(".")?.[0], + name: item?.split(".")?.[0], + options: + [ + { + code: subkey, + name: subkey, + type: boundary.boundaryType, + parent: `${item?.split(".")?.[0]}`, + }, + ] || [], + })) + )} + onSelect={(value) => { + //handleBoundaryChange(value, boundary); + }} + onClose={(value) => { + handleBoundaryChange(value, boundary); + }} + selected={selectedData?.filter((item) => item?.type === boundary?.boundaryType) || []} + optionsKey={"code"} + disabled={isDisabled} + restrictSelection={restrictSelection} + config={{ + isDropdownWithChip: true, + chipKey: "code", + numberOfChips: 4, + }} + hierarchyType={hierarchyType} + addCategorySelectAllCheck={true} + addSelectAllCheck={true} + variant="nestedmultiselect" + frozenData={frozenData} + frozenType={frozenType} + // frozenData={frozenType === "frozen" ? frozenData : []} + popUpOption={boundaryOptions} + isSearchable={true} + /> +
- ))} + ); + }) + : hierarchy?.BoundaryHierarchy?.[0]?.boundaryHierarchy + .filter((boundary, index, array) => { + // Find the index of the lowest hierarchy + const lowestIndex = array.findIndex((b) => b.boundaryType === lowest); + // Include only those boundaries that are above or equal to the lowest hierarchy + return index <= lowestIndex; + }) + .map((boundary) => ( + + + {t((hierarchyType + "_" + boundary?.boundaryType).toUpperCase())} + * + + key.startsWith(boundary.boundaryType)) + .flatMap( + ([key, value]) => + Object.entries(value || {}).map(([subkey, item]) => ({ + code: item?.split(".")?.[0], + name: subkey, + type: boundary.boundaryType, + })) || [] + )} + select={(value) => { + handleBoundaryChange(value, boundary); + }} + selected={selectedData?.filter((item) => item?.type === boundary?.boundaryType)?.[0] || {}} + optionKey={"code"} + restrictSelection={restrictSelection} + /> + + ))}
{showPopUp && ( Date: Mon, 11 Nov 2024 19:21:42 +0530 Subject: [PATCH 2/2] fixed search juridiction dropdown --- .../modules/microplan/src/components/SearchJurisdiction.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/SearchJurisdiction.js b/health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/SearchJurisdiction.js index be5cbea6535..1f794a5baf6 100644 --- a/health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/SearchJurisdiction.js +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/SearchJurisdiction.js @@ -79,6 +79,9 @@ const SearchJurisdiction = ({ boundaries, jurisdiction, onSubmit = () => { }, on options={boundaryOptions} selected={selectedBoundaries} onSelect={(e) => { + // handleBoundarySelect(e) + }} + onClose={(e) => { handleBoundarySelect(e) }} isSearchable={true}