@topconsultnpm/sdkui-react 6.19.0-dev1.9 → 6.19.0-dev2.2

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 (116) 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/TMPopUp.js +5 -18
  9. package/lib/components/base/TMTreeView.js +3 -2
  10. package/lib/components/editors/TMHtmlEditor.d.ts +5 -0
  11. package/lib/components/editors/TMHtmlEditor.js +72 -12
  12. package/lib/components/editors/TMMetadataValues.js +90 -40
  13. package/lib/components/features/archive/TMArchive.d.ts +10 -0
  14. package/lib/components/features/archive/TMArchive.js +56 -25
  15. package/lib/components/features/blog/TMBlogCommentForm.d.ts +4 -4
  16. package/lib/components/features/blog/TMBlogCommentForm.js +76 -51
  17. package/lib/components/features/documents/TMDcmtBlog.d.ts +15 -0
  18. package/lib/components/features/documents/TMDcmtBlog.js +21 -33
  19. package/lib/components/features/documents/TMDcmtForm.d.ts +17 -3
  20. package/lib/components/features/documents/TMDcmtForm.js +205 -46
  21. package/lib/components/features/documents/TMDcmtTasks.d.ts +13 -0
  22. package/lib/components/features/documents/TMDcmtTasks.js +24 -0
  23. package/lib/components/features/documents/TMDragDropOverlay.js +2 -1
  24. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +8 -1
  25. package/lib/components/features/documents/TMMasterDetailDcmts.js +6 -6
  26. package/lib/components/features/documents/TMRelationViewer.d.ts +53 -3
  27. package/lib/components/features/documents/TMRelationViewer.js +232 -85
  28. package/lib/components/features/search/TMSearch.d.ts +10 -1
  29. package/lib/components/features/search/TMSearch.js +14 -5
  30. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
  31. package/lib/components/features/search/TMSearchQueryPanel.js +36 -7
  32. package/lib/components/features/search/TMSearchResult.d.ts +10 -1
  33. package/lib/components/features/search/TMSearchResult.js +140 -422
  34. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +2 -2
  35. package/lib/components/features/search/TMSearchResultsMenuItems.js +33 -8
  36. package/lib/components/features/tasks/TMTaskForm.d.ts +38 -0
  37. package/lib/components/features/tasks/TMTaskForm.js +386 -0
  38. package/lib/components/features/tasks/TMTasksAgenda.d.ts +17 -0
  39. package/lib/components/features/tasks/TMTasksAgenda.js +107 -0
  40. package/lib/components/features/tasks/TMTasksCalendar.d.ts +21 -0
  41. package/lib/components/features/tasks/TMTasksCalendar.js +240 -0
  42. package/lib/components/features/tasks/TMTasksHeader.d.ts +14 -0
  43. package/lib/components/features/tasks/TMTasksHeader.js +37 -0
  44. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +20 -0
  45. package/lib/components/features/tasks/TMTasksPanelContent.js +65 -0
  46. package/lib/components/features/tasks/TMTasksUtils.d.ts +132 -0
  47. package/lib/components/features/tasks/TMTasksUtils.js +634 -0
  48. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +39 -0
  49. package/lib/components/features/tasks/TMTasksUtilsView.js +118 -0
  50. package/lib/components/features/tasks/TMTasksView.d.ts +40 -0
  51. package/lib/components/features/tasks/TMTasksView.js +560 -0
  52. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +3 -1
  53. package/lib/components/features/workflow/TMWorkflowPopup.js +19 -6
  54. package/lib/components/features/workflow/diagram/RecipientList.js +4 -3
  55. package/lib/components/forms/Login/Chooser.js +1 -1
  56. package/lib/components/forms/TMChooserForm.d.ts +1 -1
  57. package/lib/components/forms/TMChooserForm.js +2 -2
  58. package/lib/components/grids/TMBlogAttachments.d.ts +42 -0
  59. package/lib/components/grids/TMBlogAttachments.js +43 -0
  60. package/lib/components/grids/TMBlogHeader.d.ts +31 -0
  61. package/lib/components/grids/TMBlogHeader.js +41 -0
  62. package/lib/components/grids/{TMBlogs.d.ts → TMBlogsPost.d.ts} +42 -58
  63. package/lib/components/grids/TMBlogsPost.js +628 -0
  64. package/lib/components/grids/{TMBlogsUtils.d.ts → TMBlogsPostUtils.d.ts} +61 -47
  65. package/lib/components/grids/{TMBlogsUtils.js → TMBlogsPostUtils.js} +146 -124
  66. package/lib/components/index.d.ts +14 -1
  67. package/lib/components/index.js +15 -1
  68. package/lib/components/layout/panelManager/TMPanelManagerContext.js +7 -0
  69. package/lib/components/settings/SettingsAppearance.js +8 -0
  70. package/lib/components/viewers/TMTidViewer.js +20 -2
  71. package/lib/css/tm-sdkui.css +1 -1
  72. package/lib/helper/SDKUI_Globals.d.ts +4 -1
  73. package/lib/helper/SDKUI_Globals.js +10 -1
  74. package/lib/helper/SDKUI_Localizator.d.ts +62 -4
  75. package/lib/helper/SDKUI_Localizator.js +618 -25
  76. package/lib/helper/TMCustomSearchBar.d.ts +8 -0
  77. package/lib/helper/TMCustomSearchBar.js +54 -0
  78. package/lib/helper/TMIcons.d.ts +2 -0
  79. package/lib/helper/TMIcons.js +6 -0
  80. package/lib/helper/TMImageLibrary.d.ts +3 -2
  81. package/lib/helper/TMImageLibrary.js +230 -230
  82. package/lib/helper/TMToppyMessage.d.ts +7 -0
  83. package/lib/helper/TMToppyMessage.js +42 -0
  84. package/lib/helper/TMUtils.d.ts +10 -1
  85. package/lib/helper/TMUtils.js +42 -1
  86. package/lib/helper/dcmtsHelper.d.ts +2 -0
  87. package/lib/helper/dcmtsHelper.js +18 -0
  88. package/lib/helper/helpers.js +1 -0
  89. package/lib/helper/index.d.ts +1 -0
  90. package/lib/helper/index.js +1 -0
  91. package/lib/hooks/useRelatedDocuments.d.ts +72 -0
  92. package/lib/hooks/useRelatedDocuments.js +655 -0
  93. package/lib/index.d.ts +1 -0
  94. package/lib/index.js +1 -0
  95. package/lib/ts/types.d.ts +14 -0
  96. package/lib/ts/types.js +15 -0
  97. package/lib/utils/theme.d.ts +1 -0
  98. package/lib/utils/theme.js +1 -0
  99. package/package.json +7 -7
  100. package/lib/components/grids/TMBlogs.js +0 -721
  101. package/lib/stories/TMButton.stories.d.ts +0 -4
  102. package/lib/stories/TMButton.stories.js +0 -29
  103. package/lib/stories/TMDataGrid.stories.d.ts +0 -9
  104. package/lib/stories/TMDataGrid.stories.js +0 -310
  105. package/lib/stories/TMHtmlContentDisplay.stories.d.ts +0 -6
  106. package/lib/stories/TMHtmlContentDisplay.stories.js +0 -45
  107. package/lib/stories/TMHtmlEditor.stories.d.ts +0 -6
  108. package/lib/stories/TMHtmlEditor.stories.js +0 -49
  109. package/lib/stories/TMIcons.stories.d.ts +0 -4
  110. package/lib/stories/TMIcons.stories.js +0 -13
  111. package/lib/stories/TMSDKUI_Localizator.stories.d.ts +0 -4
  112. package/lib/stories/TMSDKUI_Localizator.stories.js +0 -123
  113. package/lib/stories/TMStoriesUtils.d.ts +0 -1
  114. package/lib/stories/TMStoriesUtils.js +0 -10
  115. package/lib/stories/TMUserAvatar.stories.d.ts +0 -6
  116. package/lib/stories/TMUserAvatar.stories.js +0 -20
