@topconsultnpm/sdkui-react-beta 6.12.37 → 6.12.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/lib/components/base/Styled.d.ts +12 -0
  2. package/lib/components/base/Styled.js +49 -3
  3. package/lib/components/base/TMFloatingToolbar.d.ts +9 -0
  4. package/lib/components/base/TMFloatingToolbar.js +99 -0
  5. package/lib/components/base/TMRightSidebar.d.ts +0 -4
  6. package/lib/components/base/TMRightSidebar.js +2 -10
  7. package/lib/components/base/TMShowAllOrMaxItemsButton.d.ts +8 -0
  8. package/lib/components/base/TMShowAllOrMaxItemsButton.js +14 -0
  9. package/lib/components/base/TMTreeView.d.ts +27 -0
  10. package/lib/components/base/TMTreeView.js +199 -0
  11. package/lib/components/grids/TMBlogs.d.ts +84 -0
  12. package/lib/components/grids/TMBlogs.js +566 -0
  13. package/lib/components/grids/TMBlogsUtils.d.ts +83 -0
  14. package/lib/components/grids/TMBlogsUtils.js +258 -0
  15. package/lib/components/index.d.ts +2 -0
  16. package/lib/components/index.js +2 -0
  17. package/lib/components/query/TMBatchUpdateForm.d.ts +12 -0
  18. package/lib/components/query/TMBatchUpdateForm.js +149 -0
  19. package/lib/components/query/TMDcmtBlog.d.ts +7 -0
  20. package/lib/components/query/TMDcmtBlog.js +34 -0
  21. package/lib/components/query/TMDcmtForm.d.ts +32 -0
  22. package/lib/components/query/TMDcmtForm.js +544 -0
  23. package/lib/components/query/TMDcmtIcon.d.ts +10 -0
  24. package/lib/components/query/TMDcmtIcon.js +52 -0
  25. package/lib/components/query/TMDcmtPreview.d.ts +26 -0
  26. package/lib/components/query/TMDcmtPreview.js +200 -0
  27. package/lib/components/query/TMFileUploader.d.ts +11 -0
  28. package/lib/components/query/TMFileUploader.js +101 -0
  29. package/lib/components/query/TMMasterDetailDcmts.d.ts +23 -0
  30. package/lib/components/query/TMMasterDetailDcmts.js +475 -0
  31. package/lib/components/query/TMQueryEditor.js +2 -2
  32. package/lib/components/query/TMQueryResultForm.d.ts +1 -7
  33. package/lib/components/query/TMQueryResultForm.js +1 -9
  34. package/lib/components/query/TMWorkflowPopup.d.ts +29 -0
  35. package/lib/components/query/TMWorkflowPopup.js +131 -0
  36. package/lib/components/search/TMSearchResult.d.ts +31 -0
  37. package/lib/components/search/TMSearchResult.js +727 -0
  38. package/lib/components/search/TMSearchResultsMenuItems.d.ts +6 -0
  39. package/lib/components/search/TMSearchResultsMenuItems.js +376 -0
  40. package/lib/helper/Enum_Localizator.d.ts +2 -1
  41. package/lib/helper/Enum_Localizator.js +20 -1
  42. package/lib/helper/SDKUI_Localizator.d.ts +24 -0
  43. package/lib/helper/SDKUI_Localizator.js +240 -0
  44. package/lib/helper/dcmtsHelper.d.ts +4 -0
  45. package/lib/helper/dcmtsHelper.js +15 -0
  46. package/lib/helper/helpers.d.ts +2 -1
  47. package/lib/helper/helpers.js +74 -1
  48. package/lib/helper/queryHelper.d.ts +7 -1
  49. package/lib/helper/queryHelper.js +105 -1
  50. package/lib/hooks/useDcmtOperations.d.ts +24 -0
  51. package/lib/hooks/useDcmtOperations.js +387 -0
  52. package/lib/hooks/useInputDialog.d.ts +5 -0
  53. package/lib/hooks/useInputDialog.js +73 -0
  54. package/lib/hooks/usePreventFileDrop.d.ts +3 -0
  55. package/lib/hooks/usePreventFileDrop.js +37 -0
  56. package/lib/index.d.ts +0 -1
  57. package/lib/index.js +0 -1
  58. package/lib/services/platform_services.d.ts +1 -1
  59. package/lib/ts/types.d.ts +54 -1
  60. package/lib/ts/types.js +34 -0
  61. package/package.json +1 -1
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import { BlogPost, BlogPostAttachment, DcmtTypeDescriptor, HomeBlogPost } from "@topconsultnpm/sdk-ts-beta";
3
+ import { FileItem } from '../base/TMFileManager';
4
+ export declare const DRAFT_TYPE_TID = 6;
5
+ export declare const colors: {
6
+ DARK_BLUE: string;
7
+ WHITE: string;
8
+ BLACK: string;
9
+ RED: string;
10
+ LIGHT_GRAY: string;
11
+ PRIMARY_BLUE: string;
12
+ PRIMARY_ORANGE: string;
13
+ PRIMARY_GREEN: string;
14
+ };
15
+ export interface TMBlogContextMenuItem {
16
+ text: string;
17
+ icon: string;
18
+ onClick?: (param?: any) => void;
19
+ operationType?: 'singleRow' | 'multiRow';
20
+ disabled?: boolean;
21
+ id?: string;
22
+ items?: Array<TMBlogContextMenuItem>;
23
+ beginGroup?: boolean;
24
+ tooltip?: string;
25
+ visible?: boolean;
26
+ }
27
+ export declare enum TMBlogsFilterCategoryId {
28
+ PublishedBlogs = 1,
29
+ SystemBlogs = 2,
30
+ DeletedBlogs = 3
31
+ }
32
+ export interface BlogPostContainerProps {
33
+ $color?: string;
34
+ $textDecoration?: string;
35
+ $backgroundColor?: string;
36
+ $isNew?: boolean;
37
+ $canNavigate?: boolean;
38
+ }
39
+ export declare const BlogPostContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, BlogPostContainerProps>> & string;
40
+ export declare const getTooltipContent: (title: string | undefined, content: JSX.Element) => import("react/jsx-runtime").JSX.Element;
41
+ export declare const highlightText: (text: string, searchText: string, isSelected: boolean) => string | (string | import("react/jsx-runtime").JSX.Element)[];
42
+ export declare const lightenColor: (hex: string, amount: number) => string;
43
+ export declare const removeFileExtension: (filename: string) => string;
44
+ export declare const getAttachmentInfo: (attachment: BlogPostAttachment, treeFs: FileItem | undefined, draftLatestInfoMap: Map<number, {
45
+ latestVersion: number;
46
+ folderId: number;
47
+ folderName: string;
48
+ fileExt: string;
49
+ fileSize: string;
50
+ }> | undefined, archivedDocumentMap: Map<number, {
51
+ tid: number;
52
+ did: number;
53
+ fileExt: string;
54
+ fileSize: string;
55
+ }> | undefined, dcmtTypeDescriptors: Map<number, DcmtTypeDescriptor>, isSelected: boolean, searchText: string, color: string) => {
56
+ name: string;
57
+ nameElement: import("react/jsx-runtime").JSX.Element;
58
+ folderId: number;
59
+ fileExt: string;
60
+ draftExist: boolean;
61
+ archivedDocumentsExist: boolean;
62
+ };
63
+ export declare const AttachmentElement: (attachment: BlogPostAttachment, treeFs: FileItem | undefined, draftLatestInfoMap: Map<number, {
64
+ latestVersion: number;
65
+ folderId: number;
66
+ folderName: string;
67
+ fileExt: string;
68
+ fileSize: string;
69
+ }> | undefined, archivedDocumentMap: Map<number, {
70
+ tid: number;
71
+ did: number;
72
+ fileExt: string;
73
+ fileSize: string;
74
+ }> | undefined, dcmtTypeDescriptors: Map<number, DcmtTypeDescriptor>, isSelected: boolean, searchText: string, color: string, handleClickAttachmentFolderFileCallback: ((folderId: number, draftId: number) => void) | undefined, downloadDcmtsAsync: (inputDcmts: Array<any> | undefined) => Promise<void>) => import("react/jsx-runtime").JSX.Element;
75
+ export declare const OwnerInitialsBadge: (blogPost: BlogPost | HomeBlogPost) => import("react/jsx-runtime").JSX.Element;
76
+ export declare const IconAndHeaderElement: (blogPost: BlogPost | HomeBlogPost, iconColor: string, isSelected: boolean, headerClickCallback: () => void, searchText: string) => import("react/jsx-runtime").JSX.Element;
77
+ export declare const findFileItemByDraftID: (tree: FileItem | undefined, draftID: number | undefined) => FileItem | null;
78
+ export declare const isHeaderFullyHidden: (header: {
79
+ showViewMode: boolean;
80
+ showFilters: boolean;
81
+ showSearchBar: boolean;
82
+ showPostsDropDown: boolean;
83
+ } | undefined) => boolean;
@@ -0,0 +1,258 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from "styled-components";
3
+ import { SDK_Globals } from "@topconsultnpm/sdk-ts-beta";
4
+ import { formatBytes, getFileIcon, IconAttachment, IconUserGroup, IconWorkspace, SDKUI_Localizator } from "../../helper";
5
+ import TMTooltip from "../base/TMTooltip";
6
+ export const DRAFT_TYPE_TID = 6;
7
+ export const colors = {
8
+ DARK_BLUE: "#1a0dab",
9
+ WHITE: "#fff",
10
+ BLACK: "#000000",
11
+ RED: '#ff0000',
12
+ LIGHT_GRAY: "#f9f9f9",
13
+ PRIMARY_BLUE: "#135596",
14
+ PRIMARY_ORANGE: "#e65b00",
15
+ PRIMARY_GREEN: "#009700"
16
+ };
17
+ export var TMBlogsFilterCategoryId;
18
+ (function (TMBlogsFilterCategoryId) {
19
+ TMBlogsFilterCategoryId[TMBlogsFilterCategoryId["PublishedBlogs"] = 1] = "PublishedBlogs";
20
+ TMBlogsFilterCategoryId[TMBlogsFilterCategoryId["SystemBlogs"] = 2] = "SystemBlogs";
21
+ TMBlogsFilterCategoryId[TMBlogsFilterCategoryId["DeletedBlogs"] = 3] = "DeletedBlogs";
22
+ })(TMBlogsFilterCategoryId || (TMBlogsFilterCategoryId = {}));
23
+ export const BlogPostContainer = styled.div `
24
+ color: ${(props) => (props.$color ?? colors.BLACK)};
25
+ text-decoration: ${(props) => (props.$textDecoration ?? 'none')};
26
+ height: auto;
27
+ background-color: ${(props) => (props.$backgroundColor ?? colors.WHITE)};
28
+ display: inline-block;
29
+ width: 100%;
30
+ max-width: 100%;
31
+ cursor: ${(props) => (props.$canNavigate ? "pointer" : "default")};
32
+ border-radius: 5px;
33
+ margin: 5px 0;
34
+ padding: 10px;
35
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
36
+ word-wrap: break-word;
37
+ white-space: pre-wrap;
38
+ font-weight: ${(props) => (props.$isNew ? 'bold' : 'normal')};
39
+ &:focus {
40
+ outline: none;
41
+ }
42
+ `;
43
+ export const getTooltipContent = (title, content) => {
44
+ return (_jsxs("div", { style: { textAlign: 'left' }, children: [_jsx("div", { style: { fontWeight: 'bold' }, children: title }), _jsx("hr", {}), content] }));
45
+ };
46
+ export const highlightText = (text, searchText, isSelected) => {
47
+ if (!searchText)
48
+ return text;
49
+ const regex = new RegExp(`(${searchText.trim()})`, 'gi');
50
+ return text.split(regex).map((part, index) => regex.test(part) ? (_jsx("span", { style: { backgroundColor: isSelected ? '#6c9023' : 'yellow' }, children: part }, index)) : (part));
51
+ };
52
+ export const lightenColor = (hex, amount) => {
53
+ let color = hex.replace('#', '');
54
+ // Expand shorthand like #123 to #112233
55
+ if (color.length === 3) {
56
+ color = color.split('').map(c => c + c).join('');
57
+ }
58
+ const num = parseInt(color, 16);
59
+ let r = (num >> 16) + amount;
60
+ let g = ((num >> 8) & 0x00FF) + amount;
61
+ let b = (num & 0x0000FF) + amount;
62
+ r = Math.min(255, Math.max(0, r));
63
+ g = Math.min(255, Math.max(0, g));
64
+ b = Math.min(255, Math.max(0, b));
65
+ return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, '0')}`;
66
+ };
67
+ export const removeFileExtension = (filename) => {
68
+ return filename.includes('.') ? filename.substring(0, filename.lastIndexOf('.')) : filename;
69
+ };
70
+ export const getAttachmentInfo = (attachment, treeFs, draftLatestInfoMap, archivedDocumentMap, dcmtTypeDescriptors, isSelected, searchText, color) => {
71
+ let nameElement = (_jsx("span", { children: `${SDKUI_Localizator.DocumentNotAvailable} (DID: ${attachment.did})` }));
72
+ let folderId = -1;
73
+ let fileExt = '';
74
+ let draftExist = false;
75
+ let archivedDocumentsExist = false;
76
+ let name = '';
77
+ if (attachment.tid === DRAFT_TYPE_TID && treeFs) {
78
+ const draftfileItem = findFileItemByDraftID(treeFs, attachment.draftID);
79
+ if (draftfileItem) {
80
+ let latestVersion = true;
81
+ let pathName = '';
82
+ draftExist = true;
83
+ let fileSize = '0';
84
+ name = draftfileItem.name;
85
+ if (draftLatestInfoMap && attachment.draftID && attachment.version) {
86
+ const draftInfo = draftLatestInfoMap.get(attachment.draftID);
87
+ if (draftInfo) {
88
+ folderId = draftInfo.folderId;
89
+ latestVersion = draftInfo.latestVersion === attachment.version;
90
+ pathName = draftInfo.folderName;
91
+ fileExt = draftInfo.fileExt;
92
+ fileSize = formatBytes(draftInfo.fileSize ? Number(draftInfo.fileSize) : 0);
93
+ }
94
+ }
95
+ const content = (_jsxs("div", { children: [_jsxs("div", { children: [_jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.Version }), ": ", attachment.version] }), draftLatestInfoMap && (_jsxs("div", { children: [_jsxs("div", { children: [_jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.LastVersion }), ": ", latestVersion ? SDKUI_Localizator.Yes : SDKUI_Localizator.No] }), _jsxs("div", { children: [_jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.Size }), ": ", fileSize] })] })), _jsx("hr", {}), _jsxs("div", { children: [_jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.Path }), ": \"", SDKUI_Localizator.Drafts, "\\", pathName.length > 0 ? (pathName + '\\') : '', name, "\""] })] }));
96
+ const tooltipContent = getTooltipContent(draftfileItem.name, content);
97
+ nameElement = (_jsx("span", { children: _jsxs(TMTooltip, { content: tooltipContent, children: [highlightText(`${draftfileItem.name} (DID: ${attachment.did})`, searchText, isSelected), "\u00A0", _jsx("span", { style: {
98
+ display: 'inline-flex',
99
+ marginLeft: '5px',
100
+ width: '20px',
101
+ height: '20px',
102
+ alignItems: 'center',
103
+ justifyContent: 'center',
104
+ backgroundColor: isSelected ? '#fff' : (latestVersion ? '#28a745' : '#cc7000'),
105
+ color: isSelected ? color : '#fff',
106
+ boxShadow: '1px 1px 2px #00000020',
107
+ borderRadius: '30px',
108
+ fontWeight: 'bold',
109
+ }, children: attachment.version })] }) }));
110
+ }
111
+ }
112
+ else if (attachment.tid) {
113
+ const descriptor = dcmtTypeDescriptors.get(attachment.tid);
114
+ let fileSize = '0';
115
+ if (archivedDocumentMap && attachment.did) {
116
+ const archivedDocumentInfo = archivedDocumentMap.get(attachment.did);
117
+ if (archivedDocumentInfo) {
118
+ archivedDocumentsExist = true;
119
+ fileExt = archivedDocumentInfo.fileExt;
120
+ fileSize = formatBytes(archivedDocumentInfo.fileSize ? Number(archivedDocumentInfo.fileSize) : 0);
121
+ }
122
+ }
123
+ if (descriptor) {
124
+ name = descriptor.name ?? "-";
125
+ const content = (_jsxs("div", { children: [archivedDocumentMap && (_jsxs("div", { children: [_jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.Size }), ": ", fileSize] })), _jsx("hr", {}), _jsxs("div", { children: [_jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.Path }), ": \"", SDKUI_Localizator.ArchivedDocuments, "\\", `${descriptor.name} (DID: ${attachment.did})`, "\""] })] }));
126
+ const tooltipContent = getTooltipContent(descriptor.name, content);
127
+ nameElement = (_jsx("span", { children: _jsx(TMTooltip, { content: tooltipContent, children: highlightText(`${name} (DID: ${attachment.did})`, searchText, isSelected) }) }));
128
+ }
129
+ }
130
+ return { name, nameElement, folderId, fileExt, draftExist, archivedDocumentsExist };
131
+ };
132
+ export const AttachmentElement = (attachment, treeFs, draftLatestInfoMap, archivedDocumentMap, dcmtTypeDescriptors, isSelected, searchText, color, handleClickAttachmentFolderFileCallback, downloadDcmtsAsync) => {
133
+ const { name, nameElement, folderId, fileExt, draftExist } = getAttachmentInfo(attachment, treeFs, draftLatestInfoMap, archivedDocumentMap, dcmtTypeDescriptors, isSelected, searchText, color);
134
+ const onClickCallback = (e) => {
135
+ e.preventDefault();
136
+ e.stopPropagation();
137
+ if (attachment.tid === DRAFT_TYPE_TID && treeFs && draftExist) {
138
+ const folderIdAttachment = folderId === 0 ? -1 : folderId;
139
+ if (handleClickAttachmentFolderFileCallback && attachment.draftID)
140
+ handleClickAttachmentFolderFileCallback(folderIdAttachment, attachment.draftID);
141
+ }
142
+ };
143
+ const onDoubleClick = (e) => {
144
+ e.preventDefault();
145
+ e.stopPropagation();
146
+ const archiveID = SDK_Globals.tmSession?.SessionDescr?.archiveID;
147
+ const fileName = `${removeFileExtension(name)}_${archiveID}_${attachment.tid}_${attachment.did}.${fileExt}`;
148
+ if (downloadDcmtsAsync)
149
+ downloadDcmtsAsync([{ TID: attachment.tid, DID: attachment.did, fileName }]);
150
+ };
151
+ return _jsx("div", { onClick: onClickCallback, onDoubleClick: onDoubleClick, style: {
152
+ display: 'inline-flex',
153
+ padding: '8px 12px',
154
+ margin: '4px',
155
+ border: '1px solid #ddd',
156
+ borderRadius: '8px',
157
+ boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
158
+ backgroundColor: isSelected ? color : colors.WHITE,
159
+ cursor: "pointer"
160
+ }, onMouseEnter: (e) => {
161
+ e.currentTarget.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.15)';
162
+ e.currentTarget.style.backgroundColor = isSelected ? lightenColor(color, 40) : '#cfcfcf';
163
+ }, onMouseLeave: (e) => {
164
+ e.currentTarget.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)';
165
+ e.currentTarget.style.backgroundColor = isSelected ? color : colors.WHITE;
166
+ }, children: _jsxs("div", { style: { alignItems: 'center', display: 'flex' }, children: [fileExt ? _jsx("span", { style: { marginRight: "10px" }, children: getFileIcon(fileExt, undefined) }) : _jsx(IconAttachment, { style: { marginRight: "5px" } }), _jsx("span", { children: nameElement })] }) }, attachment.did);
167
+ };
168
+ export const OwnerInitialsBadge = (blogPost) => {
169
+ const generateDarkColorFromName = (str) => {
170
+ // Create a hash of the string
171
+ let hash = 0;
172
+ for (let i = 0; i < str.length; i++) {
173
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
174
+ }
175
+ // Convert the hash to a color (ensure it's within RGB range)
176
+ const hue = Math.floor((hash & 0x00FFFFFF) / 0x10000);
177
+ // Define color ranges for dark red, green, yellow, and others
178
+ let colorRange;
179
+ if (hue >= 0 && hue < 30) { // Dark red
180
+ colorRange = 0; // Red hue
181
+ }
182
+ else if (hue >= 30 && hue < 90) { // Dark orange to yellow
183
+ colorRange = 60; // Yellow hue
184
+ }
185
+ else if (hue >= 90 && hue < 150) { // Dark green
186
+ colorRange = 120; // Green hue
187
+ }
188
+ else if (hue >= 150 && hue < 210) { // Dark cyan
189
+ colorRange = 180; // Cyan hue
190
+ }
191
+ else if (hue >= 210 && hue < 270) { // Dark blue
192
+ colorRange = 240; // Blue hue
193
+ }
194
+ else if (hue >= 270 && hue < 330) { // Dark purple
195
+ colorRange = 300; // Purple hue
196
+ }
197
+ else { // Dark magenta
198
+ colorRange = 360; // Magenta hue
199
+ }
200
+ // Use a low lightness value to keep the color dark
201
+ return `hsl(${colorRange}, 70%, 30%)`; // Low lightness for dark colors
202
+ };
203
+ const extractInitialsFromName = (name) => {
204
+ // If the name has 3 characters, return the first 2 characters
205
+ if (name.length >= 3) {
206
+ const lettersOnly = name.replace(/[^a-zA-Z]/g, '');
207
+ return lettersOnly.substring(0, 3).toUpperCase();
208
+ }
209
+ // If only 1 character, return that character
210
+ return name[0].toUpperCase();
211
+ };
212
+ return _jsx(TMTooltip, { content: blogPost.ownerName ?? '-', children: _jsx("div", { style: {
213
+ width: "40px",
214
+ height: "40px",
215
+ borderRadius: "50%",
216
+ backgroundColor: generateDarkColorFromName(blogPost.ownerName ?? '-'),
217
+ display: "flex",
218
+ alignItems: "center",
219
+ justifyContent: "center",
220
+ marginRight: "10px",
221
+ fontWeight: "bold",
222
+ color: colors.WHITE,
223
+ fontSize: "18px",
224
+ }, children: _jsx("span", { style: { fontSize: "12px" }, children: extractInitialsFromName(blogPost.ownerName ?? '-') }) }) });
225
+ };
226
+ export const IconAndHeaderElement = (blogPost, iconColor, isSelected, headerClickCallback, searchText) => {
227
+ return _jsxs("span", { style: { marginLeft: "5px", cursor: blogPost.classID === 'WG' ? "pointer" : "default", display: "inline-flex", alignItems: "center" }, onClick: headerClickCallback, children: [_jsx(TMTooltip, { content: blogPost.classID === 'DS' ? SDKUI_Localizator.Practice : SDKUI_Localizator.WorkGroup, children: blogPost.classID === "DS" ? (_jsx(IconWorkspace, { color: iconColor })) : (_jsx(IconUserGroup, { color: iconColor })) }), _jsx("span", { style: {
228
+ marginLeft: "5px",
229
+ textDecoration: blogPost.classID === "WG" ? "underline" : "none",
230
+ cursor: blogPost.classID === "WG" ? "pointer" : "default",
231
+ color: isSelected
232
+ ? "#fff"
233
+ : (blogPost.classID === "WG" ? colors.DARK_BLUE : colors.BLACK),
234
+ display: "inline-block" // Ensure both elements are in a row
235
+ }, onClick: headerClickCallback, children: highlightText(blogPost.header ?? '', searchText, isSelected) })] });
236
+ };
237
+ export const findFileItemByDraftID = (tree, draftID) => {
238
+ if (tree === undefined || draftID === undefined)
239
+ return null;
240
+ if (tree.id === draftID) {
241
+ return tree;
242
+ }
243
+ if (tree.items && tree.items.length > 0) {
244
+ for (const item of tree.items) {
245
+ const found = findFileItemByDraftID(item, draftID);
246
+ if (found) {
247
+ return found;
248
+ }
249
+ }
250
+ }
251
+ return null;
252
+ };
253
+ export const isHeaderFullyHidden = (header) => {
254
+ if (!header) {
255
+ return true;
256
+ }
257
+ return !header.showViewMode && !header.showFilters && !header.showSearchBar && !header.showPostsDropDown;
258
+ };
@@ -41,6 +41,8 @@ export * from './choosers/TMDcmtTypeChooser';
41
41
  export * from './choosers/TMMetadataChooser';
42
42
  export * from './choosers/TMUserChooser';
43
43
  export { default as TMValidationItemsList } from './grids/TMValidationItemsList';
44
+ export { default as TMBlogs } from './grids/TMBlogs';
45
+ export * from './query/TMDcmtIcon';
44
46
  export * from './query/TMQueryEditor';
45
47
  export * from './query/TMQueryResultForm';
46
48
  export * from './query/TMQuerySummary';
@@ -45,7 +45,9 @@ export * from './choosers/TMMetadataChooser';
45
45
  export * from './choosers/TMUserChooser';
46
46
  //grids
47
47
  export { default as TMValidationItemsList } from './grids/TMValidationItemsList';
48
+ export { default as TMBlogs } from './grids/TMBlogs';
48
49
  //query
50
+ export * from './query/TMDcmtIcon';
49
51
  export * from './query/TMQueryEditor';
50
52
  export * from './query/TMQueryResultForm';
51
53
  export * from './query/TMQuerySummary';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { DcmtInfo } from '../../ts';
3
+ interface ITMBatchUpdateFormProps {
4
+ inputDcmts: DcmtInfo[];
5
+ TID: number | undefined;
6
+ DID: number | undefined;
7
+ onBack?: () => void;
8
+ onSavedCallbackAsync?: () => Promise<void>;
9
+ onStatusChanged?: (isModified: boolean, isValid: boolean) => void;
10
+ }
11
+ declare const TMBatchUpdateForm: React.FC<ITMBatchUpdateFormProps>;
12
+ export default TMBatchUpdateForm;
@@ -0,0 +1,149 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { AccessLevels, DcmtTypeListCacheService, LayoutModes, MetadataDataDomains, ResultTypes, SDK_Globals, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
4
+ import { searchResultToMetadataValues, getSystemMetadata, calcIsModified, getListMaxItems, SDKUI_Localizator, IconHide, IconShow } from '../../helper';
5
+ import { useDcmtOperations } from '../../hooks/useDcmtOperations';
6
+ import { DcmtOperationTypes, FormModes } from '../../ts';
7
+ import { TMColors } from '../../utils/theme';
8
+ import { StyledToolbarCardContainer, StyledFormButtonsContainer } from '../base/Styled';
9
+ import TMButton from '../base/TMButton';
10
+ import { useDeviceType, DeviceType } from '../base/TMDeviceProvider';
11
+ import { TMSplitterLayout } from '../base/TMLayout';
12
+ import { TMExceptionBoxManager } from '../base/TMPopUp';
13
+ import TMShowAllOrMaxItemsButton from '../base/TMShowAllOrMaxItemsButton';
14
+ import TMSpinner from '../base/TMSpinner';
15
+ import TMToolbarCard from '../base/TMToolbarCard';
16
+ import { TMLayoutWaitingContainer } from '../base/TMWaitPanel';
17
+ import TMDistinctValues from '../choosers/TMDistinctValues';
18
+ import TMFormulaEditor, { FormulaDescriptor, FormulaHelper, FormulaTargets } from '../editors/TMFormulaEditor';
19
+ import { useMetadataEditableList } from '../editors/TMMetadataEditor';
20
+ import TMMetadataValues, { ShowCheckBoxesMode, AdvancedMenuButtons } from '../editors/TMMetadataValues';
21
+ import { TMSaveFormButtonSave, TMSaveFormButtonUndo } from '../forms/TMSaveForm';
22
+ const TMBatchUpdateForm = ({ inputDcmts, TID, DID, onSavedCallbackAsync, onBack, onStatusChanged }) => {
23
+ const [metadataValues, setMetadataValues] = useState([]);
24
+ const [metadataValuesOrig, setMetadataValuesOrig] = useState([]);
25
+ const [validationItems, setValidationItems] = useState([]);
26
+ const [showAll, setShowAll] = useState(false);
27
+ const [showAdvancedMenu, setShowAdvancedMenu] = useState(false);
28
+ const [showDistinctValuesPanel, setShowDistinctValuesPanel] = useState(false);
29
+ const [showFormulaEditor, setShowFormulaEditor] = useState(false);
30
+ const [focusedMetadataValue, setFocusedMetadataValue] = useState();
31
+ const [addOrRemoveEditableList] = useMetadataEditableList();
32
+ const { abortController, runOperationAsync, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary } = useDcmtOperations();
33
+ const deviceType = useDeviceType();
34
+ useEffect(() => {
35
+ if (!TID)
36
+ return;
37
+ if (!DID)
38
+ return;
39
+ if (isModified)
40
+ return;
41
+ retrieveMetadataAsync();
42
+ }, [TID, DID]);
43
+ useEffect(() => {
44
+ validateAsync();
45
+ onStatusChanged?.(isModified, validationItems.findIndex(o => o.ResultType != ResultTypes.SUCCESS) >= 0);
46
+ }, [metadataValues]);
47
+ const validateAsync = async () => {
48
+ let vil = [];
49
+ if (metadataValues.filter(o => o.isSelected).length <= 0)
50
+ vil.push(new ValidationItem(ResultTypes.ERROR, "isSelectd", `${'Selezionare almeno un metadato da aggiornare'}`));
51
+ else {
52
+ for (const mvd of metadataValues) {
53
+ if (!mvd.isSelected)
54
+ continue;
55
+ if (!mvd.value && !mvd.isNull)
56
+ vil.push(new ValidationItem(ResultTypes.ERROR, mvd.md?.nameLoc ?? "", `Specificare un valore (${mvd.md?.nameLoc})`));
57
+ }
58
+ }
59
+ setValidationItems(vil);
60
+ };
61
+ const retrieveMetadataAsync = async () => {
62
+ try {
63
+ await DcmtTypeListCacheService.GetAsync(TID).then(async (dtd) => {
64
+ let mdList = dtd?.metadata ?? [];
65
+ await setMetadataListAsync(mdList);
66
+ });
67
+ }
68
+ catch (e) {
69
+ let err = e;
70
+ TMExceptionBoxManager.show({ exception: err });
71
+ }
72
+ };
73
+ const setMetadataListAsync = async (mdList) => {
74
+ try {
75
+ TMSpinner.show({ description: 'Caricamento metadati...' });
76
+ let res = await SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(TID, DID, true);
77
+ let dtd = res?.dtdResult;
78
+ let rows = dtd.rows ? dtd.rows[0] : [];
79
+ let mids = res?.selectMIDs;
80
+ let metadataList = searchResultToMetadataValues(TID, dtd, rows, mids, mdList, LayoutModes.Update)
81
+ .filter(o => o.md?.dataDomain !== MetadataDataDomains.Computed &&
82
+ o.md?.perm?.canUpdate === AccessLevels.Yes &&
83
+ o.md.isSystem !== 1);
84
+ metadataList.forEach(mvd => { mvd.isSelected = false; mvd.isNull = false; });
85
+ setMetadataValuesOrig(structuredClone(metadataList));
86
+ setMetadataValues(structuredClone(metadataList));
87
+ }
88
+ catch (e) {
89
+ TMExceptionBoxManager.show({ exception: e });
90
+ }
91
+ finally {
92
+ TMSpinner.hide();
93
+ }
94
+ };
95
+ const onUndoHandler = () => {
96
+ setMetadataValues(structuredClone(metadataValuesOrig));
97
+ };
98
+ const onSavedAsync = async () => {
99
+ let dcmts = inputDcmts.slice();
100
+ dcmts.forEach(o => o.metadataValues = metadataValues);
101
+ await runOperationAsync(dcmts, DcmtOperationTypes.BatchUpdate, onSavedCallbackAsync);
102
+ };
103
+ const getFormula = () => {
104
+ let fd = new FormulaDescriptor();
105
+ fd.expression = FormulaHelper.isFormula(focusedMetadataValue?.value) ? FormulaHelper.removeFormulaTag(focusedMetadataValue?.value) : undefined;
106
+ fd.formulaTarget = FormulaTargets.BatchUpdate;
107
+ fd.items = FormulaHelper.TreeViewList(TID ?? 0, getSystemMetadata(true), undefined, FormulaTargets.BatchUpdate, SDK_Globals.dbBrand);
108
+ fd.mid = focusedMetadataValue?.mid ?? 0;
109
+ fd.tid = TID;
110
+ return fd;
111
+ };
112
+ const isModified = calcIsModified(metadataValues, metadataValuesOrig);
113
+ const errors = validationItems.filter(o => o.ResultType == ResultTypes.ERROR);
114
+ const listMaxItems = getListMaxItems(deviceType ?? DeviceType.DESKTOP);
115
+ const totalItems = metadataValues.filter(o => o.mid && o.mid > 100).length;
116
+ const metadataValuesSource = metadataValues.filter(o => o.mid && o.mid > 100).slice(0, showAll ? metadataValues.filter(o => o.mid && o.mid > 100).length : listMaxItems);
117
+ const metadataValuesSourceOrig = metadataValuesOrig.filter(o => o.mid && o.mid > 100).slice(0, showAll ? metadataValuesOrig.filter(o => o.mid && o.mid > 100).length : listMaxItems);
118
+ return (_jsx(TMLayoutWaitingContainer, { showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsxs(TMSplitterLayout, { separatorSize: 5, separatorColor: 'transparent', showSeparator: showDistinctValuesPanel || showFormulaEditor, start: showDistinctValuesPanel || showFormulaEditor ? ['50%', '50%'] : ['100%', '0%'], min: ['0', '0'], direction: 'horizontal', children: [_jsx(TMToolbarCard, { title: `${SDKUI_Localizator.BatchUpdate} (${inputDcmts.length} documenti selezionati)`, backgroundColorContainer: TMColors.default_background, toolbar: _jsx(TMButton, { btnStyle: 'icon', icon: showAdvancedMenu ? _jsx(IconHide, { color: 'white' }) : _jsx(IconShow, { color: 'white' }), caption: showAdvancedMenu ? SDKUI_Localizator.StandardMode : SDKUI_Localizator.ExpertMode, onClick: () => setShowAdvancedMenu(!showAdvancedMenu) }), onBack: deviceType === DeviceType.MOBILE ? onBack : undefined, onClose: deviceType !== DeviceType.MOBILE ? onBack : undefined, children: _jsxs(StyledToolbarCardContainer, { children: [_jsx(TMMetadataValues, { TID: TID, showAdvancedMenu: showAdvancedMenu, showCheckBoxes: ShowCheckBoxesMode.Always, showNullValueCheckBoxes: true, metadataValues: metadataValuesSource, metadataValuesOrig: metadataValuesSourceOrig, validationItems: validationItems, isOpenDistinctValues: showDistinctValuesPanel, selectedMID: focusedMetadataValue?.mid, onFocusedItemChanged: (item) => { setFocusedMetadataValue(item); }, onValueChanged: (newItems) => {
119
+ setMetadataValues((prevItems) => prevItems.map((item) => {
120
+ const newItem = newItems.find((newItem) => newItem.tid === item.tid && newItem.mid === item.mid);
121
+ return newItem ? { ...item, ...newItem } : item;
122
+ }));
123
+ }, onAdvancedMenuClick: (e) => {
124
+ switch (e.button) {
125
+ case AdvancedMenuButtons.DistinctValues:
126
+ setShowDistinctValuesPanel(!showDistinctValuesPanel);
127
+ break;
128
+ case AdvancedMenuButtons.FormulaEditor:
129
+ setShowFormulaEditor(!showFormulaEditor);
130
+ break;
131
+ }
132
+ } }), _jsxs(StyledFormButtonsContainer, { children: [_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 10 }, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '8px' }, children: [_jsx(TMSaveFormButtonSave, { showTooltip: false, btnStyle: 'advanced', advancedColor: '#f09c0a', isModified: errors.length <= 0 && isModified, formMode: FormModes.Update, errorsCount: errors.length, onSaveAsync: onSavedAsync }), _jsx(TMSaveFormButtonUndo, { btnStyle: 'toolbar', showTooltip: true, color: 'primary', isModified: isModified, formMode: FormModes.Update, onUndo: onUndoHandler })] }) }), totalItems > listMaxItems && _jsx(TMShowAllOrMaxItemsButton, { showAll: showAll, dataSourceLength: totalItems, onClick: () => { setShowAll(!showAll); } })] })] }) }), showDistinctValuesPanel && focusedMetadataValue &&
133
+ _jsx(TMDistinctValues, { tid: TID, mid: focusedMetadataValue?.mid, separator: ', ', allowAppendMode: false, onClosePanelCallback: () => setShowDistinctValuesPanel(false), onSelectionChanged: (e) => {
134
+ if (!e)
135
+ return;
136
+ setMetadataValues((prevItems) => prevItems.map((item) => item.tid == e.tid && item.mid === e.mid ? { ...item, value: e.newValue, isSelected: true } : item));
137
+ } }), showFormulaEditor && focusedMetadataValue &&
138
+ _jsx(TMToolbarCard, { title: SDKUI_Localizator.FormulaEditorTitle + (focusedMetadataValue?.md?.nameLoc ? ` (${focusedMetadataValue?.md?.nameLoc})` : ''), onClose: () => setShowFormulaEditor(false), children: _jsx(TMFormulaEditor, { isModal: false, formMode: FormModes.Update, inputData: getFormula(), showBack: false, onClose: () => setShowFormulaEditor(false), onApplied: (newFormula) => {
139
+ setMetadataValues((prevItems) => prevItems.map((item) => item.tid == newFormula.tid && item.mid === newFormula.mid ? { ...item, value: FormulaHelper.addFormulaTag(newFormula.expression), isSelected: true, isEditable: true } : item));
140
+ setFocusedMetadataValue(prevState => ({
141
+ ...prevState,
142
+ isSelected: true,
143
+ isEditable: true,
144
+ value: FormulaHelper.addFormulaTag(newFormula.expression)
145
+ }));
146
+ addOrRemoveEditableList(newFormula.mid);
147
+ } }) })] }) }));
148
+ };
149
+ export default TMBatchUpdateForm;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface ITMDcmtBlogProps {
3
+ tid: number | undefined;
4
+ did: number | undefined;
5
+ }
6
+ declare const TMDcmtBlog: React.FC<ITMDcmtBlogProps>;
7
+ export default TMDcmtBlog;
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { SDK_Globals } from '@topconsultnpm/sdk-ts-beta';
3
+ import { useEffect, useState } from 'react';
4
+ import styled from 'styled-components';
5
+ import { TMExceptionBoxManager } from '../base/TMPopUp';
6
+ import TMSpinner from '../base/TMSpinner';
7
+ import TMBlogs from '../grids/TMBlogs';
8
+ const TMDcmtBlog = ({ tid, did }) => {
9
+ const [blogsDatasource, setBlogsDatasource] = useState([]);
10
+ useEffect(() => {
11
+ if (!tid || !did)
12
+ return;
13
+ loadDataAsync(tid, did);
14
+ }, [did]);
15
+ const loadDataAsync = async (tid, did) => {
16
+ try {
17
+ TMSpinner.show({ description: 'Caricamento - Bacheca...' });
18
+ let res = await SDK_Globals.tmSession?.NewSearchEngine().BlogRetrieveAsync(tid, did);
19
+ setBlogsDatasource(res ?? []);
20
+ }
21
+ catch (e) {
22
+ let err = e;
23
+ TMExceptionBoxManager.show({ exception: err });
24
+ }
25
+ finally {
26
+ TMSpinner.hide();
27
+ }
28
+ };
29
+ return (_jsx(StyledContainer, { children: _jsx(StyledSectionContainer, { style: { position: 'relative' }, children: _jsx(StyledBoardContainer, { children: _jsx(TMBlogs, { id: "dcmt-blog", allData: blogsDatasource, showExtendedAttachments: false }) }) }) }));
30
+ };
31
+ export default TMDcmtBlog;
32
+ const StyledContainer = styled.div ` user-select: none; overflow: hidden; background-color: #ffffff; width: calc(100%); height: calc(100%); display: flex; gap: 10px; `;
33
+ const StyledSectionContainer = styled.div ` width: 100%; height: 100%; display:flex; flex-direction: column; `;
34
+ const StyledBoardContainer = styled.div `width: 100%; height: 100%; padding: 10px;`;
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { LayoutModes } from '@topconsultnpm/sdk-ts-beta';
3
+ import { FormModes } from '../../ts';
4
+ import { ITMRightSidebarItem } from '../base/TMRightSidebar';
5
+ interface ITMDcmtFormProps {
6
+ TID?: number;
7
+ DID?: number;
8
+ layoutMode?: LayoutModes;
9
+ formMode?: FormModes;
10
+ allowNavigation?: boolean;
11
+ allowRelations?: boolean;
12
+ showHeader?: boolean;
13
+ showDcmtForm?: boolean;
14
+ showPreview?: boolean;
15
+ showBoard?: boolean;
16
+ showSysMetadata?: boolean;
17
+ customRightSidebarItems?: ITMRightSidebarItem[];
18
+ showDcmtFormSidebar?: boolean;
19
+ count?: number;
20
+ itemIndex?: number;
21
+ canNext?: boolean;
22
+ canPrev?: boolean;
23
+ isClosable?: boolean;
24
+ onNext?: () => void;
25
+ onPrev?: () => void;
26
+ onClose?: () => void;
27
+ onSavedAsyncCallback?: (tid: number | undefined, did: number | undefined) => Promise<void>;
28
+ onSaveRecents?: (TIDs: number[]) => void;
29
+ onClosePreview?: () => void;
30
+ }
31
+ declare const TMDcmtForm: React.FC<ITMDcmtFormProps>;
32
+ export default TMDcmtForm;