@topconsultnpm/sdkui-react 6.21.0-dev1.5 → 6.21.0-dev1.50

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.
Files changed (61) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +2 -2
  2. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +1 -1
  3. package/lib/components/base/TMAreaManager.js +28 -11
  4. package/lib/components/base/TMFileManagerDataGridView.js +2 -2
  5. package/lib/components/base/TMPanel.js +1 -0
  6. package/lib/components/choosers/TMDataListItemChooser.js +25 -2
  7. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +1 -1
  8. package/lib/components/choosers/TMDynDataListItemChooser.js +50 -23
  9. package/lib/components/choosers/TMUserChooser.js +3 -1
  10. package/lib/components/editors/TMFormulaEditor.js +15 -3
  11. package/lib/components/editors/TMMetadataEditor.js +4 -3
  12. package/lib/components/editors/TMMetadataValues.js +1 -1
  13. package/lib/components/features/archive/TMArchive.js +1 -1
  14. package/lib/components/features/documents/TMDcmtBlog.d.ts +1 -0
  15. package/lib/components/features/documents/TMDcmtBlog.js +2 -2
  16. package/lib/components/features/documents/TMDcmtForm.js +11 -7
  17. package/lib/components/features/documents/TMDragDropOverlay.js +7 -2
  18. package/lib/components/features/documents/TMFileUploader.js +5 -4
  19. package/lib/components/features/documents/TMMasterDetailDcmts.js +74 -21
  20. package/lib/components/features/documents/TMRelationViewer.d.ts +6 -1
  21. package/lib/components/features/documents/TMRelationViewer.js +44 -7
  22. package/lib/components/features/search/TMSavedQuerySelector.js +1 -1
  23. package/lib/components/features/search/TMSearch.js +2 -0
  24. package/lib/components/features/search/TMSearchQueryEditor.js +13 -1
  25. package/lib/components/features/search/TMSearchResult.js +16 -3
  26. package/lib/components/features/search/TMViewHistoryDcmt.js +6 -0
  27. package/lib/components/features/workflow/diagram/DiagramItemForm.js +5 -1
  28. package/lib/components/features/workflow/diagram/WFDiagram.js +7 -1
  29. package/lib/components/features/workflow/diagram/xmlParser.js +13 -14
  30. package/lib/components/forms/Login/TMLoginForm.js +15 -5
  31. package/lib/components/forms/TMChooserForm.js +25 -2
  32. package/lib/components/grids/TMBlogsPost.js +1 -1
  33. package/lib/components/index.d.ts +1 -0
  34. package/lib/components/index.js +1 -0
  35. package/lib/components/pages/TMPage.js +4 -2
  36. package/lib/components/query/TMQueryCountButton.d.ts +11 -0
  37. package/lib/components/query/TMQueryCountButton.js +32 -0
  38. package/lib/components/query/TMQueryEditor.js +41 -4
  39. package/lib/components/query/TMQuerySummary.js +3 -2
  40. package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
  41. package/lib/components/viewers/TMDataListItemViewer.js +2 -2
  42. package/lib/helper/SDKUI_Globals.d.ts +2 -0
  43. package/lib/helper/SDKUI_Localizator.d.ts +1 -0
  44. package/lib/helper/SDKUI_Localizator.js +10 -0
  45. package/lib/helper/TMPdfViewer.js +143 -86
  46. package/lib/helper/TMUtils.d.ts +1 -0
  47. package/lib/helper/TMUtils.js +12 -0
  48. package/lib/helper/checkinCheckoutManager.d.ts +7 -2
  49. package/lib/helper/checkinCheckoutManager.js +220 -11
  50. package/lib/hooks/useCheckInOutOperations.d.ts +1 -1
  51. package/lib/hooks/useCheckInOutOperations.js +9 -4
  52. package/lib/hooks/useDcmtOperations.d.ts +1 -0
  53. package/lib/hooks/useDcmtOperations.js +74 -4
  54. package/lib/hooks/useDocumentOperations.js +20 -6
  55. package/lib/hooks/useForm.js +20 -14
  56. package/lib/hooks/useInputDialog.d.ts +2 -0
  57. package/lib/hooks/useInputDialog.js +37 -0
  58. package/lib/hooks/useQueryParametersDialog.js +5 -5
  59. package/lib/services/platform_services.d.ts +1 -1
  60. package/lib/services/platform_services.js +8 -0
  61. package/package.json +54 -55
