@topconsultnpm/sdkui-react 6.22.0-dev2.48 → 6.22.0-dev2.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/features/search/TMSearch.js +9 -4
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +2 -0
- package/lib/components/features/search/TMSearchQueryPanel.js +61 -2
- package/lib/helper/queryHelper.d.ts +4 -1
- package/lib/helper/queryHelper.js +5 -2
- package/package.json +1 -1
|
@@ -183,6 +183,11 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
183
183
|
await setSQDAsync(sqdToRestore?.id === SYS_ALL_DCMTS_SQD_ID ? await getSysAllDcmtsSQD(tid, false) : sqdToRestore);
|
|
184
184
|
// mruTIDs è tra le dipendenze perché setSQDAsync lo legge
|
|
185
185
|
}, [fromDTD?.id, currentTID, currentSQD, mruTIDs]);
|
|
186
|
+
// Prima di ogni ricerca il pannello rilegge i metadati del tipo documento: si recepisce il descrittore
|
|
187
|
+
// aggiornato, così anche il resto della vista (titoli, badge, form dei metadati) lavora sulla lista corrente
|
|
188
|
+
const handleDcmtTypeReloaded = useCallback((dtd) => {
|
|
189
|
+
setFromDTD(dtd);
|
|
190
|
+
}, []);
|
|
186
191
|
const onRefreshSearchAsyncDatagrid = async () => {
|
|
187
192
|
try {
|
|
188
193
|
if (lastQdSearched) {
|
|
@@ -239,10 +244,10 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
239
244
|
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
|
|
240
245
|
setMruTIDs(newMruTIDS);
|
|
241
246
|
} }), [mruTIDs, currentMruTID, deviceType]);
|
|
242
|
-
const tmSearchQueryPanelElement = useMemo(() => _jsx(TMSearchQueryPanelWrapper, { isSearchViewOnScreen: currentSearchView === TMSearchViews.Search, passToArchiveCallback: passToArchiveCallback, isExpertMode: isExpertMode, showBackToResultButton: searchResult.length > 0, fromDTD: fromDTD, SQD: currentSQD, inputMids: inputMids, maxDcmtsToBeReturned: maxDcmtsToBeReturned, onBackToResult: () => { setCurrentSearchView(TMSearchViews.Result); }, onSearchCompleted: handleSearchCompleted, onRefreshRequested: refreshSearchQueryPanelAsync, onSqdSaved: async (newSqd) => {
|
|
247
|
+
const tmSearchQueryPanelElement = useMemo(() => _jsx(TMSearchQueryPanelWrapper, { isSearchViewOnScreen: currentSearchView === TMSearchViews.Search, passToArchiveCallback: passToArchiveCallback, isExpertMode: isExpertMode, showBackToResultButton: searchResult.length > 0, fromDTD: fromDTD, SQD: currentSQD, inputMids: inputMids, maxDcmtsToBeReturned: maxDcmtsToBeReturned, onBackToResult: () => { setCurrentSearchView(TMSearchViews.Result); }, onSearchCompleted: handleSearchCompleted, onRefreshRequested: refreshSearchQueryPanelAsync, onDcmtTypeReloaded: handleDcmtTypeReloaded, onSqdSaved: async (newSqd) => {
|
|
243
248
|
await loadDataSQDsAsync(true, newSqd.masterTID);
|
|
244
249
|
await setSQDAsync(newSqd);
|
|
245
|
-
} }), [fromDTD, showSearchResults, setShowSearchResults, currentSQD, currentSearchView, isExpertMode, mruTIDs, searchResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned, handleSearchCompleted, refreshSearchQueryPanelAsync]);
|
|
250
|
+
} }), [fromDTD, showSearchResults, setShowSearchResults, currentSQD, currentSearchView, isExpertMode, mruTIDs, searchResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned, handleSearchCompleted, refreshSearchQueryPanelAsync, handleDcmtTypeReloaded]);
|
|
246
251
|
const tmSavedQuerySelectorElement = useMemo(() => _jsxs(TabPanel, { width: "100%", height: "100%", showNavButtons: true, repaintChangesOnly: true, selectedIndex: currentSQDMode, onSelectedIndexChange: (index) => setCurrentSQDMode(index), children: [(currentTID || currentSQD) ? _jsx(Item, { title: fromDTD?.nameLoc, children: _jsx(TMSavedQuerySelectorWrapper, { allowShowSearch: false, items: filteredByTIDSQDs, selectedId: currentSQD?.id, onRefreshData: () => { loadDataSQDsAsync(true); }, onItemClick: (sqd) => {
|
|
247
252
|
onSQDItemClick(sqd, setSQDAsync);
|
|
248
253
|
}, onDeleted: (sqd) => onSQDDeleted(sqd, sqd.id == currentSQD?.id ? filteredByTIDSQDs.find(o => o.id == 1) : currentSQD, setSQDAsync), refreshFavoriteSavedQueries: refreshFavoriteSavedQueries }) }) : _jsx(_Fragment, {}), _jsx(Item, { title: SDKUI_Localizator.AllFemale, children: _jsx(TMSavedQuerySelectorWrapper, { allowShowSearch: true, items: allSQDs, manageDefault: false, onItemClick: (sqd) => {
|
|
@@ -342,11 +347,11 @@ const TMRecentsManagerWrapper = ({ mruTIDs, currentMruTID, deviceType, onSelecte
|
|
|
342
347
|
onDeletedTID?.(tid);
|
|
343
348
|
} }));
|
|
344
349
|
};
|
|
345
|
-
const TMSearchQueryPanelWrapper = ({ isSearchViewOnScreen, fromDTD, SQD, isExpertMode, showBackToResultButton, onSearchCompleted, onSqdSaved, onBackToResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned, onRefreshRequested }) => {
|
|
350
|
+
const TMSearchQueryPanelWrapper = ({ isSearchViewOnScreen, fromDTD, SQD, isExpertMode, showBackToResultButton, onSearchCompleted, onSqdSaved, onBackToResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned, onRefreshRequested, onDcmtTypeReloaded }) => {
|
|
346
351
|
const { setPanelVisibilityById, toggleMaximize, countVisibleLeafPanels } = useTMPanelManagerContext();
|
|
347
352
|
const deviceType = useDeviceType();
|
|
348
353
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
349
|
-
return (_jsx(TMSearchQueryPanel, { isSearchViewOnScreen: isSearchViewOnScreen, onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('TMSearchQueryPanel', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("TMSearchQueryPanel") : undefined, isExpertMode: isExpertMode, fromDTD: fromDTD, SQD: SQD, inputMids: inputMids, onSearchCompleted: onSearchCompleted, onRefreshRequested: onRefreshRequested, onSqdSaved: onSqdSaved, showBackToResultButton: showBackToResultButton, onBackToResult: onBackToResult, passToArchiveCallback: passToArchiveCallback, maxDcmtsToBeReturned: maxDcmtsToBeReturned }));
|
|
354
|
+
return (_jsx(TMSearchQueryPanel, { isSearchViewOnScreen: isSearchViewOnScreen, onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('TMSearchQueryPanel', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("TMSearchQueryPanel") : undefined, isExpertMode: isExpertMode, fromDTD: fromDTD, SQD: SQD, inputMids: inputMids, onSearchCompleted: onSearchCompleted, onRefreshRequested: onRefreshRequested, onDcmtTypeReloaded: onDcmtTypeReloaded, onSqdSaved: onSqdSaved, showBackToResultButton: showBackToResultButton, onBackToResult: onBackToResult, passToArchiveCallback: passToArchiveCallback, maxDcmtsToBeReturned: maxDcmtsToBeReturned }));
|
|
350
355
|
};
|
|
351
356
|
const TMSavedQuerySelectorWrapper = ({ items, selectedId, allowShowSearch, manageDefault, onRefreshData, onItemClick, onDeleted, refreshFavoriteSavedQueries }) => {
|
|
352
357
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
@@ -23,6 +23,8 @@ interface ITMSearchQueryPanelProps {
|
|
|
23
23
|
}>, tid?: number) => void;
|
|
24
24
|
maxDcmtsToBeReturned?: number;
|
|
25
25
|
onRefreshRequested?: () => Promise<void>;
|
|
26
|
+
/** Notifica il tipo documento riletto dal server prima di ogni ricerca, così il chiamante allinea il proprio descrittore */
|
|
27
|
+
onDcmtTypeReloaded?: (dtd: DcmtTypeDescriptor) => void;
|
|
26
28
|
}
|
|
27
29
|
declare const TMSearchQueryPanel: React.FunctionComponent<ITMSearchQueryPanelProps>;
|
|
28
30
|
export default TMSearchQueryPanel;
|
|
@@ -24,7 +24,7 @@ import TMToppyMessage from '../../../helper/TMToppyMessage';
|
|
|
24
24
|
import TMMetadataSorterForm from './TMMetadataSorterForm';
|
|
25
25
|
import TMMetadataOutputForm from './TMMetadataOutputForm';
|
|
26
26
|
import TMTooltip from '../../base/TMTooltip';
|
|
27
|
-
const TMSearchQueryPanel = ({ isSearchViewOnScreen = true, fromDTD, showBackToResultButton, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, SQD, inputMids, onSearchCompleted, onSqdSaved, onBack, onClosePanel, allowMaximize = true, onMaximizePanel, onBackToResult, passToArchiveCallback, maxDcmtsToBeReturned, onRefreshRequested }) => {
|
|
27
|
+
const TMSearchQueryPanel = ({ isSearchViewOnScreen = true, fromDTD, showBackToResultButton, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, SQD, inputMids, onSearchCompleted, onSqdSaved, onBack, onClosePanel, allowMaximize = true, onMaximizePanel, onBackToResult, passToArchiveCallback, maxDcmtsToBeReturned, onRefreshRequested, onDcmtTypeReloaded }) => {
|
|
28
28
|
const [confirmQueryParams, ConfirmQueryParamsDialog] = useQueryParametersDialog();
|
|
29
29
|
const [qd, setQd] = useState();
|
|
30
30
|
const [lastQdParams, setLastQdParams] = useState([]);
|
|
@@ -55,6 +55,7 @@ const TMSearchQueryPanel = ({ isSearchViewOnScreen = true, fromDTD, showBackToRe
|
|
|
55
55
|
const qdRef = useRef(undefined);
|
|
56
56
|
const showAdvancedSearchRef = useRef(false);
|
|
57
57
|
const searchAsyncRef = useRef();
|
|
58
|
+
const reloadMetadataAsyncRef = useRef();
|
|
58
59
|
// Tornando dalla vista risultati il pannello dei metadati di ricerca riprende il focus,
|
|
59
60
|
// così è lui quello evidenziato: prendendo il focus gli altri pannelli ricevono l'onBlur e si disattivano
|
|
60
61
|
useEffect(() => {
|
|
@@ -173,10 +174,39 @@ const TMSearchQueryPanel = ({ isSearchViewOnScreen = true, fromDTD, showBackToRe
|
|
|
173
174
|
onSearchCompleted?.(results, searchResult?.qd, append);
|
|
174
175
|
}
|
|
175
176
|
};
|
|
177
|
+
// Tra l'apertura della ricerca e il click su Ricerca la lista dei metadati del tipo documento può essere
|
|
178
|
+
// cambiata (metadati aggiunti o rimossi lato amministrazione): prima di cercare si rileggono dal server.
|
|
179
|
+
// I valori digitati restano, mentre i filtri sui metadati non più disponibili vengono scartati.
|
|
180
|
+
// Restituisce il qd con cui eseguire la ricerca.
|
|
181
|
+
const reloadMetadataAsync = async (qdInput) => {
|
|
182
|
+
if (!qdInput?.from?.tid)
|
|
183
|
+
return qdInput;
|
|
184
|
+
let dcmtTypes;
|
|
185
|
+
try {
|
|
186
|
+
TMSpinner.show({ description: `${SDKUI_Localizator.Loading} ...`, backgroundColor: 'transparent' });
|
|
187
|
+
dcmtTypes = await getDcmtTypesByQdAsync(qdInput, true);
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
TMSpinner.hide();
|
|
191
|
+
}
|
|
192
|
+
// Rilettura non riuscita: si cerca con i metadati che si hanno, senza scartare nulla
|
|
193
|
+
if (dcmtTypes.length <= 0)
|
|
194
|
+
return qdInput;
|
|
195
|
+
setDcmtTypesList(dcmtTypes);
|
|
196
|
+
const reloadedFromDTD = dcmtTypes.find(o => o.id === qdInput.from?.tid);
|
|
197
|
+
if (reloadedFromDTD)
|
|
198
|
+
onDcmtTypeReloaded?.(reloadedFromDTD);
|
|
199
|
+
const { qd: newQd, removedCount } = dropUnavailableMetadataFromQd(qdInput, dcmtTypes);
|
|
200
|
+
if (removedCount <= 0)
|
|
201
|
+
return qdInput;
|
|
202
|
+
setQd(newQd);
|
|
203
|
+
return newQd;
|
|
204
|
+
};
|
|
176
205
|
// Allineati a ogni render: runSearch li legge quando esegue, non quando viene creata
|
|
177
206
|
qdRef.current = qd;
|
|
178
207
|
showAdvancedSearchRef.current = showAdvancedSearch;
|
|
179
208
|
searchAsyncRef.current = searchAsync;
|
|
209
|
+
reloadMetadataAsyncRef.current = reloadMetadataAsync;
|
|
180
210
|
// Unico punto di avvio della ricerca: bottone Ricerca, Ricerca e accoda e tasto Invio passano tutti da qui
|
|
181
211
|
const runSearch = useCallback((append) => {
|
|
182
212
|
if (isSearchingRef.current)
|
|
@@ -188,7 +218,9 @@ const TMSearchQueryPanel = ({ isSearchViewOnScreen = true, fromDTD, showBackToRe
|
|
|
188
218
|
// Alcuni editor committano il valore in modo asincrono: si attende un tick prima di leggere il qd definitivo
|
|
189
219
|
setTimeout(async () => {
|
|
190
220
|
try {
|
|
191
|
-
|
|
221
|
+
// I metadati si rileggono a ogni ricerca: si cerca sempre sulla lista aggiornata
|
|
222
|
+
const qdToSearch = await reloadMetadataAsyncRef.current?.(qdRef.current) ?? qdRef.current;
|
|
223
|
+
await searchAsyncRef.current?.(qdToSearch, showAdvancedSearchRef.current, append);
|
|
192
224
|
}
|
|
193
225
|
catch (ex) {
|
|
194
226
|
TMExceptionBoxManager.show({ exception: ex });
|
|
@@ -418,6 +450,33 @@ const TMSearchQueryPanel = ({ isSearchViewOnScreen = true, fromDTD, showBackToRe
|
|
|
418
450
|
} })] }));
|
|
419
451
|
};
|
|
420
452
|
export default TMSearchQueryPanel;
|
|
453
|
+
/** Scarta dal qd filtri, colonne e ordinamenti sui metadati non più esistenti o non più accessibili, in base
|
|
454
|
+
* alla lista dei metadati appena riletta dal server. I valori digitati su quelli ancora presenti si mantengono. */
|
|
455
|
+
const dropUnavailableMetadataFromQd = (qdInput, dcmtTypes) => {
|
|
456
|
+
const metadataOf = (tid) => dcmtTypes.find(o => o.id === tid)?.metadata;
|
|
457
|
+
// Un tipo documento non riletto non è verificabile: i suoi item si mantengono così come sono.
|
|
458
|
+
// Sui metadati di sistema si verifica solo l'esistenza: i loro permessi non li rendono inutilizzabili.
|
|
459
|
+
const isStillAvailable = (tid, mid, isUsable) => {
|
|
460
|
+
const metadata = metadataOf(tid);
|
|
461
|
+
if (!metadata || metadata.length <= 0 || mid == undefined)
|
|
462
|
+
return true;
|
|
463
|
+
const md = metadata.find(o => o.id === mid);
|
|
464
|
+
if (!md)
|
|
465
|
+
return false;
|
|
466
|
+
return md.isSystem == 1 || isUsable(md);
|
|
467
|
+
};
|
|
468
|
+
const canSearch = (md) => md.perm?.canSearch != AccessLevels.No;
|
|
469
|
+
const canOutput = (md) => !(md.perm?.canView == AccessLevels.No && md.perm?.canUpdate == AccessLevels.No);
|
|
470
|
+
const where = qdInput.where?.filter(o => isStillAvailable(o.tid, o.mid, canSearch)) ?? [];
|
|
471
|
+
const select = qdInput.select?.filter(o => isStillAvailable(o.tid, o.mid, canOutput)) ?? [];
|
|
472
|
+
const orderBy = qdInput.orderBy?.filter(o => isStillAvailable(o.tid, o.mid, canOutput)) ?? [];
|
|
473
|
+
const removedCount = ((qdInput.where?.length ?? 0) - where.length)
|
|
474
|
+
+ ((qdInput.select?.length ?? 0) - select.length)
|
|
475
|
+
+ ((qdInput.orderBy?.length ?? 0) - orderBy.length);
|
|
476
|
+
let qd = new QueryDescriptor();
|
|
477
|
+
qd.init({ ...qdInput, where: where, select: select, orderBy: orderBy });
|
|
478
|
+
return { qd: qd, removedCount: removedCount };
|
|
479
|
+
};
|
|
421
480
|
const searchByQdAsync = async (qdInput, searchParams) => {
|
|
422
481
|
let result;
|
|
423
482
|
let qdSearch;
|
|
@@ -5,7 +5,10 @@ export type TID_Alias = {
|
|
|
5
5
|
alias: string | undefined;
|
|
6
6
|
};
|
|
7
7
|
export declare const getTIDsByQd: (qd: QueryDescriptor | undefined) => TID_Alias[];
|
|
8
|
-
|
|
8
|
+
/** Restituisce i tipi documento (con metadati) referenziati da qd.
|
|
9
|
+
* Con refreshCache = true i descrittori vengono riletti dal server, così la lista dei metadati
|
|
10
|
+
* recepisce quelli aggiunti o rimossi dopo il popolamento della cache. */
|
|
11
|
+
export declare const getDcmtTypesByQdAsync: (qd: QueryDescriptor, refreshCache?: boolean) => Promise<import("@topconsultnpm/sdk-ts").DcmtTypeDescriptor[]>;
|
|
9
12
|
export declare const displayMetadataValue: (md: MetadataDescriptor | undefined, value: string | undefined, valueEmptyDescription?: string) => string;
|
|
10
13
|
export declare const IsParametricQuery: (qd: QueryDescriptor | undefined) => boolean;
|
|
11
14
|
export declare const addHiddenSelectItem: (select: SelectItem[], tid: number | undefined, mid: SystemMIDsAsNumber) => void;
|
|
@@ -15,8 +15,11 @@ export const getTIDsByQd = (qd) => {
|
|
|
15
15
|
}
|
|
16
16
|
return tids;
|
|
17
17
|
};
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
/** Restituisce i tipi documento (con metadati) referenziati da qd.
|
|
19
|
+
* Con refreshCache = true i descrittori vengono riletti dal server, così la lista dei metadati
|
|
20
|
+
* recepisce quelli aggiunti o rimossi dopo il popolamento della cache. */
|
|
21
|
+
export const getDcmtTypesByQdAsync = async (qd, refreshCache = false) => {
|
|
22
|
+
return await DcmtTypeListCacheService.GetFromQdAsync(qd, undefined, false, refreshCache);
|
|
20
23
|
};
|
|
21
24
|
export const displayMetadataValue = (md, value, valueEmptyDescription = "") => {
|
|
22
25
|
if (!value)
|