@topconsultnpm/sdkui-react 6.19.0-dev1.6 → 6.19.0-dev1.60

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 (95) hide show
  1. package/lib/components/base/Styled.d.ts +1 -0
  2. package/lib/components/base/Styled.js +40 -0
  3. package/lib/components/base/TMCustomButton.d.ts +11 -0
  4. package/lib/components/base/TMCustomButton.js +63 -0
  5. package/lib/components/base/TMFileManagerDataGridView.js +4 -1
  6. package/lib/components/base/TMLayout.d.ts +2 -1
  7. package/lib/components/base/TMLayout.js +2 -2
  8. package/lib/components/base/TMTreeView.js +3 -2
  9. package/lib/components/editors/TMHtmlEditor.d.ts +5 -0
  10. package/lib/components/editors/TMHtmlEditor.js +72 -12
  11. package/lib/components/editors/TMMetadataValues.js +90 -40
  12. package/lib/components/features/archive/TMArchive.d.ts +10 -0
  13. package/lib/components/features/archive/TMArchive.js +56 -25
  14. package/lib/components/features/blog/TMBlogCommentForm.d.ts +4 -4
  15. package/lib/components/features/blog/TMBlogCommentForm.js +76 -51
  16. package/lib/components/features/documents/TMDcmtBlog.d.ts +15 -0
  17. package/lib/components/features/documents/TMDcmtBlog.js +21 -33
  18. package/lib/components/features/documents/TMDcmtForm.d.ts +17 -3
  19. package/lib/components/features/documents/TMDcmtForm.js +205 -46
  20. package/lib/components/features/documents/TMDcmtTasks.d.ts +13 -0
  21. package/lib/components/features/documents/TMDcmtTasks.js +24 -0
  22. package/lib/components/features/documents/TMDragDropOverlay.js +2 -1
  23. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +8 -1
  24. package/lib/components/features/documents/TMMasterDetailDcmts.js +6 -6
  25. package/lib/components/features/documents/TMRelationViewer.d.ts +53 -3
  26. package/lib/components/features/documents/TMRelationViewer.js +232 -85
  27. package/lib/components/features/search/TMSearch.d.ts +10 -1
  28. package/lib/components/features/search/TMSearch.js +14 -5
  29. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
  30. package/lib/components/features/search/TMSearchQueryPanel.js +36 -7
  31. package/lib/components/features/search/TMSearchResult.d.ts +10 -1
  32. package/lib/components/features/search/TMSearchResult.js +139 -333
  33. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +2 -2
  34. package/lib/components/features/search/TMSearchResultsMenuItems.js +33 -8
  35. package/lib/components/features/tasks/TMTaskForm.d.ts +37 -0
  36. package/lib/components/features/tasks/TMTaskForm.js +338 -0
  37. package/lib/components/features/tasks/TMTasksAgenda.d.ts +17 -0
  38. package/lib/components/features/tasks/TMTasksAgenda.js +107 -0
  39. package/lib/components/features/tasks/TMTasksCalendar.d.ts +21 -0
  40. package/lib/components/features/tasks/TMTasksCalendar.js +240 -0
  41. package/lib/components/features/tasks/TMTasksHeader.d.ts +14 -0
  42. package/lib/components/features/tasks/TMTasksHeader.js +37 -0
  43. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +20 -0
  44. package/lib/components/features/tasks/TMTasksPanelContent.js +65 -0
  45. package/lib/components/features/tasks/TMTasksUtils.d.ts +132 -0
  46. package/lib/components/features/tasks/TMTasksUtils.js +634 -0
  47. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +32 -0
  48. package/lib/components/features/tasks/TMTasksUtilsView.js +107 -0
  49. package/lib/components/features/tasks/TMTasksView.d.ts +40 -0
  50. package/lib/components/features/tasks/TMTasksView.js +560 -0
  51. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +3 -1
  52. package/lib/components/features/workflow/TMWorkflowPopup.js +19 -6
  53. package/lib/components/forms/TMChooserForm.d.ts +1 -1
  54. package/lib/components/forms/TMChooserForm.js +2 -2
  55. package/lib/components/grids/TMBlogAttachments.d.ts +42 -0
  56. package/lib/components/grids/TMBlogAttachments.js +43 -0
  57. package/lib/components/grids/TMBlogHeader.d.ts +31 -0
  58. package/lib/components/grids/TMBlogHeader.js +41 -0
  59. package/lib/components/grids/{TMBlogs.d.ts → TMBlogsPost.d.ts} +42 -58
  60. package/lib/components/grids/TMBlogsPost.js +628 -0
  61. package/lib/components/grids/{TMBlogsUtils.d.ts → TMBlogsPostUtils.d.ts} +61 -47
  62. package/lib/components/grids/{TMBlogsUtils.js → TMBlogsPostUtils.js} +143 -124
  63. package/lib/components/index.d.ts +14 -1
  64. package/lib/components/index.js +15 -1
  65. package/lib/components/viewers/TMTidViewer.js +28 -3
  66. package/lib/css/tm-sdkui.css +1 -1
  67. package/lib/helper/SDKUI_Globals.d.ts +2 -1
  68. package/lib/helper/SDKUI_Globals.js +1 -0
  69. package/lib/helper/SDKUI_Localizator.d.ts +61 -4
  70. package/lib/helper/SDKUI_Localizator.js +608 -25
  71. package/lib/helper/TMCustomSearchBar.d.ts +8 -0
  72. package/lib/helper/TMCustomSearchBar.js +54 -0
  73. package/lib/helper/TMIcons.d.ts +2 -0
  74. package/lib/helper/TMIcons.js +6 -0
  75. package/lib/helper/TMImageLibrary.d.ts +3 -2
  76. package/lib/helper/TMImageLibrary.js +230 -230
  77. package/lib/helper/TMToppyMessage.d.ts +7 -0
  78. package/lib/helper/TMToppyMessage.js +42 -0
  79. package/lib/helper/TMUtils.d.ts +10 -1
  80. package/lib/helper/TMUtils.js +42 -1
  81. package/lib/helper/dcmtsHelper.d.ts +2 -0
  82. package/lib/helper/dcmtsHelper.js +18 -0
  83. package/lib/helper/index.d.ts +1 -0
  84. package/lib/helper/index.js +1 -0
  85. package/lib/hooks/useRelatedDocuments.d.ts +72 -0
  86. package/lib/hooks/useRelatedDocuments.js +655 -0
  87. package/lib/index.d.ts +1 -0
  88. package/lib/index.js +1 -0
  89. package/lib/stories/TMSDKUI_Localizator.stories.js +1 -1
  90. package/lib/ts/types.d.ts +14 -0
  91. package/lib/ts/types.js +15 -0
  92. package/lib/utils/theme.d.ts +1 -0
  93. package/lib/utils/theme.js +1 -0
  94. package/package.json +2 -2
  95. package/lib/components/grids/TMBlogs.js +0 -721
@@ -4,7 +4,7 @@ import { TMDataGridContextMenuItem } from '../../base/TMDataGrid';
4
4
  import { DcmtInfo, DcmtOperationTypes, DownloadModes, DownloadTypes, SearchResultContext } from '../../../ts';
5
5
  export declare const getSelectedDcmtsOrFocused: (selectedItems: Array<any>, focusedItem: any, fileFormat?: FileFormats) => DcmtInfo[];
6
6
  export declare const signatureInformationCallback: (isMobile: boolean, inputDcmts: DcmtInfo[] | undefined) => Promise<void>;