@@ -328,8 +328,8 @@ const TMLoginForm = (props) => {
328
328
  const nextStepHandler = async () => {
329
329
  if (!endpoint || (!dcmtArchive && !manualArchiveID))
330
330
  return;
331
- if (loginStep === 1 && !dcmtArchive && manualArchiveID) {
332
- const isValid = await validateManualArchiveAsync();
331
+ if (loginStep === 1 && manualArchiveID) {
332
+ const isValid = await fetchManualArchiveByIdAsync();
333
333
  if (!isValid)
334
334
  return;
335
335
  }
@@ -359,17 +359,27 @@ const TMLoginForm = (props) => {
359
359
  return;
360
360
  setLoginStep(prev => prev - 1);
361
361
  }, [loginStep]);
362
- const validateManualArchiveAsync = async () => {
363
- if (!tmSession || !manualArchiveID)
362
+ /** Retrieves and sets the archive descriptor from server using the manually entered ID. */
363
+ const fetchManualArchiveByIdAsync = async () => {
364
+ // Early exit if session or manual archive ID is not available
365
+ if (!tmSession || !manualArchiveID) {
366
+ setDcmtArchive(undefined);
364
367
  return false;
368
+ }
369
+ ;
365
370
  try {
366
371
  TMSpinner.show({ description: '' });
372
+ // Create archive engine and retrieve archive descriptor by ID
367
373
  const archiveEngine = tmSession.NewArchiveEngine();
368
- await archiveEngine.RetrieveAsync(manualArchiveID);
374
+ const result = await archiveEngine.RetrieveAsync(manualArchiveID);
375
+ // Update state with retrieved archive if valid
376
+ setDcmtArchive(result);
369
377
  return true;
370
378
  }
371
379
  catch (e) {
380
+ // Display error to user if retrieval fails
372
381
  TMExceptionBoxManager.show({ exception: e });
382
+ setDcmtArchive(undefined);
373
383
  return false;
374
384
  }
375
385
  finally {
@@ -16,17 +16,40 @@ const TMChooserForm = ({ children, title, allowMultipleSelection = false, allowA
16
16
  const [selectedRowKeys, setSelectedRowKeys] = useState(selectedIDs ?? []);
17
17
  const [focusedRowKey, setFocusedRowKey] = useState(selectedIDs?.[0]);
18
18
  const [selectedRowCounter, setSelectedRowCounter] = useState([]);
19
+ // Helper per confronto case-insensitive
20
+ const includesCaseInsensitive = (arr, value) => {
21
+ if (!arr)
22
+ return false;
23
+ if (typeof value === 'string') {
24
+ return arr.some(item => typeof item === 'string' && item.toLowerCase() === value.toLowerCase());
25
+ }
26
+ return arr.includes(value);
27
+ };
19
28
  useEffect(() => { doGetItems(false); }, [getItems]);
29
+ // Normalizza selectedRowKeys per corrispondere al case reale dei dati
30
+ const normalizeSelectedKeys = useCallback((items, keys) => {
31
+ return keys.map(key => {
32
+ if (typeof key === 'string') {
33
+ const match = items.find((item) => typeof item[keyName] === 'string' && item[keyName].toLowerCase() === key.toLowerCase());
34
+ return match ? match[keyName] : key;
35
+ }
36
+ return key;
37
+ });
38
+ }, [keyName]);
20
39
  useEffect(() => {
40
+ const normalizedKeys = normalizeSelectedKeys(allItems, selectedRowKeys);
41
+ if (JSON.stringify(normalizedKeys) !== JSON.stringify(selectedRowKeys)) {
42
+ setSelectedRowKeys(normalizedKeys);
43
+ }
21
44
  if (showOnlySelectedItems)
22
- setFilteredItems(allItems.filter((o) => selectedRowKeys?.includes(o[keyName])));
45
+ setFilteredItems(allItems.filter((o) => includesCaseInsensitive(normalizedKeys, o[keyName])));
23
46
  else
24
47
  setFilteredItems(allItems);
25
48
  }, [showOnlySelectedItems, allItems, selectedRowKeys, keyName]);
26
49
  useEffect(() => {
27
50
  setSelectedRowCounter(selectedRowKeys);
28
51
  }, [selectedRowKeys]);
29
- const getSelectedIDs = () => { return filteredItems.filter((o) => selectedRowKeys?.includes(o[keyName])).map((item) => { return convertID ? convertID(item) : item[keyName]; }); };
52
+ const getSelectedIDs = () => { return filteredItems.filter((o) => includesCaseInsensitive(selectedRowKeys, o[keyName])).map((item) => { return convertID ? convertID(item) : item[keyName]; }); };
30
53
  const getFocusedIDs = () => { return filteredItems.filter((o) => o[keyName] == focusedRowKey).map((item) => { return convertID ? convertID(item) : item[keyName]; }); };
31
54
  const renderTitle = () => { return title ? `${title} (${selectedRowCounter.length}/${filteredItems.length})` : SDKUI_Localizator.Select; };
32
55
  const doGetItems = (refreshCache) => {
@@ -41,7 +41,7 @@ const TMBlogsPost = (props) => {
41
41
  // State to manage the layout mode of the document form
42
42
  const [layoutMode, setLayoutMode] = useState("extended");
43
43
  const COMPACT_WIDTH_THRESHOLD = 465;
44
- const COMPACT_HEIGHT_THRESHOLD = 500;
44
+ const COMPACT_HEIGHT_THRESHOLD = 400;
45
45
  // State to store an array of blog posts, which can be either BlogPost or HomeBlogPost type
46
46
  const [blogPosts, setBlogPosts] = useState([]);
47
47
  // State to store the first unread post
@@ -62,6 +62,7 @@ export { default as TMBlogAttachments } from './grids/TMBlogAttachments';
62
62
  export { default as TMBlogCommentForm } from './features/blog/TMBlogCommentForm';
63
63
  export * from './query/TMQueryEditor';
64
64
  export * from './query/TMQuerySummary';
65
+ export * from './query/TMQueryCountButton';
65
66
  export { default as TMToppyDraggableHelpCenter } from './features/assistant/TMToppyDraggableHelpCenter';
66
67
  export * from './features/documents/TMDcmtForm';
67
68
  export * from './features/documents/TMDcmtIcon';
@@ -68,6 +68,7 @@ export { default as TMBlogCommentForm } from './features/blog/TMBlogCommentForm'
68
68
  //query
69
69
  export * from './query/TMQueryEditor';
70
70
  export * from './query/TMQuerySummary';
71
+ export * from './query/TMQueryCountButton';
71
72
  //assistant
72
73
  export { default as TMToppyDraggableHelpCenter } from './features/assistant/TMToppyDraggableHelpCenter';
73
74
  //documents
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useState, useEffect } from "react";
3
3
  import { SDK_Globals, ObjectClasses, ResultTypes } from "@topconsultnpm/sdk-ts";
4
4
  import DataGrid, { Column, GroupPanel, Grouping, HeaderFilter, LoadPanel, Pager, Paging, Scrolling, SearchPanel, Selection } from "devextreme-react/data-grid";
@@ -215,7 +215,9 @@ const TMPage = ({ id, objClass = ObjectClasses.None, listDisabled = false, lastR
215
215
  return;
216
216
  setSelectedItems([row.data]);
217
217
  setShowList(false);
218
- }, showColumnLines: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.showColumnLines) === 1, showRowLines: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.showRowLines) === 1, onSelectionChanged: (e) => { setSelectedItems(e.selectedRowsData); onSelectionChanged?.(e.selectedRowsData); }, children: [_jsx(GroupPanel, { visible: !!(deviceType !== DeviceType.MOBILE && showAllColumns) }), _jsx(SearchPanel, { visible: false }), _jsx(Grouping, { autoExpandAll: false }), _jsx(HeaderFilter, { visible: true }), _jsx(Selection, { mode: "multiple", showCheckBoxesMode: "onClick", selectAllMode: 'allPages' }), _jsx(Scrolling, { mode: "standard", useNative: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar) === 1 }), _jsx(Paging, { pageSize: 25 }), _jsx(Pager, { visible: true, showInfo: true, showNavigationButtons: true }), _jsx(LoadPanel, { enabled: true }), _jsx(Column, { width: 20, cellRender: cellRenderObjectIcon }), _jsx(Column, { width: 'auto', visible: showId, dataField: "id", caption: "ID" }), _jsx(Column, { width: 250, dataField: "name", caption: SDKUI_Localizator.Name, sortOrder: "asc" }), _jsx(Column, { width: 250, visible: showAllColumns, dataField: "description", caption: SDKUI_Localizator.Description }), customColumns?.map((item, index) => { return React.cloneElement(item, { key: index, visible: showAllColumns }); }), _jsx(Column, { width: 'auto', visible: showAllColumns, dataField: "ownerID", caption: SDKUI_Localizator.OwnerID }), _jsx(Column, { width: 'auto', visible: showAllColumns, dataField: "ownerName", caption: SDKUI_Localizator.OwnerName }), _jsx(Column, { width: 'auto', dataType: "date", format: Globalization.getDateDisplayFormat(), visible: showAllColumns, dataField: "creationTime", caption: SDKUI_Localizator.CreationTime }), _jsx(Column, { width: 'auto', dataType: "date", format: Globalization.getDateDisplayFormat(), visible: showAllColumns, dataField: "lastUpdateTime", caption: SDKUI_Localizator.LastUpdateTime })] })] }), detailInsteadOfContent ??
218
+ }, showColumnLines: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.showColumnLines) === 1, showRowLines: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.showRowLines) === 1, onSelectionChanged: (e) => { setSelectedItems(e.selectedRowsData); onSelectionChanged?.(e.selectedRowsData); }, children: [_jsx(GroupPanel, { visible: !!(deviceType !== DeviceType.MOBILE && showAllColumns) }), _jsx(SearchPanel, { visible: false }), _jsx(Grouping, { autoExpandAll: false }), _jsx(HeaderFilter, { visible: true }), _jsx(Selection, { mode: "multiple", showCheckBoxesMode: "onClick", selectAllMode: 'allPages' }), _jsx(Scrolling, { mode: "standard", useNative: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar) === 1 }), _jsx(Paging, { pageSize: 25 }), _jsx(Pager, { visible: true, showInfo: true, showNavigationButtons: true }), _jsx(LoadPanel, { enabled: true }), _jsx(Column, { width: 20, cellRender: cellRenderObjectIcon }), _jsx(Column, { width: 'auto', visible: showId, dataField: "id", caption: "ID" }), _jsx(Column, { width: 250, dataField: "name", caption: SDKUI_Localizator.Name, sortOrder: "asc" }), objClass == ObjectClasses.User ?
219
+ _jsxs(_Fragment, { children: [_jsx(Column, { width: 'auto', dataField: "type", caption: SDKUI_Localizator.Type }), _jsx(Column, { width: 'auto', dataField: "fn", caption: SDKUI_Localizator.User_FirstName }), _jsx(Column, { width: 'auto', dataField: "ln", caption: SDKUI_Localizator.User_LastName })] })
220
+ : _jsx(_Fragment, {}), _jsx(Column, { width: 250, visible: objClass == ObjectClasses.User ? true : showAllColumns, dataField: "description", caption: SDKUI_Localizator.Description }), customColumns?.map((item, index) => { return React.cloneElement(item, { key: index, visible: showAllColumns }); }), _jsx(Column, { width: 'auto', visible: showAllColumns, dataField: "ownerID", caption: SDKUI_Localizator.OwnerID }), _jsx(Column, { width: 'auto', visible: showAllColumns, dataField: "ownerName", caption: SDKUI_Localizator.OwnerName }), _jsx(Column, { width: 'auto', dataType: "date", format: Globalization.getDateDisplayFormat(), visible: showAllColumns, dataField: "creationTime", caption: SDKUI_Localizator.CreationTime }), _jsx(Column, { width: 'auto', dataType: "date", format: Globalization.getDateDisplayFormat(), visible: showAllColumns, dataField: "lastUpdateTime", caption: SDKUI_Localizator.LastUpdateTime })] })] }), detailInsteadOfContent ??
219
221
  _jsx(TMLayoutItem, { children: selectedItems.length == 1 || formMode == FormModes.Create || formMode == FormModes.Duplicate ?
220
222
  _jsx(TMToolbarCard, { onBack: deviceType === DeviceType.MOBILE ? () => setShowList(true) : undefined, title: calcSaveFormTitle(objName, formMode, selectedItems.length == 0 ? -1 : selectedItems[0].id, detailTitlePathKeys), children: getDetailFormWithProps() })
221
223
  :
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { QueryDescriptor, QueryParameterDescriptor } from '@topconsultnpm/sdk-ts';
3
+ interface ITMQueryCountButton {
4
+ qd?: QueryDescriptor;
5
+ lastparams: QueryParameterDescriptor[] | undefined;
6
+ disabled?: boolean;
7
+ showSpinner: boolean;
8
+ onLastQueryParamsChanged?: (params: QueryParameterDescriptor[]) => void;
9
+ }
10
+ declare const TMQueryCountButton: React.FunctionComponent<ITMQueryCountButton>;
11
+ export default TMQueryCountButton;
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import TMButton from '../base/TMButton';
3
+ import { getQueryCountAsync, IconCount, IsParametricQuery, SDKUI_Localizator } from '../../helper';
4
+ import { useQueryParametersDialog } from '../../hooks/useQueryParametersDialog';
5
+ const TMQueryCountButton = ({ qd, lastparams, disabled, showSpinner, onLastQueryParamsChanged }) => {
6
+ const [confirmQueryParams, ConfirmQueryParamsDialog] = useQueryParametersDialog();
7
+ const getQueryCountLocalAsync = async () => {
8
+ if (qd == undefined)
9
+ return;
10
+ let qdLocal = { ...qd };
11
+ const whereCopy = qdLocal.where?.map((curItem) => ({ ...curItem }));
12
+ if (IsParametricQuery(qd)) {
13
+ const qdParams = await confirmQueryParams(qdLocal, lastparams);
14
+ if (!qdParams || qdParams.length <= 0)
15
+ return;
16
+ for (const qpd of qdParams) {
17
+ let wi = whereCopy?.find(o => o.value1 == qpd.name);
18
+ if (wi)
19
+ wi.value1 = wi.value1?.replace(wi.value1, !qpd.value ? '' : qpd.value.toString());
20
+ else {
21
+ wi = whereCopy?.find(o => o.value2 == qpd.name);
22
+ if (wi)
23
+ wi.value2 = wi.value2?.replace(wi.value2, !qpd.value ? '' : qpd.value.toString());
24
+ }
25
+ }
26
+ onLastQueryParamsChanged?.(qdParams ?? []);
27
+ }
28
+ await getQueryCountAsync({ ...qdLocal, where: whereCopy }, showSpinner);
29
+ };
30
+ return (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: 'toolbar', caption: SDKUI_Localizator.Count, icon: _jsx(IconCount, {}), disabled: disabled, onClick: async () => await getQueryCountLocalAsync() }), _jsx(ConfirmQueryParamsDialog, {})] }));
31
+ };
32
+ export default TMQueryCountButton;
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from 'react';
3
3
  import { SDK_Localizator, AccessLevels, OnJoinItem, JoinTypes, PlatformObjectValidator, MetadataDataDomains, DcmtTypeListCacheService, JoinItem, MetadataDataTypes, OrderByItem, QueryFunctions, QueryOperators, ResultTypes, SelectItem, SDK_Globals, UserListCacheService, WhereItem, SearchEngine, SelectItemVisibilities, DataListCacheService, QueryValidatorOptions, TMPropertyNames, AppModules, LayoutModes } from '@topconsultnpm/sdk-ts';
