@topconsultnpm/sdkui-react 6.19.0-dev1.53 → 6.19.0-dev1.55

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 (35) hide show
  1. package/lib/components/base/TMLayout.d.ts +2 -1
  2. package/lib/components/base/TMLayout.js +2 -2
  3. package/lib/components/features/documents/TMDcmtBlog.js +1 -1
  4. package/lib/components/features/search/TMSearch.js +1 -1
  5. package/lib/components/features/search/TMSearchResult.js +10 -1
  6. package/lib/components/features/tasks/TMTaskForm.d.ts +33 -0
  7. package/lib/components/features/tasks/TMTaskForm.js +291 -0
  8. package/lib/components/features/tasks/TMTasksAgenda.d.ts +17 -0
  9. package/lib/components/features/tasks/TMTasksAgenda.js +107 -0
  10. package/lib/components/features/tasks/TMTasksCalendar.d.ts +21 -0
  11. package/lib/components/features/tasks/TMTasksCalendar.js +240 -0
  12. package/lib/components/features/tasks/TMTasksHeader.d.ts +14 -0
  13. package/lib/components/features/tasks/TMTasksHeader.js +37 -0
  14. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +19 -0
  15. package/lib/components/features/tasks/TMTasksPanelContent.js +74 -0
  16. package/lib/components/features/tasks/TMTasksUtils.d.ts +130 -0
  17. package/lib/components/features/tasks/TMTasksUtils.js +602 -0
  18. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +32 -0
  19. package/lib/components/features/tasks/TMTasksUtilsView.js +107 -0
  20. package/lib/components/features/tasks/TMTasksView.d.ts +37 -0
  21. package/lib/components/features/tasks/TMTasksView.js +555 -0
  22. package/lib/components/features/workflow/TMWorkflowPopup.js +2 -2
  23. package/lib/components/grids/TMBlogsPost.js +27 -27
  24. package/lib/components/grids/TMBlogsPostUtils.js +1 -1
  25. package/lib/components/index.d.ts +8 -0
  26. package/lib/components/index.js +9 -0
  27. package/lib/helper/SDKUI_Localizator.d.ts +54 -4
  28. package/lib/helper/SDKUI_Localizator.js +526 -25
  29. package/lib/helper/TMCustomSearchBar.d.ts +8 -0
  30. package/lib/helper/TMCustomSearchBar.js +54 -0
  31. package/lib/helper/TMToppyMessage.js +1 -1
  32. package/lib/helper/TMUtils.d.ts +10 -1
  33. package/lib/helper/TMUtils.js +42 -1
  34. package/lib/stories/TMSDKUI_Localizator.stories.js +1 -1
  35. package/package.json +1 -1
