Skip to content

Commit 4255749

Browse files
author
manasa
committed
updated
1 parent abd2acf commit 4255749

File tree

5 files changed

+276
-274
lines changed

5 files changed

+276
-274
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
import React, { createElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
2+
import { Button, Grid, Select, MenuItem, Box } from '@mui/material';
3+
4+
import PConnectHOC from '../../../../bridge/react_pconnect';
5+
import TemplateContext from '../TemplateContext';
6+
import componentCachePersistUtils from '../SearchGroup/persistUtils';
7+
8+
import { getCacheInfo, isValidInput } from './utils';
9+
import { useCacheWhenListViewReady } from './hooks';
10+
11+
const PComponent = PConnectHOC();
12+
13+
export const initializeSearchFields = (searchFields, getPConnect, referenceListClassID, searchFieldRestoreValues = {}) => {
14+
const filtersProperties = {};
15+
searchFields.forEach(field => {
16+
let val = '';
17+
const { value, defaultValue = '' } = field.config;
18+
const propPath = PCore.getAnnotationUtils().getPropertyName(value);
19+
20+
if (searchFieldRestoreValues[propPath]) {
21+
val = searchFieldRestoreValues[propPath];
22+
} else if (PCore.getAnnotationUtils().isProperty(defaultValue)) {
23+
val = getPConnect().getValue(defaultValue.split(' ')[1]);
24+
} else if (defaultValue.startsWith('@L')) {
25+
val = defaultValue.split(' ')[1];
26+
} else {
27+
val = defaultValue;
28+
}
29+
30+
filtersProperties[propPath] = val;
31+
32+
const valueSplit = value.split('@P ')[1]?.split('.').filter(Boolean) ?? [];
33+
valueSplit.pop();
34+
35+
if (valueSplit.length) {
36+
let path = '';
37+
let currentClassID = referenceListClassID;
38+
valueSplit.forEach(item => {
39+
path = path.length ? `${path}.${item}` : item;
40+
currentClassID = (PCore.getMetadataUtils().getPropertyMetadata(item, currentClassID) as any).pageClass;
41+
if (currentClassID) {
42+
filtersProperties[`${path}.classID`] = currentClassID;
43+
}
44+
});
45+
}
46+
});
47+
return filtersProperties;
48+
};
49+
50+
const flattenObj = obj => {
51+
const result = {};
52+
Object.keys(obj).forEach(key => {
53+
if (!['context_data', 'pageInstructions'].includes(key)) {
54+
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
55+
const temp = flattenObj(obj[key]);
56+
Object.keys(temp).forEach(nestedKey => {
57+
result[`${key}.${nestedKey}`] = temp[nestedKey];
58+
});
59+
} else {
60+
result[key] = obj[key];
61+
}
62+
}
63+
});
64+
return result;
65+
};
66+
67+
export default function SearchGroups(props) {
68+
const localizedVal = PCore.getLocaleUtils().getLocaleValue;
69+
const { getPConnect, editableField, localeReference, setShowRecords, searchSelectCacheKey, cache } = props;
70+
const referenceFieldName = editableField.replaceAll('.', '_');
71+
72+
const state: any = useRef({ searchFields: {}, activeGroupId: '' }).current;
73+
const options = componentCachePersistUtils.getComponentStateOptions(getPConnect);
74+
75+
const { searchGroups: groups, referenceList } = getPConnect().getConfigProps();
76+
const { useCache, initialActiveGroupId } = getCacheInfo(cache, groups);
77+
const [activeGroupId, setActiveGroupId] = useState(initialActiveGroupId);
78+
const [transientItemID, setTransientItemID] = useState<any>(null);
79+
const [previousFormValues, setPreviousFormValues] = useState<any>(null);
80+
const viewName = getPConnect().getCurrentView();
81+
82+
const rawGroupsConfig = getPConnect().getRawConfigProps().searchGroups;
83+
const activeGroupIndex = groups.findIndex(group => group.config.id === activeGroupId);
84+
const { children: searchFieldsChildren = [] } = activeGroupIndex !== -1 ? rawGroupsConfig[activeGroupIndex] : {};
85+
const searchFields = searchFieldsChildren.map(field => ({
86+
...field,
87+
config: { ...field.config, isSearchField: true }
88+
}));
89+
90+
const searchByRef = useRef(null);
91+
const searchFieldsRef = useRef(null);
92+
const isValidatorField = searchFields.some(field => field.config.validator);
93+
const { classID: referenceListClassID } = PCore.getMetadataUtils().getDataPageMetadata(referenceList) as any;
94+
95+
const initialSearchFields = useMemo(
96+
() =>
97+
initializeSearchFields(
98+
searchFields,
99+
getPConnect,
100+
referenceListClassID,
101+
useCache && cache.activeGroupId === activeGroupId ? cache.searchFields : {}
102+
),
103+
[activeGroupId, getPConnect, cache.searchFields]
104+
);
105+
106+
useEffect(() => {
107+
if (transientItemID) {
108+
const filtersWithClassID = {
109+
...initialSearchFields,
110+
classID: referenceListClassID
111+
};
112+
// @ts-ignore
113+
PCore.getContainerUtils().replaceTransientData({ transientItemID, data: filtersWithClassID });
114+
}
115+
}, [activeGroupId]);
116+
117+
useEffect(() => {
118+
const filtersWithClassID = {
119+
...initialSearchFields,
120+
classID: referenceListClassID
121+
};
122+
123+
const transientId = getPConnect()
124+
.getContainerManager()
125+
.addTransientItem({ id: `${referenceFieldName}-${viewName}`, data: filtersWithClassID });
126+
setTransientItemID(transientId);
127+
}, []);
128+
129+
const getFilterData = useCallback(() => {
130+
// @ts-ignore
131+
let changes = PCore.getFormUtils().getSubmitData(transientItemID, {
132+
isTransientContext: true,
133+
includeDisabledFields: true
134+
});
135+
136+
if (Object.keys(cache.searchFields ?? {}).length > 0 && Object.keys(changes).length === 1) {
137+
changes = cache.searchFields;
138+
}
139+
140+
const formValues = flattenObj(changes);
141+
142+
if (!PCore.isDeepEqual(previousFormValues, formValues) && PCore.getFormUtils().isFormValid(transientItemID) && isValidInput(formValues)) {
143+
if (isValidatorField) {
144+
// @ts-ignore
145+
PCore.getMessageManager().clearContextMessages({ context: transientItemID });
146+
}
147+
setPreviousFormValues(formValues);
148+
setShowRecords(true);
149+
PCore.getPubSubUtils().publish(PCore.getEvents().getTransientEvent().UPDATE_PROMOTED_FILTERS, {
150+
payload: formValues,
151+
showRecords: true,
152+
viewName
153+
});
154+
}
155+
156+
state.activeGroupId = activeGroupId;
157+
state.searchFields = changes;
158+
state.selectedCategory = viewName;
159+
160+
componentCachePersistUtils.setComponentCache({ cacheKey: searchSelectCacheKey, state, options });
161+
}, [transientItemID, setShowRecords, viewName, activeGroupId, previousFormValues]);
162+
163+
const resetFilterData = useCallback(() => {
164+
// @ts-ignore
165+
PCore.getNavigationUtils().resetComponentCache(searchSelectCacheKey);
166+
const resetPayload = {
167+
transientItemID,
168+
data: initializeSearchFields(searchFields, getPConnect, referenceListClassID),
169+
options: { reset: true }
170+
};
171+
// @ts-ignore
172+
PCore.getContainerUtils().updateTransientData(resetPayload);
173+
}, [transientItemID, initialSearchFields]);
174+
175+
useCacheWhenListViewReady(cache, viewName, useCache, getFilterData, searchSelectCacheKey);
176+
177+
const searchDropdown = groups.length > 1 && (
178+
<Grid container spacing={2}>
179+
<Select value={activeGroupId} onChange={e => setActiveGroupId(e.target.value)} ref={searchByRef} fullWidth>
180+
{groups.map(group => (
181+
<MenuItem key={group.config.id} value={group.config.id}>
182+
{group.config.label}
183+
</MenuItem>
184+
))}
185+
</Select>
186+
</Grid>
187+
);
188+
189+
const actionButtons = (
190+
<Box display='flex' gap={2}>
191+
<Button variant='outlined' onClick={resetFilterData}>
192+
{localizedVal('Reset', 'SimpleTable')}
193+
</Button>
194+
<Button variant='contained' onClick={getFilterData}>
195+
{localizedVal('Search', 'SimpleTable')}
196+
</Button>
197+
</Box>
198+
);
199+
200+
const searchFieldsViewConfig = {
201+
name: 'SearchFields',
202+
type: 'View',
203+
config: {
204+
template: 'DefaultForm',
205+
NumCols: '3',
206+
contextName: transientItemID,
207+
readOnly: false,
208+
context: transientItemID,
209+
localeReference
210+
},
211+
children: [
212+
{
213+
name: 'Fields',
214+
type: 'Region',
215+
children: searchFields
216+
}
217+
]
218+
};
219+
220+
const searchFieldsC11nEnv = PCore.createPConnect({
221+
meta: searchFieldsViewConfig,
222+
options: {
223+
hasForm: true,
224+
contextName: transientItemID
225+
}
226+
});
227+
228+
const templateContext = useContext(TemplateContext);
229+
const templateContextValue = useMemo(() => ({ ...templateContext, outerColumnCount: undefined }), []);
230+
231+
const searchFieldsViewComp = transientItemID ? (
232+
<TemplateContext.Provider value={templateContextValue}>
233+
<div ref={searchFieldsRef}>{createElement(PComponent, { ...searchFieldsC11nEnv })}</div>
234+
</TemplateContext.Provider>
235+
) : null;
236+
237+
const childrenToRender = [searchDropdown, searchFieldsViewComp, actionButtons];
238+
239+
return (
240+
<Box display='flex' flexDirection='column' gap={2}>
241+
{childrenToRender.map((child, index) => (
242+
// eslint-disable-next-line react/no-array-index-key
243+
<React.Fragment key={index}>{child}</React.Fragment>
244+
))}
245+
</Box>
246+
);
247+
}

0 commit comments

Comments
 (0)