4
4
  import styled from 'styled-components';
5
5
  import Accordion, { Item } from 'devextreme-react/accordion';
6
- import { SDKUI_Localizator, IconSearch, IconCount, getQueryCountAsync, calcIsModified, IconClear, IconAddCircleOutline, IconDotsVerticalCircleOutline, IconHide, IconShow, IconDraggabledots, genUniqueId, LocalizeQueryOperators, LocalizeQueryFunctions, LocalizeQueryJoinTypes, IconArchiveDoc, IconArrowRight, SDKUI_Globals } from '../../helper';
6
+ import { SDKUI_Localizator, IconSearch, calcIsModified, IconClear, IconAddCircleOutline, IconDotsVerticalCircleOutline, IconHide, IconShow, IconDraggabledots, genUniqueId, LocalizeQueryOperators, LocalizeQueryFunctions, LocalizeQueryJoinTypes, IconArchiveDoc, IconArrowRight, SDKUI_Globals } from '../../helper';
7
7
  import { displayMetadataValue, getDcmtTypesByQdAsync, getTIDsByQd, IsParametricQuery, prepareQdForSearchAsync } from '../../helper/queryHelper';
8
8
  import { useOutsideClick } from '../../hooks/useOutsideClick';
9
9
  import { FormModes, SearchResultContext } from '../../ts';