@@ -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;
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { TaskDescriptor } from "@topconsultnpm/sdk-ts";
3
+ import { FormModes } from '../../../ts';
4
+ interface TMTasksCalendarProps {
5
+ id: string;
6
+ visualizedTasks: Array<TaskDescriptor>;
7
+ showId: boolean;
8
+ showSearch: boolean;
9
+ fromCell: boolean;
10
+ toCell: boolean;
11
+ openTaskForm: (formMode: FormModes, task?: TaskDescriptor) => void;
12
+ onDeleteCallback: (rowIds: Array<number>) => void;
13
+ currentCalendarDate: Date;
14
+ setCurrentCalendarDate: React.Dispatch<React.SetStateAction<Date>>;
15
+ setCalendarStartDate: React.Dispatch<React.SetStateAction<Date | undefined>>;
16
+ setCalendarEndDate: React.Dispatch<React.SetStateAction<Date | undefined>>;
17
+ focusedRowKey: number | undefined;
18
+ handleFocusedRowChange: (row: TaskDescriptor | undefined) => void;
19
+ }
20
+ declare const TMTasksCalendar: (props: TMTasksCalendarProps) => import("react/jsx-runtime").JSX.Element;
21
+ export default TMTasksCalendar;
@@ -0,0 +1,240 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import ArrayStore from 'devextreme/data/array_store';
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { Priorities, Task_States } from "@topconsultnpm/sdk-ts";
5
+ import Scheduler, { Resource } from 'devextreme-react/scheduler';
6
+ import { calculateNumberOfDays, highlightTaskText, priorityLegend, renderTaskIcons, taskStateIconMap, TMActionCalendar } from './TMTasksUtilsView';
7
+ import { checkIfNew, convertToSchedulerAppointments, findTasksBySearch, formatDate, getPriorityColor, getPriorityLocalizatorValue, getStatusLocalizatorValue, prioritiesResourceData } from './TMTasksUtils';
8
+ import LoadIndicator from 'devextreme-react/cjs/load-indicator';
9
+ import { FormModes } from '../../../ts';
10
+ import { SDKUI_Localizator } from '../../../helper';
11
+ import TMTooltip from '../../base/TMTooltip';
12
+ import TMCustomSearchBar from '../../../helper/TMCustomSearchBar';
13
+ const views = ['month'];
14
+ let clickTimeout = null; // Timeout reference
15
+ let clickCount = 0; // Click counter
16
+ let lastClickedCell = null;
17
+ const TMTasksCalendar = (props) => {
18
+ const { id, visualizedTasks, showId, showSearch, fromCell, toCell, openTaskForm, onDeleteCallback, currentCalendarDate, setCurrentCalendarDate, focusedRowKey, handleFocusedRowChange, setCalendarStartDate, setCalendarEndDate } = props;
19
+ const [isMobile, setIsMobile] = useState(false);
20
+ const mobileBreakpoint = 768;
21
+ const [schedulerData, setSchedulerData] = useState([]);
22
+ const [isRange, setIsRange] = useState(false);
23
+ const [loading, setLoading] = useState(false);
24
+ const [searchText, setSearchText] = useState('');
25
+ const containerRef = useRef(null);
26
+ const schedulerRef = useRef(null);
27
+ useEffect(() => {
28
+ const updateDimensions = (entries) => {
29
+ for (let entry of entries) {
30
+ const { width } = entry.contentRect;
31
+ setIsMobile(width <= mobileBreakpoint);
32
+ }
33
+ if (schedulerRef.current && schedulerRef.current.instance) {
34
+ schedulerRef.current.instance().repaint();
35
+ }
36
+ };
37
+ const resizeObserver = new ResizeObserver(updateDimensions);
38
+ if (containerRef.current) {
39
+ resizeObserver.observe(containerRef.current);
40
+ }
41
+ return () => {
42
+ if (containerRef.current) {
43
+ resizeObserver.unobserve(containerRef.current);
44
+ }
45
+ };
46
+ }, [containerRef]);
47
+ useEffect(() => {
48
+ setSchedulerData(convertToSchedulerAppointments(visualizedTasks));
49
+ }, [visualizedTasks]);
50
+ useEffect(() => {
51
+ let timeoutId;
52
+ if (searchText.length > 0) {
53
+ setLoading(true);
54
+ timeoutId = setTimeout(() => {
55
+ const filteredTasks = findTasksBySearch(visualizedTasks, searchText);
56
+ setSchedulerData(convertToSchedulerAppointments(filteredTasks));
57
+ setLoading(false);
58
+ }, 300);
59
+ }
60
+ else {
61
+ setSchedulerData(convertToSchedulerAppointments(visualizedTasks));
62
+ setLoading(false);
63
+ }
64
+ return () => {
65
+ clearTimeout(timeoutId);
66
+ };
67
+ }, [searchText]);
68
+ // Runs the handleContentReady function whenever the currentCalendarDate changes, ensuring the scheduler scrolls to the correct date
69
+ useEffect(() => {
70
+ handleContentReady();
71
+ }, [currentCalendarDate]);
72
+ // Scrolls the scheduler to the current date or the start of the view based on the current calendar date
73
+ const handleContentReady = () => {
74
+ if (schedulerRef.current === null)
75
+ return;
76
+ const schedulerInstance = schedulerRef.current.instance();
77
+ const startOfView = schedulerInstance.getStartViewDate();
78
+ const endOfView = schedulerInstance.getEndViewDate();
79
+ if (currentCalendarDate >= startOfView && currentCalendarDate <= endOfView) {
80
+ schedulerInstance.scrollTo(currentCalendarDate);
81
+ }
82
+ else {
83
+ schedulerInstance.scrollTo(startOfView);
84
+ }
85
+ };
86
+ const handleAppointmentClick = (e) => {
87
+ // Capture the appointment ID
88
+ const appointmentId = e.appointmentData.id;
89
+ const task = visualizedTasks.find(task => task.id === appointmentId);
90
+ if (task)
91
+ handleFocusedRowChange(task);
92
+ };
93
+ // Double-click appointment handler
94
+ const handleAppointmentDblClick = (e) => {
95
+ if (e === undefined || e.event === undefined || e.appointmentData.id === undefined)
96
+ return;
97
+ e.event.preventDefault();
98
+ e.cancel = true;
99
+ const task = visualizedTasks.find(task => task.id === e.appointmentData.id);
100
+ if (task) {
101
+ handleFocusedRowChange(task);
102
+ openTaskForm(FormModes.Update, task);
103
+ }
104
+ };
105
+ const onAppointmentContextMenu = (e) => {
106
+ if (e === undefined || e.event === undefined || e.appointmentData.id === undefined)
107
+ return;
108
+ e.event.preventDefault();
109
+ const { id } = e.appointmentData;
110
+ // Update the state with the new set of selected appointments
111
+ const task = visualizedTasks.find(task => task.id === id);
112
+ if (task)
113
+ handleFocusedRowChange(task);
114
+ setCalendarStartDate(undefined);
115
+ setCalendarEndDate(undefined);
116
+ };
117
+ const onCellContextMenu = (e) => {
118
+ if (e === undefined || e.event === undefined)
119
+ return;
120
+ e.event.preventDefault();
121
+ handleFocusedRowChange(undefined);
122
+ if (!isRange) {
123
+ setCalendarStartDate(e.cellData.startDate);
124
+ const endDateWithTime = new Date(e.cellData.endDate);
125
+ endDateWithTime.setDate(endDateWithTime.getDate() - 1);
126
+ endDateWithTime.setHours(23, 59, 0, 0);
127
+ setCalendarEndDate(endDateWithTime);
128
+ }
129
+ };
130
+ const appointmentTooltipComponent = (params) => {
131
+ if (params === undefined || params.data === undefined || params.data.appointmentData === undefined)
132
+ return;
133
+ const { appointmentData } = params.data;
134
+ const currentTask = visualizedTasks.find(task => task.id !== undefined && task.id === appointmentData.id);
135
+ if (currentTask === undefined || currentTask.id === undefined)
136
+ return;
137
+ const priority = getPriorityLocalizatorValue(currentTask.priority ?? Priorities.None);
138
+ const startTime = currentTask.startTime;
139
+ const endTime = currentTask.endTime;
140
+ const remTime = currentTask.remTime;
141
+ const stateLabel = currentTask.state ?? Task_States.None;
142
+ const stateTooltipLabel = getStatusLocalizatorValue(stateLabel);
143
+ const pdg = currentTask.pdG || undefined;
144
+ const ID1Name = currentTask.iD1Name || '';
145
+ const isNew = checkIfNew(currentTask.fromID, currentTask.isNew);
146
+ const numberOfDays = calculateNumberOfDays(startTime, endTime);
147
+ return _jsxs("div", { className: "dx-tooltip-appointment-item", onClick: (e) => { e.preventDefault(); e.stopPropagation(); }, style: { backgroundColor: getPriorityColor(currentTask.priority ?? Priorities.None) }, children: [_jsxs("div", { className: "dx-tooltip-appointment-item-content", style: { width: '70%', cursor: 'auto' }, children: [_jsx("div", { style: { display: "flex" }, children: renderTaskIcons({ stateLabel, stateTooltipLabel, pdg, ID1Name, endTime, remTime, isNew, numberOfDays }) }), _jsxs("div", { className: "dx-tooltip-appointment-item-content-subject", children: [" ", showId && _jsxs("span", { children: [highlightTaskText(appointmentData.id.toString(), searchText, appointmentData.id), " - "] }), " ", highlightTaskText(appointmentData.text ?? '', searchText, currentTask.id)] }), _jsx("div", { className: "dx-tooltip-appointment-item-content-date", children: startTime !== undefined && (_jsxs("span", { children: [SDKUI_Localizator.StartDate, ": ", formatDate(startTime)] })) }), _jsx("div", { className: "dx-tooltip-appointment-item-content-date", children: endTime !== undefined && (_jsxs("span", { children: [SDKUI_Localizator.Expiration, ": ", formatDate(endTime)] })) }), _jsxs("div", { className: "dx-tooltip-appointment-item-content-subject", children: [SDKUI_Localizator.Priority, ": ", highlightTaskText(priority, searchText, currentTask.id)] }), _jsxs("div", { className: "dx-tooltip-appointment-item-content-subject", children: [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, ")"] })] })] })] })] }), _jsx(TMActionCalendar, { currentTask: currentTask, openTaskForm: openTaskForm, onDeleteCallback: onDeleteCallback })] });
148
+ };
149
+ const onCurrentCalendarDateChange = (value) => {
150
+ // Exit early if it's not a valid Date
151
+ if (!(value instanceof Date) || isNaN(value.getTime())) {
152
+ return;
153
+ }
154
+ setCurrentCalendarDate(value);
155
+ setSearchText('');
156
+ };
157
+ // Custom appointment component to render each appointment
158
+ const appointmentComponent = (params) => {
159
+ if (!params || !params.data)
160
+ return null;
161
+ const { appointmentData } = params.data;
162
+ // Define inline styles for the selected appointment
163
+ const isSelected = focusedRowKey === appointmentData.id;
164
+ let stateLabel = undefined;
165
+ let stateTooltipLabel = undefined;
166
+ const currentTask = visualizedTasks.find(task => task.id !== undefined && task.id === appointmentData.id);
167
+ stateLabel = currentTask?.state ?? Task_States.None;
168
+ stateTooltipLabel = getStatusLocalizatorValue(stateLabel);
169
+ const inlineStyles = isSelected ? { backgroundColor: '#2559A5', boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)', fontWeight: 'bold', color: 'white', cursor: 'pointer', transition: 'all 0.3s ease-in-out', } : {};
170
+ const centerStyles = { display: 'flex', justifyContent: 'center', alignItems: 'center', textAlign: 'center', height: '100%' };
171
+ return (_jsxs("div", { id: "appointment-" + appointmentData.id.toString(), style: { ...inlineStyles, ...centerStyles }, children: [(stateLabel && stateTooltipLabel) && _jsxs(TMTooltip, { content: stateTooltipLabel, children: [" ", _jsxs("div", { children: [taskStateIconMap(15).get(stateLabel), "\u00A0"] })] }), showId && _jsxs("span", { children: [highlightTaskText(appointmentData.id.toString(), searchText, appointmentData.id), "\u00A0-\u00A0"] }), appointmentData.text] }));
172
+ };
173
+ const handleCellClick = (e) => {
174
+ handleFocusedRowChange(undefined);
175
+ clickCount += 1;
176
+ if (clickTimeout)
177
+ clearTimeout(clickTimeout);
178
+ clickTimeout = setTimeout(() => {
179
+ if (clickCount === 1) {
180
+ // Single click logic
181
+ setCalendarStartDate(e.cellData.startDate);
182
+ const endDateWithTime = new Date(e.cellData.endDate);
183
+ endDateWithTime.setDate(endDateWithTime.getDate() - 1);
184
+ endDateWithTime.setHours(23, 59, 59, 0);
185
+ setCalendarEndDate(endDateWithTime);
186
+ }
187
+ else if (clickCount === 2) {
188
+ // Double click logic (only on the same cell)
189
+ if (lastClickedCell && lastClickedCell.startDate === e.cellData.startDate && lastClickedCell.endDate === e.cellData.endDate) {
190
+ // Double click on the same cell
191
+ setCalendarStartDate(e.cellData.startDate);
192
+ const endDateWithTime = new Date(e.cellData.endDate);
193
+ endDateWithTime.setDate(endDateWithTime.getDate() - 1);
194
+ endDateWithTime.setHours(23, 59, 59, 0);
195
+ setCalendarEndDate(endDateWithTime);
196
+ openTaskForm(FormModes.Create, undefined); // Open the task form
197
+ }
198
+ }
199
+ // Reset click count
200
+ clickCount = 0;
201
+ }, 200); // Delay for double-click detection
202
+ // Save the current cell as the last clicked cell
203
+ lastClickedCell = { startDate: e.cellData.startDate, endDate: e.cellData.endDate };
204
+ };
205
+ const handleAppointmentFormOpening = (e) => {
206
+ // Cancel the default form opening
207
+ e.cancel = true;
208
+ // If no appointment data, return
209
+ if (!e.appointmentData)
210
+ return;
211
+ // Show the tooltip manually
212
+ e.component.showAppointmentTooltip(e.appointmentData, "#appointment-" + e.appointmentData.id.toString());
213
+ };
214
+ const onOptionChanged = ({ name, value }) => {
215
+ if (typeof name === 'string' && Array.isArray(value)) {
216
+ if (name === "selectedCellData") {
217
+ const startDate = value[0]?.startDate;
218
+ const endDate = value[value.length - 1]?.endDate;
219
+ if (startDate && endDate) {
220
+ setCalendarStartDate(startDate);
221
+ // Set the endDate to 23:59:59 and subtract one day
222
+ const endDateWithTime = new Date(endDate);
223
+ endDateWithTime.setDate(endDateWithTime.getDate() - 1);
224
+ endDateWithTime.setHours(23, 59, 59, 0);
225
+ setCalendarEndDate(endDateWithTime);
226
+ setIsRange(true);
227
+ }
228
+ }
229
+ }
230
+ };
231
+ const onWrapperContextMenu = useCallback(() => {
232
+ handleFocusedRowChange(undefined);
233
+ }, []);
234
+ const onWrapperClick = useCallback(() => {
235
+ handleFocusedRowChange(undefined);
236
+ }, []);
237
+ return (_jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', height: "48px", padding: 5 }, 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: _jsx(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, {}) })
238
+ : _jsx("div", { id: `tasks-calendar-wrapper-${id}`, style: { width: "100%", height: "100%" }, onContextMenu: onWrapperContextMenu, onClick: onWrapperClick, children: _jsx(Scheduler, { ref: schedulerRef, id: "tasks-calendar", dataSource: new ArrayStore({ key: 'tasks-calendar-data', data: schedulerData }), views: views, defaultCurrentView: "month", adaptivityEnabled: isMobile, editing: false, width: "100%", height: "100%", currentDate: currentCalendarDate, appointmentComponent: appointmentComponent, onAppointmentFormOpening: handleAppointmentFormOpening, appointmentTooltipComponent: appointmentTooltipComponent, onAppointmentDblClick: handleAppointmentDblClick, onCurrentDateChange: onCurrentCalendarDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onCellContextMenu: onCellContextMenu, onCellClick: handleCellClick, onAppointmentClick: handleAppointmentClick, onContentReady: handleContentReady, onOptionChanged: onOptionChanged, children: _jsx(Resource, { dataSource: prioritiesResourceData, fieldExpr: "priority", label: "Priority" }) }) }) })] }));
239
+ };
240
+ export default TMTasksCalendar;
@@ -0,0 +1,14 @@
1
+ import { TaskDescriptor } from '@topconsultnpm/sdk-ts';
2
+ import { TaskViewType } from './TMTasksUtils';
3
+ import React from 'react';
4
+ interface TMTasksHeaderProps {
5
+ activeComponent: TaskViewType;
6
+ updateActiveComponent: (newComponent: TaskViewType) => void;
7
+ allTasks: Array<TaskDescriptor>;
8
+ appliedGlobalFilters: Array<number>;
9
+ setAppliedGlobalFilters: React.Dispatch<React.SetStateAction<Array<number>>>;
10
+ color?: string;
11
+ height?: string;
12
+ }
13
+ declare const TMTasksHeader: (props: TMTasksHeaderProps) => import("react/jsx-runtime").JSX.Element;
14
+ export default TMTasksHeader;
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from 'styled-components';
3
+ import { treeFilterDataSource } from './TMTasksUtilsView';
4
+ import { FilterCategoryId, TaskView } from './TMTasksUtils';
5
+ import { useEffect, useRef, useState } from 'react';
6
+ import ScrollView from 'devextreme-react/cjs/scroll-view';
7
+ import TMTooltip from '../../base/TMTooltip';
8
+ import { SDKUI_Localizator } from '../../../helper';
9
+ import TMDropDown from '../../editors/TMDropDown';
10
+ import TMTreeDropDown from '../../editors/TMTreeDropDown';
11
+ const StyledListHeader = styled.div ` border-bottom: 1px solid #e6e6e6; width: 100%; height: ${props => props.$height}; min-height: 55px; display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding: 10px 20px; `;
12
+ const StyledViewChangerContainer = styled.div ` width: 100%; height: 100%; display: flex; flex-direction: row; gap: 8px; align-items: left; `;
13
+ const TMTasksHeader = (props) => {
14
+ const { activeComponent, color, height, appliedGlobalFilters, setAppliedGlobalFilters, updateActiveComponent, allTasks } = props;
15
+ const containerRef = useRef(null);
16
+ const [treeDataSource, setTreeDataSource] = useState([]);
17
+ useEffect(() => {
18
+ setTreeDataSource(treeFilterDataSource(allTasks));
19
+ }, [allTasks]);
20
+ // Function to disable right-click
21
+ const handleContextMenu = (e) => {
22
+ e.preventDefault();
23
+ };
24
+ const onSelectListOrCalendarCallback = (e) => {
25
+ const { value } = e.target;
26
+ updateActiveComponent(value);
27
+ };
28
+ const isValidKey = (key) => {
29
+ return key !== FilterCategoryId.AllStates && key !== FilterCategoryId.AllPriorities;
30
+ };
31
+ return (_jsx(StyledListHeader, { ref: containerRef, "$color": color ?? 'black', "$height": height ?? '100%', onContextMenu: handleContextMenu, children: _jsx(ScrollView, { width: "100%", height: "100%", direction: "horizontal", useNative: true, children: _jsxs(StyledViewChangerContainer, { children: [_jsx(TMTooltip, { content: SDKUI_Localizator.SelectViewMode, showEvent: "mouseenter", hideEvent: "mouseleave", position: "top", children: _jsx(TMDropDown, { elementStyle: { minWidth: "120px", width: "120px", height: "29px" }, dataSource: [
32
+ { value: TaskView.AGENDA_TASK, display: "Agenda", icon: 'clock' },
33
+ { value: TaskView.CALENDAR_TASK, display: SDKUI_Localizator.Calendar, icon: 'event' },
34
+ { value: TaskView.LIST_TASK, display: SDKUI_Localizator.List, icon: 'fields' },
35
+ ], value: activeComponent, onValueChanged: onSelectListOrCalendarCallback }) }), _jsx(TMTreeDropDown, { dataSource: treeDataSource, values: appliedGlobalFilters, setValues: setAppliedGlobalFilters, displayExpr: false, isValidKey: isValidKey, elementStyle: { minWidth: "250px", height: "29px" } })] }) }) }));
36
+ };
37
+ export default TMTasksHeader;
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import { HomeBlogPost, TaskDescriptor, UserDescriptor } from "@topconsultnpm/sdk-ts";
3
+ import { DcmtInfo, FormModes, TaskContext } from "../../../ts";
4
+ interface TMTasksPanelContentProps {
5
+ id: string;
6
+ allTasks: Array<TaskDescriptor>;
7
+ getAllTasks: () => Promise<void>;
8
+ deleteTaskByIdsCallback: (deletedTaskIds: Array<number>) => Promise<void>;
9
+ addTaskCallback: (task: TaskDescriptor) => Promise<void>;
10
+ editTaskCallback: (task: TaskDescriptor) => Promise<void>;
11
+ handleNavigateToWGs: (value: HomeBlogPost | number) => Promise<void>;
12
+ handleNavigateToDossiers: (value: HomeBlogPost | number) => Promise<void>;
13
+ taskContext?: TaskContext;
14
+ usersList?: Array<UserDescriptor>;
15
+ onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, onRefreshSearchAsync?: (() => Promise<void>)) => void;
16
+ s4TViewerDialogComponent?: React.ReactNode;
17
+ afterTaskSaved?: (task: TaskDescriptor | undefined, formMode: FormModes | undefined, forceRefresh?: boolean) => Promise<void>;
18
+ }
19
+ declare const TMTasksPanelContent: (props: TMTasksPanelContentProps) => import("react/jsx-runtime").JSX.Element;
20
+ export default TMTasksPanelContent;
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useCallback, useEffect } from "react";
3
+ import { useState } from "react";
4
+ import { applyContextFilters, AssignedTab, FilterCategoryId, filterTreeTask, getTaskAssignedToMe, TaskView } from "./TMTasksUtils";
5
+ import { getTaskAssignedByMe } from "../tasks/TMTasksUtils";
6
+ import TMTasksView from "./TMTasksView";
7
+ import TMTasksHeader from "./TMTasksHeader";
8
+ const TMTasksPanelContent = (props) => {
9
+ // Destructure the common props
10
+ const { id, handleNavigateToWGs, handleNavigateToDossiers, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, taskContext, usersList, onOpenS4TViewerRequest, s4TViewerDialogComponent, afterTaskSaved } = props;
11
+ // activeComponent holds the current task view type, which is determined based on the `layout` prop
12
+ const [activeComponent, setActiveComponent] = useState(TaskView.LIST_TASK);
13
+ // State to store clicked task to process for editing
14
+ const [currentTask, setCurrentTask] = useState(null);
15
+ // State to hold tasks that are currently visualized
16
+ const [visualizedTasks, setVisualizedTasks] = useState([]);
17
+ // State to count tasks in different categories
18
+ const [assignedToMeCount, setAssignedToMeCount] = useState(0);
19
+ const [assignedByMeCount, setAssignedByMeCount] = useState(0);
20
+ const [allTasksFilteredCount, setAllTasksFilteredCount] = useState(0);
21
+ // State to manage the active tab
22
+ const [activeTabIndex, setActiveTabIndex] = useState(AssignedTab.AssignedToMe);
23
+ // appliedGlobalFilters is a state variable that holds an array of filter category IDs (numbers)
24
+ const [appliedGlobalFilters, setAppliedGlobalFilters] = useState([FilterCategoryId.Expiring, FilterCategoryId.NewAssignedActivities, FilterCategoryId.New, FilterCategoryId.InProgress, FilterCategoryId.Pending, FilterCategoryId.Postponed, FilterCategoryId.Low, FilterCategoryId.High]);
25
+ // showContextualWG is a state variable that determines whether the contextual working group filter is visible
26
+ const [showContextualWG, setShowContextualWG] = useState(true);
27
+ // showContextualDossier is a state variable that determines whether the contextual dossier filter is visible
28
+ const [showContextualDossier, setShowContextualDossier] = useState(true);
29
+ // showContextualDocument is a state variable that determines whether the contextual document filter is visible
30
+ const [showContextualDocument, setShowContextualDocument] = useState(true);
31
+ // showId is a state variable that determines whether an ID-related component or feature should be displayed
32
+ const [showId, setShowId] = useState(false);
33
+ // showSearch is a state variable that controls the visibility of a search-related component or feature
34
+ const [showSearch, setShowSearch] = useState(true);
35
+ const contextualTasks = React.useMemo(() => {
36
+ return applyContextFilters(allTasks, showContextualWG, showContextualDossier, showContextualDocument, taskContext);
37
+ }, [allTasks, showContextualWG, showContextualDossier, showContextualDocument, taskContext]);
38
+ useEffect(() => {
39
+ const getFilteredTasks = (tab) => {
40
+ let tasks = allTasks;
41
+ switch (tab) {
42
+ case AssignedTab.AssignedToMe:
43
+ tasks = getTaskAssignedToMe(tasks);
44
+ break;
45
+ case AssignedTab.AssignedByMe:
46
+ tasks = getTaskAssignedByMe(tasks);
47
+ break;
48
+ default:
49
+ break;
50
+ }
51
+ tasks = applyContextFilters(tasks, showContextualWG, showContextualDossier, showContextualDocument, taskContext);
52
+ tasks = filterTreeTask(tasks, appliedGlobalFilters);
53
+ return tasks;
54
+ };
55
+ setAssignedToMeCount(getFilteredTasks(AssignedTab.AssignedToMe).length);
56
+ setAssignedByMeCount(getFilteredTasks(AssignedTab.AssignedByMe).length);
57
+ setAllTasksFilteredCount(getFilteredTasks(AssignedTab.All).length);
58
+ setVisualizedTasks(getFilteredTasks(activeTabIndex));
59
+ }, [allTasks, appliedGlobalFilters, activeTabIndex, showContextualWG, showContextualDossier, showContextualDocument, taskContext]);
60
+ const updateActiveComponent = useCallback((newComponent) => {
61
+ setActiveComponent(newComponent);
62
+ }, []);
63
+ return _jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsx(TMTasksHeader, { height: "55px", activeComponent: activeComponent, updateActiveComponent: updateActiveComponent, allTasks: contextualTasks, appliedGlobalFilters: appliedGlobalFilters, setAppliedGlobalFilters: setAppliedGlobalFilters }), _jsx("div", { style: { width: "100%", height: "calc(100% - 55px)" }, children: _jsx(TMTasksView, { id: id, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, currentTask: currentTask, setCurrentTask: setCurrentTask, visualizedTasks: visualizedTasks, activeComponent: activeComponent, activeTabIndex: activeTabIndex, setActiveTabIndex: setActiveTabIndex, assignedToMeCount: assignedToMeCount, assignedByMeCount: assignedByMeCount, allTasksFilteredCount: allTasksFilteredCount, showId: showId, setShowId: setShowId, showSearch: showSearch, setShowSearch: setShowSearch, showContextualWG: showContextualWG, setShowContextualWG: setShowContextualWG, showContextualDossier: showContextualDossier, setShowContextualDossier: setShowContextualDossier, showContextualDocument: showContextualDocument, setShowContextualDocument: setShowContextualDocument, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, taskContext: taskContext, usersList: usersList, onOpenS4TViewerRequest: onOpenS4TViewerRequest, s4TViewerDialogComponent: s4TViewerDialogComponent, afterTaskSaved: afterTaskSaved }) })] });
64
+ };
65
+ export default TMTasksPanelContent;