@topconsultnpm/sdkui-react 6.20.0-dev1.5 → 6.20.0-dev1.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +4 -0
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +302 -0
- package/lib/components/NewComponents/ContextMenu/hooks.d.ts +13 -0
- package/lib/components/NewComponents/ContextMenu/hooks.js +61 -0
- package/lib/components/NewComponents/ContextMenu/index.d.ts +2 -0
- package/lib/components/NewComponents/ContextMenu/index.js +1 -0
- package/lib/components/NewComponents/ContextMenu/styles.d.ts +31 -0
- package/lib/components/NewComponents/ContextMenu/styles.js +336 -0
- package/lib/components/NewComponents/ContextMenu/types.d.ts +38 -0
- package/lib/components/NewComponents/ContextMenu/types.js +1 -0
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +4 -0
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +686 -0
- package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +2 -0
- package/lib/components/NewComponents/FloatingMenuBar/index.js +2 -0
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +47 -0
- package/lib/components/NewComponents/FloatingMenuBar/styles.js +346 -0
- package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +28 -0
- package/lib/components/NewComponents/FloatingMenuBar/types.js +1 -0
- package/lib/components/base/TMCustomButton.js +61 -17
- package/lib/components/base/TMDataGrid.d.ts +7 -4
- package/lib/components/base/TMDataGrid.js +112 -11
- package/lib/components/choosers/TMMetadataChooser.js +8 -1
- package/lib/components/editors/TMMetadataValues.js +23 -5
- package/lib/components/features/documents/TMDcmtForm.d.ts +13 -1
- package/lib/components/features/documents/TMDcmtForm.js +385 -193
- package/lib/components/features/documents/TMDcmtPreview.js +37 -66
- package/lib/components/features/documents/TMMasterDetailDcmts.js +1 -1
- package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
- package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +5 -10
- package/lib/components/features/search/TMSearch.js +30 -5
- package/lib/components/features/search/TMSearchQueryPanel.js +13 -12
- package/lib/components/features/search/TMSearchResult.js +58 -208
- package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
- package/lib/components/features/search/TMSearchResultsMenuItems.js +205 -169
- package/lib/components/features/search/TMSignSettingsForm.js +1 -1
- package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
- package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
- package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
- package/lib/components/features/tasks/TMTasksView.js +2 -2
- package/lib/components/features/workflow/diagram/WFDiagram.js +2 -2
- package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
- package/lib/components/forms/Login/LoginValidatorService.js +7 -2
- package/lib/components/forms/Login/TMLoginForm.js +34 -6
- package/lib/components/forms/TMChooserForm.js +1 -1
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +1 -0
- package/lib/css/tm-sdkui.css +1 -1
- package/lib/helper/SDKUI_Globals.d.ts +17 -0
- package/lib/helper/SDKUI_Globals.js +9 -0
- package/lib/helper/SDKUI_Localizator.d.ts +2 -1
- package/lib/helper/SDKUI_Localizator.js +11 -1
- package/lib/helper/TMIcons.d.ts +1 -0
- package/lib/helper/TMIcons.js +3 -0
- package/lib/helper/TMPdfViewer.d.ts +8 -0
- package/lib/helper/TMPdfViewer.js +187 -0
- package/lib/helper/checkinCheckoutManager.d.ts +32 -2
- package/lib/helper/checkinCheckoutManager.js +115 -38
- package/lib/helper/devextremeCustomMessages.d.ts +30 -0
- package/lib/helper/devextremeCustomMessages.js +30 -0
- package/lib/helper/helpers.d.ts +2 -1
- package/lib/helper/helpers.js +12 -2
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/helper/queryHelper.js +29 -0
- package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
- package/lib/hooks/useCheckInOutOperations.js +223 -0
- package/lib/hooks/useWorkflowApprove.d.ts +4 -0
- package/lib/hooks/useWorkflowApprove.js +14 -1
- package/package.json +5 -2
- package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export declare const Overlay: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
2
|
+
$visible: boolean;
|
|
3
|
+
}>> & string;
|
|
4
|
+
export declare const FloatingContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("styled-components/dist/types").Substitute<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
5
|
+
ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
|
|
6
|
+
}>, {
|
|
7
|
+
$x: number;
|
|
8
|
+
$y: number;
|
|
9
|
+
$orientation: "horizontal" | "vertical";
|
|
10
|
+
$isDragging: boolean;
|
|
11
|
+
$isConfigMode: boolean;
|
|
12
|
+
$isConstrained?: boolean;
|
|
13
|
+
}>, {
|
|
14
|
+
$x: number;
|
|
15
|
+
$y: number;
|
|
16
|
+
$orientation: "horizontal" | "vertical";
|
|
17
|
+
$isDragging: boolean;
|
|
18
|
+
$isConfigMode: boolean;
|
|
19
|
+
$isConstrained?: boolean;
|
|
20
|
+
}>> & string;
|
|
21
|
+
export declare const GripHandle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
22
|
+
$orientation: "horizontal" | "vertical";
|
|
23
|
+
}>> & string;
|
|
24
|
+
export declare const Separator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
25
|
+
$orientation: "horizontal" | "vertical";
|
|
26
|
+
}>> & string;
|
|
27
|
+
export declare const MenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
|
|
28
|
+
$isActive?: boolean;
|
|
29
|
+
}>> & string;
|
|
30
|
+
export declare const ConfigButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
31
|
+
export declare const ApplyButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
32
|
+
export declare const ContextMenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "$isActive"> & {
|
|
33
|
+
$isActive?: boolean;
|
|
34
|
+
}, "ref"> & {
|
|
35
|
+
ref?: ((instance: HTMLButtonElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLButtonElement> | null | undefined;
|
|
36
|
+
}, never>> & string;
|
|
37
|
+
export declare const AddButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
38
|
+
export declare const RemoveButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
39
|
+
export declare const UndoButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
40
|
+
export declare const DraggableItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
41
|
+
$isDragging: boolean;
|
|
42
|
+
$isDragOver: boolean;
|
|
43
|
+
}>> & string;
|
|
44
|
+
export declare const ContextMenuWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
45
|
+
export declare const ButtonGroup: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
46
|
+
$orientation: "horizontal" | "vertical";
|
|
47
|
+
}>> & string;
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import styled, { keyframes, css } from 'styled-components';
|
|
2
|
+
const fadeIn = keyframes `
|
|
3
|
+
from {
|
|
4
|
+
opacity: 0;
|
|
5
|
+
transform: scale(0.95);
|
|
6
|
+
}
|
|
7
|
+
to {
|
|
8
|
+
opacity: 1;
|
|
9
|
+
transform: scale(1);
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
const shake = keyframes `
|
|
13
|
+
0%, 100% { transform: translateX(0); }
|
|
14
|
+
25% { transform: translateX(-2px); }
|
|
15
|
+
75% { transform: translateX(2px); }
|
|
16
|
+
`;
|
|
17
|
+
export const Overlay = styled.div `
|
|
18
|
+
position: fixed;
|
|
19
|
+
top: 0;
|
|
20
|
+
left: 0;
|
|
21
|
+
right: 0;
|
|
22
|
+
bottom: 0;
|
|
23
|
+
background: rgba(255, 255, 255, 0.8);
|
|
24
|
+
z-index: 9998;
|
|
25
|
+
display: ${props => props.$visible ? 'block' : 'none'};
|
|
26
|
+
animation: ${fadeIn} 0.2s ease-out;
|
|
27
|
+
backdrop-filter: blur(2px);
|
|
28
|
+
|
|
29
|
+
[data-theme='dark'] & {
|
|
30
|
+
background: rgba(0, 0, 0, 0.8);
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
export const FloatingContainer = styled.div.attrs(props => ({
|
|
34
|
+
style: {
|
|
35
|
+
left: `${props.$x}px`,
|
|
36
|
+
top: `${props.$y}px`,
|
|
37
|
+
},
|
|
38
|
+
})) `
|
|
39
|
+
position: ${props => props.$isConstrained ? 'absolute' : 'fixed'};
|
|
40
|
+
z-index: ${props => props.$isConfigMode ? 9999 : 10000};
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: ${props => props.$orientation === 'horizontal' ? 'row' : 'column'};
|
|
43
|
+
align-items: center;
|
|
44
|
+
background: linear-gradient(135deg, #0071BC 0%, #1B1464 100%);
|
|
45
|
+
border: 1px solid #667eea;
|
|
46
|
+
border-radius: 14px;
|
|
47
|
+
padding: 6px;
|
|
48
|
+
gap: 3px;
|
|
49
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
|
|
50
|
+
0 6px 16px rgba(0, 0, 0, 0.2);
|
|
51
|
+
cursor: ${props => props.$isDragging ? 'grabbing' : 'default'};
|
|
52
|
+
user-select: none;
|
|
53
|
+
animation: ${props => props.$isConfigMode && css `${shake} 0.3s ease-in-out`};
|
|
54
|
+
transition: none;
|
|
55
|
+
|
|
56
|
+
&:hover {
|
|
57
|
+
background: linear-gradient(135deg, #0071BC 0%, #1B1464 100%);
|
|
58
|
+
border: 1px solid #667eea;
|
|
59
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
|
|
60
|
+
0 6px 16px rgba(0, 0, 0, 0.2);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
[data-theme='dark'] & {
|
|
64
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
65
|
+
border: 1px solid #1a1a2e;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
69
|
+
border: 1px solid #1a1a2e;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
export const GripHandle = styled.div `
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
justify-content: center;
|
|
77
|
+
padding: ${props => props.$orientation === 'horizontal' ? '10px 6px' : '6px 10px'};
|
|
78
|
+
cursor: grab;
|
|
79
|
+
color: rgba(255, 255, 255, 0.7);
|
|
80
|
+
transition: all 0.2s ease;
|
|
81
|
+
border-radius: 6px;
|
|
82
|
+
|
|
83
|
+
&:hover {
|
|
84
|
+
background: rgba(255, 255, 255, 0.1);
|
|
85
|
+
color: rgba(255, 255, 255, 1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:active {
|
|
89
|
+
cursor: grabbing;
|
|
90
|
+
background: rgba(255, 255, 255, 0.15);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
svg {
|
|
94
|
+
width: 14px;
|
|
95
|
+
height: 14px;
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
98
|
+
export const Separator = styled.div `
|
|
99
|
+
background: rgba(255, 255, 255, 0.25);
|
|
100
|
+
width: ${props => props.$orientation === 'horizontal' ? '1px' : '100%'};
|
|
101
|
+
height: ${props => props.$orientation === 'horizontal' ? '24px' : '1px'};
|
|
102
|
+
margin: ${props => props.$orientation === 'horizontal' ? '0 4px' : '4px 0'};
|
|
103
|
+
flex-shrink: 0;
|
|
104
|
+
`;
|
|
105
|
+
export const MenuButton = styled.button `
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
width: 34px;
|
|
110
|
+
height: 34px;
|
|
111
|
+
background: transparent;
|
|
112
|
+
border: none;
|
|
113
|
+
border-radius: 8px;
|
|
114
|
+
color: white;
|
|
115
|
+
font-size: 16px;
|
|
116
|
+
cursor: pointer;
|
|
117
|
+
transition: background 0.2s ease;
|
|
118
|
+
position: relative;
|
|
119
|
+
|
|
120
|
+
&:hover:not(:disabled) {
|
|
121
|
+
background: rgba(255, 255, 255, 0.2);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
&:active:not(:disabled) {
|
|
125
|
+
opacity: 0.8;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
&:disabled {
|
|
129
|
+
opacity: 0.5;
|
|
130
|
+
cursor: default;
|
|
131
|
+
color: rgba(255, 255, 255, 0.6);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
svg {
|
|
135
|
+
width: 18px;
|
|
136
|
+
height: 18px;
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
export const ConfigButton = styled.button `
|
|
140
|
+
display: flex;
|
|
141
|
+
align-items: center;
|
|
142
|
+
justify-content: center;
|
|
143
|
+
width: 21px;
|
|
144
|
+
height: 21px;
|
|
145
|
+
background: transparent;
|
|
146
|
+
border: none;
|
|
147
|
+
border-radius: 4px;
|
|
148
|
+
color: rgba(255, 255, 255, 0.5);
|
|
149
|
+
font-size: 10px;
|
|
150
|
+
cursor: pointer;
|
|
151
|
+
transition: all 0.2s ease;
|
|
152
|
+
padding: 4px;
|
|
153
|
+
|
|
154
|
+
&:hover:not(:disabled) {
|
|
155
|
+
background: rgba(255, 255, 255, 0.1);
|
|
156
|
+
color: rgba(255, 255, 255, 0.8);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
&:active:not(:disabled) {
|
|
160
|
+
transform: scale(0.9);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
&:disabled {
|
|
164
|
+
opacity: 0.3;
|
|
165
|
+
cursor: not-allowed;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
svg {
|
|
169
|
+
width: 16px;
|
|
170
|
+
height: 16px;
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
export const ApplyButton = styled.button `
|
|
174
|
+
display: flex;
|
|
175
|
+
align-items: center;
|
|
176
|
+
justify-content: center;
|
|
177
|
+
width: 24px;
|
|
178
|
+
height: 24px;
|
|
179
|
+
background: transparent;
|
|
180
|
+
border: none;
|
|
181
|
+
border-radius: 4px;
|
|
182
|
+
color: rgba(34, 197, 94, 1);
|
|
183
|
+
font-size: 10px;
|
|
184
|
+
cursor: pointer;
|
|
185
|
+
transition: all 0.2s ease;
|
|
186
|
+
padding: 3px;
|
|
187
|
+
|
|
188
|
+
&:hover:not(:disabled) {
|
|
189
|
+
background: rgba(255, 255, 255, 0.1);
|
|
190
|
+
color: rgba(34, 197, 94, 1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
&:active:not(:disabled) {
|
|
194
|
+
transform: scale(0.9);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&:disabled {
|
|
198
|
+
opacity: 0.3;
|
|
199
|
+
cursor: default;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
svg {
|
|
203
|
+
width: 20px;
|
|
204
|
+
height: 20px;
|
|
205
|
+
}
|
|
206
|
+
`;
|
|
207
|
+
export const ContextMenuButton = styled(MenuButton) `
|
|
208
|
+
svg {
|
|
209
|
+
transform: translateY(0);
|
|
210
|
+
}
|
|
211
|
+
`;
|
|
212
|
+
export const AddButton = styled.button `
|
|
213
|
+
display: flex;
|
|
214
|
+
align-items: center;
|
|
215
|
+
justify-content: center;
|
|
216
|
+
width: 28px;
|
|
217
|
+
height: 28px;
|
|
218
|
+
background: rgba(255, 255, 255, 0.15);
|
|
219
|
+
border: 1px dashed rgba(255, 255, 255, 0.4);
|
|
220
|
+
border-radius: 8px;
|
|
221
|
+
color: white;
|
|
222
|
+
font-size: 20px;
|
|
223
|
+
font-weight: bold;
|
|
224
|
+
line-height: 0;
|
|
225
|
+
cursor: pointer;
|
|
226
|
+
transition: all 0.2s ease;
|
|
227
|
+
position: relative;
|
|
228
|
+
margin-right: 6px;
|
|
229
|
+
margin-left: 8px;
|
|
230
|
+
padding: 0;
|
|
231
|
+
|
|
232
|
+
&:hover {
|
|
233
|
+
background: rgba(255, 255, 255, 0.25);
|
|
234
|
+
border-color: rgba(255, 255, 255, 0.6);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
&:active {
|
|
238
|
+
transform: scale(0.95);
|
|
239
|
+
}
|
|
240
|
+
`;
|
|
241
|
+
export const RemoveButton = styled.button `
|
|
242
|
+
position: absolute;
|
|
243
|
+
top: -6px;
|
|
244
|
+
right: -6px;
|
|
245
|
+
width: 20px;
|
|
246
|
+
height: 20px;
|
|
247
|
+
background: #ef4444;
|
|
248
|
+
border: none;
|
|
249
|
+
border-radius: 50%;
|
|
250
|
+
color: white;
|
|
251
|
+
font-size: 14px;
|
|
252
|
+
font-weight: bold;
|
|
253
|
+
line-height: 0;
|
|
254
|
+
cursor: pointer;
|
|
255
|
+
display: flex;
|
|
256
|
+
align-items: center;
|
|
257
|
+
justify-content: center;
|
|
258
|
+
padding: 0;
|
|
259
|
+
transition: all 0.2s ease;
|
|
260
|
+
z-index: 1;
|
|
261
|
+
|
|
262
|
+
&:hover {
|
|
263
|
+
background: #dc2626;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
&:active {
|
|
267
|
+
background: #b91c1c;
|
|
268
|
+
}
|
|
269
|
+
`;
|
|
270
|
+
export const UndoButton = styled.button `
|
|
271
|
+
display: flex;
|
|
272
|
+
align-items: center;
|
|
273
|
+
justify-content: center;
|
|
274
|
+
width: 24px;
|
|
275
|
+
height: 24px;
|
|
276
|
+
background: transparent;
|
|
277
|
+
border: none;
|
|
278
|
+
border-radius: 4px;
|
|
279
|
+
color: rgba(249, 115, 22, 1);
|
|
280
|
+
font-size: 10px;
|
|
281
|
+
cursor: pointer;
|
|
282
|
+
transition: all 0.2s ease;
|
|
283
|
+
padding: 2px;
|
|
284
|
+
|
|
285
|
+
&:hover:not(:disabled) {
|
|
286
|
+
background: rgba(255, 255, 255, 0.1);
|
|
287
|
+
color: rgba(249, 115, 22, 1);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
&:active:not(:disabled) {
|
|
291
|
+
transform: scale(0.9);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
&:disabled {
|
|
295
|
+
opacity: 0.3;
|
|
296
|
+
cursor: default;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
svg {
|
|
300
|
+
width: 16px;
|
|
301
|
+
height: 16px;
|
|
302
|
+
}
|
|
303
|
+
`;
|
|
304
|
+
export const DraggableItem = styled.div `
|
|
305
|
+
position: relative;
|
|
306
|
+
opacity: ${props => props.$isDragging ? 0.3 : 1};
|
|
307
|
+
transform: ${props => {
|
|
308
|
+
if (props.$isDragging)
|
|
309
|
+
return 'scale(1.1) rotate(5deg)';
|
|
310
|
+
if (props.$isDragOver)
|
|
311
|
+
return 'scale(1.05)';
|
|
312
|
+
return 'scale(1)';
|
|
313
|
+
}};
|
|
314
|
+
transition: all 0.2s ease;
|
|
315
|
+
filter: ${props => props.$isDragging ? 'brightness(1.3)' : 'brightness(1)'};
|
|
316
|
+
|
|
317
|
+
${props => props.$isDragging && css `
|
|
318
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
|
319
|
+
z-index: 100;
|
|
320
|
+
`}
|
|
321
|
+
|
|
322
|
+
${props => props.$isDragOver && css `
|
|
323
|
+
&::before {
|
|
324
|
+
content: '';
|
|
325
|
+
position: absolute;
|
|
326
|
+
top: -4px;
|
|
327
|
+
left: 50%;
|
|
328
|
+
transform: translateX(-50%);
|
|
329
|
+
width: 40px;
|
|
330
|
+
height: 3px;
|
|
331
|
+
background: rgba(255, 255, 255, 0.8);
|
|
332
|
+
border-radius: 2px;
|
|
333
|
+
box-shadow: 0 0 8px rgba(255, 255, 255, 0.6);
|
|
334
|
+
}
|
|
335
|
+
`}
|
|
336
|
+
`;
|
|
337
|
+
export const ContextMenuWrapper = styled.div `
|
|
338
|
+
position: static;
|
|
339
|
+
display: contents;
|
|
340
|
+
`;
|
|
341
|
+
export const ButtonGroup = styled.div `
|
|
342
|
+
display: flex;
|
|
343
|
+
flex-direction: ${props => props.$orientation === 'vertical' ? 'column' : 'row'};
|
|
344
|
+
align-items: center;
|
|
345
|
+
gap: 0;
|
|
346
|
+
`;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TMContextMenuItemProps } from '../ContextMenu';
|
|
2
|
+
export interface TMFloatingMenuItem {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
icon: React.ReactNode;
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
isPinned?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface TMFloatingMenuBarProps {
|
|
11
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
12
|
+
contextMenuItems?: TMContextMenuItemProps[];
|
|
13
|
+
isConstrained?: boolean;
|
|
14
|
+
defaultPosition?: Position;
|
|
15
|
+
maxItems?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface Position {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
}
|
|
21
|
+
export interface TMFloatingMenuBarState {
|
|
22
|
+
position: Position;
|
|
23
|
+
isDragging: boolean;
|
|
24
|
+
isConfigMode: boolean;
|
|
25
|
+
orientation: 'horizontal' | 'vertical';
|
|
26
|
+
items: TMFloatingMenuItem[];
|
|
27
|
+
draggedItemIndex: number | null;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,31 +4,68 @@ import TMModal from './TMModal';
|
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import { SDKUI_Localizator, TMLayoutWaitingContainer } from '../..';
|
|
6
6
|
import { getButtonAttributes, getSelectedItem } from '../../helper/dcmtsHelper';
|
|
7
|
+
import { DeviceType, useDeviceType } from './TMDeviceProvider';
|
|
7
8
|
const IframeContainer = styled.div `
|
|
8
9
|
display: flex;
|
|
9
10
|
height: 100%;
|
|
10
11
|
flex-direction: column;
|
|
11
|
-
|
|
12
|
+
position: relative;
|
|
12
13
|
`;
|
|
13
14
|
const StyledIframe = styled.iframe `
|
|
14
15
|
border: none;
|
|
15
16
|
flex: 1;
|
|
16
17
|
`;
|
|
18
|
+
const LoadingOverlay = styled.div `
|
|
19
|
+
position: absolute;
|
|
20
|
+
top: 0;
|
|
21
|
+
left: 0;
|
|
22
|
+
right: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
background-color: rgba(128, 128, 128, 0.3);
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
z-index: 1000;
|
|
29
|
+
|
|
30
|
+
&::after {
|
|
31
|
+
content: '';
|
|
32
|
+
width: 40px;
|
|
33
|
+
height: 40px;
|
|
34
|
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
35
|
+
border-top-color: #fff;
|
|
36
|
+
border-radius: 50%;
|
|
37
|
+
animation: spin 0.8s linear infinite;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@keyframes spin {
|
|
41
|
+
to {
|
|
42
|
+
transform: rotate(360deg);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
17
46
|
const TMCustomButton = (props) => {
|
|
18
47
|
const { button, isModal = true, formData, selectedItems, onClose } = props;
|
|
19
48
|
const { appName: scriptUrl, arguments: args } = button;
|
|
49
|
+
const Device = useDeviceType();
|
|
20
50
|
const iframeRef = useRef(null);
|
|
21
51
|
const attributes = useMemo(() => getButtonAttributes(args, formData, selectedItems), [args, formData, selectedItems]);
|
|
22
52
|
const RunOnce = button.mode === "RunOnce";
|
|
23
53
|
const [loading, setLoading] = useState(true);
|
|
24
54
|
const [error, setError] = useState(false);
|
|
25
|
-
const
|
|
55
|
+
const itemsToProcess = useMemo(() => selectedItems && selectedItems.length > 0 ? selectedItems : [attributes], [selectedItems, attributes]);
|
|
26
56
|
// Stati per il wait panel
|
|
27
|
-
const [showWaitPanel, setShowWaitPanel] = useState(
|
|
28
|
-
const [waitPanelText, setWaitPanelText] = useState(SDKUI_Localizator.CustomButtonActions.replaceParams(1,
|
|
57
|
+
const [showWaitPanel, setShowWaitPanel] = useState(itemsToProcess.length > 0 && !RunOnce);
|
|
58
|
+
const [waitPanelText, setWaitPanelText] = useState(SDKUI_Localizator.CustomButtonActions.replaceParams(1, itemsToProcess.length));
|
|
29
59
|
const [waitPanelValue, setWaitPanelValue] = useState(0);
|
|
30
|
-
const [waitPanelMaxValue, setWaitPanelMaxValue] = useState(
|
|
60
|
+
const [waitPanelMaxValue, setWaitPanelMaxValue] = useState(itemsToProcess.length);
|
|
31
61
|
const [abortController, setAbortController] = useState(undefined);
|
|
62
|
+
// Aggiungi timestamp all'URL per evitare cache
|
|
63
|
+
const iframeUrl = useMemo(() => {
|
|
64
|
+
if (!scriptUrl)
|
|
65
|
+
return '';
|
|
66
|
+
const separator = scriptUrl.includes('?') ? '&' : '?';
|
|
67
|
+
return `${scriptUrl}${separator}t=${Date.now()}`;
|
|
68
|
+
}, [scriptUrl]);
|
|
32
69
|
const targetOrigin = useMemo(() => {
|
|
33
70
|
if (!scriptUrl)
|
|
34
71
|
return '*';
|
|
@@ -41,26 +78,35 @@ const TMCustomButton = (props) => {
|
|
|
41
78
|
}
|
|
42
79
|
}, [scriptUrl]);
|
|
43
80
|
const handleLoad = () => setLoading(false);
|
|
81
|
+
const isMobile = Device === DeviceType.MOBILE;
|
|
44
82
|
const handleError = () => {
|
|
45
83
|
setLoading(false);
|
|
46
84
|
setError(true);
|
|
47
85
|
};
|
|
48
86
|
const executeSequentially = async (controller) => {
|
|
49
|
-
if (!
|
|
87
|
+
if (!itemsToProcess)
|
|
50
88
|
return;
|
|
51
|
-
for (const [index, item] of
|
|
89
|
+
for (const [index, item] of itemsToProcess.entries()) {
|
|
52
90
|
if (controller.signal.aborted)
|
|
53
91
|
break;
|
|
54
|
-
setWaitPanelText(SDKUI_Localizator.CustomButtonActions.replaceParams(index + 1,
|
|
92
|
+
setWaitPanelText(SDKUI_Localizator.CustomButtonActions.replaceParams(index + 1, itemsToProcess.length));
|
|
55
93
|
setWaitPanelValue(index);
|
|
56
94
|
// Attendi che l'iframe sia pronto e invia il messaggio
|
|
57
95
|
await new Promise((resolve) => {
|
|
58
96
|
const checkIframe = setInterval(() => {
|
|
59
97
|
if (iframeRef.current?.contentWindow) {
|
|
60
98
|
clearInterval(checkIframe);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
99
|
+
if (selectedItems && selectedItems.length > 0) {
|
|
100
|
+
//devo convertire item in formData
|
|
101
|
+
const processedItem = getSelectedItem(args, formData, item);
|
|
102
|
+
postMessageIframe(processedItem);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
postMessageIframe(item);
|
|
106
|
+
}
|
|
107
|
+
//imposta 100% se sono all'ultimo item
|
|
108
|
+
if (index === itemsToProcess.length - 1)
|
|
109
|
+
setWaitPanelValue(index + 1);
|
|
64
110
|
// Attendi prima di passare al prossimo
|
|
65
111
|
setTimeout(() => {
|
|
66
112
|
setWaitPanelValue(index + 1);
|
|
@@ -82,8 +128,7 @@ const TMCustomButton = (props) => {
|
|
|
82
128
|
useEffect(() => {
|
|
83
129
|
if (loading || error)
|
|
84
130
|
return;
|
|
85
|
-
|
|
86
|
-
if (!RunOnce && selectedItemsCount > 0) {
|
|
131
|
+
if (!RunOnce && itemsToProcess.length > 0) {
|
|
87
132
|
// esegui per ogni item selezionato
|
|
88
133
|
const controller = new AbortController();
|
|
89
134
|
controller.signal.addEventListener('abort', () => {
|
|
@@ -91,7 +136,7 @@ const TMCustomButton = (props) => {
|
|
|
91
136
|
onClose?.();
|
|
92
137
|
});
|
|
93
138
|
setAbortController(controller);
|
|
94
|
-
setWaitPanelMaxValue(
|
|
139
|
+
setWaitPanelMaxValue(itemsToProcess.length);
|
|
95
140
|
executeSequentially(controller);
|
|
96
141
|
}
|
|
97
142
|
else {
|
|
@@ -103,7 +148,6 @@ const TMCustomButton = (props) => {
|
|
|
103
148
|
onClose?.();
|
|
104
149
|
}, 2000);
|
|
105
150
|
}
|
|
106
|
-
//clearTimeout(timeoutIframe);
|
|
107
151
|
}
|
|
108
152
|
}, [loading, error, RunOnce]);
|
|
109
153
|
useEffect(() => {
|
|
@@ -112,7 +156,7 @@ const TMCustomButton = (props) => {
|
|
|
112
156
|
onClose?.();
|
|
113
157
|
}
|
|
114
158
|
}, []);
|
|
115
|
-
const iframeContent = (_jsxs(IframeContainer, { style: !RunOnce ? { visibility: 'hidden' } : {}, children: [error && _jsx("div", { children: "Si \u00E8 verificato un errore nel caricamento del contenuto." }), !error && _jsx(StyledIframe, { ref: iframeRef, loading: 'lazy', onLoad: handleLoad, onError: handleError, src:
|
|
116
|
-
return isModal && RunOnce ? (_jsx(TMModal, { title: button.title, width: '60%', height: '70%', resizable: true, expandable: true, onClose: onClose, children: iframeContent })) : !RunOnce && (_jsxs(_Fragment, { children: [_jsx(TMLayoutWaitingContainer, { showWaitPanel: showWaitPanel, waitPanelTitle: SDKUI_Localizator.CustomButtonAction, showWaitPanelPrimary: true, waitPanelTextPrimary: waitPanelText, waitPanelValuePrimary: waitPanelValue, waitPanelMaxValuePrimary: waitPanelMaxValue, showWaitPanelSecondary: false, isCancelable: true, abortController: abortController, children: undefined }), iframeContent] }));
|
|
159
|
+
const iframeContent = (_jsxs(IframeContainer, { style: !RunOnce ? { visibility: 'hidden' } : {}, children: [loading && _jsx(LoadingOverlay, {}), error && _jsx("div", { children: "Si \u00E8 verificato un errore nel caricamento del contenuto." }), !error && _jsx(StyledIframe, { ref: iframeRef, loading: 'lazy', onLoad: handleLoad, onError: handleError, src: iframeUrl })] }));
|
|
160
|
+
return isModal && RunOnce ? (_jsx(TMModal, { title: button.title, width: isMobile ? '95%' : '60%', height: isMobile ? '95%' : '70%', resizable: isMobile ? false : true, expandable: isMobile ? false : true, onClose: onClose, children: iframeContent })) : !RunOnce && (_jsxs(_Fragment, { children: [_jsx(TMLayoutWaitingContainer, { showWaitPanel: showWaitPanel, waitPanelTitle: SDKUI_Localizator.CustomButtonAction, showWaitPanelPrimary: true, waitPanelTextPrimary: waitPanelText, waitPanelValuePrimary: waitPanelValue, waitPanelMaxValuePrimary: waitPanelMaxValue, showWaitPanelSecondary: false, isCancelable: true, abortController: abortController, children: undefined }), iframeContent] }));
|
|
117
161
|
};
|
|
118
162
|
export default TMCustomButton;
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { IColumnProps, IDataGridOptions, IMasterDetailProps } from 'devextreme-react/data-grid';
|
|
3
3
|
import dxDataGrid from 'devextreme/ui/data_grid';
|
|
4
4
|
import { ITMCounterContainerProps } from './TMCounterContainer';
|
|
5
|
+
import { TMContextMenuItemProps } from '../NewComponents/ContextMenu/types';
|
|
5
6
|
export interface TMDataGridContextMenuItem {
|
|
6
7
|
text: string;
|
|
7
8
|
icon: string;
|
|
@@ -31,16 +32,16 @@ export interface TMDataGridProps<T> extends IDataGridOptions {
|
|
|
31
32
|
pageSize?: TMDataGridPageSize;
|
|
32
33
|
/** Configures the search panel position in the toolbar */
|
|
33
34
|
searchPanelToolbarPosition?: 'before' | 'default';
|
|
34
|
-
/**
|
|
35
|
-
|
|
35
|
+
/** Trigger to set focus on SearchPanel (only if visible) - change the number to trigger focus */
|
|
36
|
+
searchPanelFocusTrigger?: number;
|
|
36
37
|
/** Show the header filter */
|
|
37
38
|
showHeaderFilter?: boolean;
|
|
38
39
|
/** Show the filter panel */
|
|
39
40
|
showFilterPanel?: boolean;
|
|
40
41
|
/** Show the load panel */
|
|
41
42
|
showLoadPanel?: boolean;
|
|
42
|
-
/** Show the column chooser */
|
|
43
|
-
|
|
43
|
+
/** Show the header column chooser in context menu */
|
|
44
|
+
showHeaderColumnChooser?: boolean;
|
|
44
45
|
/** Show the search panel */
|
|
45
46
|
showSearchPanel?: boolean;
|
|
46
47
|
/** Show the group panel */
|
|
@@ -51,6 +52,8 @@ export interface TMDataGridProps<T> extends IDataGridOptions {
|
|
|
51
52
|
masterDetail?: IMasterDetailProps;
|
|
52
53
|
/** On Has Filters Change */
|
|
53
54
|
onHasFiltersChange?: (hasFilters: boolean) => void;
|
|
55
|
+
/** Custom context menu items - when provided, replaces DevExtreme's native context menu with TMContextMenu */
|
|
56
|
+
customContextMenuItems?: TMContextMenuItemProps[];
|
|
54
57
|
}
|
|
55
58
|
declare const TMDataGrid: React.ForwardRefExoticComponent<TMDataGridProps<unknown> & React.RefAttributes<dxDataGrid<any, any>>>;
|
|
56
59
|
export default TMDataGrid;
|