@@ -30,6 +30,7 @@ import TMMetadataEditor from '../editors/TMMetadataEditor';
30
30
  import { ContextMenu } from '../NewComponents/ContextMenu';
31
31
  import { useQueryParametersDialog } from '../../hooks/useQueryParametersDialog';
32
32
  import TMSearchResult from '../features/search/TMSearchResult';
33
+ import TMQueryCountButton from './TMQueryCountButton';
33
34
  export const StyledRowItem = styled.div ` display: flex; flex-direction: row; align-items: center; justify-content: flex-start; margin-bottom: 5px; gap: 3px; `;
34
35
  export const StyledItemWrapper = styled.div ` border-radius: ${props => props.$borderRadius ?? '4px'}; padding: 4px; font-size: 1rem; user-select: none; width: max-content; `;
35
36
  export const StyledAccordionItemContainer = styled.div ` width: 100%; padding: 2px; display: flex; flex-direction: column; overflow-x: auto; align-items: flex-start; margin-left: 5px; gap: 3px; max-height: 300px; `;
@@ -242,6 +243,35 @@ const TMQueryEditor = ({ formMode, inputData, onQDChanged, isExpertMode, showDis
242
243
  curJoinItem.on = onJoinCopy;
243
244
  setFormData({ ...formData, join: joinCopy });
244
245
  };
246
+ const onChange_OnJoinItem_Or = (or, index, indexOn) => {
247
+ const joinCopy = formData?.join?.map((ji) => { return { ...ji }; }) ?? [];
248
+ let curJoinItem = joinCopy[index];
249
+ const onJoinCopy = curJoinItem.on?.map((curItem, curIndex) => {
250
+ if (indexOn != curIndex)
251
+ return curItem;
252
+ let newOn = new OnJoinItem();
253
+ newOn.init({ ...curItem, or: or });
254
+ return newOn;
255
+ });
256
+ curJoinItem.on = onJoinCopy;
257
+ setFormData({ ...formData, join: joinCopy });
258
+ };
259
+ const onChange_OnJoinItem_Brackets = (value, isLeft, index, indexOn) => {
260
+ const joinCopy = formData?.join?.map((ji) => { return { ...ji }; }) ?? [];
261
+ let curJoinItem = joinCopy[index];
262
+ const onJoinCopy = curJoinItem.on?.map((curItem, curIndex) => {
263
+ if (indexOn != curIndex)
264
+ return curItem;
265
+ let newOn = new OnJoinItem();
266
+ if (isLeft)
267
+ newOn.init({ ...curItem, leftBrackets: value });
268
+ else
269
+ newOn.init({ ...curItem, rightBrackets: value });
270
+ return newOn;
271
+ });
272
+ curJoinItem.on = onJoinCopy;
273
+ setFormData({ ...formData, join: joinCopy });
274
+ };
245
275
  const getJoinTypesMenuItems = (index) => {
246
276
  let items = [
247
277
  { name: LocalizeQueryJoinTypes(JoinTypes.InnerJoin), onClick: () => onChange_JoinItem_JoinType(JoinTypes.InnerJoin, index) },
@@ -703,7 +733,7 @@ const TMQueryEditor = ({ formMode, inputData, onQDChanged, isExpertMode, showDis
703
733
  }
704
734
  };
705
735
  // #endregion
706
- return (_jsxs(_Fragment, { children: [_jsxs(TMApplyForm, { isModal: false, formMode: formMode, isModified: calcIsModified(formData, formDataOrig), exception: exception, validationItems: validationItems, hasNavigation: false, customToolbarElements: _jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: 'toolbar', caption: SDKUI_Localizator.Search, color: 'tertiary', icon: _jsx(IconSearch, {}), disabled: errorsCount > 0, onClick: async () => await onSearchAsync(formData) }), _jsx(TMButton, { btnStyle: 'toolbar', caption: SDKUI_Localizator.Count, icon: _jsx(IconCount, {}), disabled: errorsCount > 0, onClick: () => getQueryCountAsync(formData, true) }), SDK_Globals.tmSession?.SessionDescr?.appModuleID == AppModules.SURFER && _jsx(TMButton, { caption: "Passa ad archiviazione", icon: _jsx(IconArchiveDoc, {}), btnStyle: 'toolbar', fontSize: '1.3rem', onClick: () => { ShowAlert({ message: "TODO Passa ad archiviazione", mode: 'info', title: `${"TODO"}`, duration: 3000 }); } }), SDK_Globals.tmSession?.SessionDescr?.appModuleID == AppModules.SURFER && _jsx(TMButton, { caption: "Vai a risultato", icon: _jsx(IconArrowRight, {}), btnStyle: 'toolbar', fontSize: '1.3rem', onClick: () => { ShowAlert({ message: "TODO Vai a risultato", mode: 'info', title: `${"TODO"}`, duration: 3000 }); } })] }), showToolbar: showToolbar, showApply: showApply, showUndo: showUndo, showBack: showBack, onApply: () => applyData(), onClose: () => onClose?.(), onUndo: () => setFormData(formDataOrig), children: [_jsxs(Accordion, { elementAttr: { class: 'tm-query-dx-accordion' }, height: height, multiple: true, collapsible: true, repaintChangesOnly: true, deferRendering: false, animationDuration: 0, onContentReady: (e) => {
736
+ return (_jsxs(_Fragment, { children: [_jsxs(TMApplyForm, { isModal: false, formMode: formMode, isModified: calcIsModified(formData, formDataOrig), exception: exception, validationItems: validationItems, hasNavigation: false, customToolbarElements: _jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: 'toolbar', caption: SDKUI_Localizator.Search, color: 'tertiary', icon: _jsx(IconSearch, {}), disabled: errorsCount > 0, onClick: async () => await onSearchAsync(formData) }), _jsx(TMQueryCountButton, { qd: { ...formData }, lastparams: lastQdParams, onLastQueryParamsChanged: (params) => { setLastQdParams(params); }, disabled: errorsCount > 0, showSpinner: true }), SDK_Globals.tmSession?.SessionDescr?.appModuleID == AppModules.SURFER && _jsx(TMButton, { caption: "Passa ad archiviazione", icon: _jsx(IconArchiveDoc, {}), btnStyle: 'toolbar', fontSize: '1.3rem', onClick: () => { ShowAlert({ message: "TODO Passa ad archiviazione", mode: 'info', title: `${"TODO"}`, duration: 3000 }); } }), SDK_Globals.tmSession?.SessionDescr?.appModuleID == AppModules.SURFER && _jsx(TMButton, { caption: "Vai a risultato", icon: _jsx(IconArrowRight, {}), btnStyle: 'toolbar', fontSize: '1.3rem', onClick: () => { ShowAlert({ message: "TODO Vai a risultato", mode: 'info', title: `${"TODO"}`, duration: 3000 }); } })] }), showToolbar: showToolbar, showApply: showApply, showUndo: showUndo, showBack: showBack, onApply: () => applyData(), onClose: () => onClose?.(), onUndo: () => setFormData(formDataOrig), children: [_jsxs(Accordion, { elementAttr: { class: 'tm-query-dx-accordion' }, height: height, multiple: true, collapsible: true, repaintChangesOnly: true, deferRendering: false, animationDuration: 0, onContentReady: (e) => {
707
737
  let items = e.component.option("items");
708
738
  if (items && items.length > 0) {
709
739
  for (let i = 0; i < items.length; i++) {
@@ -739,7 +769,10 @@ const TMQueryEditor = ({ formMode, inputData, onQDChanged, isExpertMode, showDis
739
769
  setFormData({ ...formData, join: joinCopy });
740
770
  }
741
771
  }
742
- ] }), _jsx(TMMetadataChooser, { disabled: isReadOnly, showEditButton: false, getColorIndex: getColorIndex, showCompleteMetadataName: showCompleteMetadataName, openEditorOnSummaryClick: true, showBorder: false, borderRadius: borderRadius, showId: showId, backgroundColor: getColorIndex({ tid: onItem.leftTID, alias: onItem.leftAlias }), qd: formData, values: onItem.leftTID ? [{ tid: onItem.leftTID, mid: onItem.leftMID, aliasTID: onItem.leftAlias }] : [], onValueChanged: (values) => { values.length > 0 && onChange_OnJoinMetadatoLeft(values[0], index, indexOn); }, updateIsModalOpen: updateIsModalOpen }), _jsx(TMQdDropDownMenu, { backgroundColor: colorOperator, color: 'green', borderRadius: borderRadius, content: _jsx(StyledItemWrapper, { children: LocalizeQueryOperators(onItem.operator) }), items: [] }), _jsx(TMMetadataChooser, { disabled: isReadOnly, showEditButton: false, getColorIndex: getColorIndex, showCompleteMetadataName: showCompleteMetadataName, openEditorOnSummaryClick: true, showBorder: false, borderRadius: borderRadius, showId: showId, backgroundColor: getColorIndex({ tid: onItem.rightTID, alias: onItem.rightAlias }), qd: formData, values: onItem.rightTID ? [{ tid: onItem.rightTID, mid: onItem.rightMID, aliasTID: onItem.rightAlias }] : [], onValueChanged: (values) => { values.length > 0 && onChange_OnJoinMetadatoRight(values[0], index, indexOn); }, updateIsModalOpen: updateIsModalOpen })] }, indexOn));
772
+ ] }), _jsx(TMQdDropDownMenu, { disabled: indexOn == 0, color: 'green', content: _jsx("div", { style: { fontSize: '1rem' }, children: onItem.or ? 'OR' : 'AND' }), items: [
773
+ { name: 'AND', onClick: () => onChange_OnJoinItem_Or(false, index, indexOn) },
774
+ { name: 'OR', onClick: () => onChange_OnJoinItem_Or(true, index, indexOn) }
775
+ ] }), _jsx(TMQdEditableItem, { value: onItem.leftBrackets, allowedPattern: /\(/g, backgroundColor: colorBrackets, onValueChanged: (value) => { onChange_OnJoinItem_Brackets(value, true, index, indexOn); } }), _jsx(TMMetadataChooser, { disabled: isReadOnly, showEditButton: false, getColorIndex: getColorIndex, showCompleteMetadataName: showCompleteMetadataName, openEditorOnSummaryClick: true, showBorder: false, borderRadius: borderRadius, showId: showId, backgroundColor: getColorIndex({ tid: onItem.leftTID, alias: onItem.leftAlias }), qd: formData, values: onItem.leftTID ? [{ tid: onItem.leftTID, mid: onItem.leftMID, aliasTID: onItem.leftAlias }] : [], onValueChanged: (values) => { values.length > 0 && onChange_OnJoinMetadatoLeft(values[0], index, indexOn); }, updateIsModalOpen: updateIsModalOpen }), _jsx(TMQdDropDownMenu, { backgroundColor: colorOperator, color: 'green', borderRadius: borderRadius, content: _jsx(StyledItemWrapper, { children: LocalizeQueryOperators(onItem.operator) }), items: [] }), _jsx(TMMetadataChooser, { disabled: isReadOnly, showEditButton: false, getColorIndex: getColorIndex, showCompleteMetadataName: showCompleteMetadataName, openEditorOnSummaryClick: true, showBorder: false, borderRadius: borderRadius, showId: showId, backgroundColor: getColorIndex({ tid: onItem.rightTID, alias: onItem.rightAlias }), qd: formData, values: onItem.rightTID ? [{ tid: onItem.rightTID, mid: onItem.rightMID, aliasTID: onItem.rightAlias }] : [], onValueChanged: (values) => { values.length > 0 && onChange_OnJoinMetadatoRight(values[0], index, indexOn); }, updateIsModalOpen: updateIsModalOpen }), _jsx(TMQdEditableItem, { value: onItem.rightBrackets, allowedPattern: /\)/g, backgroundColor: colorBrackets, onValueChanged: (value) => { onChange_OnJoinItem_Brackets(value, false, index, indexOn); } })] }, indexOn));
743
776
  })] }, `${ji.tid}_${index}`));