7
- export declare const getCommandsMenuItems: (isMobile: boolean, dtd: DcmtTypeDescriptor | undefined, selectedItems: Array<any>, focusedItem: any, context: SearchResultContext, showFloatingBar: boolean, workingGroupContext: WorkingGroupDescriptor | undefined, showSearch: boolean, setShowFloatingBar: React.Dispatch<React.SetStateAction<boolean>>, openFormHandler: (layoutMode: LayoutModes) => void, downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, downloadMode: DownloadModes, onFileDownloaded?: (dcmtFile: File | undefined) => void, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>, runOperationAsync: (inputDcmts: DcmtInfo[] | undefined, dcmtOperationType: DcmtOperationTypes, actionAfterOperationAsync?: () => Promise<void>) => Promise<void>, onRefreshSearchAsync: (() => Promise<void>) | undefined, onRefreshDataRowsAsync: (() => Promise<void>) | undefined, onRefreshAfterAddDcmtToFavs: (() => void) | undefined, confirmFormat: () => Promise<FileFormats>, confirmAttachments: (list: FileDescriptor[]) => Promise<string[] | undefined>, openTaskFormHandler: () => void, openDetailDcmtsFormHandler: (value: boolean) => void, openMasterDcmtsFormHandler: (value: boolean) => void, openBatchUpdateFormHandler: (value: boolean) => void, openExportForm: () => void, handleToggleSearch: () => void, handleSignApprove: () => void, openWGsCopyMoveForm?: ((mode: "copyToWgDraft" | "copyToWgArchivedDoc", dcmtTypeDescriptor: DcmtTypeDescriptor, documents: Array<DcmtInfo>) => void), openCommentFormCallback?: ((documents: Array<DcmtInfo>) => void), openEditPdf?: ((documents: Array<DcmtInfo>) => void), openAddDocumentForm?: () => void, passToArchiveCallback?: (outputMids: Array<{
7
+ export declare const getCommandsMenuItems: (isMobile: boolean, dtd: DcmtTypeDescriptor | undefined, selectedItems: Array<any>, focusedItem: any, context: SearchResultContext, showFloatingBar: boolean, workingGroupContext: WorkingGroupDescriptor | undefined, showSearch: boolean, setShowFloatingBar: React.Dispatch<React.SetStateAction<boolean>>, openFormHandler: (layoutMode: LayoutModes) => void, openSharedArchiveHandler: () => Promise<void>, showSharedDcmtsHandler: () => Promise<void>, downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, downloadMode: DownloadModes, onFileDownloaded?: (dcmtFile: File | undefined) => void, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>, runOperationAsync: (inputDcmts: DcmtInfo[] | undefined, dcmtOperationType: DcmtOperationTypes, actionAfterOperationAsync?: () => Promise<void>) => Promise<void>, onRefreshSearchAsync: (() => Promise<void>) | undefined, onRefreshDataRowsAsync: (() => Promise<void>) | undefined, onRefreshAfterAddDcmtToFavs: (() => void) | undefined, confirmFormat: () => Promise<FileFormats>, confirmAttachments: (list: FileDescriptor[]) => Promise<string[] | undefined>, openTaskFormHandler: () => void, openDetailDcmtsFormHandler: (value: boolean) => void, openMasterDcmtsFormHandler: (value: boolean) => void, openBatchUpdateFormHandler: (value: boolean) => void, openExportForm: () => void, handleToggleSearch: () => void, handleSignApprove: () => void, openWGsCopyMoveForm?: ((mode: "copyToWgDraft" | "copyToWgArchivedDoc", dcmtTypeDescriptor: DcmtTypeDescriptor, documents: Array<DcmtInfo>) => void), openCommentFormCallback?: ((documents: Array<DcmtInfo>) => void), openEditPdf?: ((documents: Array<DcmtInfo>) => void), openAddDocumentForm?: () => void, passToArchiveCallback?: (outputMids: Array<{
8
8
  mid: number;
9
9
  value: string;
10
- }>) => void, archiveMasterDocuments?: (tid: number | undefined) => Promise<void>, archiveDetailDocuments?: (tid: number | undefined) => Promise<void>, hasMasterRelation?: boolean, hasDetailRelation?: boolean, canArchiveMasterRelation?: boolean, canArchiveDetailRelation?: boolean, pairManyToManyDocuments?: (isPairing: boolean) => Promise<void>) => Array<TMDataGridContextMenuItem>;
10
+ }>, tid?: number) => void, archiveMasterDocuments?: (tid: number | undefined) => Promise<void>, archiveDetailDocuments?: (tid: number | undefined) => Promise<void>, hasMasterRelation?: boolean, hasDetailRelation?: boolean, canArchiveMasterRelation?: boolean, canArchiveDetailRelation?: boolean, pairManyToManyDocuments?: (isPairing: boolean) => Promise<void>, hasManyToManyRelation?: boolean) => Array<TMDataGridContextMenuItem>;
@@ -1,6 +1,6 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { AccessLevels, AccessLevelsEx, AppModules, FileFormats, LayoutModes, SDK_Globals, DcmtTypeListCacheService, LicenseModuleStatus } from '@topconsultnpm/sdk-ts';
3
- import { IconActivity, IconArchiveDoc, IconBatchUpdate, IconCheckFile, IconCheckIn, IconCircleInfo, IconCloseCircle, IconConvertFilePdf, IconDelete, IconDotsVerticalCircleOutline, IconDownload, IconEdit, IconExportTo, IconFileDots, IconHide, IconInfo, IconMenuCAArchive, IconPlatform, IconPreview, IconRelation, IconSearch, IconShow, IconStar, IconSubstFile, IconUndo, IconUserGroupOutline, SDKUI_Localizator, svgToString, searchResultToMetadataValues, IconSignaturePencil, IconArchiveMaster, IconArchiveDetail, IconDetailDcmts, isPdfEditorEnabled } from '../../../helper';
3
+ import { IconActivity, IconArchiveDoc, IconBatchUpdate, IconCheckFile, IconCheckIn, IconCircleInfo, IconCloseCircle, IconConvertFilePdf, IconDelete, IconDotsVerticalCircleOutline, IconDownload, IconEdit, IconExportTo, IconFileDots, IconHide, IconInfo, IconMenuCAArchive, IconPlatform, IconPreview, IconRelation, IconSearch, IconShow, IconStar, IconSubstFile, IconUndo, IconUserGroupOutline, SDKUI_Localizator, svgToString, searchResultToMetadataValues, IconSignaturePencil, IconArchiveMaster, IconArchiveDetail, IconDetailDcmts, isPdfEditorEnabled, IconPair, IconUnpair, IconSharedDcmt } from '../../../helper';
4
4
  import ShowAlert from '../../base/TMAlert';
5
5
  import { TMMessageBoxManager, ButtonNames, TMExceptionBoxManager } from '../../base/TMPopUp';
6
6
  import TMSpinner from '../../base/TMSpinner';
@@ -75,7 +75,7 @@ export const signatureInformationCallback = async (isMobile, inputDcmts) => {
75
75
  TMExceptionBoxManager.show({ exception: error });
76
76
  }
77
77
  };