@@ -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,19 @@
1
+ import React from "react";
2
+ import { TaskDescriptor, UserDescriptor } from "@topconsultnpm/sdk-ts";
3
+ import { DcmtInfo, 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: (workGroupId: number) => void;
12
+ handleNavigateToDossiers: (dossierId: number) => void;
13
+ taskContext?: TaskContext;
14
+ usersList?: Array<UserDescriptor>;
15
+ onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, onRefreshSearchAsync?: (() => Promise<void>)) => void;
16
+ s4TViewerDialogComponent?: React.ReactNode;
17
+ }
18
+ declare const TMTasksPanelContent: (props: TMTasksPanelContentProps) => import("react/jsx-runtime").JSX.Element;
19
+ export default TMTasksPanelContent;
@@ -0,0 +1,74 @@
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 { 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 } = 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
+ // showId is a state variable that determines whether an ID-related component or feature should be displayed
30
+ const [showId, setShowId] = useState(false);
31
+ // showSearch is a state variable that controls the visibility of a search-related component or feature
32
+ const [showSearch, setShowSearch] = useState(true);
33
+ const contextualTasks = React.useMemo(() => {
34
+ let tasks = allTasks;
35
+ if (showContextualWG && taskContext && taskContext.workingGroup && taskContext.workingGroup.id) {
36
+ tasks = tasks.filter(task => task.iD1 === taskContext.workingGroup.id);
37
+ }
38
+ if (showContextualDossier && taskContext && taskContext.dossier && taskContext.dossier.id) {
39
+ tasks = tasks.filter(task => task.iD1 === taskContext.dossier.id);
40
+ }
41
+ return tasks;
42
+ }, [allTasks, showContextualWG, showContextualDossier, taskContext]);
43
+ useEffect(() => {
44
+ const getFilteredTasks = (tab) => {
45
+ let tasks = allTasks;
46
+ switch (tab) {
47
+ case AssignedTab.AssignedToMe:
48
+ tasks = getTaskAssignedToMe(tasks);
49
+ break;
50
+ case AssignedTab.AssignedByMe:
51
+ tasks = getTaskAssignedByMe(tasks);
52
+ break;
53
+ default:
54
+ break;
55
+ }
56
+ if (showContextualWG && taskContext && taskContext.workingGroup && taskContext.workingGroup.id) {
57
+ tasks = tasks.filter(task => task.iD1 === taskContext.workingGroup?.id);
58
+ }
59
+ if (showContextualDossier && taskContext && taskContext.dossier && taskContext.dossier.id) {
60
+ tasks = tasks.filter(task => task.iD1 === taskContext.dossier?.id);
61
+ }
62
+ return filterTreeTask(tasks, appliedGlobalFilters);
63
+ };
64
+ setAssignedToMeCount(getFilteredTasks(AssignedTab.AssignedToMe).length);
65
+ setAssignedByMeCount(getFilteredTasks(AssignedTab.AssignedByMe).length);
66
+ setAllTasksFilteredCount(getFilteredTasks(AssignedTab.All).length);
67
+ setVisualizedTasks(getFilteredTasks(activeTabIndex));
68
+ }, [allTasks, appliedGlobalFilters, activeTabIndex, showContextualWG, showContextualDossier, taskContext]);
69
+ const updateActiveComponent = useCallback((newComponent) => {
70
+ setActiveComponent(newComponent);
71
+ }, []);
72
+ 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, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, taskContext: taskContext, usersList: usersList, onOpenS4TViewerRequest: onOpenS4TViewerRequest, s4TViewerDialogComponent: s4TViewerDialogComponent }) })] });
73
+ };
74
+ export default TMTasksPanelContent;
@@ -0,0 +1,130 @@
1
+ import { Appointment } from 'devextreme/ui/scheduler';
2
+ import { ContextMenuTypes } from 'devextreme-react/cjs/context-menu';
3
+ import { TaskDescriptor, Task_States, PdGs, Priorities, ValidationItem } from '@topconsultnpm/sdk-ts';
4
+ import { FormModes } from '../../../ts';
5
+ import { TMDataGridContextMenuItem } from '../../base/TMDataGrid';
6
+ export declare const TEXT_SELECTED_COLOR = "#ff5e1a";
7
+ export declare const BG_COLOR_INACTIVE_WIDGET = "#fff";
8
+ export declare const BG_COLOR_ACTIVE_WIDGET = "#fff0b7";
9
+ export declare const TEXT_NOT_SELECTED_COLOR = "#2559A5";
10
+ export declare const TODAY_ROW_HIGHLIGHT_BG_COLOR = "#ffb74d";
11
+ export declare const NOT_TODAY_ROW_HIGHLIGHT_COLOR = "#ff0000";
12
+ export declare const NOT_TODAY_ROW_HIGHLIGHT_BG_COLOR = "#81d7fe";
13
+ export declare const START_DATE_MUST_BE_BEFORE_END_DATE = "StartDateMustBeBeforeEndDate";
14
+ export declare const REMINDER_TIME_MUST_BE_BEFORE_END_TIME = "ReminderTimeMustBeBeforeEndTime";
15
+ export declare enum AssignedTab {
16
+ AssignedToMe = 0,
17
+ AssignedByMe = 1,
18
+ All = 2,
19
+ TaskNotPersonalAssignedToMe = 3,
20
+ TaskPersonalAssignedToMe = 4
21
+ }
22
+ export type ContextMenuItem = ContextMenuTypes.Item & {
23
+ onItemClick?: (e: ContextMenuTypes.ItemClickEvent) => void;
24
+ };
25
+ export interface IFieldsEditability {
26
+ name: boolean;
27
+ description: boolean;
28
+ fromID: boolean;
29
+ assignedTO: boolean;
30
+ status: boolean;
31
+ priority: boolean;
32
+ startDate: boolean;
33
+ endDate: boolean;
34
+ remTime: boolean;
35
+ }
36
+ export declare const sortTasks: (tasks: Array<TaskDescriptor>) => Array<TaskDescriptor>;
37
+ export declare const taskIsToday: (startTime: Date, endTime: Date) => boolean;
38
+ export declare const taskIsExpiringSoon: (endTime: Date, remTime?: Date) => boolean;
39
+ export declare const appointmentBackgroundColorFn: (startTime: Date, endTime: Date) => string;
40
+ export declare const getPriorityLocalizatorValues: () => Array<{
41
+ value: string;
42
+ display: string;
43
+ }>;
44
+ export declare const getPriorityId: (priority: Priorities) => number;
45
+ export declare const getPriorityColor: (priority: Priorities) => string;
46
+ export declare const LIGTH_CYAN = "#80DEEA";
47
+ export declare const LIGTH_RED_ORGANGE = "#FFAB91";
48
+ export declare const prioritiesResourceData: Array<{
49
+ id?: number;
50
+ text: string;
51
+ color?: string;
52
+ }>;
53
+ export declare const getStatusLocalizatorValues: () => Array<{
54
+ value: string;
55
+ display: string;
56
+ }>;
57
+ export declare const getStatusLocalizatorValue: (status: Task_States) => string;
58
+ export declare const getPriorityLocalizatorValue: (priority: Priorities) => string;
59
+ export declare const getTaskAssignedToMe: (tasks: Array<TaskDescriptor>) => Array<TaskDescriptor>;
60
+ export declare const getTaskNotPersonalAssignedToMe: (tasks: Array<TaskDescriptor>) => Array<TaskDescriptor>;
61
+ export declare const getTaskPersonalAssignedToMe: (tasks: Array<TaskDescriptor>) => Array<TaskDescriptor>;
62
+ export declare const getTaskAssignedByMe: (tasks: Array<TaskDescriptor>) => Array<TaskDescriptor>;
63
+ export declare const getHeaderStatusFilterConfig: () => {
64
+ enabled: boolean;
65
+ dataSource: {
66
+ text: string;
67
+ value: string;
68
+ }[];
69
+ };
70
+ export declare const getHeaderPriorityFilterConfig: () => {
71
+ enabled: boolean;
72
+ dataSource: {
73
+ text: string;
74
+ value: string;
75
+ }[];
76
+ };
77
+ export declare const TaskView: {
78
+ LIST_TASK: string;
79
+ AGENDA_TASK: string;
80
+ CALENDAR_TASK: string;
81
+ };
82
+ export type TaskViewType = typeof TaskView[keyof typeof TaskView];
83
+ export declare enum Extended_Task_States {
84
+ Init = "Init",
85
+ Expiring = "Expiring",
86
+ AssignedToMe = "AssignedToMe",
87
+ AssignedByMe = "AssignedByMe",
88
+ NewAssignedActivities = "NewAssignedActivities"
89
+ }
90
+ export declare const getTaskColor: (taskState: Task_States) => {
91
+ color: string;
92
+ };
93
+ export declare const mergeUniqueTasks: (existing: Array<TaskDescriptor>, // Array of existing tasks
94
+ newTasks: Array<TaskDescriptor>) => Array<TaskDescriptor>;
95
+ export declare const getOriginLabel: (pdg: PdGs | undefined, ID1Name: string | undefined) => string;
96
+ export declare const taskValidatorAsync: (taskDescriptor: TaskDescriptor) => Promise<ValidationItem[]>;
97
+ export declare const gotoPDGExtendedLabel: (gotoVisible: boolean, pdg: PdGs, iD1Name: string | undefined) => string;
98
+ export declare const convertToSchedulerAppointments: (tasks: Array<TaskDescriptor>) => Array<Appointment>;
99
+ export declare const formatDate: (date: Date) => string;
100
+ export declare const areDifferentIDs: (fromID: number | undefined, userID: number | undefined) => boolean;
101
+ export declare const createTasksMenuItems: (taskDescriptor: TaskDescriptor | undefined, showId: boolean, setShowId: React.Dispatch<React.SetStateAction<boolean>>, showSearch: boolean, setShowSearch: React.Dispatch<React.SetStateAction<boolean>>, openTaskForm: (formMode: FormModes, task?: TaskDescriptor) => void, editTaskCallback: (rowId: number | undefined) => void, duplicateTaskCallback: (rowId: number | undefined) => void, onDeleteCallback: (rowIds: Array<number>) => void, markAsStatus: (rowIds: Array<number>, status: Task_States) => void, getAllTasks: () => Promise<void>, fromWG: boolean, showContextualWG: boolean, setShowContextualWG: React.Dispatch<React.SetStateAction<boolean>>, fromDossier: boolean, showContextualDossier: boolean, setShowContextualDossier: React.Dispatch<React.SetStateAction<boolean>>, showGoToToday: boolean, handleGoToToday?: () => void, fromDatagrid?: boolean) => Array<TMDataGridContextMenuItem>;
102
+ export declare const checkIfNew: (fromId: number | undefined, isNew: number | undefined) => boolean;
103
+ export declare const getNewTaskCount: (tasks: Array<TaskDescriptor>) => number;
104
+ export declare const isTaskAssignedToAnotherUser: (task: TaskDescriptor) => boolean;
105
+ export declare const getMondayOfCurrentWeek: (date: Date) => Date;
106
+ export declare const getSundayOfCurrentWeek: (date: Date) => Date;
107
+ export declare const getFirstDayOfMonth: (date: Date) => Date;
108
+ export declare const getLastDayOfMonth: (date: Date) => Date;
109
+ export declare const findTasksBySearch: (visualizedTasks: Array<TaskDescriptor>, searchText: string) => TaskDescriptor[];
110
+ export interface CellData {
111
+ startDate: Date;
112
+ endDate: Date;
113
+ groups?: Record<string, unknown>;
114
+ text?: string;
115
+ }
116
+ export declare enum FilterCategoryId {
117
+ AllStates = 1,
118
+ AllPriorities = 2,
119
+ NewAssignedActivities = 1.05,
120
+ Expiring = 1.1,
121
+ New = 1.2,
122
+ InProgress = 1.3,
123
+ Completed = 1.4,
124
+ Pending = 1.5,
125
+ Postponed = 1.6,
126
+ Low = 2.1,
127
+ Normal = 2.2,
128
+ High = 2.3
129
+ }
130
+ export declare const filterTreeTask: (tasks: Array<TaskDescriptor>, filtersApplied: Array<FilterCategoryId>) => Array<TaskDescriptor>;