744
777
  }), _jsx(TMVilViewer, { vil: validationItems.filter((o) => o.PropertyName === TMPropertyNames.join) })] }) }) }), canShowSelect && _jsx(Item, { title: SDK_Localizator.QuerySelect, titleRender: (tabItemProps) => renderAccordionTitle(tabItemProps, selectCount, validationItems.filter((o) => o.PropertyName == TMPropertyNames.select)), children: _jsx(StyledAccordionItemContainer, { children: _jsxs(StyledAccordionItemContent, { "$disabled": isReadOnly, children: [_jsx(TMVilViewer, { vil: validationItems.filter((o) => o.PropertyName === TMPropertyNames.select) }), (!formData?.select || formData?.select.length <= 0) && !isReadOnly &&
745
778
  _jsxs(StyledRowItem, { children: [_jsx(TMButton, { btnStyle: 'normal', disabled: !formData?.from?.tid, caption: SDKUI_Localizator.Add, onClick: onAdd_SelectItem }), dcmtTypesList.length == 1
@@ -795,7 +828,11 @@ const TMQdEditableItem = ({ value, placeHolder, width, backgroundColor, allowedP
795
828
  return (_jsx("div", { ref: ref, children: isComponentVisible ?
796
829
  _jsx(TMTextBox, { elementStyle: { marginLeft: '5px', marginRight: '5px' }, width: width ?? '50px', autoFocus: true, value: value ?? '', onValueChanged: handleTextBoxValueChanged, allowedPattern: allowedPattern })
797
830
  :
798
- _jsx(StyledItemWrapper, { onClick: () => setIsComponentVisible(true), style: { backgroundColor: backgroundColor, cursor: 'pointer' }, children: value ?? placeHolder }) }));
831
+ _jsx(StyledItemWrapper, { onClick: () => setIsComponentVisible(true), style: {
832
+ backgroundColor: backgroundColor,
833
+ cursor: 'pointer',
834
+ minHeight: '24px'
835
+ }, children: value ?? placeHolder }) }));
799
836
  };
800
837
  const TMQdWhereItemValue = ({ whereItem, index, queryParamsDynDataList, onlyEditing = false, onValueChanged, onCascadeRefreshDynDataLists, updateIsModalOpen }) => {
801
838
  let EditingModes;
@@ -5,10 +5,11 @@ import { QueryDescriptor, ResultTypes, TMScopeNames } from '@topconsultnpm/sdk-t
5
5
  import { FontSize } from '../../utils/theme';
6
6
  import TMQueryEditor from './TMQueryEditor';
7
7
  import TMButton from '../base/TMButton';
8
- import { getQueryCountAsync, IconCount, IconEraser, IconPencil, SDKUI_Localizator } from '../../helper';
8
+ import { IconEraser, IconPencil, SDKUI_Localizator } from '../../helper';
9
9
  import TMVilViewer from '../base/TMVilViewer';
10
10
  import { FormModes } from '../../ts';
11
11
  import TMModal from '../base/TMModal';
12
+ import TMQueryCountButton from './TMQueryCountButton';
12
13
  // #region Style
13
14
  const StyledWrapper = styled.div `
14
15
  display: flex;
@@ -28,7 +29,7 @@ const TMQuerySummary = ({ children, qd, validateSelect = true, validateOrderBy =
28
29
  const [showEditor, setShowEditor] = useState(false);
29
30
  const validationItemsQd = validationItems.filter(o => o.PropertyScopes.includes(TMScopeNames.qd) || o.PropertyName == TMScopeNames.qd);
30
31
  const useInternalEditor = onEditClick === undefined;
31
- return (_jsxs(StyledWrapper, { children: [_jsxs(StyledQueryToolbar, { children: [_jsx(TMButton, { caption: SDKUI_Localizator.QueryDefine, icon: _jsx(IconPencil, { fontSize: 16 }), btnStyle: 'toolbar', onClick: () => onEditClick ? onEditClick() : setShowEditor(true) }), _jsx(TMButton, { caption: SDKUI_Localizator.QueryCount, icon: _jsx(IconCount, { fontSize: 16 }), disabled: validationItemsQd.filter(o => o.ResultType == ResultTypes.ERROR).length > 0, btnStyle: 'toolbar', onClick: () => getQueryCountAsync(qd, true) }), _jsx(TMButton, { caption: SDKUI_Localizator.QueryClear, icon: _jsx(IconEraser, { fontSize: 16 }), btnStyle: 'toolbar', onClick: () => onValueChanged?.(new QueryDescriptor()) }), children] }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', width: '100%', overflowX: 'auto' }, children: [qd && qd.from &&
32
+ return (_jsxs(StyledWrapper, { children: [_jsxs(StyledQueryToolbar, { children: [_jsx(TMButton, { caption: SDKUI_Localizator.QueryDefine, icon: _jsx(IconPencil, { fontSize: 16 }), btnStyle: 'toolbar', onClick: () => onEditClick ? onEditClick() : setShowEditor(true) }), _jsx(TMQueryCountButton, { qd: { ...qd }, lastparams: [], disabled: validationItemsQd.filter(o => o.ResultType == ResultTypes.ERROR).length > 0, showSpinner: true }), _jsx(TMButton, { caption: SDKUI_Localizator.QueryClear, icon: _jsx(IconEraser, { fontSize: 16 }), btnStyle: 'toolbar', onClick: () => onValueChanged?.(new QueryDescriptor()) }), children] }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', width: '100%', overflowX: 'auto' }, children: [qd && qd.from &&
32
33
  _jsx(TMQueryEditor, { formMode: FormModes.ReadOnly, inputData: qd, showDistinct: showDistinct, isModal: false, showToolbar: false, validateSelect: validateSelect, validateOrderBy: validateOrderBy, raiseWarningForOnlyMetadataDcmtTypes: raiseWarningForOnlyMetadataDcmtTypes }), _jsx("div", { style: { padding: '0px 5px' }, children: _jsx(TMVilViewer, { vil: validationItemsQd }) })] }), useInternalEditor && showEditor &&
33
34
  _jsx(TMModal, { title: SDKUI_Localizator.QueryDefine, children: _jsx(TMQueryEditor, { formMode: FormModes.Update, inputData: qd, isModal: true, showDistinct: showDistinct, raiseWarningForOnlyMetadataDcmtTypes: raiseWarningForOnlyMetadataDcmtTypes, validateSelect: validateSelect, validateOrderBy: validateOrderBy, onApplied: (newValue) => onValueChanged?.(newValue), onClose: () => { setShowEditor(false); } }) })] }));
34
35
  };
@@ -5,7 +5,8 @@ interface ITMDataListItemViewerProps {
5
5
  value?: string | Date | number;
6
6
  viewMode?: DataListViewModes;
7
7
  showTooltip?: boolean;
8
+ width?: string;
8
9
  }
9
- declare const TMDataListItemViewer: ({ dataListId, value, viewMode, showTooltip }: ITMDataListItemViewerProps) => import("react/jsx-runtime").JSX.Element | null;
10
+ declare const TMDataListItemViewer: ({ dataListId, value, viewMode, showTooltip, width }: ITMDataListItemViewerProps) => import("react/jsx-runtime").JSX.Element | null;
10
11
  export default TMDataListItemViewer;
11
12
  export declare const cellRenderDataListItem: (data: DataGridTypes.ColumnCellTemplateData, dataListId?: number, viewMode?: DataListViewModes) => import("react/jsx-runtime").JSX.Element;
@@ -5,7 +5,7 @@ import { SDKUI_Localizator } from '../../helper';
5
5
  import TMTooltip from '../base/TMTooltip';
6
6
  import { TMExceptionBoxManager } from '../base/TMPopUp';
7
7
  import { useDataListItem } from '../../hooks/useDataListItem';
8
- const TMDataListItemViewer = ({ dataListId, value, viewMode = DataListViewModes.ImageAndDescription, showTooltip = true }) => {
8
+ const TMDataListItemViewer = ({ dataListId, value, viewMode = DataListViewModes.ImageAndDescription, showTooltip = true, width = '100%' }) => {
9
9
  const { loadDataListsAsync, getDataListItem, renderDataListCell, convertToDataListValue } = useDataListItem();
10
10
  const [dataListItem, setDataListItem] = useState(undefined);
11
11
  useEffect(() => {
@@ -36,7 +36,7 @@ const TMDataListItemViewer = ({ dataListId, value, viewMode = DataListViewModes.
36
36
  return null;
37
37
  }
38
38
  const content = renderDataListCell(value, dataListId, viewMode);
39
- return showTooltip ? (_jsx(TMTooltip, { content: dataListItem ? dataListItem.value : SDKUI_Localizator.ValueNotPresent, parentStyle: { width: '100%' }, childStyle: { width: '100%' }, children: content })) : content;
39
+ return showTooltip ? (_jsx(TMTooltip, { content: dataListItem ? dataListItem.value : SDKUI_Localizator.ValueNotPresent, parentStyle: { width }, childStyle: { width }, children: content })) : content;
40
40
  };
41
41
  export default TMDataListItemViewer;
42
42
  export const cellRenderDataListItem = (data, dataListId, viewMode) => {
@@ -123,4 +123,6 @@ export declare class DcmtFormSettings {
123
123
  }
124
124
  export declare class SDKUI_Globals {
125
125
  static userSettings: UserSettings;
126
+ /** Global handler for scanner requests. Set by the host app (e.g. surfer) to open the scanner UI. */
127
+ static scanRequestHandler?: (mode: 'new' | 'edit', onFileScanned: (file: File) => void, onCancel: () => void, existingFile?: File) => void;
126
128
  }
@@ -569,6 +569,7 @@ export declare class SDKUI_Localizator {
569
569
  static get FormErrorsProceedQuestion(): "Es gibt Fehler im Formular. Wenn Sie fortfahren, werden die Daten nicht gespeichert. Möchten Sie trotzdem fortfahren?" | "There are errors in the form. If you continue, the data will not be saved. Do you want to proceed anyway?" | "Hay errores en el formulario. Si continúas, los datos no se guardarán. ¿Quieres proceder de todos modos?" | "Il y a des erreurs dans le formulaire. Si vous continuez, les données ne seront pas enregistrées. Voulez-vous continuer quand même?" | "Há erros no formulário. Se continuar, os dados não serão salvos. Deseja prosseguir mesmo assim?" | "Ci sono errori nel form. Se continui, i dati non saranno salvati. Vuoi comunque procedere?";
570
570
  static get SavedQueryNew(): "Neue Suche speichern" | "Save new search" | "Guardar nueva búsqueda" | "Enregistrer la nouvelle recherche" | "Guardar nova pesquisa" | "Salva nuova ricerca";
571
571
  static get SavedQueryUpdate(): "Suche bearbeiten" | "Modify query" | "Modificar búsqueda" | "Modifie la recherche" | "Mudar pesquisa" | "Modifica ricerca";
572
+ static get ScanFeatureUnavailableInThisContext(): "Scanfunktionen sind in diesem Kontext nicht verfugbar." | "Scanning features are not available in this context." | "Las funciones de escaneo no estan disponibles en este contexto." | "Les fonctionnalites de numerisation ne sont pas disponibles dans ce contexte." | "Os recursos de digitalizacao nao estao disponiveis neste contexto." | "Funzionalita di scansione non disponibili in questo contesto.";
572
573
  static get Search(): "Auf der Suche nach" | "Search" | "Búsqueda" | "Recherche" | "Pesquisa" | "Ricerca";
573
574
  static get SearchAction(): "Search" | "Suche" | "Buscar" | "Chercher" | "Pesquisar" | "Cerca";
574
575
  static get Search_Advanced(): "Erweiterte Suche" | "Advanced search" | "Búsqueda avanzada" | "Recherche avancée" | "Pesquisa Avançada" | "Ricerca avanzata";
@@ -5661,6 +5661,16 @@ export class SDKUI_Localizator {
5661
5661
  default: return "Modifica ricerca";
5662
5662
  }
5663
5663
  }
5664
+ static get ScanFeatureUnavailableInThisContext() {
5665
+ switch (this._cultureID) {
5666
+ case CultureIDs.De_DE: return "Scanfunktionen sind in diesem Kontext nicht verfugbar.";
5667
+ case CultureIDs.En_US: return "Scanning features are not available in this context.";
5668
+ case CultureIDs.Es_ES: return "Las funciones de escaneo no estan disponibles en este contexto.";
5669
+ case CultureIDs.Fr_FR: return "Les fonctionnalites de numerisation ne sont pas disponibles dans ce contexte.";
5670
+ case CultureIDs.Pt_PT: return "Os recursos de digitalizacao nao estao disponiveis neste contexto.";
5671
+ default: return "Funzionalita di scansione non disponibili in questo contesto.";
5672
+ }
5673
+ }
5664
5674
  static get Search() {
5665
5675
  switch (this._cultureID) {
5666
5676
  case CultureIDs.De_DE: return "Auf der Suche nach";