78
- export const getCommandsMenuItems = (isMobile, dtd, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, onRefreshDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, confirmAttachments, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, hasMasterRelation, hasDetailRelation, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToManyDocuments) => {
78
+ export const getCommandsMenuItems = (isMobile, dtd, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, onRefreshDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, confirmAttachments, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, hasMasterRelation, hasDetailRelation, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToManyDocuments, hasManyToManyRelation) => {
79
79
  const isPdfEditorLicensed = SDK_Globals?.license?.dcmtArchiveLicenses?.[0]?.siX_60007?.status === LicenseModuleStatus.Licensed;
80
80
  let pdfEditorAvailable = false;
81
81
  if (dtd && dtd.widgets && dtd.widgets.length > 0) {
@@ -235,7 +235,7 @@ export const getCommandsMenuItems = (isMobile, dtd, selectedItems, focusedItem,
235
235
  ?.filter(md => md.mid && md.mid > 100 && md.value && md.value.length > 0)
236
236
  .map(md => ({ mid: md.mid, value: md.value })) || [];
237
237
  TMSpinner.hide();
238
- passToArchiveCallback?.(outputMids);
238
+ passToArchiveCallback?.(outputMids, item.TID);
239
239
  }
240
240
  catch (error) {
241
241
  TMSpinner.hide();
@@ -346,17 +346,17 @@ export const getCommandsMenuItems = (isMobile, dtd, selectedItems, focusedItem,
346
346
  disabled: disabledForMultiRow(selectedItems, focusedItem),
347
347
  items: [
348
348
  {
349
- icon: svgToString(_jsx(IconRelation, {})),
349
+ icon: svgToString(_jsx(IconPair, {})),
350
350
  text: "Abbina documenti molti a molti",
351
351
  operationType: 'multiRow',
352
- disabled: disabledForMultiRow(selectedItems, focusedItem),
352
+ disabled: !hasManyToManyRelation || disabledForMultiRow(selectedItems, focusedItem),
353
353
  onClick: async () => await pairManyToManyDocuments?.(true)
354
354
  },
355
355
  {
356
- icon: svgToString(_jsx(IconRelation, {})),
356
+ icon: svgToString(_jsx(IconUnpair, {})),
357
357
  text: "Disabbina documenti molti a molti",
358
358
  operationType: 'multiRow',
359
- disabled: disabledForMultiRow(selectedItems, focusedItem),
359
+ disabled: !hasManyToManyRelation || disabledForMultiRow(selectedItems, focusedItem),
360
360
  onClick: async () => await pairManyToManyDocuments?.(false)
361
361
  },
362
362
  {
@@ -394,6 +394,30 @@ export const getCommandsMenuItems = (isMobile, dtd, selectedItems, focusedItem,
394
394
  ]
395
395
  };
396
396
  };
397
+ const sharedDcmtsMenuItem = () => {
398
+ return {
399
+ icon: svgToString(_jsx(IconSharedDcmt, {})),
400
+ text: 'Documenti condivisi',
401
+ operationType: 'multiRow',
402
+ disabled: disabledForMultiRow(selectedItems, focusedItem),
403
+ items: [
404
+ {
405
+ icon: svgToString(_jsx(IconSharedDcmt, {})),
406
+ text: "Archiviazione condivisa",
407
+ operationType: 'singleRow',
408
+ disabled: disabledForSingleRow(selectedItems, focusedItem),
409
+ onClick: async () => { await openSharedArchiveHandler(); }
410
+ },
411
+ {
412
+ icon: svgToString(_jsx(IconSharedDcmt, {})),
413
+ text: "Mostra documenti condivisi",
414
+ operationType: 'multiRow',
415
+ disabled: disabledForMultiRow(selectedItems, focusedItem),
416
+ onClick: async () => { await showSharedDcmtsHandler(); }
417
+ }
418
+ ]
419
+ };
420
+ };
397
421
  /* const shareMenuItem = (): TMDataGridContextMenuItem => {
398
422
  return {
399
423
  icon: svgToString(<IconShare />),
@@ -625,8 +649,9 @@ export const getCommandsMenuItems = (isMobile, dtd, selectedItems, focusedItem,
625
649
  ]
626
650
  },
627
651
  signatureMenuItem(),
628
- // checkinMenuItem(),
652
+ // checkinMenuItem(),\
629
653
  relationsMenuItem(),
654
+ sharedDcmtsMenuItem(),
630
655
  // shareMenuItem(),
631
656
  fullTextSearchMenuItem(),
632
657
  otherMenuItem(),
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { TaskDescriptor, UserDescriptor, HomeBlogPost } from '@topconsultnpm/sdk-ts';
3
+ import { DcmtInfo, FormModes, TaskContext } from '../../../ts';
4
+ export interface TMTaskFormProps {
5
+ allTasks: Array<TaskDescriptor>;
6
+ getAllTasks: () => Promise<void>;
7
+ deleteTaskByIdsCallback: (deletedTaskIds: Array<number>) => Promise<void>;
8
+ addTaskCallback: (task: TaskDescriptor) => Promise<void>;
9
+ editTaskCallback: (task: TaskDescriptor) => Promise<void>;
10
+ handleNavigateToWGs: (value: HomeBlogPost | number) => Promise<void>;
11
+ handleNavigateToDossiers: (value: HomeBlogPost | number) => Promise<void>;
12
+ id: number;
13
+ title: string;
14
+ isModal: boolean;
15
+ formMode: FormModes;
16
+ visualizedTasks: Array<TaskDescriptor>;
17
+ currentTask: TaskDescriptor | null;
18
+ setCurrentTask?: React.Dispatch<React.SetStateAction<TaskDescriptor | null>>;
19
+ selectedRowKeys: Array<number>;
20
+ handleFocusedRowKeyChange?: (row: TaskDescriptor | undefined) => void;
21
+ onStatusChanged?: () => void;
22
+ onSaved?: (newTask: TaskDescriptor) => void;
23
+ onClose?: () => void;
24
+ onCancel?: () => void;
25
+ taskContext?: TaskContext;
26
+ startDate?: Date;
27
+ endDate?: Date;
28
+ showBackButton?: boolean;
29
+ hasNavigation?: boolean;
30
+ width?: string;
31
+ height?: string;
32
+ usersList?: Array<UserDescriptor>;
33
+ onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, onRefreshSearchAsync?: (() => Promise<void>)) => void;
34
+ s4TViewerDialogComponent?: React.ReactNode;
35
+ }
36
+ declare const TMTaskForm: (props: TMTaskFormProps) => import("react/jsx-runtime").JSX.Element;
37
+ export default TMTaskForm;
@@ -0,0 +1,338 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { ObjectClasses, TaskDescriptor, Priorities, PdGs, SDK_Globals, UserListCacheService, SDK_Localizator, Task_States } from '@topconsultnpm/sdk-ts';
4
+ import { areDifferentIDs, formatDate, getOriginLabel, getPriorityLocalizatorValue, getPriorityLocalizatorValues, getStatusLocalizatorValues, gotoPDGExtendedLabel, taskValidatorAsync } from './TMTasksUtils';
5
+ import ScrollView from 'devextreme-react/cjs/scroll-view';
6
+ import TMLayoutContainer from '../../base/TMLayout';
7
+ import { FormModes } from '../../../ts';
8
+ import { useWorkflowApprove } from '../../../hooks/useWorkflowApprove';
9
+ import { SaveFormOptions, useSaveForm } from '../../../hooks/useForm';
10
+ import { SDKUI_Localizator, calcIsModified, TMConditionalWrapper, getPdgsIconMap, DateDisplayTypes } from '../../../helper';
11
+ import { TMExceptionBoxManager } from '../../base/TMPopUp';
12
+ import TMSpinner from '../../base/TMSpinner';
13
+ import TMTooltip from '../../base/TMTooltip';
14
+ import TMUserChooser from '../../choosers/TMUserChooser';
15
+ import TMDateBox from '../../editors/TMDateBox';
16
+ import TMDropDown from '../../editors/TMDropDown';
17
+ import TMTextArea from '../../editors/TMTextArea';
18
+ import TMTextBox from '../../editors/TMTextBox';
19
+ import TMSaveForm from '../../forms/TMSaveForm';
20
+ import TMDcmtForm from '../documents/TMDcmtForm';
21
+ import styled from 'styled-components';
22
+ import { TMColors } from '../../../utils/theme';
23
+ const ResponseCommentWrapper = styled.div `
24
+ position: relative;
25
+ width: 100%;
26
+ `;
27
+ const ResponseCommentLabel = styled.label `
28
+ position: absolute;
29
+ top: -8px;
30
+ left: 12px;
31
+ background-color: white;
32
+ padding: 0 4px;
33
+ font-size: 0.9rem;
34
+ color: rgb(80,80,80);
35
+ display: inline-flex;
36
+ align-items: center;
37
+ gap: 4px;
38
+ `;
39
+ const ResponseCommentTextArea = styled.textarea.attrs({
40
+ maxLength: 500,
41
+ }) `
42
+ width: 100%;
43
+ height: 100px;
44
+ border: 1px solid ${props => props.$isValid ? (props.$isModifiedWhen ? "#E29000" : '#b4b4b4') : TMColors.error};
45
+ border-radius: 10px;
46
+ padding: 10px;
47
+ resize: none;
48
+ cursor: ${props => props.disabled ? 'not-allowed' : 'text'};
49
+ &:focus {
50
+ outline: none;
51
+ border-bottom: 4px solid ${props => props.$isValid ? TMColors.primaryColor : TMColors.error};
52
+ }
53
+ `;
54
+ const ResponseCommentCharacterCounter = styled.div `
55
+ text-align: right;
56
+ font-size: 0.8rem;
57
+ color: #6c757d;
58
+ margin-top: 4px;
59
+ `;
60
+ const TMTaskForm = (props) => {
61
+ // Custom hook to manage workflow approval data
62
+ const { refreshWorkflowApprove } = useWorkflowApprove();
63
+ const validator = async (taskDescriptor) => { return await taskValidatorAsync(taskDescriptor); };
64
+ // Destructure the props object to extract individual properties
65
+ const { id, title, isModal, formMode, visualizedTasks, editTaskCallback, currentTask, setCurrentTask, selectedRowKeys, handleFocusedRowKeyChange, onStatusChanged, onSaved, onClose, onCancel, taskContext, startDate, endDate, showBackButton = true, hasNavigation = true, width = "100%", height = "100%", usersList, onOpenS4TViewerRequest, s4TViewerDialogComponent, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, handleNavigateToWGs, handleNavigateToDossiers } = props;
66
+ const sfo = new SaveFormOptions();
67
+ sfo.objClass = ObjectClasses.Task;
68
+ const customizeFormData = (task) => {
69
+ if (taskContext?.document && formMode === FormModes.Create) {
70
+ task.pdG = PdGs.DT;
71
+ task.iD1 = taskContext.document.tid;
72
+ task.iD2 = taskContext.document.did;
73
+ }
74
+ else if (taskContext?.workingGroup && formMode === FormModes.Create) {
75
+ task.pdG = PdGs.WG;
76
+ task.iD1 = taskContext.workingGroup.id;
77
+ }
78
+ else if (taskContext?.dossier && formMode === FormModes.Create) {
79
+ task.pdG = PdGs.CF;
80
+ task.iD1 = taskContext.dossier.id;
81
+ if (currentTask)
82
+ task.name = currentTask.name;
83
+ }
84
+ else if (taskContext?.workItem && formMode === FormModes.Create) {
85
+ task.pdG = PdGs.DT;
86
+ task.iD1 = taskContext.workItem.tid;
87
+ task.iD2 = taskContext.workItem.did;
88
+ task.toID = 0;
89
+ }
90
+ return task;
91
+ };
92
+ const { formData, setFormData, formDataOrig, validationItems, exception, saveDataAsync } = useSaveForm(formMode, id, sfo, validator, onSaved, onStatusChanged, customizeFormData);
93
+ const containerRef = useRef(null);
94
+ const [isMobile, setIsMobile] = useState(false);
95
+ const [showDcmtForm, setShowDcmtForm] = useState(false);
96
+ const mobileBreakpoint = 768;
97
+ const [users, setUsers] = useState([]); // State to store the users
98
+ // Initial state for the fields' editability (readonly)
99
+ const [fieldsReadOnly, setFieldsReadOnly] = useState({
100
+ name: false,
101
+ description: false,
102
+ fromID: false,
103
+ assignedTO: false,
104
+ status: false,
105
+ priority: false,
106
+ startDate: false,
107
+ endDate: false,
108
+ remTime: false,
109
+ response: false
110
+ });
111
+ useEffect(() => {
112
+ const fetchUsers = async () => {
113
+ try {
114
+ // Show spinner while loading
115
+ TMSpinner.show({ description: `${SDKUI_Localizator.Loading} - ${SDK_Localizator.Users} ...` });
116
+ const userList = await UserListCacheService.GetAllAsync();
117
+ setUsers(userList); // Update state with the fetched users
118
+ }
119
+ catch (err) {
120
+ TMExceptionBoxManager.show({ exception: err });
121
+ }
122
+ finally {
123
+ TMSpinner.hide();
124
+ }
125
+ };
126
+ fetchUsers();
127
+ }, []);
128
+ useEffect(() => {
129
+ if (isModal)
130
+ setIsMobile(true);
131
+ }, [isModal]);
132
+ useEffect(() => {
133
+ if (formDataOrig && formMode === FormModes.Update) {
134
+ const isTaskAssignedByDifferentUser = areDifferentIDs(formDataOrig.fromID, SDK_Globals.tmSession?.SessionDescr?.userID);
135
+ setFieldsReadOnly({
136
+ name: isTaskAssignedByDifferentUser,
137
+ description: isTaskAssignedByDifferentUser,
138
+ fromID: isTaskAssignedByDifferentUser,
139
+ assignedTO: isTaskAssignedByDifferentUser,
140
+ status: false,
141
+ priority: isTaskAssignedByDifferentUser,
142
+ startDate: isTaskAssignedByDifferentUser,
143
+ endDate: isTaskAssignedByDifferentUser,
144
+ remTime: false,
145
+ response: false
146
+ });
147
+ const newTaskDescriptor = new TaskDescriptor();
148
+ Object.assign(newTaskDescriptor, formDataOrig);
149
+ newTaskDescriptor.isNew = 0;
150
+ editTaskCallback(newTaskDescriptor);
151
+ }
152
+ else if (formDataOrig && formMode === FormModes.Create && taskContext?.dossier && currentTask) {
153
+ setFieldsReadOnly({
154
+ name: true,
155
+ description: false,
156
+ fromID: false,
157
+ assignedTO: false,
158
+ status: false,
159
+ priority: false,
160
+ startDate: false,
161
+ endDate: false,
162
+ remTime: false,
163
+ response: false
164
+ });
165
+ }
166
+ }, [formDataOrig, formMode]);
167
+ useEffect(() => {
168
+ if (!isModal) {
169
+ // Function to handle resize events and update the mobile state based on container width.
170
+ const updateDimensions = (entries) => {
171
+ for (let entry of entries) {
172
+ const { width } = entry.contentRect;
173
+ setIsMobile(width <= mobileBreakpoint);
174
+ }
175
+ };
176
+ // Create a ResizeObserver to observe container size changes
177
+ const resizeObserver = new ResizeObserver(updateDimensions);
178
+ if (containerRef.current) {
179
+ resizeObserver.observe(containerRef.current);
180
+ }
181
+ // Cleanup: Stop observing when the component unmounts or the dependency changes.
182
+ return () => {
183
+ if (containerRef.current) {
184
+ resizeObserver.unobserve(containerRef.current);
185
+ }
186
+ };
187
+ }
188
+ return undefined;
189
+ }, [containerRef, isModal]); // Dependency array ensures this effect runs when containerRef changes.
190
+ // Function to handle changes in the status value of a TM Drop Down
191
+ const onStatusValueChange = (e) => {
192
+ if (!e?.target?.value)
193
+ return;
194
+ setFormData({ ...formData ?? {}, state: e?.target?.value });
195
+ };
196
+ // Function to handle changes in the priority value of a TM Drop Down
197
+ const onPriorityValueChange = (e) => {
198
+ if (!e?.target?.value)
199
+ return;
200
+ setFormData({ ...formData ?? {}, priority: e?.target?.value });
201
+ };
202
+ const onAnswerChange = (e) => {
203
+ setFormData({ ...formData ?? {}, response: e.target.value ?? '' });
204
+ };
205
+ // Function to handle the undo action
206
+ const onUndoCallback = () => {
207
+ setFormData(formDataOrig);
208
+ };
209
+ const canNext = () => {
210
+ if (currentTask === null)
211
+ return false;
212
+ if (visualizedTasks.length === 1)
213
+ return false;
214
+ let index = visualizedTasks.findIndex(item => item.id === currentTask.id);
215
+ if (index < visualizedTasks.length - 1) {
216
+ return true;
217
+ }
218
+ else {
219
+ return false;
220
+ }
221
+ };
222
+ const canPrev = () => {
223
+ if (currentTask === null)
224
+ return false;
225
+ if (visualizedTasks.length === 1)
226
+ return false;
227
+ let index = visualizedTasks.findIndex(item => item.id === currentTask.id);
228
+ if (index > 0) {
229
+ return true;
230
+ }
231
+ else {
232
+ return false;
233
+ }
234
+ };
235
+ const onNextCallback = () => {
236
+ if (currentTask === null)
237
+ return;
238
+ if (visualizedTasks.length === 0)
239
+ return;
240
+ let index = visualizedTasks.findIndex(item => item.id === currentTask.id);
241
+ const nextTask = visualizedTasks[index + 1];
242
+ if (nextTask) {
243
+ setCurrentTask?.(nextTask);
244
+ if (nextTask.id)
245
+ handleFocusedRowKeyChange?.(nextTask);
246
+ }
247
+ };
248
+ const onPrevCallback = () => {
249
+ if (currentTask === null)
250
+ return;
251
+ if (visualizedTasks.length === 0)
252
+ return;
253
+ let index = visualizedTasks.findIndex(item => item.id === currentTask.id);
254
+ const prevTask = visualizedTasks[index - 1];
255
+ if (prevTask) {
256
+ setCurrentTask?.(prevTask);
257
+ if (prevTask.id)
258
+ handleFocusedRowKeyChange?.(prevTask);
259
+ }
260
+ };
261
+ const gotoPDGExtendedLabelClickCallback = () => {
262
+ // Return early if formData is not defined
263
+ if (!formData)
264
+ return;
265
+ // Destructure needed properties from formData
266
+ const { pdG = PdGs.None, iD1, iD2, iD1Name } = formData;
267
+ // Check if pdG is None
268
+ if (pdG === PdGs.None)
269
+ return;
270
+ // If both id1 and id2 are present and pdg is of type DT, show the document form
271
+ if (iD1 && iD2 && pdG === PdGs.DT) {
272
+ setShowDcmtForm(true);
273
+ return; // Exit the function after showing the form
274
+ }
275
+ if (iD1 && pdG === PdGs.WG) {
276
+ // Working Group navigation
277
+ if (handleNavigateToWGs) {
278
+ handleNavigateToWGs(iD1);
279
+ }
280
+ return; // Exit the function after navigation
281
+ }
282
+ if (iD1 && pdG === PdGs.CF) {
283
+ // Dossier navigation
284
+ if (handleNavigateToDossiers) {
285
+ handleNavigateToDossiers(iD1);
286
+ }
287
+ return; // Exit the function after navigation
288
+ }
289
+ // Otherwise, alert the user with the provided information
290
+ alert(gotoPDGExtendedLabel(false, pdG, iD1Name));
291
+ };
292
+ const handleStartTimeContentReady = () => {
293
+ setTimeout(() => { if (startDate && !formData?.startTime && formMode === FormModes.Create) {
294
+ setFormData(prev => ({ ...prev, startTime: startDate }));
295
+ } }, 100);
296
+ };
297
+ const handleEndTimeContentReady = () => {
298
+ setTimeout(() => { if (endDate && !formData?.endTime && formMode === FormModes.Create) {
299
+ setFormData(prev => ({ ...prev, endTime: endDate }));
300
+ } }, 200);
301
+ };
302
+ const onCloseCallback = () => {
303
+ if (formData && formData.id) {
304
+ if (!selectedRowKeys.includes(formData.id)) {
305
+ handleFocusedRowKeyChange?.(formData);
306
+ }
307
+ }
308
+ onClose?.();
309
+ };
310
+ const onTaskCompleted = async (task) => {
311
+ await editTaskCallback(task);
312
+ onClose?.();
313
+ };
314
+ return (_jsx("div", { style: { width: "100%", height: "100%", overflow: "auto" }, ref: containerRef, children: _jsx(TMSaveForm, { width: width, height: height, id: id, title: title, isModal: isModal, formMode: formMode, onSaveAsync: saveDataAsync, onClose: onCloseCallback, onUndo: onUndoCallback, exception: exception, isModified: calcIsModified(formData, formDataOrig), validationItems: validationItems, showBackButton: showBackButton, hasNavigation: (hasNavigation && formMode !== FormModes.Create), canNext: canNext(), onNext: onNextCallback, canPrev: canPrev(), onPrev: onPrevCallback, showToolbar: !(showDcmtForm && formData?.iD1 && formData?.iD2), children: _jsxs(_Fragment, { children: [_jsx(ScrollView, { direction: "vertical", useNative: true, height: "calc(100% - 35px)", children: _jsx("div", { style: { marginRight: "5px" }, children: _jsxs(TMLayoutContainer, { direction: 'vertical', gap: 2, children: [(formMode === FormModes.Update && areDifferentIDs(formDataOrig?.fromID, SDK_Globals.tmSession?.SessionDescr?.userID)) && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsxs("div", { style: { width: '100%', display: 'flex', alignItems: 'center', color: "#E29000" }, children: [_jsx("i", { className: "dx-icon-info", style: { fontSize: 20 } }), "\u00A0", _jsx("span", { children: SDKUI_Localizator.TaskAssignedMessage.replaceParams(formDataOrig?.fromName ?? '') })] }) }), taskContext?.workItem === undefined && (!areDifferentIDs(formData?.fromID, SDK_Globals.tmSession?.SessionDescr?.userID)
315
+ && !areDifferentIDs(formData?.toID, SDK_Globals.tmSession?.SessionDescr?.userID))
316
+ && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsxs("div", { style: { width: '100%', display: 'flex', alignItems: 'center', color: "#2559A5" }, children: [_jsx("i", { className: "dx-icon-info", style: { fontSize: 20 } }), "\u00A0", _jsx("span", { children: SDKUI_Localizator.PersonalTaskAssignmentMessage })] }) }), (!areDifferentIDs(formData?.fromID, SDK_Globals.tmSession?.SessionDescr?.userID)
317
+ && areDifferentIDs(formData?.toID, SDK_Globals.tmSession?.SessionDescr?.userID))
318
+ && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsxs("div", { style: { width: '100%', display: 'flex', alignItems: 'center', color: "#2559A5" }, children: [_jsx("i", { className: "dx-icon-info", style: { fontSize: 20 } }), "\u00A0", _jsx("span", { children: SDKUI_Localizator.TaskAssignedToUserMessage.replaceParams(users.find(user => user.id === formData?.toID)?.name ?? '-') })] }) }), (formMode === FormModes.Create && taskContext && taskContext.workingGroup && taskContext.workingGroup.id) && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%', display: 'flex', alignItems: 'center', color: "#000", marginTop: 10 }, children: _jsxs(TMTooltip, { content: getOriginLabel(PdGs.WG, taskContext.workingGroup.name), children: [_jsx("span", { children: getPdgsIconMap().get(PdGs.WG) }), "\u00A0", _jsx("span", { children: getOriginLabel(PdGs.WG, taskContext.workingGroup.name) })] }) }) }), (formMode === FormModes.Create && taskContext && taskContext.dossier && taskContext.dossier.id) && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%', display: 'flex', alignItems: 'center', color: "#000", marginTop: 10 }, children: _jsxs(TMTooltip, { content: getOriginLabel(PdGs.CF, taskContext.dossier.name), children: [_jsx("span", { children: getPdgsIconMap().get(PdGs.CF) }), "\u00A0", _jsx("span", { children: getOriginLabel(PdGs.CF, taskContext.dossier.name) })] }) }) }), (formMode === FormModes.Create && taskContext && taskContext.document && taskContext.document.tid && taskContext.document.did && taskContext.document.name) && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%', display: 'flex', alignItems: 'center', color: "#000", marginTop: 10 }, children: _jsxs(TMTooltip, { content: getOriginLabel(PdGs.DT, taskContext.document.name), children: [_jsx("span", { children: getPdgsIconMap().get(PdGs.DT) }), "\u00A0", _jsx("span", { children: getOriginLabel(PdGs.DT, taskContext.document.name) })] }) }) }), (formMode === FormModes.Create && taskContext && taskContext.workItem && taskContext.workItem.tid && taskContext.workItem.did && taskContext.workItem.name) && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%', display: 'flex', alignItems: 'center', color: "#000", marginTop: 10 }, children: _jsxs(TMTooltip, { content: getOriginLabel(PdGs.DT, taskContext.workItem.name), children: [_jsx("span", { children: getPdgsIconMap().get(PdGs.DT) }), "\u00A0", _jsx("span", { children: getOriginLabel(PdGs.DT, taskContext.workItem.name) })] }) }) }), (formMode === FormModes.Update && formData?.pdG && formData?.iD1Name) && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%' }, children: _jsx("div", { style: { display: 'flex', alignItems: 'center', marginTop: 10 }, children: _jsx(TMTooltip, { content: formData?.pdG && formData?.pdG !== PdGs.None ? gotoPDGExtendedLabel(true, formData?.pdG, formData?.iD1Name) : '', children: _jsxs("span", { onClick: () => formData?.pdG && formData?.pdG !== PdGs.None ? gotoPDGExtendedLabelClickCallback() : null, style: {
319
+ display: 'flex',
320
+ alignItems: 'center',
321
+ color: formData?.pdG && formData?.pdG !== PdGs.None ? '#1a0dab' : '#000',
322
+ cursor: formData?.pdG && formData?.pdG !== PdGs.None ? 'pointer' : 'default',
323
+ textDecoration: formData?.pdG && formData?.pdG !== PdGs.None ? 'underline' : 'none',
324
+ fontWeight: 'bold',
325
+ transition: 'color 0.2s ease-in-out'
326
+ }, children: [_jsx("span", { children: getPdgsIconMap().get(formData?.pdG) }), "\u00A0", _jsx("span", { children: getOriginLabel(formData?.pdG, formData?.iD1Name) })] }) }) }) }) }), _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.Name, value: formData?.name ?? '', readOnly: fieldsReadOnly.name, autoFocus: true, maxLength: 100, isModifiedWhen: formData?.name !== formDataOrig?.name, onValueChanged: (e) => { setFormData({ ...formData ?? {}, name: e.target.value }); }, validationItems: validationItems?.filter(o => o.PropertyName === SDKUI_Localizator.Name) }) }) }), _jsx("div", { style: { width: '100%' }, children: _jsx(TMTextArea, { label: SDKUI_Localizator.Description, value: formData?.description ?? '', maxLength: 200, readOnly: fieldsReadOnly.description, isModifiedWhen: formData?.description !== formDataOrig?.description, onValueChanged: (e) => { setFormData({ ...formData ?? {}, description: e.target.value }); }, validationItems: validationItems?.filter(o => o.PropertyName === SDKUI_Localizator.Description), resize: false }) }), _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: (formMode === FormModes.Create || !areDifferentIDs(formDataOrig?.fromID, SDK_Globals.tmSession?.SessionDescr?.userID)) ?
327
+ _jsx("div", { id: "assignedToAnotherUserField", style: { width: isMobile ? '100%' : '50%' }, children: _jsx(TMUserChooser, { dataSource: usersList ?? undefined, allowMultipleSelection: false, label: SDKUI_Localizator.AssignedTo, readOnly: fieldsReadOnly.assignedTO, values: formData?.toID ? [formData?.toID] : [], isModifiedWhen: formData?.toID !== formDataOrig?.toID, validationItems: validationItems?.filter(o => o.PropertyName === SDKUI_Localizator.AssignedTo), onValueChanged: (newValue) => {
328
+ if (newValue === undefined)
329
+ return;
330
+ setFormData({ ...formData ?? {}, toID: newValue[0] });
331
+ } }) })
332
+ : formMode === FormModes.Update && _jsxs(_Fragment, { children: [areDifferentIDs(formDataOrig?.fromID, SDK_Globals.tmSession?.SessionDescr?.userID) && _jsx("div", { style: { width: isMobile ? '100%' : '50%' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.AssignedBy, value: formData?.fromName ?? '', readOnly: true }) }), areDifferentIDs(formDataOrig?.toID, SDK_Globals.tmSession?.SessionDescr?.userID) && _jsx("div", { style: { width: isMobile ? '100%' : '50%' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.AssignedTo, value: formData?.toName ?? '', readOnly: true }) })] }) }), _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsxs(_Fragment, { children: [_jsx("div", { style: { width: isMobile ? '100%' : '50%' }, children: _jsx(TMDropDown, { label: SDKUI_Localizator.Status, value: formData?.state, dataSource: getStatusLocalizatorValues(), isModifiedWhen: formData?.state !== formDataOrig?.state, onValueChanged: onStatusValueChange, readOnly: fieldsReadOnly.status }) }), _jsx("div", { style: { width: isMobile ? '100%' : '50%' }, children: !fieldsReadOnly.priority ? _jsx(TMDropDown, { label: SDKUI_Localizator.Priority, value: formData?.priority, dataSource: getPriorityLocalizatorValues(), isModifiedWhen: formData?.priority !== formDataOrig?.priority, onValueChanged: onPriorityValueChange })
333
+ : _jsx(TMTextBox, { label: SDKUI_Localizator.Priority, value: getPriorityLocalizatorValue(formData?.priority ?? Priorities.Low), readOnly: true }) })] }) }), _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 10 }, children: children }), children: _jsxs(_Fragment, { children: [_jsx("div", { style: { width: isMobile ? '100%' : '50%', marginTop: 10 }, children: !fieldsReadOnly.startDate ? _jsx(TMDateBox, { id: "start-date", resetTimeToZeroOnKeyPress: false, label: SDKUI_Localizator.StartDate, dateDisplayType: DateDisplayTypes.DateTime, value: formData?.startTime, isModifiedWhen: formData?.startTime !== formDataOrig?.startTime, validationItems: validationItems?.filter(o => o.PropertyName === SDKUI_Localizator.ErrorStartEndDate), onContentReady: handleStartTimeContentReady, onValueChange: (value) => { setFormData({ ...formData ?? {}, startTime: value }); }, showClearButton: true }) : _jsx(TMTextBox, { label: SDKUI_Localizator.StartDate, value: formData?.startTime ? formatDate(formData?.startTime) : '', readOnly: true }) }), _jsx("div", { style: { width: isMobile ? '100%' : '50%', marginTop: 10 }, children: !fieldsReadOnly.startDate ? _jsx(TMDateBox, { id: "end-date", resetTimeToZeroOnKeyPress: false, label: SDKUI_Localizator.Expiration, dateDisplayType: DateDisplayTypes.DateTime, value: formData?.endTime, isModifiedWhen: formData?.endTime !== formDataOrig?.endTime, validationItems: validationItems?.filter(o => o.PropertyName === SDKUI_Localizator.ErrorStartEndDate || o.PropertyName === SDKUI_Localizator.ErrorEndRemDate), onContentReady: handleEndTimeContentReady, onValueChange: (value) => { setFormData({ ...formData ?? {}, endTime: value }); }, showClearButton: true, readOnly: fieldsReadOnly.endDate }) : _jsx(TMTextBox, { label: SDKUI_Localizator.Expiration, value: formData?.endTime ? formatDate(formData?.endTime) : '', readOnly: true }) })] }) }), _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 3 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%', marginTop: 10 }, children: _jsx(TMDateBox, { id: "alert-time", resetTimeToZeroOnKeyPress: false, label: SDKUI_Localizator.Reminder, dateDisplayType: DateDisplayTypes.DateTime, value: formData?.remTime ?? undefined, isModifiedWhen: formData?.remTime !== formDataOrig?.remTime, validationItems: validationItems?.filter(o => o.PropertyName === SDKUI_Localizator.ErrorEndRemDate), onValueChange: (value) => { setFormData({ ...formData ?? {}, remTime: value }); }, showClearButton: true, readOnly: fieldsReadOnly.remTime }) }) }), (formData?.state && [Task_States.Completed, Task_States.Waiting, Task_States.Deferred].includes(formData?.state) ||
334
+ (formData?.response ?? "") !== "") && _jsx(TMConditionalWrapper, { condition: !isMobile, wrapper: children => _jsx("div", { style: { display: 'flex', flexDirection: 'row', width: '100%', gap: 3 }, children: children }), children: _jsx("div", { style: { width: isMobile ? '100%' : '50%', marginTop: 10 }, children: _jsxs(ResponseCommentWrapper, { children: [_jsx(ResponseCommentTextArea, { id: "responseId", name: "response", "$isValid": true, value: formData?.response ?? '', onChange: onAnswerChange, "$isModifiedWhen": formData?.response !== formDataOrig?.response, disabled: (formData?.response ?? "") !== "" &&
335
+ (formData?.state && ![Task_States.Completed, Task_States.Waiting, Task_States.Deferred].includes(formData?.state)) }), _jsxs(ResponseCommentLabel, { htmlFor: "responseId", children: [SDKUI_Localizator.Answer, _jsxs(TMTooltip, { content: SDKUI_Localizator.AnswerTooltip, children: [" ", _jsx("i", { className: 'dx-icon-info' }), " "] })] }), _jsx(ResponseCommentCharacterCounter, { children: `${500 - (formData?.response ?? '').length} ${SDKUI_Localizator.CharactersRemaining}` })] }) }) })] }) }) }), (showDcmtForm && formData?.iD1 && formData?.iD2) &&
336
+ _jsx(TMDcmtForm, { titleModal: formData.iD1Name ?? '-', isModal: true, TID: formData.iD1, DID: formData.iD2, allowButtonsRefs: true, taskMoreInfo: formData, onWFOperationCompleted: refreshWorkflowApprove, onTaskCompleted: onTaskCompleted, onClose: () => { setShowDcmtForm(false); }, onOpenS4TViewerRequest: onOpenS4TViewerRequest, s4TViewerDialogComponent: s4TViewerDialogComponent, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers })] }) }) }));
337
+ };
338
+ export default TMTaskForm;
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { TaskDescriptor } from "@topconsultnpm/sdk-ts";
3
+ import { FormModes } from "../../../ts";
4
+ interface TMTasksAgendaProps {
5
+ id: string;
6
+ showId: boolean;
7
+ showSearch: boolean;
8
+ visualizedTasks: Array<TaskDescriptor>;
9
+ fromCell: boolean;
10
+ toCell: boolean;
11
+ currentAgendaDate: Date;
12
+ setCurrentAgendaDate: React.Dispatch<React.SetStateAction<Date>>;
13
+ openTaskForm: (formMode: FormModes, task?: TaskDescriptor) => void;
14
+ handleFocusedRowChange: (row: TaskDescriptor | undefined) => void;
15
+ }
16
+ declare const TMTasksAgenda: React.MemoExoticComponent<(props: TMTasksAgendaProps) => import("react/jsx-runtime").JSX.Element>;
17
+ export default TMTasksAgenda;
@@ -0,0 +1,107 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useCallback, useEffect, useState } from "react";
3
+ import ArrayStore from "devextreme/data/array_store";
4
+ import Scheduler from "devextreme-react/cjs/scheduler";
5
+ import { calculateNumberOfDays, highlightTaskText, priorityLegend, renderTaskIcons } from "./TMTasksUtilsView";
6
+ import { Priorities, Task_States } from "@topconsultnpm/sdk-ts";
7
+ import { checkIfNew, convertToSchedulerAppointments, findTasksBySearch, formatDate, getPriorityColor, getStatusLocalizatorValue } from "./TMTasksUtils";
8
+ import ScrollView from "devextreme-react/cjs/scroll-view";
9
+ import LoadIndicator from "devextreme-react/cjs/load-indicator";
10
+ import { FormModes } from "../../../ts";
11
+ import { SDKUI_Localizator } from "../../../helper";
12
+ import TMCustomSearchBar from "../../../helper/TMCustomSearchBar";
13
+ import TMTooltip from "../../base/TMTooltip";
14
+ const TMTasksAgenda = React.memo((props) => {
15
+ const views = ['agenda'];
16
+ const { id, showId, showSearch, visualizedTasks, fromCell, toCell, currentAgendaDate, setCurrentAgendaDate, openTaskForm, handleFocusedRowChange } = props;
17
+ const [schedulerData, setSchedulerData] = useState([]);
18
+ const [loading, setLoading] = useState(false);
19
+ const [searchText, setSearchText] = useState('');
20
+ useEffect(() => {
21
+ setSchedulerData(convertToSchedulerAppointments(visualizedTasks));
22
+ }, [visualizedTasks]);
23
+ useEffect(() => {
24
+ let timeoutId;
25
+ if (searchText.length > 0) {
26
+ setLoading(true);
27
+ timeoutId = setTimeout(() => {
28
+ const filteredTasks = findTasksBySearch(visualizedTasks, searchText);
29
+ setSchedulerData(convertToSchedulerAppointments(filteredTasks));
30
+ setLoading(false);
31
+ }, 300);
32
+ }
33
+ else {
34
+ setSchedulerData(convertToSchedulerAppointments(visualizedTasks));
35
+ setLoading(false);
36
+ }
37
+ return () => {
38
+ clearTimeout(timeoutId);
39
+ };
40
+ }, [searchText]);
41
+ const appointmentRender = useCallback((params) => {
42
+ const currentTask = visualizedTasks.find(task => task.id !== undefined && task.id === params.appointmentData.id);
43
+ if (currentTask === undefined || currentTask.id === undefined)
44
+ return;
45
+ const startTime = currentTask.startTime;
46
+ const endTime = currentTask.endTime;
47
+ const remTime = currentTask.remTime;
48
+ const stateLabel = currentTask.state ?? Task_States.None;
49
+ const stateTooltipLabel = getStatusLocalizatorValue(stateLabel);
50
+ const pdg = currentTask.pdG ?? undefined;
51
+ const ID1Name = currentTask.iD1Name ?? '';
52
+ const isNew = checkIfNew(currentTask.fromID, currentTask.isNew);
53
+ const numberOfDays = calculateNumberOfDays(startTime, endTime);
54
+ const priority = currentTask.priority ?? Priorities.None;
55
+ let bgColor = 'transparent';
56
+ if (priority)
57
+ bgColor = getPriorityColor(priority);
58
+ return _jsx("div", { style: { width: "100%", height: "100%", display: 'flex', flexDirection: 'column', justifyContent: 'flex-start', alignItems: 'flex-end', backgroundColor: bgColor }, children: _jsx(ScrollView, { width: "100%", height: "100%", direction: "both", useNative: true, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', width: '100%', fontWeight: isNew ? 'bold' : 'normal' }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [showId && _jsxs("span", { children: [highlightTaskText(currentTask.id.toString(), searchText, currentTask.id), " - "] }), renderTaskIcons({ stateLabel, stateTooltipLabel, pdg, ID1Name, endTime, remTime, isNew, numberOfDays }), "\u00A0", _jsx("span", { style: { fontWeight: "bold" }, children: highlightTaskText(currentTask.name ?? '', searchText, currentTask.id) })] }), _jsxs("div", { children: [startTime !== undefined && (_jsxs("span", { children: [SDKUI_Localizator.StartDate, ": ", formatDate(startTime), " - \u00A0"] })), endTime !== undefined && (_jsxs("span", { children: [SDKUI_Localizator.Expiration, ": ", formatDate(endTime)] }))] })] }), fromCell && _jsxs("div", { style: { display: 'flex', alignItems: 'center', alignSelf: 'flex-end' }, children: [_jsxs("span", { children: [SDKUI_Localizator.AssignedBy, ":"] }), "\u00A0", _jsxs("div", { children: [highlightTaskText(currentTask.fromName ?? '', searchText, currentTask.id), (showId && currentTask.fromID) && _jsxs("span", { children: ["(", currentTask.fromID, ")"] })] })] }), toCell && _jsxs("div", { style: { display: 'flex', alignItems: 'center', alignSelf: 'flex-end' }, children: [_jsxs("span", { children: [SDKUI_Localizator.AssignedTo, ":"] }), "\u00A0", _jsxs("div", { children: [highlightTaskText(currentTask.toName ?? '', searchText, currentTask.id), (showId && currentTask.toID) && _jsxs("span", { children: ["(", currentTask.toID, ")"] })] })] })] }) }) });
59
+ }, [visualizedTasks, searchText]);
60
+ // handle appointment click handler
61
+ const handleAppointmentClick = useCallback((e) => {
62
+ if (e === undefined || e.event === undefined || e.appointmentData.id === undefined)
63
+ return;
64
+ e.event.preventDefault();
65
+ e.cancel = true;
66
+ const { id } = e.appointmentData;
67
+ // Update the state with the new set of selected appointments
68
+ const task = visualizedTasks.find(task => task.id === id);
69
+ if (task) {
70
+ handleFocusedRowChange(task);
71
+ }
72
+ }, [visualizedTasks]);
73
+ const onAppointmentContextMenu = useCallback((e) => {
74
+ if (e === undefined || e.event === undefined || e.appointmentData.id === undefined)
75
+ return;
76
+ e.event.preventDefault();
77
+ const { id } = e.appointmentData;
78
+ // Update the state with the new set of selected appointments
79
+ const task = visualizedTasks.find(task => task.id === id);
80
+ if (task) {
81
+ handleFocusedRowChange(task);
82
+ }
83
+ }, []);
84
+ const onCurrentDateChange = useCallback((value) => {
85
+ // Exit early if it's not a valid Date
86
+ if (!(value instanceof Date) || isNaN(value.getTime())) {
87
+ return;
88
+ }
89
+ setCurrentAgendaDate(value);
90
+ setSearchText('');
91
+ }, []);
92
+ // Double-click appointment handler
93
+ const handleAppointmentDblClick = useCallback((e) => {
94
+ if (e === undefined || e.event === undefined || e.appointmentData.id === undefined)
95
+ return;
96
+ e.event.preventDefault();
97
+ e.cancel = true;
98
+ const task = visualizedTasks.find(task => task.id === e.appointmentData.id);
99
+ if (task) {
100
+ handleFocusedRowChange(task);
101
+ openTaskForm(FormModes.Update, task);
102
+ }
103
+ }, [visualizedTasks]);
104
+ return _jsxs("div", { style: { height: "100%", width: "100%" }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', height: "48px" }, children: [_jsx("div", { style: { width: showSearch ? "160px" : "0", marginLeft: '10px' }, children: showSearch && (_jsx(TMCustomSearchBar, { initialValue: searchText, onSearchChange: (value) => setSearchText(value) })) }), _jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: "default" }, children: _jsxs(TMTooltip, { content: priorityLegend(), children: [" ", SDKUI_Localizator.PriorityLegend] }) })] }), _jsx("div", { style: { height: "calc(100% - 48px)", width: "100%" }, children: loading ? _jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", width: "100%" }, children: _jsx(LoadIndicator, {}) })
105
+ : _jsx("div", { id: `tasks-agenda-wrapper-${id}`, style: { width: "100%", height: "100%" }, onContextMenu: () => { handleFocusedRowChange(undefined); }, onClick: () => { handleFocusedRowChange(undefined); }, children: _jsx(Scheduler, { id: "tasks-agenda", defaultCurrentView: "agenda", dataSource: new ArrayStore({ key: `tasks-agenda-data`, data: schedulerData }), width: "100%", height: "100%", editing: false, views: views, currentDate: currentAgendaDate, appointmentRender: appointmentRender, onAppointmentDblClick: handleAppointmentDblClick, onCurrentDateChange: onCurrentDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onAppointmentClick: handleAppointmentClick }) }) })] });
106
+ });
107
+ export default TMTasksAgenda;