@vention/machine-apps-components 0.0.0-dev.4527.a3d343ca7
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/README.md +859 -0
- package/index.esm.d.ts +1 -0
- package/index.esm.js +3658 -0
- package/package.json +40 -0
- package/src/constants/z-index.d.ts +8 -0
- package/src/contexts/i18n-context.d.ts +12 -0
- package/src/contexts/i18n-provider.d.ts +13 -0
- package/src/hooks/use-auto-scroll-input.d.ts +6 -0
- package/src/hooks/use-i18n.d.ts +19 -0
- package/src/i18n/config.d.ts +8 -0
- package/src/i18n/locales/de.d.ts +131 -0
- package/src/i18n/locales/en.d.ts +131 -0
- package/src/i18n/locales/es.d.ts +131 -0
- package/src/i18n/locales/fr.d.ts +131 -0
- package/src/i18n/utils.d.ts +13 -0
- package/src/index.d.ts +27 -0
- package/src/lib/action-button/action-button.d.ts +14 -0
- package/src/lib/action-button/action-button.stories.d.ts +15 -0
- package/src/lib/file-upload-panel/file-upload-panel.d.ts +23 -0
- package/src/lib/file-upload-panel/file-upload-panel.stories.d.ts +12 -0
- package/src/lib/i18n-settings/i18n-settings.d.ts +8 -0
- package/src/lib/i18n-settings/i18n-settings.stories.d.ts +7 -0
- package/src/lib/logs/log-filter-form.d.ts +9 -0
- package/src/lib/logs/logs-pagination.d.ts +8 -0
- package/src/lib/logs/logs-panel.d.ts +59 -0
- package/src/lib/logs/logs-panel.stories.d.ts +6 -0
- package/src/lib/logs/logs-table.d.ts +15 -0
- package/src/lib/navigation-bar/navigation-bar-item.d.ts +17 -0
- package/src/lib/navigation-bar/navigation-bar.d.ts +20 -0
- package/src/lib/navigation-bar/navigation-bar.stories.d.ts +6 -0
- package/src/lib/navigation-bar/navigation-confirmation-modal.d.ts +7 -0
- package/src/lib/navigation-bar/password-protection-modal.d.ts +8 -0
- package/src/lib/navigation-bar/password-protection-modal.stories.d.ts +6 -0
- package/src/lib/navigation-bar/time-label.d.ts +6 -0
- package/src/lib/product-form-list/product-form-list.d.ts +27 -0
- package/src/lib/product-form-list/product-form-list.stories.d.ts +18 -0
- package/src/lib/settings-page/settings-page.d.ts +11 -0
- package/src/lib/settings-page/settings-page.stories.d.ts +9 -0
- package/src/lib/sidebar/sidebar.d.ts +18 -0
- package/src/lib/sidebar/sidebar.stories.d.ts +8 -0
- package/src/lib/status-top-bar/status-top-bar-button.d.ts +17 -0
- package/src/lib/status-top-bar/status-top-bar.d.ts +27 -0
- package/src/lib/status-top-bar/status-top-bar.stories.d.ts +10 -0
- package/src/lib/step-progress-circle/step-progress-circle.d.ts +14 -0
- package/src/lib/step-progress-circle/step-progress-circle.stories.d.ts +16 -0
- package/src/lib/utils/api-config-utils.d.ts +34 -0
- package/src/lib/utils/device-utils.d.ts +14 -0
- package/src/test-setup.d.ts +1 -0
- package/src/test-utils.d.ts +13 -0
- package/src/types/user-level.d.ts +6 -0
package/index.esm.js
ADDED
|
@@ -0,0 +1,3658 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import React, { createContext, useState, useEffect, useCallback, useContext, useMemo, memo, useRef, forwardRef, useImperativeHandle } from 'react';
|
|
3
|
+
import i18n from 'i18next';
|
|
4
|
+
import { initReactI18next, useTranslation } from 'react-i18next';
|
|
5
|
+
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
6
|
+
import dayjs from 'dayjs';
|
|
7
|
+
import utc from 'dayjs/plugin/utc';
|
|
8
|
+
import timezone from 'dayjs/plugin/timezone';
|
|
9
|
+
import 'dayjs/locale/en';
|
|
10
|
+
import 'dayjs/locale/fr';
|
|
11
|
+
import 'dayjs/locale/de';
|
|
12
|
+
import 'dayjs/locale/es';
|
|
13
|
+
import { Box, useTheme, Typography, Button, InputAdornment, IconButton, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, List, ListItem, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
|
|
14
|
+
import { VentionSelect, VentionModalBase, VentionIcon, VentionTextInput, COLORS, VentionButton, VentionStatusIndicator, VentionSpinner, VentionAlert, VentionDropZone, VentionUploadFile, VentionIconButton } from '@vention/machine-ui';
|
|
15
|
+
import { tss } from 'tss-react/mui';
|
|
16
|
+
import { useLocation, useNavigate } from 'react-router-dom';
|
|
17
|
+
|
|
18
|
+
const I18nContext = createContext(undefined);
|
|
19
|
+
|
|
20
|
+
var enTranslations = {
|
|
21
|
+
common: {
|
|
22
|
+
units: {
|
|
23
|
+
mm: "mm",
|
|
24
|
+
in: "in",
|
|
25
|
+
metric: "Metric",
|
|
26
|
+
imperial: "Imperial"
|
|
27
|
+
},
|
|
28
|
+
settings: {
|
|
29
|
+
unitSystem: "Unit System",
|
|
30
|
+
timezone: "Timezone",
|
|
31
|
+
autoDetect: "Auto-detect",
|
|
32
|
+
locale: "Language"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
actionButton: {
|
|
36
|
+
home: "Home",
|
|
37
|
+
start: "Start",
|
|
38
|
+
stop: "Stop",
|
|
39
|
+
pause: "Pause",
|
|
40
|
+
reset: "Reset",
|
|
41
|
+
clear: "Clear",
|
|
42
|
+
run: "Run",
|
|
43
|
+
resume: "Resume"
|
|
44
|
+
},
|
|
45
|
+
logs: {
|
|
46
|
+
table: {
|
|
47
|
+
date: "Date",
|
|
48
|
+
type: "Type",
|
|
49
|
+
code: "Code",
|
|
50
|
+
message: "Message",
|
|
51
|
+
description: "Description"
|
|
52
|
+
},
|
|
53
|
+
type: {
|
|
54
|
+
error: "Error",
|
|
55
|
+
warning: "Warning",
|
|
56
|
+
info: "Info"
|
|
57
|
+
},
|
|
58
|
+
emptyState: {
|
|
59
|
+
noLogs: "You have no logs"
|
|
60
|
+
},
|
|
61
|
+
loading: "Loading logs...",
|
|
62
|
+
loadingMore: "Loading more logs...",
|
|
63
|
+
noMoreLogs: "No more logs to load",
|
|
64
|
+
error: {
|
|
65
|
+
loading: "Error loading logs"
|
|
66
|
+
},
|
|
67
|
+
filter: {
|
|
68
|
+
from: "From",
|
|
69
|
+
to: "To",
|
|
70
|
+
type: "Type",
|
|
71
|
+
sort: "Sort",
|
|
72
|
+
reset: "Reset",
|
|
73
|
+
typeOptions: {
|
|
74
|
+
all: "All",
|
|
75
|
+
error: "Error",
|
|
76
|
+
warning: "Warning",
|
|
77
|
+
info: "Info"
|
|
78
|
+
},
|
|
79
|
+
sortOptions: {
|
|
80
|
+
latest: "From latest",
|
|
81
|
+
oldest: "From oldest"
|
|
82
|
+
},
|
|
83
|
+
chooseType: "Choose type"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
navigation: {
|
|
87
|
+
pages: {
|
|
88
|
+
home: "Home",
|
|
89
|
+
operation: "Operation",
|
|
90
|
+
logs: "Logs",
|
|
91
|
+
calibration: "Calibration",
|
|
92
|
+
settings: "Settings"
|
|
93
|
+
},
|
|
94
|
+
bar: {
|
|
95
|
+
controlCenter: "Control Center",
|
|
96
|
+
support: "Support"
|
|
97
|
+
},
|
|
98
|
+
modal: {
|
|
99
|
+
exit: {
|
|
100
|
+
title: "You are about to exit the application",
|
|
101
|
+
message: "Please make sure your changes are saved before you leave the app."
|
|
102
|
+
},
|
|
103
|
+
goToControlCenter: "Go to Control Center",
|
|
104
|
+
goToRemoteSupport: "Go to Remote Support",
|
|
105
|
+
password: {
|
|
106
|
+
title: "Administrator login required",
|
|
107
|
+
label: "Password",
|
|
108
|
+
error: "Incorrect password",
|
|
109
|
+
confirm: "Confirm"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
pagination: {
|
|
114
|
+
page: "Page",
|
|
115
|
+
of: "of"
|
|
116
|
+
},
|
|
117
|
+
fileUploadPanel: {
|
|
118
|
+
defaultTitle: "Upload Files",
|
|
119
|
+
dropzoneTitle: "Drop files here or click to browse",
|
|
120
|
+
defaultFileCriteria: "All file types accepted"
|
|
121
|
+
},
|
|
122
|
+
stepProgressCircle: {
|
|
123
|
+
title: {
|
|
124
|
+
progress: "Progress",
|
|
125
|
+
manufacturing: "Manufacturing",
|
|
126
|
+
processing: "Processing",
|
|
127
|
+
uploading: "Uploading",
|
|
128
|
+
notstarted: "Not Started",
|
|
129
|
+
ready: "Ready",
|
|
130
|
+
inprogress: "In Progress",
|
|
131
|
+
complete: "Complete",
|
|
132
|
+
loading: "Loading",
|
|
133
|
+
waiting: "Waiting",
|
|
134
|
+
warning: "Warning",
|
|
135
|
+
error: "Error"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
productFormList: {
|
|
139
|
+
add: "Add",
|
|
140
|
+
cancel: "Cancel",
|
|
141
|
+
save: "Save",
|
|
142
|
+
create: "Create",
|
|
143
|
+
modify: "Edit",
|
|
144
|
+
new: "New",
|
|
145
|
+
delete: "Delete",
|
|
146
|
+
deleteConfirmation: "Are you sure you want to delete this item?",
|
|
147
|
+
emptyState: "No items yet. Click Add to create one."
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
var frTranslations = {
|
|
152
|
+
common: {
|
|
153
|
+
units: {
|
|
154
|
+
mm: "mm",
|
|
155
|
+
in: "po",
|
|
156
|
+
metric: "Métrique",
|
|
157
|
+
imperial: "Impérial"
|
|
158
|
+
},
|
|
159
|
+
settings: {
|
|
160
|
+
unitSystem: "Système d'unités",
|
|
161
|
+
timezone: "Fuseau horaire",
|
|
162
|
+
autoDetect: "Détection automatique",
|
|
163
|
+
locale: "Langue"
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
actionButton: {
|
|
167
|
+
home: "Origine",
|
|
168
|
+
start: "Démarrer",
|
|
169
|
+
stop: "Arrêter",
|
|
170
|
+
pause: "Pause",
|
|
171
|
+
reset: "Réinitialiser",
|
|
172
|
+
clear: "Effacer",
|
|
173
|
+
run: "Exécuter",
|
|
174
|
+
resume: "Reprendre"
|
|
175
|
+
},
|
|
176
|
+
logs: {
|
|
177
|
+
table: {
|
|
178
|
+
date: "Date",
|
|
179
|
+
type: "Type",
|
|
180
|
+
code: "Code",
|
|
181
|
+
message: "Message",
|
|
182
|
+
description: "Description"
|
|
183
|
+
},
|
|
184
|
+
type: {
|
|
185
|
+
error: "Erreur",
|
|
186
|
+
warning: "Avertissement",
|
|
187
|
+
info: "Information"
|
|
188
|
+
},
|
|
189
|
+
emptyState: {
|
|
190
|
+
noLogs: "Vous n'avez aucun journal"
|
|
191
|
+
},
|
|
192
|
+
loading: "Chargement des journaux...",
|
|
193
|
+
loadingMore: "Chargement de plus de journaux...",
|
|
194
|
+
noMoreLogs: "Aucun autre journal à charger",
|
|
195
|
+
error: {
|
|
196
|
+
loading: "Erreur lors du chargement des journaux"
|
|
197
|
+
},
|
|
198
|
+
filter: {
|
|
199
|
+
from: "De",
|
|
200
|
+
to: "À",
|
|
201
|
+
type: "Type",
|
|
202
|
+
sort: "Trier",
|
|
203
|
+
reset: "Réinitialiser",
|
|
204
|
+
typeOptions: {
|
|
205
|
+
all: "Tous",
|
|
206
|
+
error: "Erreur",
|
|
207
|
+
warning: "Avertissement",
|
|
208
|
+
info: "Information"
|
|
209
|
+
},
|
|
210
|
+
sortOptions: {
|
|
211
|
+
latest: "Du plus récent",
|
|
212
|
+
oldest: "Du plus ancien"
|
|
213
|
+
},
|
|
214
|
+
chooseType: "Choisir le type"
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
navigation: {
|
|
218
|
+
pages: {
|
|
219
|
+
home: "Accueil",
|
|
220
|
+
operation: "Opération",
|
|
221
|
+
logs: "Journaux",
|
|
222
|
+
calibration: "Calibration",
|
|
223
|
+
settings: "Paramètres"
|
|
224
|
+
},
|
|
225
|
+
bar: {
|
|
226
|
+
controlCenter: "Centre de contrôle",
|
|
227
|
+
support: "Support"
|
|
228
|
+
},
|
|
229
|
+
modal: {
|
|
230
|
+
exit: {
|
|
231
|
+
title: "Vous êtes sur le point de quitter l'application",
|
|
232
|
+
message: "Veuillez vous assurer que vos modifications sont enregistrées avant de quitter l'application."
|
|
233
|
+
},
|
|
234
|
+
goToControlCenter: "Aller au Centre de contrôle",
|
|
235
|
+
goToRemoteSupport: "Aller au Support à distance",
|
|
236
|
+
password: {
|
|
237
|
+
title: "Connexion administrateur requise",
|
|
238
|
+
label: "Mot de passe",
|
|
239
|
+
error: "Mot de passe incorrect",
|
|
240
|
+
confirm: "Confirmer"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
pagination: {
|
|
245
|
+
page: "Page",
|
|
246
|
+
of: "sur"
|
|
247
|
+
},
|
|
248
|
+
fileUploadPanel: {
|
|
249
|
+
defaultTitle: "Téléverser des fichiers",
|
|
250
|
+
dropzoneTitle: "Déposez les fichiers ici ou cliquez pour parcourir",
|
|
251
|
+
defaultFileCriteria: "Tous les types de fichiers acceptés"
|
|
252
|
+
},
|
|
253
|
+
stepProgressCircle: {
|
|
254
|
+
title: {
|
|
255
|
+
progress: "Progression",
|
|
256
|
+
manufacturing: "Fabrication",
|
|
257
|
+
processing: "Traitement",
|
|
258
|
+
uploading: "Téléversement",
|
|
259
|
+
notstarted: "Non démarré",
|
|
260
|
+
ready: "Prêt",
|
|
261
|
+
inprogress: "En cours",
|
|
262
|
+
complete: "Terminé",
|
|
263
|
+
loading: "Chargement",
|
|
264
|
+
waiting: "En attente",
|
|
265
|
+
warning: "Avertissement",
|
|
266
|
+
error: "Erreur"
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
productFormList: {
|
|
270
|
+
add: "Ajouter",
|
|
271
|
+
cancel: "Annuler",
|
|
272
|
+
save: "Sauvegarder",
|
|
273
|
+
create: "Créer",
|
|
274
|
+
modify: "Modifier",
|
|
275
|
+
new: "Nouveau",
|
|
276
|
+
delete: "Supprimer",
|
|
277
|
+
deleteConfirmation: "Êtes-vous sûr de vouloir supprimer cet élément?",
|
|
278
|
+
emptyState: "Aucun élément. Cliquez sur Ajouter pour en créer un."
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
var deTranslations = {
|
|
283
|
+
common: {
|
|
284
|
+
units: {
|
|
285
|
+
mm: "mm",
|
|
286
|
+
in: "Zoll",
|
|
287
|
+
metric: "Metrisch",
|
|
288
|
+
imperial: "Imperial"
|
|
289
|
+
},
|
|
290
|
+
settings: {
|
|
291
|
+
unitSystem: "Einheitensystem",
|
|
292
|
+
timezone: "Zeitzone",
|
|
293
|
+
autoDetect: "Automatisch erkennen",
|
|
294
|
+
locale: "Sprache"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
actionButton: {
|
|
298
|
+
home: "Referenzfahrt",
|
|
299
|
+
start: "Starten",
|
|
300
|
+
stop: "Stoppen",
|
|
301
|
+
pause: "Pause",
|
|
302
|
+
reset: "Zurücksetzen",
|
|
303
|
+
clear: "Löschen",
|
|
304
|
+
run: "Ausführen",
|
|
305
|
+
resume: "Fortsetzen"
|
|
306
|
+
},
|
|
307
|
+
logs: {
|
|
308
|
+
table: {
|
|
309
|
+
date: "Datum",
|
|
310
|
+
type: "Typ",
|
|
311
|
+
code: "Code",
|
|
312
|
+
message: "Nachricht",
|
|
313
|
+
description: "Beschreibung"
|
|
314
|
+
},
|
|
315
|
+
type: {
|
|
316
|
+
error: "Fehler",
|
|
317
|
+
warning: "Warnung",
|
|
318
|
+
info: "Information"
|
|
319
|
+
},
|
|
320
|
+
emptyState: {
|
|
321
|
+
noLogs: "Sie haben keine Protokolle"
|
|
322
|
+
},
|
|
323
|
+
loading: "Protokolle werden geladen...",
|
|
324
|
+
loadingMore: "Weitere Protokolle werden geladen...",
|
|
325
|
+
noMoreLogs: "Keine weiteren Protokolle zum Laden",
|
|
326
|
+
error: {
|
|
327
|
+
loading: "Fehler beim Laden der Protokolle"
|
|
328
|
+
},
|
|
329
|
+
filter: {
|
|
330
|
+
from: "Von",
|
|
331
|
+
to: "Bis",
|
|
332
|
+
type: "Typ",
|
|
333
|
+
sort: "Sortieren",
|
|
334
|
+
reset: "Zurücksetzen",
|
|
335
|
+
typeOptions: {
|
|
336
|
+
all: "Alle",
|
|
337
|
+
error: "Fehler",
|
|
338
|
+
warning: "Warnung",
|
|
339
|
+
info: "Information"
|
|
340
|
+
},
|
|
341
|
+
sortOptions: {
|
|
342
|
+
latest: "Neueste zuerst",
|
|
343
|
+
oldest: "Älteste zuerst"
|
|
344
|
+
},
|
|
345
|
+
chooseType: "Typ auswählen"
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
navigation: {
|
|
349
|
+
pages: {
|
|
350
|
+
home: "Startseite",
|
|
351
|
+
operation: "Betrieb",
|
|
352
|
+
logs: "Protokolle",
|
|
353
|
+
calibration: "Kalibrierung",
|
|
354
|
+
settings: "Einstellungen"
|
|
355
|
+
},
|
|
356
|
+
bar: {
|
|
357
|
+
controlCenter: "Kontrollzentrum",
|
|
358
|
+
support: "Support"
|
|
359
|
+
},
|
|
360
|
+
modal: {
|
|
361
|
+
exit: {
|
|
362
|
+
title: "Sie sind dabei, die Anwendung zu verlassen",
|
|
363
|
+
message: "Bitte stellen Sie sicher, dass Ihre Änderungen gespeichert sind, bevor Sie die App verlassen."
|
|
364
|
+
},
|
|
365
|
+
goToControlCenter: "Zum Kontrollzentrum gehen",
|
|
366
|
+
goToRemoteSupport: "Zum Remote-Support gehen",
|
|
367
|
+
password: {
|
|
368
|
+
title: "Administrator-Anmeldung erforderlich",
|
|
369
|
+
label: "Passwort",
|
|
370
|
+
error: "Falsches Passwort",
|
|
371
|
+
confirm: "Bestätigen"
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
pagination: {
|
|
376
|
+
page: "Seite",
|
|
377
|
+
of: "von"
|
|
378
|
+
},
|
|
379
|
+
fileUploadPanel: {
|
|
380
|
+
defaultTitle: "Dateien hochladen",
|
|
381
|
+
dropzoneTitle: "Dateien hier ablegen oder klicken zum Durchsuchen",
|
|
382
|
+
defaultFileCriteria: "Alle Dateitypen akzeptiert"
|
|
383
|
+
},
|
|
384
|
+
stepProgressCircle: {
|
|
385
|
+
title: {
|
|
386
|
+
progress: "Fortschritt",
|
|
387
|
+
manufacturing: "Fertigung",
|
|
388
|
+
processing: "Verarbeitung",
|
|
389
|
+
uploading: "Hochladen",
|
|
390
|
+
notstarted: "Nicht gestartet",
|
|
391
|
+
ready: "Bereit",
|
|
392
|
+
inprogress: "In Bearbeitung",
|
|
393
|
+
complete: "Abgeschlossen",
|
|
394
|
+
loading: "Laden",
|
|
395
|
+
waiting: "Warten",
|
|
396
|
+
warning: "Warnung",
|
|
397
|
+
error: "Fehler"
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
productFormList: {
|
|
401
|
+
add: "Hinzufügen",
|
|
402
|
+
cancel: "Abbrechen",
|
|
403
|
+
save: "Speichern",
|
|
404
|
+
create: "Erstellen",
|
|
405
|
+
modify: "Bearbeiten",
|
|
406
|
+
new: "Neu",
|
|
407
|
+
delete: "Löschen",
|
|
408
|
+
deleteConfirmation: "Sind Sie sicher, dass Sie dieses Element löschen möchten?",
|
|
409
|
+
emptyState: "Noch keine Elemente. Klicken Sie auf Hinzufügen, um eines zu erstellen."
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
var esTranslations = {
|
|
414
|
+
common: {
|
|
415
|
+
units: {
|
|
416
|
+
mm: "mm",
|
|
417
|
+
in: "pulg",
|
|
418
|
+
metric: "Métrico",
|
|
419
|
+
imperial: "Imperial"
|
|
420
|
+
},
|
|
421
|
+
settings: {
|
|
422
|
+
unitSystem: "Sistema de unidades",
|
|
423
|
+
timezone: "Zona horaria",
|
|
424
|
+
autoDetect: "Detección automática",
|
|
425
|
+
locale: "Idioma"
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
actionButton: {
|
|
429
|
+
home: "Origen",
|
|
430
|
+
start: "Iniciar",
|
|
431
|
+
stop: "Detener",
|
|
432
|
+
pause: "Pausar",
|
|
433
|
+
reset: "Restablecer",
|
|
434
|
+
clear: "Limpiar",
|
|
435
|
+
run: "Ejecutar",
|
|
436
|
+
resume: "Reanudar"
|
|
437
|
+
},
|
|
438
|
+
logs: {
|
|
439
|
+
table: {
|
|
440
|
+
date: "Fecha",
|
|
441
|
+
type: "Tipo",
|
|
442
|
+
code: "Código",
|
|
443
|
+
message: "Mensaje",
|
|
444
|
+
description: "Descripción"
|
|
445
|
+
},
|
|
446
|
+
type: {
|
|
447
|
+
error: "Error",
|
|
448
|
+
warning: "Advertencia",
|
|
449
|
+
info: "Información"
|
|
450
|
+
},
|
|
451
|
+
emptyState: {
|
|
452
|
+
noLogs: "No tienes registros"
|
|
453
|
+
},
|
|
454
|
+
loading: "Cargando registros...",
|
|
455
|
+
loadingMore: "Cargando más registros...",
|
|
456
|
+
noMoreLogs: "No hay más registros para cargar",
|
|
457
|
+
error: {
|
|
458
|
+
loading: "Error al cargar los registros"
|
|
459
|
+
},
|
|
460
|
+
filter: {
|
|
461
|
+
from: "Desde",
|
|
462
|
+
to: "Hasta",
|
|
463
|
+
type: "Tipo",
|
|
464
|
+
sort: "Ordenar",
|
|
465
|
+
reset: "Restablecer",
|
|
466
|
+
typeOptions: {
|
|
467
|
+
all: "Todos",
|
|
468
|
+
error: "Error",
|
|
469
|
+
warning: "Advertencia",
|
|
470
|
+
info: "Información"
|
|
471
|
+
},
|
|
472
|
+
sortOptions: {
|
|
473
|
+
latest: "Más recientes",
|
|
474
|
+
oldest: "Más antiguos"
|
|
475
|
+
},
|
|
476
|
+
chooseType: "Elegir tipo"
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
navigation: {
|
|
480
|
+
pages: {
|
|
481
|
+
home: "Inicio",
|
|
482
|
+
operation: "Operación",
|
|
483
|
+
logs: "Registros",
|
|
484
|
+
calibration: "Calibración",
|
|
485
|
+
settings: "Ajustes"
|
|
486
|
+
},
|
|
487
|
+
bar: {
|
|
488
|
+
controlCenter: "Centro de control",
|
|
489
|
+
support: "Soporte"
|
|
490
|
+
},
|
|
491
|
+
modal: {
|
|
492
|
+
exit: {
|
|
493
|
+
title: "Estás a punto de salir de la aplicación",
|
|
494
|
+
message: "Por favor, asegúrate de que tus cambios estén guardados antes de salir de la aplicación."
|
|
495
|
+
},
|
|
496
|
+
goToControlCenter: "Ir al Centro de control",
|
|
497
|
+
goToRemoteSupport: "Ir al Soporte remoto",
|
|
498
|
+
password: {
|
|
499
|
+
title: "Se requiere inicio de sesión de administrador",
|
|
500
|
+
label: "Contraseña",
|
|
501
|
+
error: "Contraseña incorrecta",
|
|
502
|
+
confirm: "Confirmar"
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
pagination: {
|
|
507
|
+
page: "Página",
|
|
508
|
+
of: "de"
|
|
509
|
+
},
|
|
510
|
+
fileUploadPanel: {
|
|
511
|
+
defaultTitle: "Subir archivos",
|
|
512
|
+
dropzoneTitle: "Suelta los archivos aquí o haz clic para explorar",
|
|
513
|
+
defaultFileCriteria: "Se aceptan todos los tipos de archivos"
|
|
514
|
+
},
|
|
515
|
+
stepProgressCircle: {
|
|
516
|
+
title: {
|
|
517
|
+
progress: "Progreso",
|
|
518
|
+
manufacturing: "Fabricación",
|
|
519
|
+
processing: "Procesamiento",
|
|
520
|
+
uploading: "Subiendo",
|
|
521
|
+
notstarted: "No iniciado",
|
|
522
|
+
ready: "Listo",
|
|
523
|
+
inprogress: "En progreso",
|
|
524
|
+
complete: "Completo",
|
|
525
|
+
loading: "Cargando",
|
|
526
|
+
waiting: "Esperando",
|
|
527
|
+
warning: "Advertencia",
|
|
528
|
+
error: "Error"
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
productFormList: {
|
|
532
|
+
add: "Agregar",
|
|
533
|
+
cancel: "Cancelar",
|
|
534
|
+
save: "Guardar",
|
|
535
|
+
create: "Crear",
|
|
536
|
+
modify: "Editar",
|
|
537
|
+
new: "Nuevo",
|
|
538
|
+
delete: "Eliminar",
|
|
539
|
+
deleteConfirmation: "¿Está seguro de que desea eliminar este elemento?",
|
|
540
|
+
emptyState: "Aún no hay elementos. Haz clic en Agregar para crear uno."
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
dayjs.extend(utc);
|
|
545
|
+
dayjs.extend(timezone);
|
|
546
|
+
if (!i18n.isInitialized) {
|
|
547
|
+
const getStoredTimezone = function getStoredTimezone() {
|
|
548
|
+
if (typeof window === "undefined") return "auto";
|
|
549
|
+
try {
|
|
550
|
+
const stored = localStorage.getItem("machine-apps-components:timezone");
|
|
551
|
+
return stored || "auto";
|
|
552
|
+
} catch (_a) {
|
|
553
|
+
return "auto";
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
const initialTimezone = getStoredTimezone();
|
|
557
|
+
if (initialTimezone !== "auto" && typeof window !== "undefined") {
|
|
558
|
+
try {
|
|
559
|
+
dayjs.tz.setDefault(initialTimezone);
|
|
560
|
+
} catch (error) {
|
|
561
|
+
console.warn("i18n: Failed to set default timezone", error);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
i18n.use(LanguageDetector).use(initReactI18next).init({
|
|
565
|
+
resources: {
|
|
566
|
+
en: {
|
|
567
|
+
translation: enTranslations
|
|
568
|
+
},
|
|
569
|
+
fr: {
|
|
570
|
+
translation: frTranslations
|
|
571
|
+
},
|
|
572
|
+
de: {
|
|
573
|
+
translation: deTranslations
|
|
574
|
+
},
|
|
575
|
+
es: {
|
|
576
|
+
translation: esTranslations
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
fallbackLng: "en",
|
|
580
|
+
defaultNS: "translation",
|
|
581
|
+
interpolation: {
|
|
582
|
+
escapeValue: false
|
|
583
|
+
},
|
|
584
|
+
detection: {
|
|
585
|
+
order: ["localStorage", "navigator"],
|
|
586
|
+
lookupLocalStorage: "machine-apps-components:locale",
|
|
587
|
+
caches: ["localStorage"]
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
i18n.on("languageChanged", function handleLanguageChanged(lng) {
|
|
591
|
+
const dayjsLocale = lng.split("-")[0];
|
|
592
|
+
try {
|
|
593
|
+
dayjs.locale(dayjsLocale);
|
|
594
|
+
} catch (error) {
|
|
595
|
+
console.warn("i18n: Failed to set dayjs locale", error);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
const getSupportedLanguages = function getSupportedLanguages() {
|
|
600
|
+
try {
|
|
601
|
+
if (!i18n.isInitialized) {
|
|
602
|
+
return ["en", "fr", "de", "es"];
|
|
603
|
+
}
|
|
604
|
+
const resources = i18n.options.resources || {};
|
|
605
|
+
const languages = Object.keys(resources);
|
|
606
|
+
return languages.length > 0 ? languages : ["en", "fr", "de", "es"];
|
|
607
|
+
} catch (error) {
|
|
608
|
+
console.warn("Error getting supported languages:", error);
|
|
609
|
+
return ["en", "fr", "de", "es"];
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
const getLanguageDisplayName = function getLanguageDisplayName(code) {
|
|
613
|
+
const languageNames = {
|
|
614
|
+
en: "English",
|
|
615
|
+
fr: "Français",
|
|
616
|
+
es: "Español",
|
|
617
|
+
de: "Deutsch"
|
|
618
|
+
};
|
|
619
|
+
return languageNames[code] || code.toUpperCase();
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
const STORAGE_KEYS = {
|
|
623
|
+
locale: "machine-apps-components:locale",
|
|
624
|
+
unitSystem: "machine-apps-components:unitSystem",
|
|
625
|
+
timezone: "machine-apps-components:timezone"
|
|
626
|
+
};
|
|
627
|
+
const normalizeLocale = function normalizeLocale(locale, supportedLanguages) {
|
|
628
|
+
const normalized = locale.split("-")[0].toLowerCase();
|
|
629
|
+
if (supportedLanguages.includes(normalized)) {
|
|
630
|
+
return normalized;
|
|
631
|
+
}
|
|
632
|
+
return supportedLanguages.length > 0 ? supportedLanguages[0] : "en";
|
|
633
|
+
};
|
|
634
|
+
const I18nProvider = function I18nProvider({
|
|
635
|
+
children,
|
|
636
|
+
defaultLocale = "en",
|
|
637
|
+
defaultUnitSystem = "metric",
|
|
638
|
+
defaultTimezone = "auto",
|
|
639
|
+
supportedLanguages = ["en", "fr", "de", "es"]
|
|
640
|
+
}) {
|
|
641
|
+
const [locale, setLocaleState] = useState(function getInitialLocale() {
|
|
642
|
+
if (typeof window === "undefined") return normalizeLocale(defaultLocale, supportedLanguages);
|
|
643
|
+
try {
|
|
644
|
+
const stored = localStorage.getItem(STORAGE_KEYS.locale);
|
|
645
|
+
if (stored) {
|
|
646
|
+
return normalizeLocale(stored, supportedLanguages);
|
|
647
|
+
}
|
|
648
|
+
return normalizeLocale(defaultLocale, supportedLanguages);
|
|
649
|
+
} catch (_a) {
|
|
650
|
+
return normalizeLocale(defaultLocale, supportedLanguages);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
const [unitSystem, setUnitSystemState] = useState(function getInitialUnitSystem() {
|
|
654
|
+
if (typeof window === "undefined") return defaultUnitSystem;
|
|
655
|
+
try {
|
|
656
|
+
const stored = localStorage.getItem(STORAGE_KEYS.unitSystem);
|
|
657
|
+
if (stored === "metric" || stored === "imperial") {
|
|
658
|
+
return stored;
|
|
659
|
+
}
|
|
660
|
+
return defaultUnitSystem;
|
|
661
|
+
} catch (_a) {
|
|
662
|
+
return defaultUnitSystem;
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
const [timezone, setTimezoneState] = useState(function getInitialTimezone() {
|
|
666
|
+
if (typeof window === "undefined") return defaultTimezone;
|
|
667
|
+
try {
|
|
668
|
+
const stored = localStorage.getItem(STORAGE_KEYS.timezone);
|
|
669
|
+
return stored || defaultTimezone;
|
|
670
|
+
} catch (_a) {
|
|
671
|
+
return defaultTimezone;
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
useEffect(function syncI18nLocale() {
|
|
675
|
+
const normalizedLocale = normalizeLocale(locale, supportedLanguages);
|
|
676
|
+
i18n.changeLanguage(normalizedLocale);
|
|
677
|
+
if (typeof window !== "undefined") {
|
|
678
|
+
localStorage.setItem(STORAGE_KEYS.locale, normalizedLocale);
|
|
679
|
+
}
|
|
680
|
+
}, [locale, supportedLanguages]);
|
|
681
|
+
useEffect(function persistUnitSystem() {
|
|
682
|
+
if (typeof window !== "undefined") {
|
|
683
|
+
localStorage.setItem(STORAGE_KEYS.unitSystem, unitSystem);
|
|
684
|
+
}
|
|
685
|
+
}, [unitSystem]);
|
|
686
|
+
useEffect(function syncDayjsTimezone() {
|
|
687
|
+
if (typeof window === "undefined") return;
|
|
688
|
+
localStorage.setItem(STORAGE_KEYS.timezone, timezone);
|
|
689
|
+
try {
|
|
690
|
+
const dayjsWithTz = dayjs;
|
|
691
|
+
if (dayjsWithTz.tz && typeof dayjsWithTz.tz.setDefault === "function") {
|
|
692
|
+
if (timezone !== "auto") {
|
|
693
|
+
dayjsWithTz.tz.setDefault(timezone);
|
|
694
|
+
} else {
|
|
695
|
+
const detected = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
696
|
+
dayjsWithTz.tz.setDefault(detected);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
} catch (error) {
|
|
700
|
+
console.warn("Failed to set timezone:", error);
|
|
701
|
+
}
|
|
702
|
+
}, [timezone]);
|
|
703
|
+
const setLocale = useCallback(function setLocale(newLocale) {
|
|
704
|
+
setLocaleState(normalizeLocale(newLocale, supportedLanguages));
|
|
705
|
+
}, [supportedLanguages]);
|
|
706
|
+
const setUnitSystem = useCallback(function setUnitSystem(newSystem) {
|
|
707
|
+
setUnitSystemState(newSystem);
|
|
708
|
+
}, []);
|
|
709
|
+
const setTimezone = useCallback(function setTimezone(newTimezone) {
|
|
710
|
+
setTimezoneState(newTimezone);
|
|
711
|
+
}, []);
|
|
712
|
+
const value = {
|
|
713
|
+
locale,
|
|
714
|
+
unitSystem,
|
|
715
|
+
timezone,
|
|
716
|
+
supportedLanguages,
|
|
717
|
+
setLocale,
|
|
718
|
+
setUnitSystem,
|
|
719
|
+
setTimezone
|
|
720
|
+
};
|
|
721
|
+
return jsx(I18nContext.Provider, {
|
|
722
|
+
value: value,
|
|
723
|
+
children: children
|
|
724
|
+
});
|
|
725
|
+
};
|
|
726
|
+
I18nProvider.displayName = "I18nProvider";
|
|
727
|
+
|
|
728
|
+
const MM_TO_INCH = 0.0393701;
|
|
729
|
+
const INCH_TO_MM = 25.4;
|
|
730
|
+
function mmToInches(mm) {
|
|
731
|
+
return mm * MM_TO_INCH;
|
|
732
|
+
}
|
|
733
|
+
function inchesToMm(inches) {
|
|
734
|
+
return inches * INCH_TO_MM;
|
|
735
|
+
}
|
|
736
|
+
function formatValueToDisplayUnit(value, unitSystem, options) {
|
|
737
|
+
var _a;
|
|
738
|
+
const decimals = (_a = options === null || options === void 0 ? void 0 : options.decimals) !== null && _a !== void 0 ? _a : 2;
|
|
739
|
+
const showUnit = (options === null || options === void 0 ? void 0 : options.showUnit) !== false;
|
|
740
|
+
if (unitSystem === "imperial") {
|
|
741
|
+
const inches = mmToInches(value);
|
|
742
|
+
return showUnit ? `${inches.toFixed(decimals)} in` : inches.toFixed(decimals);
|
|
743
|
+
}
|
|
744
|
+
return showUnit ? `${value.toFixed(decimals)} mm` : value.toFixed(decimals);
|
|
745
|
+
}
|
|
746
|
+
function convertDisplayValueToMm(displayValue, unitSystem) {
|
|
747
|
+
if (unitSystem === "imperial") {
|
|
748
|
+
return inchesToMm(displayValue);
|
|
749
|
+
}
|
|
750
|
+
return displayValue;
|
|
751
|
+
}
|
|
752
|
+
function getUnitDisplayLabel(unitSystem) {
|
|
753
|
+
return unitSystem === "imperial" ? "in" : "mm";
|
|
754
|
+
}
|
|
755
|
+
function getAvailableTimezones() {
|
|
756
|
+
return ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Toronto", "America/Vancouver", "Europe/London", "Europe/Paris", "Europe/Berlin", "Europe/Madrid", "Europe/Rome", "Asia/Tokyo", "Asia/Shanghai", "Asia/Hong_Kong", "Asia/Singapore", "Australia/Sydney", "Australia/Melbourne", "UTC"];
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const DEFAULT_VALUES = {
|
|
760
|
+
locale: "en",
|
|
761
|
+
unitSystem: "metric",
|
|
762
|
+
timezone: "auto",
|
|
763
|
+
supportedLanguages: ["en"],
|
|
764
|
+
setLocale: function defaultSetLocale(_newLocale) {
|
|
765
|
+
return undefined;
|
|
766
|
+
},
|
|
767
|
+
setUnitSystem: function defaultSetUnitSystem(_system) {
|
|
768
|
+
return undefined;
|
|
769
|
+
},
|
|
770
|
+
setTimezone: function defaultSetTimezone(_tz) {
|
|
771
|
+
return undefined;
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
const useI18n = function useI18n() {
|
|
775
|
+
const {
|
|
776
|
+
t
|
|
777
|
+
} = useTranslation();
|
|
778
|
+
const context = useContext(I18nContext);
|
|
779
|
+
const {
|
|
780
|
+
locale = DEFAULT_VALUES.locale,
|
|
781
|
+
unitSystem = DEFAULT_VALUES.unitSystem,
|
|
782
|
+
timezone = DEFAULT_VALUES.timezone,
|
|
783
|
+
supportedLanguages = DEFAULT_VALUES.supportedLanguages,
|
|
784
|
+
setLocale = DEFAULT_VALUES.setLocale,
|
|
785
|
+
setUnitSystem = DEFAULT_VALUES.setUnitSystem,
|
|
786
|
+
setTimezone = DEFAULT_VALUES.setTimezone
|
|
787
|
+
} = context || {};
|
|
788
|
+
const formatDate = useCallback(function formatDate(utcTimestamp, format) {
|
|
789
|
+
const tz = timezone === "auto" ? Intl.DateTimeFormat().resolvedOptions().timeZone : timezone;
|
|
790
|
+
try {
|
|
791
|
+
const dayjsWithTz = dayjs;
|
|
792
|
+
const hasTimezonePlugin = dayjsWithTz.tz && typeof dayjsWithTz.utc === "function";
|
|
793
|
+
if (hasTimezonePlugin) {
|
|
794
|
+
const utcInstance = dayjsWithTz.utc(utcTimestamp);
|
|
795
|
+
return utcInstance.tz(tz).locale(locale.split("-")[0]).format(format || "YYYY-MM-DD HH:mm:ss");
|
|
796
|
+
}
|
|
797
|
+
return dayjs(utcTimestamp).locale(locale.split("-")[0]).format(format || "YYYY-MM-DD HH:mm:ss");
|
|
798
|
+
} catch (error) {
|
|
799
|
+
return dayjs(utcTimestamp).locale(locale.split("-")[0]).format(format || "YYYY-MM-DD HH:mm:ss");
|
|
800
|
+
}
|
|
801
|
+
}, [timezone, locale]);
|
|
802
|
+
const formatValueToDisplayUnit$1 = useCallback(function formatValueToDisplayUnit$1(value, options) {
|
|
803
|
+
return formatValueToDisplayUnit(value, unitSystem, options);
|
|
804
|
+
}, [unitSystem]);
|
|
805
|
+
const convertDisplayValueToMmValue = useCallback(function convertDisplayValueToMmValue(value) {
|
|
806
|
+
return convertDisplayValueToMm(value, unitSystem);
|
|
807
|
+
}, [unitSystem]);
|
|
808
|
+
const getUnitDisplayLabelValue = useCallback(function getUnitDisplayLabelValue() {
|
|
809
|
+
return getUnitDisplayLabel(unitSystem);
|
|
810
|
+
}, [unitSystem]);
|
|
811
|
+
return {
|
|
812
|
+
t,
|
|
813
|
+
formatDate,
|
|
814
|
+
formatValueToDisplayUnit: formatValueToDisplayUnit$1,
|
|
815
|
+
convertDisplayValueToMm: convertDisplayValueToMmValue,
|
|
816
|
+
getUnitDisplayLabel: getUnitDisplayLabelValue,
|
|
817
|
+
locale,
|
|
818
|
+
unitSystem,
|
|
819
|
+
timezone,
|
|
820
|
+
supportedLanguages,
|
|
821
|
+
setLocale,
|
|
822
|
+
setUnitSystem,
|
|
823
|
+
setTimezone
|
|
824
|
+
};
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
const I18nSettings = function I18nSettings({
|
|
828
|
+
className,
|
|
829
|
+
layout = "stacked"
|
|
830
|
+
}) {
|
|
831
|
+
const {
|
|
832
|
+
classes,
|
|
833
|
+
cx
|
|
834
|
+
} = useStyles$g({
|
|
835
|
+
layout
|
|
836
|
+
});
|
|
837
|
+
const {
|
|
838
|
+
locale,
|
|
839
|
+
unitSystem,
|
|
840
|
+
timezone,
|
|
841
|
+
supportedLanguages,
|
|
842
|
+
setLocale,
|
|
843
|
+
setUnitSystem,
|
|
844
|
+
setTimezone,
|
|
845
|
+
t
|
|
846
|
+
} = useI18n();
|
|
847
|
+
const unitSystemOptions = useMemo(function getUnitSystemOptions() {
|
|
848
|
+
return [{
|
|
849
|
+
value: "metric",
|
|
850
|
+
displayText: t("common.units.metric", {
|
|
851
|
+
defaultValue: "Metric"
|
|
852
|
+
})
|
|
853
|
+
}, {
|
|
854
|
+
value: "imperial",
|
|
855
|
+
displayText: t("common.units.imperial", {
|
|
856
|
+
defaultValue: "Imperial"
|
|
857
|
+
})
|
|
858
|
+
}];
|
|
859
|
+
}, [t]);
|
|
860
|
+
const timezoneOptions = useMemo(function getTimezoneOptions() {
|
|
861
|
+
const timezones = getAvailableTimezones();
|
|
862
|
+
return [{
|
|
863
|
+
value: "auto",
|
|
864
|
+
displayText: t("common.settings.autoDetect", {
|
|
865
|
+
defaultValue: "Auto-detect"
|
|
866
|
+
})
|
|
867
|
+
}, ...timezones.map(tz => ({
|
|
868
|
+
value: tz,
|
|
869
|
+
displayText: tz
|
|
870
|
+
}))];
|
|
871
|
+
}, [t]);
|
|
872
|
+
const localeOptions = useMemo(function getLocaleOptions() {
|
|
873
|
+
return supportedLanguages.map(langCode => ({
|
|
874
|
+
value: langCode,
|
|
875
|
+
displayText: getLanguageDisplayName(langCode)
|
|
876
|
+
}));
|
|
877
|
+
}, [supportedLanguages]);
|
|
878
|
+
const handleUnitSystemChange = function handleUnitSystemChange(event) {
|
|
879
|
+
setUnitSystem(event.target.value);
|
|
880
|
+
};
|
|
881
|
+
const handleTimezoneChange = function handleTimezoneChange(event) {
|
|
882
|
+
setTimezone(event.target.value);
|
|
883
|
+
};
|
|
884
|
+
const handleLocaleChange = function handleLocaleChange(event) {
|
|
885
|
+
setLocale(event.target.value);
|
|
886
|
+
};
|
|
887
|
+
return jsxs(Box, {
|
|
888
|
+
className: cx(classes.container, className),
|
|
889
|
+
children: [jsx(Box, {
|
|
890
|
+
className: classes.settingItem,
|
|
891
|
+
children: jsx(VentionSelect, {
|
|
892
|
+
size: "xx-large",
|
|
893
|
+
variant: "outlined",
|
|
894
|
+
labelText: t("common.settings.unitSystem"),
|
|
895
|
+
value: unitSystem,
|
|
896
|
+
onChange: handleUnitSystemChange,
|
|
897
|
+
menuItems: unitSystemOptions
|
|
898
|
+
})
|
|
899
|
+
}), jsx(Box, {
|
|
900
|
+
className: classes.settingItem,
|
|
901
|
+
children: jsx(VentionSelect, {
|
|
902
|
+
size: "xx-large",
|
|
903
|
+
variant: "outlined",
|
|
904
|
+
labelText: t("common.settings.timezone"),
|
|
905
|
+
value: timezone,
|
|
906
|
+
onChange: handleTimezoneChange,
|
|
907
|
+
menuItems: timezoneOptions
|
|
908
|
+
})
|
|
909
|
+
}), supportedLanguages.length > 1 && jsx(Box, {
|
|
910
|
+
className: classes.settingItem,
|
|
911
|
+
children: jsx(VentionSelect, {
|
|
912
|
+
size: "xx-large",
|
|
913
|
+
variant: "outlined",
|
|
914
|
+
labelText: t("common.settings.locale"),
|
|
915
|
+
value: locale,
|
|
916
|
+
onChange: handleLocaleChange,
|
|
917
|
+
menuItems: localeOptions
|
|
918
|
+
})
|
|
919
|
+
})]
|
|
920
|
+
});
|
|
921
|
+
};
|
|
922
|
+
I18nSettings.displayName = "I18nSettings";
|
|
923
|
+
const useStyles$g = tss.withParams().create(({
|
|
924
|
+
theme,
|
|
925
|
+
layout
|
|
926
|
+
}) => ({
|
|
927
|
+
container: {
|
|
928
|
+
display: "flex",
|
|
929
|
+
flexDirection: layout === "horizontal" ? "row" : "column",
|
|
930
|
+
flexWrap: layout === "horizontal" ? "wrap" : "nowrap",
|
|
931
|
+
gap: theme.spacing(3),
|
|
932
|
+
width: "100%"
|
|
933
|
+
},
|
|
934
|
+
settingItem: layout === "horizontal" ? {
|
|
935
|
+
flex: "1 1 250px",
|
|
936
|
+
maxWidth: "350px"
|
|
937
|
+
} : {
|
|
938
|
+
width: "100%",
|
|
939
|
+
maxWidth: "400px"
|
|
940
|
+
}
|
|
941
|
+
}));
|
|
942
|
+
|
|
943
|
+
function TimeLabel({
|
|
944
|
+
className,
|
|
945
|
+
color
|
|
946
|
+
}) {
|
|
947
|
+
const theme = useTheme();
|
|
948
|
+
const {
|
|
949
|
+
formatDate,
|
|
950
|
+
timezone,
|
|
951
|
+
locale
|
|
952
|
+
} = useI18n();
|
|
953
|
+
const [timeLabel, setTimeLabel] = useState(() => {
|
|
954
|
+
try {
|
|
955
|
+
return formatDate(Date.now(), "HH:mm");
|
|
956
|
+
} catch (_a) {
|
|
957
|
+
return new Date().toLocaleTimeString([], {
|
|
958
|
+
hour: "numeric",
|
|
959
|
+
minute: "2-digit"
|
|
960
|
+
}).toLowerCase().replace(" ", "");
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
useEffect(function updateTimeLabelOnTimezoneChange() {
|
|
964
|
+
try {
|
|
965
|
+
const formatted = formatDate(Date.now(), "HH:mm");
|
|
966
|
+
setTimeLabel(formatted);
|
|
967
|
+
} catch (_a) {
|
|
968
|
+
setTimeLabel(new Date().toLocaleTimeString([], {
|
|
969
|
+
hour: "numeric",
|
|
970
|
+
minute: "2-digit"
|
|
971
|
+
}).toLowerCase().replace(" ", ""));
|
|
972
|
+
}
|
|
973
|
+
}, [formatDate, timezone, locale]);
|
|
974
|
+
useEffect(function updateTimeLabel() {
|
|
975
|
+
const intervalId = setInterval(() => {
|
|
976
|
+
try {
|
|
977
|
+
const formatted = formatDate(Date.now(), "HH:mm");
|
|
978
|
+
setTimeLabel(formatted);
|
|
979
|
+
} catch (_a) {
|
|
980
|
+
setTimeLabel(new Date().toLocaleTimeString([], {
|
|
981
|
+
hour: "numeric",
|
|
982
|
+
minute: "2-digit"
|
|
983
|
+
}).toLowerCase().replace(" ", ""));
|
|
984
|
+
}
|
|
985
|
+
}, 1000);
|
|
986
|
+
return () => clearInterval(intervalId);
|
|
987
|
+
}, [formatDate, timezone, locale]);
|
|
988
|
+
return jsx(Typography, {
|
|
989
|
+
className: className,
|
|
990
|
+
color: color !== null && color !== void 0 ? color : theme.palette.common.white,
|
|
991
|
+
children: timeLabel
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* Detects if the current device has touch screen capabilities
|
|
997
|
+
* @returns true if the device supports touch events, false otherwise
|
|
998
|
+
*/
|
|
999
|
+
const isTouchScreenDevice = () => {
|
|
1000
|
+
return "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
1001
|
+
};
|
|
1002
|
+
/**
|
|
1003
|
+
* Closes the custom UI by sending a message to the parent window
|
|
1004
|
+
*/
|
|
1005
|
+
const closeCustomUi = () => {
|
|
1006
|
+
window.parent.postMessage("closeCustomUi", "*");
|
|
1007
|
+
};
|
|
1008
|
+
/**
|
|
1009
|
+
* Navigates to a specific route in the Control Center
|
|
1010
|
+
* @param route - The route to navigate to (remoteSupport or controlCenterHomepage)
|
|
1011
|
+
*/
|
|
1012
|
+
const navigateControlCenter = route => {
|
|
1013
|
+
const capitalizedRoute = route.charAt(0).toUpperCase() + route.slice(1);
|
|
1014
|
+
window.parent.postMessage(`navigateTo${capitalizedRoute}`, "*");
|
|
1015
|
+
};
|
|
1016
|
+
|
|
1017
|
+
const NavigationConfirmationModal = function NavigationConfirmationModal(props) {
|
|
1018
|
+
const {
|
|
1019
|
+
isOpen,
|
|
1020
|
+
destination,
|
|
1021
|
+
onClose
|
|
1022
|
+
} = props;
|
|
1023
|
+
const {
|
|
1024
|
+
classes
|
|
1025
|
+
} = useStyles$f();
|
|
1026
|
+
const {
|
|
1027
|
+
t
|
|
1028
|
+
} = useI18n();
|
|
1029
|
+
const handleConfirm = function handleConfirm() {
|
|
1030
|
+
if (!destination) return;
|
|
1031
|
+
onClose();
|
|
1032
|
+
if (destination === "controlCenter") {
|
|
1033
|
+
closeCustomUi();
|
|
1034
|
+
} else {
|
|
1035
|
+
navigateControlCenter(destination);
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
const getButtonText = function getButtonText() {
|
|
1039
|
+
if (destination === "controlCenter") {
|
|
1040
|
+
return t("navigation.modal.goToControlCenter", {
|
|
1041
|
+
defaultValue: "Go to Control Center"
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
return t("navigation.modal.goToRemoteSupport", {
|
|
1045
|
+
defaultValue: "Go to Remote Support"
|
|
1046
|
+
});
|
|
1047
|
+
};
|
|
1048
|
+
return jsx(VentionModalBase, {
|
|
1049
|
+
isOpen: isOpen,
|
|
1050
|
+
onClose: onClose,
|
|
1051
|
+
modalSize: "xx-large",
|
|
1052
|
+
isTouchDevice: isTouchScreenDevice(),
|
|
1053
|
+
width: "1312px",
|
|
1054
|
+
children: jsxs(Box, {
|
|
1055
|
+
className: classes.modalContent,
|
|
1056
|
+
children: [jsx(Box, {
|
|
1057
|
+
className: classes.iconContainer,
|
|
1058
|
+
children: jsx(VentionIcon, {
|
|
1059
|
+
type: "alert-triangle-filled",
|
|
1060
|
+
size: 56,
|
|
1061
|
+
color: "#F59E0B"
|
|
1062
|
+
})
|
|
1063
|
+
}), jsx(Typography, {
|
|
1064
|
+
className: classes.title,
|
|
1065
|
+
children: t("navigation.modal.exit.title", {
|
|
1066
|
+
defaultValue: "You are about to exit the application"
|
|
1067
|
+
})
|
|
1068
|
+
}), jsx(Typography, {
|
|
1069
|
+
className: classes.body,
|
|
1070
|
+
children: t("navigation.modal.exit.message", {
|
|
1071
|
+
defaultValue: "Please make sure your changes are saved before you leave the app."
|
|
1072
|
+
})
|
|
1073
|
+
}), jsx(Button, {
|
|
1074
|
+
onClick: handleConfirm,
|
|
1075
|
+
className: classes.button,
|
|
1076
|
+
disableRipple: true,
|
|
1077
|
+
children: jsx(Box, {
|
|
1078
|
+
className: classes.buttonLabel,
|
|
1079
|
+
children: jsx(Typography, {
|
|
1080
|
+
className: classes.buttonText,
|
|
1081
|
+
children: getButtonText()
|
|
1082
|
+
})
|
|
1083
|
+
})
|
|
1084
|
+
})]
|
|
1085
|
+
})
|
|
1086
|
+
});
|
|
1087
|
+
};
|
|
1088
|
+
const useStyles$f = tss.create(({
|
|
1089
|
+
theme
|
|
1090
|
+
}) => ({
|
|
1091
|
+
modalContent: {
|
|
1092
|
+
display: "flex",
|
|
1093
|
+
flexDirection: "column",
|
|
1094
|
+
alignItems: "center",
|
|
1095
|
+
padding: "0 96px 24px 96px",
|
|
1096
|
+
height: "360px",
|
|
1097
|
+
boxSizing: "border-box"
|
|
1098
|
+
},
|
|
1099
|
+
iconContainer: {
|
|
1100
|
+
marginBottom: theme.spacing(7)
|
|
1101
|
+
},
|
|
1102
|
+
title: Object.assign(Object.assign({}, theme.typography.hmiText28SemiBold), {
|
|
1103
|
+
textAlign: "center",
|
|
1104
|
+
marginBottom: theme.spacing(6)
|
|
1105
|
+
}),
|
|
1106
|
+
body: Object.assign(Object.assign({}, theme.typography.hmiText22Regular), {
|
|
1107
|
+
textAlign: "center"
|
|
1108
|
+
}),
|
|
1109
|
+
button: {
|
|
1110
|
+
minWidth: "320px",
|
|
1111
|
+
width: "auto",
|
|
1112
|
+
maxWidth: "100%",
|
|
1113
|
+
height: "80px",
|
|
1114
|
+
backgroundColor: theme.palette.button.filled,
|
|
1115
|
+
borderRadius: "4px",
|
|
1116
|
+
padding: "8px 16px",
|
|
1117
|
+
boxSizing: "border-box",
|
|
1118
|
+
marginTop: "auto",
|
|
1119
|
+
"&:hover": {
|
|
1120
|
+
backgroundColor: theme.palette.button.filledHover
|
|
1121
|
+
}
|
|
1122
|
+
},
|
|
1123
|
+
buttonLabel: {
|
|
1124
|
+
display: "flex",
|
|
1125
|
+
alignItems: "center",
|
|
1126
|
+
justifyContent: "center",
|
|
1127
|
+
padding: "0 8px",
|
|
1128
|
+
boxSizing: "border-box",
|
|
1129
|
+
width: "100%"
|
|
1130
|
+
},
|
|
1131
|
+
buttonText: {
|
|
1132
|
+
fontFamily: "Inter",
|
|
1133
|
+
fontSize: "24px",
|
|
1134
|
+
fontWeight: 600,
|
|
1135
|
+
lineHeight: "32px",
|
|
1136
|
+
color: theme.palette.common.white,
|
|
1137
|
+
textAlign: "center",
|
|
1138
|
+
whiteSpace: "nowrap"
|
|
1139
|
+
}
|
|
1140
|
+
}));
|
|
1141
|
+
|
|
1142
|
+
const PasswordProtectionModal = function PasswordProtectionModal(props) {
|
|
1143
|
+
const {
|
|
1144
|
+
isOpen,
|
|
1145
|
+
onClose,
|
|
1146
|
+
onSuccess,
|
|
1147
|
+
correctPassword
|
|
1148
|
+
} = props;
|
|
1149
|
+
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
|
|
1150
|
+
const {
|
|
1151
|
+
classes
|
|
1152
|
+
} = useStyles$e();
|
|
1153
|
+
const {
|
|
1154
|
+
t
|
|
1155
|
+
} = useI18n();
|
|
1156
|
+
const [password, setPassword] = useState("");
|
|
1157
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
1158
|
+
const [error, setError] = useState(false);
|
|
1159
|
+
const handleConfirm = function handleConfirm() {
|
|
1160
|
+
if (password === correctPassword) {
|
|
1161
|
+
setPassword("");
|
|
1162
|
+
setError(false);
|
|
1163
|
+
onSuccess();
|
|
1164
|
+
onClose();
|
|
1165
|
+
} else {
|
|
1166
|
+
setError(true);
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
const handleClose = function handleClose() {
|
|
1170
|
+
setPassword("");
|
|
1171
|
+
setError(false);
|
|
1172
|
+
onClose();
|
|
1173
|
+
};
|
|
1174
|
+
useEffect(function handleKeyboardVisibility() {
|
|
1175
|
+
if (!isOpen || !isTouchScreenDevice()) {
|
|
1176
|
+
setIsKeyboardVisible(false);
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
const checkKeyboard = () => {
|
|
1180
|
+
const keyboard = document.getElementById("virtual_keyboard");
|
|
1181
|
+
setIsKeyboardVisible(keyboard !== null);
|
|
1182
|
+
};
|
|
1183
|
+
checkKeyboard();
|
|
1184
|
+
const observer = new MutationObserver(checkKeyboard);
|
|
1185
|
+
observer.observe(document.body, {
|
|
1186
|
+
childList: true,
|
|
1187
|
+
subtree: true
|
|
1188
|
+
});
|
|
1189
|
+
return () => {
|
|
1190
|
+
observer.disconnect();
|
|
1191
|
+
setIsKeyboardVisible(false);
|
|
1192
|
+
};
|
|
1193
|
+
}, [isOpen]);
|
|
1194
|
+
return jsxs(Fragment, {
|
|
1195
|
+
children: [jsx("style", {
|
|
1196
|
+
children: isKeyboardVisible && `
|
|
1197
|
+
[data-testid="vention-modal-container"] {
|
|
1198
|
+
transform: translateY(-22.5vh) !important;
|
|
1199
|
+
transition: transform 0.3s ease-out;
|
|
1200
|
+
}
|
|
1201
|
+
`
|
|
1202
|
+
}), jsx(VentionModalBase, {
|
|
1203
|
+
isOpen: isOpen,
|
|
1204
|
+
onClose: handleClose,
|
|
1205
|
+
modalSize: "x-large",
|
|
1206
|
+
isTouchDevice: isTouchScreenDevice(),
|
|
1207
|
+
width: "1120px",
|
|
1208
|
+
backDropClickClosable: false,
|
|
1209
|
+
children: jsxs(Box, {
|
|
1210
|
+
className: classes.modalContent,
|
|
1211
|
+
children: [jsx(Typography, {
|
|
1212
|
+
className: classes.title,
|
|
1213
|
+
children: t("navigation.modal.password.title", {
|
|
1214
|
+
defaultValue: "Administrator login required"
|
|
1215
|
+
})
|
|
1216
|
+
}), jsx(Box, {
|
|
1217
|
+
component: "form",
|
|
1218
|
+
id: "password-form",
|
|
1219
|
+
onSubmit: event => {
|
|
1220
|
+
event.preventDefault();
|
|
1221
|
+
handleConfirm();
|
|
1222
|
+
},
|
|
1223
|
+
className: classes.inputContainer,
|
|
1224
|
+
children: jsx(VentionTextInput, {
|
|
1225
|
+
label: t("navigation.modal.password.label", {
|
|
1226
|
+
defaultValue: "Password"
|
|
1227
|
+
}),
|
|
1228
|
+
type: showPassword ? "text" : "password",
|
|
1229
|
+
value: password,
|
|
1230
|
+
onChange: event => {
|
|
1231
|
+
setPassword(event.target.value);
|
|
1232
|
+
setError(false);
|
|
1233
|
+
},
|
|
1234
|
+
state: error ? "error" : "default",
|
|
1235
|
+
helperText: error ? t("navigation.modal.password.error", {
|
|
1236
|
+
defaultValue: "Incorrect password"
|
|
1237
|
+
}) : "",
|
|
1238
|
+
fullWidth: true,
|
|
1239
|
+
size: "xx-large",
|
|
1240
|
+
InputProps: {
|
|
1241
|
+
endAdornment: jsx(InputAdornment, {
|
|
1242
|
+
position: "end",
|
|
1243
|
+
children: jsx(IconButton, {
|
|
1244
|
+
onClick: () => setShowPassword(!showPassword),
|
|
1245
|
+
edge: "end",
|
|
1246
|
+
disableRipple: true,
|
|
1247
|
+
type: "button",
|
|
1248
|
+
children: jsx(VentionIcon, {
|
|
1249
|
+
type: showPassword ? "eye-closed" : "eye",
|
|
1250
|
+
size: 28,
|
|
1251
|
+
color: "#0f172a"
|
|
1252
|
+
})
|
|
1253
|
+
})
|
|
1254
|
+
})
|
|
1255
|
+
}
|
|
1256
|
+
})
|
|
1257
|
+
}), jsx(Button, {
|
|
1258
|
+
className: classes.button,
|
|
1259
|
+
disableRipple: true,
|
|
1260
|
+
type: "submit",
|
|
1261
|
+
form: "password-form",
|
|
1262
|
+
children: jsx(Box, {
|
|
1263
|
+
className: classes.buttonLabel,
|
|
1264
|
+
children: jsx(Typography, {
|
|
1265
|
+
className: classes.buttonText,
|
|
1266
|
+
children: t("navigation.modal.password.confirm", {
|
|
1267
|
+
defaultValue: "Confirm"
|
|
1268
|
+
})
|
|
1269
|
+
})
|
|
1270
|
+
})
|
|
1271
|
+
})]
|
|
1272
|
+
})
|
|
1273
|
+
})]
|
|
1274
|
+
});
|
|
1275
|
+
};
|
|
1276
|
+
const useStyles$e = tss.create(({
|
|
1277
|
+
theme
|
|
1278
|
+
}) => ({
|
|
1279
|
+
modalContent: {
|
|
1280
|
+
display: "flex",
|
|
1281
|
+
flexDirection: "column",
|
|
1282
|
+
alignItems: "center",
|
|
1283
|
+
padding: "64px 96px 64px 96px",
|
|
1284
|
+
gap: theme.spacing(7),
|
|
1285
|
+
boxSizing: "border-box",
|
|
1286
|
+
height: "324px"
|
|
1287
|
+
},
|
|
1288
|
+
title: {
|
|
1289
|
+
fontFamily: "Inter",
|
|
1290
|
+
fontSize: "36px",
|
|
1291
|
+
fontWeight: 700,
|
|
1292
|
+
lineHeight: "48px",
|
|
1293
|
+
textAlign: "center",
|
|
1294
|
+
color: theme.palette.text.primary
|
|
1295
|
+
},
|
|
1296
|
+
inputContainer: {
|
|
1297
|
+
width: "499px",
|
|
1298
|
+
display: "flex",
|
|
1299
|
+
flexDirection: "column",
|
|
1300
|
+
gap: theme.spacing(1)
|
|
1301
|
+
},
|
|
1302
|
+
button: {
|
|
1303
|
+
width: "250px",
|
|
1304
|
+
height: "64px",
|
|
1305
|
+
backgroundColor: theme.palette.button.filled,
|
|
1306
|
+
borderRadius: "4px",
|
|
1307
|
+
padding: "8px",
|
|
1308
|
+
boxSizing: "border-box",
|
|
1309
|
+
"&:hover": {
|
|
1310
|
+
backgroundColor: theme.palette.button.filledHover
|
|
1311
|
+
}
|
|
1312
|
+
},
|
|
1313
|
+
buttonLabel: {
|
|
1314
|
+
display: "flex",
|
|
1315
|
+
alignItems: "center",
|
|
1316
|
+
justifyContent: "center",
|
|
1317
|
+
padding: "0 8px",
|
|
1318
|
+
boxSizing: "border-box"
|
|
1319
|
+
},
|
|
1320
|
+
buttonText: {
|
|
1321
|
+
fontFamily: "Inter",
|
|
1322
|
+
fontSize: "24px",
|
|
1323
|
+
fontWeight: 600,
|
|
1324
|
+
lineHeight: "32px",
|
|
1325
|
+
color: theme.palette.common.white,
|
|
1326
|
+
textAlign: "center",
|
|
1327
|
+
whiteSpace: "nowrap"
|
|
1328
|
+
}
|
|
1329
|
+
}));
|
|
1330
|
+
|
|
1331
|
+
const NavigationBarItem = function NavigationBarItem(props) {
|
|
1332
|
+
const {
|
|
1333
|
+
icon,
|
|
1334
|
+
iconDisabled,
|
|
1335
|
+
label,
|
|
1336
|
+
path,
|
|
1337
|
+
onClick,
|
|
1338
|
+
password,
|
|
1339
|
+
isDisabled = false,
|
|
1340
|
+
location,
|
|
1341
|
+
handleNavigate,
|
|
1342
|
+
currentPassword,
|
|
1343
|
+
setPasswordProtectedItem
|
|
1344
|
+
} = props;
|
|
1345
|
+
const {
|
|
1346
|
+
classes,
|
|
1347
|
+
cx
|
|
1348
|
+
} = useStyles$d();
|
|
1349
|
+
const {
|
|
1350
|
+
t
|
|
1351
|
+
} = useI18n();
|
|
1352
|
+
const isActive = (location === null || location === void 0 ? void 0 : location.pathname) === path;
|
|
1353
|
+
const currentIcon = isDisabled && iconDisabled ? iconDisabled : icon;
|
|
1354
|
+
const handleItemClick = function handleItemClick() {
|
|
1355
|
+
if (isDisabled || !handleNavigate || !setPasswordProtectedItem) return;
|
|
1356
|
+
if (password && password !== currentPassword) {
|
|
1357
|
+
setPasswordProtectedItem(props);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
onClick ? onClick() : handleNavigate(path);
|
|
1361
|
+
};
|
|
1362
|
+
return jsxs(Button, {
|
|
1363
|
+
disableRipple: true,
|
|
1364
|
+
disabled: isDisabled,
|
|
1365
|
+
onClick: handleItemClick,
|
|
1366
|
+
className: cx(classes.tabButton, {
|
|
1367
|
+
[classes.active]: isActive,
|
|
1368
|
+
[classes.disabled]: isDisabled
|
|
1369
|
+
}),
|
|
1370
|
+
children: [jsx(Box, {
|
|
1371
|
+
className: classes.navIcon,
|
|
1372
|
+
children: currentIcon
|
|
1373
|
+
}), jsx(Typography, {
|
|
1374
|
+
className: classes.navLabel,
|
|
1375
|
+
children: t(label, {
|
|
1376
|
+
defaultValue: label
|
|
1377
|
+
})
|
|
1378
|
+
})]
|
|
1379
|
+
});
|
|
1380
|
+
};
|
|
1381
|
+
const useStyles$d = tss.create(({
|
|
1382
|
+
theme
|
|
1383
|
+
}) => ({
|
|
1384
|
+
tabButton: {
|
|
1385
|
+
display: "flex",
|
|
1386
|
+
alignItems: "center",
|
|
1387
|
+
justifyContent: "center",
|
|
1388
|
+
flexDirection: "column",
|
|
1389
|
+
height: "96px",
|
|
1390
|
+
width: 184,
|
|
1391
|
+
gap: theme.spacing(2),
|
|
1392
|
+
borderRadius: 8,
|
|
1393
|
+
backgroundColor: "transparent",
|
|
1394
|
+
transition: "background-color 0.2s",
|
|
1395
|
+
"&:hover": {
|
|
1396
|
+
backgroundColor: theme.palette.button.filledHover
|
|
1397
|
+
},
|
|
1398
|
+
color: theme.palette.common.white,
|
|
1399
|
+
"&.Mui-disabled": {
|
|
1400
|
+
color: theme.palette.common.white
|
|
1401
|
+
}
|
|
1402
|
+
},
|
|
1403
|
+
active: {
|
|
1404
|
+
backgroundColor: theme.palette.button.filledPressed
|
|
1405
|
+
},
|
|
1406
|
+
disabled: {
|
|
1407
|
+
opacity: 0.5,
|
|
1408
|
+
cursor: "not-allowed",
|
|
1409
|
+
"&:hover": {
|
|
1410
|
+
backgroundColor: "transparent"
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
navIcon: {
|
|
1414
|
+
width: 32,
|
|
1415
|
+
height: 32,
|
|
1416
|
+
display: "flex",
|
|
1417
|
+
alignItems: "center",
|
|
1418
|
+
justifyContent: "center"
|
|
1419
|
+
},
|
|
1420
|
+
navLabel: Object.assign({}, theme.typography.hmiText22Regular)
|
|
1421
|
+
}));
|
|
1422
|
+
|
|
1423
|
+
const Z_INDEX = {
|
|
1424
|
+
NAVIGATION: 1100,
|
|
1425
|
+
MENU: 1200,
|
|
1426
|
+
MENU_OVERLAY: 1210,
|
|
1427
|
+
MODAL: 1300,
|
|
1428
|
+
SNACKBAR: 1400,
|
|
1429
|
+
TOOLTIP: 1500
|
|
1430
|
+
};
|
|
1431
|
+
|
|
1432
|
+
const iconSize = 32;
|
|
1433
|
+
const NavigationBarRoot = function NavigationBarRoot(props) {
|
|
1434
|
+
var _a;
|
|
1435
|
+
const {
|
|
1436
|
+
children,
|
|
1437
|
+
showTimer = true,
|
|
1438
|
+
onControlCenterClick,
|
|
1439
|
+
onSupportClick,
|
|
1440
|
+
disabledNavigationItems = [],
|
|
1441
|
+
isControlCenterDisabled = false,
|
|
1442
|
+
isSupportDisabled = false,
|
|
1443
|
+
showControlCenterButton = true,
|
|
1444
|
+
showSupportButton = true,
|
|
1445
|
+
variant = "fixed"
|
|
1446
|
+
} = props;
|
|
1447
|
+
const location = useLocation();
|
|
1448
|
+
const navigate = useNavigate();
|
|
1449
|
+
const theme = useTheme();
|
|
1450
|
+
const {
|
|
1451
|
+
classes
|
|
1452
|
+
} = useStyles$c({
|
|
1453
|
+
variant
|
|
1454
|
+
});
|
|
1455
|
+
const {
|
|
1456
|
+
t
|
|
1457
|
+
} = useI18n();
|
|
1458
|
+
const [modalDestination, setModalDestination] = useState(null);
|
|
1459
|
+
const [passwordProtectedItem, setPasswordProtectedItem] = useState(null);
|
|
1460
|
+
const [currentPassword, setCurrentPassword] = useState(null);
|
|
1461
|
+
const disabledSet = new Set(disabledNavigationItems);
|
|
1462
|
+
const getFadedColor = function getFadedColor(color, opacity = 1) {
|
|
1463
|
+
return `${color}${Math.round(opacity * 255).toString(16).padStart(2, "0")}`;
|
|
1464
|
+
};
|
|
1465
|
+
const handleNavigate = function handleNavigate(path) {
|
|
1466
|
+
if (location.pathname !== path) navigate(path);
|
|
1467
|
+
};
|
|
1468
|
+
useEffect(function updateCurrentPassword() {
|
|
1469
|
+
const currentPage = React.Children.toArray(children).find(child => React.isValidElement(child) && child.type === NavigationBarItem && child.props.path === location.pathname);
|
|
1470
|
+
const currentPagePassword = React.isValidElement(currentPage) ? currentPage.props.password : undefined;
|
|
1471
|
+
setCurrentPassword(currentPagePassword !== null && currentPagePassword !== void 0 ? currentPagePassword : null);
|
|
1472
|
+
}, [location.pathname, children]);
|
|
1473
|
+
const handleControlCenterClick = function handleControlCenterClick() {
|
|
1474
|
+
if (isControlCenterDisabled) return;
|
|
1475
|
+
if (onControlCenterClick) {
|
|
1476
|
+
onControlCenterClick();
|
|
1477
|
+
} else {
|
|
1478
|
+
setModalDestination("controlCenter");
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
const handleSupportClick = function handleSupportClick() {
|
|
1482
|
+
if (isSupportDisabled) return;
|
|
1483
|
+
if (onSupportClick) {
|
|
1484
|
+
onSupportClick();
|
|
1485
|
+
} else {
|
|
1486
|
+
setModalDestination("remoteSupport");
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
const handlePasswordSuccess = function handlePasswordSuccess() {
|
|
1490
|
+
if (passwordProtectedItem) {
|
|
1491
|
+
if (passwordProtectedItem.onClick) {
|
|
1492
|
+
passwordProtectedItem.onClick();
|
|
1493
|
+
} else {
|
|
1494
|
+
handleNavigate(passwordProtectedItem.path);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
};
|
|
1498
|
+
const processedChildren = React.Children.map(children, function processChild(child) {
|
|
1499
|
+
if (!React.isValidElement(child)) return child;
|
|
1500
|
+
if (child.type !== NavigationBarItem) return child;
|
|
1501
|
+
const itemId = child.props.id;
|
|
1502
|
+
const isDisabled = disabledSet.has(itemId);
|
|
1503
|
+
return React.cloneElement(child, Object.assign(Object.assign({}, child.props), {
|
|
1504
|
+
isDisabled: isDisabled,
|
|
1505
|
+
location: location,
|
|
1506
|
+
handleNavigate: handleNavigate,
|
|
1507
|
+
currentPassword: currentPassword,
|
|
1508
|
+
setPasswordProtectedItem: setPasswordProtectedItem
|
|
1509
|
+
}));
|
|
1510
|
+
});
|
|
1511
|
+
const handleCloseConfirmation = function handleCloseConfirmation() {
|
|
1512
|
+
setModalDestination(null);
|
|
1513
|
+
};
|
|
1514
|
+
const handleClosePassword = function handleClosePassword() {
|
|
1515
|
+
setPasswordProtectedItem(null);
|
|
1516
|
+
};
|
|
1517
|
+
return jsxs(Fragment, {
|
|
1518
|
+
children: [jsx(NavigationConfirmationModal, {
|
|
1519
|
+
isOpen: modalDestination !== null,
|
|
1520
|
+
destination: modalDestination,
|
|
1521
|
+
onClose: handleCloseConfirmation
|
|
1522
|
+
}), jsx(PasswordProtectionModal, {
|
|
1523
|
+
isOpen: passwordProtectedItem !== null,
|
|
1524
|
+
onClose: handleClosePassword,
|
|
1525
|
+
onSuccess: handlePasswordSuccess,
|
|
1526
|
+
correctPassword: (_a = passwordProtectedItem === null || passwordProtectedItem === void 0 ? void 0 : passwordProtectedItem.password) !== null && _a !== void 0 ? _a : ""
|
|
1527
|
+
}), jsx("footer", {
|
|
1528
|
+
className: classes.root,
|
|
1529
|
+
children: jsxs(Box, {
|
|
1530
|
+
className: classes.container,
|
|
1531
|
+
children: [jsx(Box, {
|
|
1532
|
+
className: classes.sideClusterLeft,
|
|
1533
|
+
children: showControlCenterButton && jsx(VentionButton, {
|
|
1534
|
+
disableRipple: true,
|
|
1535
|
+
onClick: handleControlCenterClick,
|
|
1536
|
+
disabled: isControlCenterDisabled,
|
|
1537
|
+
className: classes.sideButton,
|
|
1538
|
+
style: {
|
|
1539
|
+
backgroundColor: isControlCenterDisabled ? getFadedColor(theme.palette.background.brand) : theme.palette.background.brand,
|
|
1540
|
+
borderColor: isControlCenterDisabled ? getFadedColor(theme.palette.border.onColor) : theme.palette.border.onColor,
|
|
1541
|
+
opacity: isControlCenterDisabled ? 0.5 : 1,
|
|
1542
|
+
cursor: isControlCenterDisabled ? "not-allowed" : "pointer"
|
|
1543
|
+
},
|
|
1544
|
+
children: jsx(Typography, {
|
|
1545
|
+
className: classes.sideButtonLabel,
|
|
1546
|
+
style: {
|
|
1547
|
+
color: isControlCenterDisabled ? getFadedColor(theme.palette.common.white) : theme.palette.common.white
|
|
1548
|
+
},
|
|
1549
|
+
children: t("navigation.bar.controlCenter", {
|
|
1550
|
+
defaultValue: "Control Center"
|
|
1551
|
+
})
|
|
1552
|
+
})
|
|
1553
|
+
})
|
|
1554
|
+
}), jsx("nav", {
|
|
1555
|
+
className: classes.tabBarButtonContainer,
|
|
1556
|
+
children: processedChildren
|
|
1557
|
+
}), jsxs(Box, {
|
|
1558
|
+
className: classes.sideClusterRight,
|
|
1559
|
+
children: [showSupportButton && jsx(VentionButton, {
|
|
1560
|
+
disableRipple: true,
|
|
1561
|
+
onClick: handleSupportClick,
|
|
1562
|
+
disabled: isSupportDisabled,
|
|
1563
|
+
className: classes.sideButton,
|
|
1564
|
+
style: {
|
|
1565
|
+
backgroundColor: isSupportDisabled ? getFadedColor(theme.palette.background.brand) : theme.palette.background.brand,
|
|
1566
|
+
borderColor: isSupportDisabled ? getFadedColor(theme.palette.border.onColor) : theme.palette.border.onColor,
|
|
1567
|
+
opacity: isSupportDisabled ? 0.5 : 1,
|
|
1568
|
+
cursor: isSupportDisabled ? "not-allowed" : "pointer"
|
|
1569
|
+
},
|
|
1570
|
+
iconLeft: jsx(VentionIcon, {
|
|
1571
|
+
size: iconSize,
|
|
1572
|
+
color: isSupportDisabled ? getFadedColor(theme.palette.common.white) : theme.palette.common.white,
|
|
1573
|
+
type: "headset-filled"
|
|
1574
|
+
}),
|
|
1575
|
+
children: jsx(Typography, {
|
|
1576
|
+
className: classes.sideButtonLabel,
|
|
1577
|
+
style: {
|
|
1578
|
+
color: isSupportDisabled ? getFadedColor(theme.palette.common.white) : theme.palette.common.white
|
|
1579
|
+
},
|
|
1580
|
+
children: t("navigation.bar.support", {
|
|
1581
|
+
defaultValue: "Support"
|
|
1582
|
+
})
|
|
1583
|
+
})
|
|
1584
|
+
}), showTimer && jsx(TimeLabel, {
|
|
1585
|
+
className: classes.timeLabel,
|
|
1586
|
+
color: theme.palette.common.white
|
|
1587
|
+
})]
|
|
1588
|
+
})]
|
|
1589
|
+
})
|
|
1590
|
+
})]
|
|
1591
|
+
});
|
|
1592
|
+
};
|
|
1593
|
+
const useStyles$c = tss.withParams().create(({
|
|
1594
|
+
theme,
|
|
1595
|
+
variant
|
|
1596
|
+
}) => ({
|
|
1597
|
+
root: Object.assign({
|
|
1598
|
+
boxSizing: "border-box",
|
|
1599
|
+
display: "flex",
|
|
1600
|
+
justifyContent: "center",
|
|
1601
|
+
alignItems: "center",
|
|
1602
|
+
height: "120px",
|
|
1603
|
+
padding: theme.spacing(2, 6)
|
|
1604
|
+
}, variant === "fixed" ? {
|
|
1605
|
+
backgroundColor: COLORS.slate[900],
|
|
1606
|
+
position: "fixed",
|
|
1607
|
+
left: 0,
|
|
1608
|
+
right: 0,
|
|
1609
|
+
bottom: 0,
|
|
1610
|
+
borderTop: `1px solid ${COLORS.slate[800]}`,
|
|
1611
|
+
zIndex: Z_INDEX.NAVIGATION
|
|
1612
|
+
} : {
|
|
1613
|
+
backgroundColor: theme.palette.background.defaultInverse,
|
|
1614
|
+
position: "relative",
|
|
1615
|
+
width: "100%",
|
|
1616
|
+
borderTop: `1px solid ${theme.palette.border.inverse}`,
|
|
1617
|
+
flexShrink: 0
|
|
1618
|
+
}),
|
|
1619
|
+
container: {
|
|
1620
|
+
display: "flex",
|
|
1621
|
+
alignItems: "center",
|
|
1622
|
+
justifyContent: "space-between",
|
|
1623
|
+
position: "relative",
|
|
1624
|
+
width: "100%",
|
|
1625
|
+
gap: "20px",
|
|
1626
|
+
height: theme.spacing(13)
|
|
1627
|
+
},
|
|
1628
|
+
sideClusterLeft: {
|
|
1629
|
+
display: "flex",
|
|
1630
|
+
alignItems: "center",
|
|
1631
|
+
gap: theme.spacing(8)
|
|
1632
|
+
},
|
|
1633
|
+
sideClusterRight: {
|
|
1634
|
+
display: "flex",
|
|
1635
|
+
alignItems: "center",
|
|
1636
|
+
gap: theme.spacing(8)
|
|
1637
|
+
},
|
|
1638
|
+
sideButton: {
|
|
1639
|
+
display: "flex",
|
|
1640
|
+
flexDirection: "row",
|
|
1641
|
+
alignItems: "center",
|
|
1642
|
+
justifyContent: "center",
|
|
1643
|
+
height: theme.spacing(11),
|
|
1644
|
+
padding: theme.spacing(2, 4),
|
|
1645
|
+
backgroundColor: theme.palette.background.brand,
|
|
1646
|
+
borderRadius: 4,
|
|
1647
|
+
border: `2px solid ${theme.palette.border.onColor}`,
|
|
1648
|
+
color: theme.palette.common.white,
|
|
1649
|
+
textTransform: "none",
|
|
1650
|
+
minWidth: 0,
|
|
1651
|
+
"&:hover": {
|
|
1652
|
+
backgroundColor: theme.palette.button.filledHover
|
|
1653
|
+
},
|
|
1654
|
+
"&.Mui-disabled": {
|
|
1655
|
+
color: theme.palette.common.white
|
|
1656
|
+
}
|
|
1657
|
+
},
|
|
1658
|
+
sideButtonLabel: {
|
|
1659
|
+
display: "flex",
|
|
1660
|
+
justifyContent: "center",
|
|
1661
|
+
alignItems: "center",
|
|
1662
|
+
fontSize: 24,
|
|
1663
|
+
fontFamily: "Inter",
|
|
1664
|
+
fontStyle: "normal",
|
|
1665
|
+
fontWeight: 600,
|
|
1666
|
+
lineHeight: "32px"
|
|
1667
|
+
},
|
|
1668
|
+
timeLabel: Object.assign(Object.assign({}, theme.typography.hmiText22Regular), {
|
|
1669
|
+
fontWeight: 600
|
|
1670
|
+
}),
|
|
1671
|
+
tabBarButtonContainer: {
|
|
1672
|
+
display: "flex",
|
|
1673
|
+
alignItems: "center",
|
|
1674
|
+
justifyContent: "center",
|
|
1675
|
+
position: "absolute",
|
|
1676
|
+
left: "50%",
|
|
1677
|
+
transform: "translateX(-50%)",
|
|
1678
|
+
gap: theme.spacing(5),
|
|
1679
|
+
height: "104px"
|
|
1680
|
+
}
|
|
1681
|
+
}));
|
|
1682
|
+
const NavigationBar = Object.assign(NavigationBarRoot, {
|
|
1683
|
+
Item: NavigationBarItem
|
|
1684
|
+
});
|
|
1685
|
+
|
|
1686
|
+
const StatusTopBarButton = function StatusTopBarButton(props) {
|
|
1687
|
+
const {
|
|
1688
|
+
label,
|
|
1689
|
+
onClick,
|
|
1690
|
+
backgroundColor,
|
|
1691
|
+
backgroundColorHover,
|
|
1692
|
+
borderColor,
|
|
1693
|
+
textColor,
|
|
1694
|
+
width = 208,
|
|
1695
|
+
height = 80,
|
|
1696
|
+
icon,
|
|
1697
|
+
iconDisabled,
|
|
1698
|
+
visible = true,
|
|
1699
|
+
disabled = false
|
|
1700
|
+
} = props;
|
|
1701
|
+
const {
|
|
1702
|
+
classes
|
|
1703
|
+
} = useStyles$b();
|
|
1704
|
+
if (!visible) return null;
|
|
1705
|
+
const getFadedColor = function getFadedColor(color, opacity = 1) {
|
|
1706
|
+
return `${color}${Math.round(opacity * 255).toString(16).padStart(2, "0")}`;
|
|
1707
|
+
};
|
|
1708
|
+
const hasBackgroundColor = !!backgroundColor;
|
|
1709
|
+
const variant = hasBackgroundColor ? "filled-brand" : "outline";
|
|
1710
|
+
const finalBackgroundColor = disabled && backgroundColor ? getFadedColor(backgroundColor) : backgroundColor;
|
|
1711
|
+
const finalBackgroundColorHover = disabled && backgroundColorHover ? getFadedColor(backgroundColorHover) : backgroundColorHover;
|
|
1712
|
+
const finalBorderColor = disabled && borderColor ? getFadedColor(borderColor) : borderColor;
|
|
1713
|
+
const finalTextColor = disabled && textColor ? getFadedColor(textColor) : textColor;
|
|
1714
|
+
const finalIcon = disabled && iconDisabled ? iconDisabled : icon;
|
|
1715
|
+
const handleClick = function handleClick() {
|
|
1716
|
+
if (!disabled && onClick) {
|
|
1717
|
+
onClick();
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
return jsx(VentionButton, {
|
|
1721
|
+
variant: variant,
|
|
1722
|
+
onClick: handleClick,
|
|
1723
|
+
disabled: disabled || !onClick,
|
|
1724
|
+
className: classes.actionButton,
|
|
1725
|
+
style: {
|
|
1726
|
+
width,
|
|
1727
|
+
height,
|
|
1728
|
+
backgroundColor: finalBackgroundColor || "transparent",
|
|
1729
|
+
border: finalBorderColor ? `1px solid ${finalBorderColor}` : undefined
|
|
1730
|
+
},
|
|
1731
|
+
sx: {
|
|
1732
|
+
"&:hover": {
|
|
1733
|
+
backgroundColor: finalBackgroundColorHover || finalBackgroundColor
|
|
1734
|
+
}
|
|
1735
|
+
},
|
|
1736
|
+
iconLeft: finalIcon ? jsx(Box, {
|
|
1737
|
+
className: classes.iconWrapper,
|
|
1738
|
+
children: finalIcon
|
|
1739
|
+
}) : undefined,
|
|
1740
|
+
children: jsx(Typography, {
|
|
1741
|
+
className: classes.actionLabel,
|
|
1742
|
+
style: {
|
|
1743
|
+
color: finalTextColor
|
|
1744
|
+
},
|
|
1745
|
+
children: label
|
|
1746
|
+
})
|
|
1747
|
+
});
|
|
1748
|
+
};
|
|
1749
|
+
const useStyles$b = tss.create(({
|
|
1750
|
+
theme
|
|
1751
|
+
}) => ({
|
|
1752
|
+
actionButton: {
|
|
1753
|
+
display: "flex",
|
|
1754
|
+
alignItems: "center",
|
|
1755
|
+
justifyContent: "center",
|
|
1756
|
+
gap: theme.spacing(1),
|
|
1757
|
+
padding: theme.spacing(1, 2),
|
|
1758
|
+
borderRadius: 4,
|
|
1759
|
+
minHeight: 0,
|
|
1760
|
+
minWidth: 0
|
|
1761
|
+
},
|
|
1762
|
+
iconWrapper: {
|
|
1763
|
+
padding: "5px",
|
|
1764
|
+
display: "flex",
|
|
1765
|
+
alignItems: "center",
|
|
1766
|
+
justifyContent: "center"
|
|
1767
|
+
},
|
|
1768
|
+
actionLabel: {
|
|
1769
|
+
fontWeight: 600,
|
|
1770
|
+
fontSize: 24,
|
|
1771
|
+
lineHeight: "32px",
|
|
1772
|
+
textTransform: "none",
|
|
1773
|
+
padding: theme.spacing(1)
|
|
1774
|
+
}
|
|
1775
|
+
}));
|
|
1776
|
+
|
|
1777
|
+
const StatusTopBarRoot = function StatusTopBarRoot(props) {
|
|
1778
|
+
const {
|
|
1779
|
+
status,
|
|
1780
|
+
buttonConfigs = [],
|
|
1781
|
+
variant = "light"
|
|
1782
|
+
} = props;
|
|
1783
|
+
const {
|
|
1784
|
+
classes
|
|
1785
|
+
} = useStyles$a({
|
|
1786
|
+
variant
|
|
1787
|
+
});
|
|
1788
|
+
const visibleButtons = buttonConfigs.filter(config => config.visible !== false);
|
|
1789
|
+
const hasVisibleButtons = visibleButtons.length > 0;
|
|
1790
|
+
return jsxs("header", {
|
|
1791
|
+
className: classes.root,
|
|
1792
|
+
children: [jsxs("div", {
|
|
1793
|
+
className: classes.content,
|
|
1794
|
+
children: [jsx("div", {
|
|
1795
|
+
className: classes.leftArea,
|
|
1796
|
+
children: status && jsx(VentionStatusIndicator, {
|
|
1797
|
+
size: "xx-large",
|
|
1798
|
+
dotColor: status.color,
|
|
1799
|
+
label: status.label
|
|
1800
|
+
})
|
|
1801
|
+
}), hasVisibleButtons && jsx("div", {
|
|
1802
|
+
className: classes.rightArea,
|
|
1803
|
+
children: visibleButtons.map(config => jsx(StatusTopBarButton, Object.assign({}, config, {
|
|
1804
|
+
visible: true
|
|
1805
|
+
}), config.id))
|
|
1806
|
+
})]
|
|
1807
|
+
}), jsx("div", {
|
|
1808
|
+
className: classes.bottomBorder
|
|
1809
|
+
})]
|
|
1810
|
+
});
|
|
1811
|
+
};
|
|
1812
|
+
const useStyles$a = tss.withParams().create(({
|
|
1813
|
+
theme,
|
|
1814
|
+
variant
|
|
1815
|
+
}) => ({
|
|
1816
|
+
root: {
|
|
1817
|
+
boxSizing: "border-box",
|
|
1818
|
+
position: "relative",
|
|
1819
|
+
width: "100%",
|
|
1820
|
+
backgroundColor: variant === "dark" ? theme.palette.background.defaultInverse : theme.palette.common.white,
|
|
1821
|
+
height: "120px",
|
|
1822
|
+
flexShrink: 0
|
|
1823
|
+
},
|
|
1824
|
+
content: {
|
|
1825
|
+
display: "flex",
|
|
1826
|
+
alignItems: "center",
|
|
1827
|
+
justifyContent: "space-between",
|
|
1828
|
+
padding: theme.spacing(5, 4)
|
|
1829
|
+
},
|
|
1830
|
+
leftArea: {
|
|
1831
|
+
display: "flex",
|
|
1832
|
+
alignItems: "center",
|
|
1833
|
+
"& .MuiTypography-root": {
|
|
1834
|
+
color: variant === "dark" ? theme.palette.common.white : theme.palette.text.primary
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
rightArea: {
|
|
1838
|
+
display: "flex",
|
|
1839
|
+
alignItems: "center",
|
|
1840
|
+
gap: theme.spacing(2),
|
|
1841
|
+
height: theme.spacing(10)
|
|
1842
|
+
},
|
|
1843
|
+
bottomBorder: {
|
|
1844
|
+
position: "absolute",
|
|
1845
|
+
left: 0,
|
|
1846
|
+
right: 0,
|
|
1847
|
+
bottom: 0,
|
|
1848
|
+
height: 1,
|
|
1849
|
+
backgroundColor: theme.palette.divider
|
|
1850
|
+
}
|
|
1851
|
+
}));
|
|
1852
|
+
const StatusTopBar = StatusTopBarRoot;
|
|
1853
|
+
|
|
1854
|
+
const Sidebar = function Sidebar(props) {
|
|
1855
|
+
const {
|
|
1856
|
+
items,
|
|
1857
|
+
variant = "card"
|
|
1858
|
+
} = props;
|
|
1859
|
+
const {
|
|
1860
|
+
classes
|
|
1861
|
+
} = useStyles$9({
|
|
1862
|
+
variant
|
|
1863
|
+
});
|
|
1864
|
+
return jsx(Box, {
|
|
1865
|
+
className: classes.container,
|
|
1866
|
+
children: items.map(item => jsx(SidebarItemComponent, {
|
|
1867
|
+
item: item,
|
|
1868
|
+
variant: variant
|
|
1869
|
+
}, item.id))
|
|
1870
|
+
});
|
|
1871
|
+
};
|
|
1872
|
+
const ICON_SIZE = 32;
|
|
1873
|
+
const SidebarItemComponent = function SidebarItemComponent(props) {
|
|
1874
|
+
const {
|
|
1875
|
+
item,
|
|
1876
|
+
variant
|
|
1877
|
+
} = props;
|
|
1878
|
+
const {
|
|
1879
|
+
classes
|
|
1880
|
+
} = useSidebarItemStyles({
|
|
1881
|
+
state: item.state,
|
|
1882
|
+
variant
|
|
1883
|
+
});
|
|
1884
|
+
const isDisabled = item.state === "disabled";
|
|
1885
|
+
return jsx(Button, {
|
|
1886
|
+
className: classes.button,
|
|
1887
|
+
onClick: item.onClick,
|
|
1888
|
+
disabled: isDisabled,
|
|
1889
|
+
disableRipple: true,
|
|
1890
|
+
disableFocusRipple: true,
|
|
1891
|
+
disableTouchRipple: true,
|
|
1892
|
+
"data-testid": `sidebar-item-${item.id}`,
|
|
1893
|
+
children: jsxs(Box, {
|
|
1894
|
+
className: classes.content,
|
|
1895
|
+
children: [jsxs(Box, {
|
|
1896
|
+
className: classes.leftSection,
|
|
1897
|
+
children: [item.icon ? jsx(Box, {
|
|
1898
|
+
className: classes.iconWrapper,
|
|
1899
|
+
children: item.icon
|
|
1900
|
+
}) : jsx(Box, {
|
|
1901
|
+
className: classes.iconPlaceholder
|
|
1902
|
+
}), jsxs(Box, {
|
|
1903
|
+
className: classes.textContainer,
|
|
1904
|
+
children: [jsx(Typography, {
|
|
1905
|
+
className: classes.title,
|
|
1906
|
+
children: item.title
|
|
1907
|
+
}), item.subtitle && jsx(Typography, {
|
|
1908
|
+
className: classes.subtitle,
|
|
1909
|
+
children: item.subtitle
|
|
1910
|
+
})]
|
|
1911
|
+
})]
|
|
1912
|
+
}), item.iconType && jsx(Box, {
|
|
1913
|
+
className: classes.rightSection,
|
|
1914
|
+
children: jsx(Box, {
|
|
1915
|
+
className: classes.rightIcon,
|
|
1916
|
+
children: jsx(VentionIcon, {
|
|
1917
|
+
type: item.iconType,
|
|
1918
|
+
size: ICON_SIZE
|
|
1919
|
+
})
|
|
1920
|
+
})
|
|
1921
|
+
})]
|
|
1922
|
+
})
|
|
1923
|
+
});
|
|
1924
|
+
};
|
|
1925
|
+
const useStyles$9 = tss.withParams().create(({
|
|
1926
|
+
theme,
|
|
1927
|
+
variant
|
|
1928
|
+
}) => ({
|
|
1929
|
+
container: Object.assign({
|
|
1930
|
+
display: "flex",
|
|
1931
|
+
flexDirection: "column",
|
|
1932
|
+
width: "100%"
|
|
1933
|
+
}, variant === "card" ? {
|
|
1934
|
+
padding: theme.spacing(2),
|
|
1935
|
+
gap: theme.spacing(1)
|
|
1936
|
+
} : {
|
|
1937
|
+
padding: 0,
|
|
1938
|
+
gap: 0
|
|
1939
|
+
})
|
|
1940
|
+
}));
|
|
1941
|
+
const useSidebarItemStyles = tss.withParams().create(function createSidebarItemStyles({
|
|
1942
|
+
theme,
|
|
1943
|
+
state,
|
|
1944
|
+
variant
|
|
1945
|
+
}) {
|
|
1946
|
+
const isActive = state === "active";
|
|
1947
|
+
const isDisabled = state === "disabled";
|
|
1948
|
+
const isAccentVariant = variant === "accent";
|
|
1949
|
+
const getButtonStyles = () => {
|
|
1950
|
+
const baseStyles = {
|
|
1951
|
+
width: "100%",
|
|
1952
|
+
minHeight: theme.spacing(14),
|
|
1953
|
+
padding: theme.spacing(3, 4),
|
|
1954
|
+
textAlign: "left",
|
|
1955
|
+
textTransform: "none",
|
|
1956
|
+
display: "flex",
|
|
1957
|
+
alignItems: "center",
|
|
1958
|
+
justifyContent: "flex-start",
|
|
1959
|
+
transition: "all 0.2s ease"
|
|
1960
|
+
};
|
|
1961
|
+
if (isAccentVariant) {
|
|
1962
|
+
return Object.assign(Object.assign({}, baseStyles), {
|
|
1963
|
+
borderRadius: 0,
|
|
1964
|
+
backgroundColor: isActive ? theme.palette.background.surface1active : "transparent",
|
|
1965
|
+
border: "none",
|
|
1966
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
1967
|
+
"&:hover": {
|
|
1968
|
+
backgroundColor: isDisabled ? "transparent" : isActive ? theme.palette.background.surface1active : theme.palette.action.hover
|
|
1969
|
+
}
|
|
1970
|
+
});
|
|
1971
|
+
}
|
|
1972
|
+
return Object.assign(Object.assign({}, baseStyles), {
|
|
1973
|
+
borderRadius: theme.spacing(2),
|
|
1974
|
+
backgroundColor: isActive ? theme.palette.background.surface1active : theme.palette.background.paper,
|
|
1975
|
+
border: `1px solid ${isActive ? theme.palette.border.main : theme.palette.divider}`,
|
|
1976
|
+
"&:hover": {
|
|
1977
|
+
backgroundColor: isDisabled ? theme.palette.background.paper : isActive ? theme.palette.background.surface1active : theme.palette.action.hover,
|
|
1978
|
+
borderColor: isDisabled ? theme.palette.divider : theme.palette.border.main
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
};
|
|
1982
|
+
return {
|
|
1983
|
+
button: getButtonStyles(),
|
|
1984
|
+
content: {
|
|
1985
|
+
display: "flex",
|
|
1986
|
+
alignItems: "center",
|
|
1987
|
+
justifyContent: "space-between",
|
|
1988
|
+
width: "100%",
|
|
1989
|
+
height: "100%"
|
|
1990
|
+
},
|
|
1991
|
+
leftSection: {
|
|
1992
|
+
display: "flex",
|
|
1993
|
+
alignItems: "center",
|
|
1994
|
+
gap: theme.spacing(3),
|
|
1995
|
+
flex: 1
|
|
1996
|
+
},
|
|
1997
|
+
iconWrapper: {
|
|
1998
|
+
display: "flex",
|
|
1999
|
+
alignItems: "center",
|
|
2000
|
+
justifyContent: "center",
|
|
2001
|
+
color: isActive ? theme.palette.background.defaultInverse : theme.palette.icon.tertiary,
|
|
2002
|
+
"& svg": {
|
|
2003
|
+
color: isActive ? theme.palette.background.defaultInverse : theme.palette.icon.tertiary
|
|
2004
|
+
}
|
|
2005
|
+
},
|
|
2006
|
+
iconPlaceholder: {
|
|
2007
|
+
width: theme.spacing(4)
|
|
2008
|
+
},
|
|
2009
|
+
textContainer: {
|
|
2010
|
+
display: "flex",
|
|
2011
|
+
flexDirection: "column",
|
|
2012
|
+
gap: theme.spacing(1)
|
|
2013
|
+
},
|
|
2014
|
+
title: Object.assign(Object.assign({}, theme.typography.heading24SemiBold), {
|
|
2015
|
+
color: isDisabled ? theme.palette.text.disabled : theme.palette.text.primary
|
|
2016
|
+
}),
|
|
2017
|
+
subtitle: Object.assign(Object.assign({}, theme.typography.hmiText20Regular), {
|
|
2018
|
+
color: isDisabled ? theme.palette.text.disabled : theme.palette.text.primary
|
|
2019
|
+
}),
|
|
2020
|
+
rightSection: {
|
|
2021
|
+
display: "flex",
|
|
2022
|
+
alignItems: "center",
|
|
2023
|
+
marginLeft: theme.spacing(2)
|
|
2024
|
+
},
|
|
2025
|
+
rightIcon: {
|
|
2026
|
+
display: "flex",
|
|
2027
|
+
alignItems: "center",
|
|
2028
|
+
color: isActive ? theme.palette.icon.primary : theme.palette.icon.tertiary,
|
|
2029
|
+
"& svg": {
|
|
2030
|
+
color: isActive ? theme.palette.icon.primary : theme.palette.icon.tertiary
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
};
|
|
2034
|
+
});
|
|
2035
|
+
|
|
2036
|
+
const LogsTable = memo(({
|
|
2037
|
+
logs = [],
|
|
2038
|
+
isLoading = false,
|
|
2039
|
+
error = null,
|
|
2040
|
+
onLoadMoreLogs,
|
|
2041
|
+
hasMoreLogs,
|
|
2042
|
+
onLogClick,
|
|
2043
|
+
tableHeight,
|
|
2044
|
+
emptyStateMessage,
|
|
2045
|
+
emptyStateIcon
|
|
2046
|
+
}) => {
|
|
2047
|
+
const {
|
|
2048
|
+
classes,
|
|
2049
|
+
cx
|
|
2050
|
+
} = useStyles$8({
|
|
2051
|
+
tableHeight
|
|
2052
|
+
});
|
|
2053
|
+
const theme = useTheme();
|
|
2054
|
+
const {
|
|
2055
|
+
t,
|
|
2056
|
+
formatDate
|
|
2057
|
+
} = useI18n();
|
|
2058
|
+
const loadMoreRef = useRef(null);
|
|
2059
|
+
const emptyMessage = emptyStateMessage || t("logs.emptyState.noLogs", {
|
|
2060
|
+
defaultValue: "You have no logs"
|
|
2061
|
+
});
|
|
2062
|
+
useEffect(function setupInfiniteScroll() {
|
|
2063
|
+
if (!onLoadMoreLogs || !hasMoreLogs || !loadMoreRef.current) return;
|
|
2064
|
+
const observer = new IntersectionObserver(entries => {
|
|
2065
|
+
if (entries[0].isIntersecting && hasMoreLogs) {
|
|
2066
|
+
onLoadMoreLogs();
|
|
2067
|
+
}
|
|
2068
|
+
}, {
|
|
2069
|
+
threshold: 0.1
|
|
2070
|
+
});
|
|
2071
|
+
observer.observe(loadMoreRef.current);
|
|
2072
|
+
return function cleanupInfiniteScroll() {
|
|
2073
|
+
observer.disconnect();
|
|
2074
|
+
};
|
|
2075
|
+
}, [onLoadMoreLogs, hasMoreLogs]);
|
|
2076
|
+
if (isLoading) {
|
|
2077
|
+
return jsx(Box, {
|
|
2078
|
+
className: classes.tableSection,
|
|
2079
|
+
children: jsxs(Box, {
|
|
2080
|
+
className: classes.centerState,
|
|
2081
|
+
children: [jsx(VentionSpinner, {
|
|
2082
|
+
size: "large"
|
|
2083
|
+
}), jsx(Typography, {
|
|
2084
|
+
variant: "heading24Medium",
|
|
2085
|
+
sx: {
|
|
2086
|
+
marginTop: 2
|
|
2087
|
+
},
|
|
2088
|
+
children: t("logs.loading", {
|
|
2089
|
+
defaultValue: "Loading logs..."
|
|
2090
|
+
})
|
|
2091
|
+
})]
|
|
2092
|
+
})
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
if (error) {
|
|
2096
|
+
return jsx(Box, {
|
|
2097
|
+
className: classes.tableSection,
|
|
2098
|
+
children: jsx(Box, {
|
|
2099
|
+
className: classes.errorState,
|
|
2100
|
+
children: jsx(VentionAlert, {
|
|
2101
|
+
severity: "error",
|
|
2102
|
+
title: t("logs.error.loading", {
|
|
2103
|
+
defaultValue: "Error loading logs"
|
|
2104
|
+
}),
|
|
2105
|
+
descriptionText: error,
|
|
2106
|
+
size: "large"
|
|
2107
|
+
})
|
|
2108
|
+
})
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
2111
|
+
if (!logs || logs.length === 0) {
|
|
2112
|
+
return jsx(Box, {
|
|
2113
|
+
className: classes.tableSection,
|
|
2114
|
+
children: jsxs(Box, {
|
|
2115
|
+
className: classes.centerState,
|
|
2116
|
+
children: [emptyStateIcon && jsx(Box, {
|
|
2117
|
+
className: classes.emptyStateIcon,
|
|
2118
|
+
children: emptyStateIcon
|
|
2119
|
+
}), jsx(Typography, {
|
|
2120
|
+
variant: "heading24Medium",
|
|
2121
|
+
children: emptyMessage
|
|
2122
|
+
})]
|
|
2123
|
+
})
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
const getTypeClassName = level => {
|
|
2127
|
+
switch (level) {
|
|
2128
|
+
case "error":
|
|
2129
|
+
return classes.errorType;
|
|
2130
|
+
case "warning":
|
|
2131
|
+
return classes.warningType;
|
|
2132
|
+
case "info":
|
|
2133
|
+
return classes.infoType;
|
|
2134
|
+
default:
|
|
2135
|
+
return "";
|
|
2136
|
+
}
|
|
2137
|
+
};
|
|
2138
|
+
const renderTypeIcon = level => {
|
|
2139
|
+
if (level === "error") {
|
|
2140
|
+
return jsx(VentionIcon, {
|
|
2141
|
+
size: 20,
|
|
2142
|
+
type: "alert-circle-filled",
|
|
2143
|
+
color: theme.palette.error.main
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
if (level === "warning") {
|
|
2147
|
+
return jsx(VentionIcon, {
|
|
2148
|
+
size: 20,
|
|
2149
|
+
type: "alert-triangle-filled",
|
|
2150
|
+
color: theme.palette.warning.main
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2153
|
+
return jsx(VentionIcon, {
|
|
2154
|
+
size: 20,
|
|
2155
|
+
type: "info-circle-filled",
|
|
2156
|
+
color: theme.palette.info.main
|
|
2157
|
+
});
|
|
2158
|
+
};
|
|
2159
|
+
const formatLogDate = dateStr => {
|
|
2160
|
+
try {
|
|
2161
|
+
const timestamp = new Date(dateStr).getTime();
|
|
2162
|
+
if (isNaN(timestamp)) {
|
|
2163
|
+
return dateStr;
|
|
2164
|
+
}
|
|
2165
|
+
return formatDate(timestamp, "YYYY-MM-DD h:mm:ssa");
|
|
2166
|
+
} catch (_a) {
|
|
2167
|
+
try {
|
|
2168
|
+
const date = new Date(dateStr);
|
|
2169
|
+
if (isNaN(date.getTime())) return dateStr;
|
|
2170
|
+
return date.toLocaleString("en-US", {
|
|
2171
|
+
year: "numeric",
|
|
2172
|
+
month: "2-digit",
|
|
2173
|
+
day: "2-digit",
|
|
2174
|
+
hour: "numeric",
|
|
2175
|
+
minute: "2-digit",
|
|
2176
|
+
second: "2-digit",
|
|
2177
|
+
hour12: true
|
|
2178
|
+
});
|
|
2179
|
+
} catch (_b) {
|
|
2180
|
+
return dateStr;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
};
|
|
2184
|
+
return jsxs(Box, {
|
|
2185
|
+
className: classes.tableSection,
|
|
2186
|
+
children: [jsx(TableContainer, {
|
|
2187
|
+
component: Paper,
|
|
2188
|
+
className: classes.tableContainer,
|
|
2189
|
+
children: jsxs(Table, {
|
|
2190
|
+
stickyHeader: true,
|
|
2191
|
+
children: [jsx(TableHead, {
|
|
2192
|
+
className: classes.tableHead,
|
|
2193
|
+
children: jsxs(TableRow, {
|
|
2194
|
+
children: [jsx(TableCell, {
|
|
2195
|
+
className: classes.iconHeaderCell
|
|
2196
|
+
}), jsx(TableCell, {
|
|
2197
|
+
className: classes.tableHeaderCell,
|
|
2198
|
+
children: jsx(Typography, {
|
|
2199
|
+
variant: "heading24Medium",
|
|
2200
|
+
className: classes.tableText,
|
|
2201
|
+
children: t("logs.table.date", {
|
|
2202
|
+
defaultValue: "Date"
|
|
2203
|
+
})
|
|
2204
|
+
})
|
|
2205
|
+
}), jsx(TableCell, {
|
|
2206
|
+
className: classes.tableHeaderCell,
|
|
2207
|
+
children: jsx(Typography, {
|
|
2208
|
+
variant: "heading24Medium",
|
|
2209
|
+
className: classes.tableText,
|
|
2210
|
+
children: t("logs.table.type", {
|
|
2211
|
+
defaultValue: "Type"
|
|
2212
|
+
})
|
|
2213
|
+
})
|
|
2214
|
+
}), jsx(TableCell, {
|
|
2215
|
+
className: classes.tableHeaderCell,
|
|
2216
|
+
children: jsx(Typography, {
|
|
2217
|
+
variant: "heading24Medium",
|
|
2218
|
+
className: classes.tableText,
|
|
2219
|
+
children: t("logs.table.code", {
|
|
2220
|
+
defaultValue: "Code"
|
|
2221
|
+
})
|
|
2222
|
+
})
|
|
2223
|
+
}), jsx(TableCell, {
|
|
2224
|
+
className: classes.tableHeaderCell,
|
|
2225
|
+
children: jsx(Typography, {
|
|
2226
|
+
variant: "heading24Medium",
|
|
2227
|
+
className: classes.tableText,
|
|
2228
|
+
children: t("logs.table.message", {
|
|
2229
|
+
defaultValue: "Message"
|
|
2230
|
+
})
|
|
2231
|
+
})
|
|
2232
|
+
}), jsx(TableCell, {
|
|
2233
|
+
className: classes.tableHeaderCell,
|
|
2234
|
+
children: jsx(Typography, {
|
|
2235
|
+
variant: "heading24Medium",
|
|
2236
|
+
className: classes.tableText,
|
|
2237
|
+
children: t("logs.table.description", {
|
|
2238
|
+
defaultValue: "Description"
|
|
2239
|
+
})
|
|
2240
|
+
})
|
|
2241
|
+
})]
|
|
2242
|
+
})
|
|
2243
|
+
}), jsx(TableBody, {
|
|
2244
|
+
children: logs.map(log => jsxs(TableRow, {
|
|
2245
|
+
hover: true,
|
|
2246
|
+
onClick: onLogClick ? () => onLogClick(log) : undefined,
|
|
2247
|
+
className: onLogClick ? classes.clickableRow : undefined,
|
|
2248
|
+
children: [jsx(TableCell, {
|
|
2249
|
+
className: classes.iconCell,
|
|
2250
|
+
children: jsx(Box, {
|
|
2251
|
+
className: classes.iconWrapper,
|
|
2252
|
+
children: renderTypeIcon(log.level)
|
|
2253
|
+
})
|
|
2254
|
+
}), jsx(TableCell, {
|
|
2255
|
+
children: jsx(Typography, {
|
|
2256
|
+
variant: "heading24Medium",
|
|
2257
|
+
className: classes.tableText,
|
|
2258
|
+
children: formatLogDate(log.date)
|
|
2259
|
+
})
|
|
2260
|
+
}), jsx(TableCell, {
|
|
2261
|
+
className: cx(classes.typeCell, getTypeClassName(log.level)),
|
|
2262
|
+
children: jsx(Typography, {
|
|
2263
|
+
variant: "heading24Medium",
|
|
2264
|
+
className: classes.tableText,
|
|
2265
|
+
children: t(`logs.type.${log.level}`, {
|
|
2266
|
+
defaultValue: log.level
|
|
2267
|
+
})
|
|
2268
|
+
})
|
|
2269
|
+
}), jsx(TableCell, {
|
|
2270
|
+
children: jsx(Typography, {
|
|
2271
|
+
variant: "heading24Medium",
|
|
2272
|
+
className: classes.tableText,
|
|
2273
|
+
children: log.code
|
|
2274
|
+
})
|
|
2275
|
+
}), jsx(TableCell, {
|
|
2276
|
+
children: jsx(Typography, {
|
|
2277
|
+
variant: "heading24Medium",
|
|
2278
|
+
className: classes.tableText,
|
|
2279
|
+
children: log.message
|
|
2280
|
+
})
|
|
2281
|
+
}), jsx(TableCell, {
|
|
2282
|
+
children: jsx(Typography, {
|
|
2283
|
+
variant: "heading24Medium",
|
|
2284
|
+
className: classes.tableText,
|
|
2285
|
+
children: log.description
|
|
2286
|
+
})
|
|
2287
|
+
})]
|
|
2288
|
+
}, log.id))
|
|
2289
|
+
})]
|
|
2290
|
+
})
|
|
2291
|
+
}), onLoadMoreLogs && hasMoreLogs && jsxs(Box, {
|
|
2292
|
+
ref: loadMoreRef,
|
|
2293
|
+
className: classes.loadMoreTrigger,
|
|
2294
|
+
children: [jsx(VentionSpinner, {
|
|
2295
|
+
size: "medium"
|
|
2296
|
+
}), jsx(Typography, {
|
|
2297
|
+
variant: "uiText14Regular",
|
|
2298
|
+
className: classes.loadMoreText,
|
|
2299
|
+
children: t("logs.loadingMore", {
|
|
2300
|
+
defaultValue: "Loading more logs..."
|
|
2301
|
+
})
|
|
2302
|
+
})]
|
|
2303
|
+
}), onLoadMoreLogs && !hasMoreLogs && logs.length > 0 && jsx(Box, {
|
|
2304
|
+
className: classes.endMessage,
|
|
2305
|
+
children: jsx(Typography, {
|
|
2306
|
+
variant: "uiText14Regular",
|
|
2307
|
+
children: t("logs.noMoreLogs", {
|
|
2308
|
+
defaultValue: "No more logs to load"
|
|
2309
|
+
})
|
|
2310
|
+
})
|
|
2311
|
+
})]
|
|
2312
|
+
});
|
|
2313
|
+
});
|
|
2314
|
+
LogsTable.displayName = "LogsTable";
|
|
2315
|
+
const useStyles$8 = tss.withParams().create(({
|
|
2316
|
+
theme,
|
|
2317
|
+
tableHeight
|
|
2318
|
+
}) => ({
|
|
2319
|
+
tableSection: {
|
|
2320
|
+
display: "flex",
|
|
2321
|
+
flexDirection: "column",
|
|
2322
|
+
alignItems: "center",
|
|
2323
|
+
gap: theme.spacing(4),
|
|
2324
|
+
alignSelf: "stretch",
|
|
2325
|
+
flex: 1,
|
|
2326
|
+
height: "auto"
|
|
2327
|
+
},
|
|
2328
|
+
centerState: {
|
|
2329
|
+
display: "flex",
|
|
2330
|
+
flexDirection: "column",
|
|
2331
|
+
alignItems: "center",
|
|
2332
|
+
justifyContent: "center",
|
|
2333
|
+
flex: 1,
|
|
2334
|
+
color: theme.palette.text.secondary
|
|
2335
|
+
},
|
|
2336
|
+
errorState: {
|
|
2337
|
+
display: "flex",
|
|
2338
|
+
alignItems: "center",
|
|
2339
|
+
justifyContent: "center",
|
|
2340
|
+
flex: 1,
|
|
2341
|
+
padding: theme.spacing(4)
|
|
2342
|
+
},
|
|
2343
|
+
tableContainer: Object.assign({
|
|
2344
|
+
width: "100%",
|
|
2345
|
+
flex: 1,
|
|
2346
|
+
overflow: "auto",
|
|
2347
|
+
minHeight: "560px"
|
|
2348
|
+
}, tableHeight && {
|
|
2349
|
+
maxHeight: tableHeight
|
|
2350
|
+
}),
|
|
2351
|
+
tableHead: {
|
|
2352
|
+
backgroundColor: theme.palette.background.default,
|
|
2353
|
+
borderBottom: `1px solid ${theme.palette.background.mutedSlate}`
|
|
2354
|
+
},
|
|
2355
|
+
iconHeaderCell: {
|
|
2356
|
+
width: 40,
|
|
2357
|
+
backgroundColor: theme.palette.background.default
|
|
2358
|
+
},
|
|
2359
|
+
tableHeaderCell: {
|
|
2360
|
+
fontWeight: 200,
|
|
2361
|
+
backgroundColor: theme.palette.background.default,
|
|
2362
|
+
color: theme.palette.text.tertiary
|
|
2363
|
+
},
|
|
2364
|
+
iconCell: {
|
|
2365
|
+
width: 40
|
|
2366
|
+
},
|
|
2367
|
+
iconWrapper: {
|
|
2368
|
+
display: "flex",
|
|
2369
|
+
alignItems: "center",
|
|
2370
|
+
justifyContent: "center"
|
|
2371
|
+
},
|
|
2372
|
+
typeCell: {
|
|
2373
|
+
textTransform: "capitalize",
|
|
2374
|
+
fontWeight: 500
|
|
2375
|
+
},
|
|
2376
|
+
errorType: {
|
|
2377
|
+
color: theme.palette.error.main
|
|
2378
|
+
},
|
|
2379
|
+
warningType: {
|
|
2380
|
+
color: theme.palette.warning.main
|
|
2381
|
+
},
|
|
2382
|
+
infoType: {
|
|
2383
|
+
color: theme.palette.info.main
|
|
2384
|
+
},
|
|
2385
|
+
loadMoreTrigger: {
|
|
2386
|
+
display: "flex",
|
|
2387
|
+
flexDirection: "column",
|
|
2388
|
+
alignItems: "center",
|
|
2389
|
+
justifyContent: "center",
|
|
2390
|
+
padding: theme.spacing(4),
|
|
2391
|
+
color: theme.palette.text.secondary
|
|
2392
|
+
},
|
|
2393
|
+
loadMoreText: {
|
|
2394
|
+
marginTop: theme.spacing(1)
|
|
2395
|
+
},
|
|
2396
|
+
clickableRow: {
|
|
2397
|
+
cursor: "pointer",
|
|
2398
|
+
"&:hover": {
|
|
2399
|
+
backgroundColor: theme.palette.action.hover
|
|
2400
|
+
}
|
|
2401
|
+
},
|
|
2402
|
+
emptyStateIcon: {
|
|
2403
|
+
marginBottom: theme.spacing(2),
|
|
2404
|
+
display: "flex",
|
|
2405
|
+
alignItems: "center",
|
|
2406
|
+
justifyContent: "center"
|
|
2407
|
+
},
|
|
2408
|
+
endMessage: {
|
|
2409
|
+
display: "flex",
|
|
2410
|
+
alignItems: "center",
|
|
2411
|
+
justifyContent: "center",
|
|
2412
|
+
padding: theme.spacing(4),
|
|
2413
|
+
color: theme.palette.text.secondary
|
|
2414
|
+
},
|
|
2415
|
+
tableText: {
|
|
2416
|
+
fontSize: "20px",
|
|
2417
|
+
lineHeight: "24px"
|
|
2418
|
+
}
|
|
2419
|
+
}));
|
|
2420
|
+
|
|
2421
|
+
const LogFilterForm = memo(({
|
|
2422
|
+
onFilterChange,
|
|
2423
|
+
onReset,
|
|
2424
|
+
initialFilters
|
|
2425
|
+
}) => {
|
|
2426
|
+
var _a, _b, _c, _d;
|
|
2427
|
+
const {
|
|
2428
|
+
classes
|
|
2429
|
+
} = useStyles$7();
|
|
2430
|
+
const {
|
|
2431
|
+
t
|
|
2432
|
+
} = useI18n();
|
|
2433
|
+
const handleFilterChangeRef = useRef(onFilterChange);
|
|
2434
|
+
useEffect(function updateFilterChangeRef() {
|
|
2435
|
+
handleFilterChangeRef.current = onFilterChange;
|
|
2436
|
+
}, [onFilterChange]);
|
|
2437
|
+
const [fromDate, setFromDate] = useState((_a = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.fromDate) !== null && _a !== void 0 ? _a : "");
|
|
2438
|
+
const [toDate, setToDate] = useState((_b = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.toDate) !== null && _b !== void 0 ? _b : "");
|
|
2439
|
+
const [logType, setLogType] = useState((_c = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.logType) !== null && _c !== void 0 ? _c : null);
|
|
2440
|
+
const [sortOrder, setSortOrder] = useState((_d = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.sortOrder) !== null && _d !== void 0 ? _d : "latest");
|
|
2441
|
+
const prevInitialFiltersRef = useRef(initialFilters);
|
|
2442
|
+
useEffect(function syncInitialFilters() {
|
|
2443
|
+
if (prevInitialFiltersRef.current !== initialFilters) {
|
|
2444
|
+
prevInitialFiltersRef.current = initialFilters;
|
|
2445
|
+
if (initialFilters) {
|
|
2446
|
+
if (initialFilters.fromDate !== undefined) setFromDate(initialFilters.fromDate);
|
|
2447
|
+
if (initialFilters.toDate !== undefined) setToDate(initialFilters.toDate);
|
|
2448
|
+
if (initialFilters.logType !== undefined) setLogType(initialFilters.logType);
|
|
2449
|
+
if (initialFilters.sortOrder !== undefined) setSortOrder(initialFilters.sortOrder);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}, [initialFilters]);
|
|
2453
|
+
const typeOptions = useMemo(() => [{
|
|
2454
|
+
value: "",
|
|
2455
|
+
displayText: t("logs.filter.typeOptions.all", {
|
|
2456
|
+
defaultValue: "All"
|
|
2457
|
+
})
|
|
2458
|
+
}, {
|
|
2459
|
+
value: "error",
|
|
2460
|
+
displayText: t("logs.filter.typeOptions.error", {
|
|
2461
|
+
defaultValue: "Error"
|
|
2462
|
+
})
|
|
2463
|
+
}, {
|
|
2464
|
+
value: "warning",
|
|
2465
|
+
displayText: t("logs.filter.typeOptions.warning", {
|
|
2466
|
+
defaultValue: "Warning"
|
|
2467
|
+
})
|
|
2468
|
+
}, {
|
|
2469
|
+
value: "info",
|
|
2470
|
+
displayText: t("logs.filter.typeOptions.info", {
|
|
2471
|
+
defaultValue: "Info"
|
|
2472
|
+
})
|
|
2473
|
+
}], [t]);
|
|
2474
|
+
const sortOptions = useMemo(() => [{
|
|
2475
|
+
value: "latest",
|
|
2476
|
+
displayText: t("logs.filter.sortOptions.latest", {
|
|
2477
|
+
defaultValue: "From latest"
|
|
2478
|
+
})
|
|
2479
|
+
}, {
|
|
2480
|
+
value: "oldest",
|
|
2481
|
+
displayText: t("logs.filter.sortOptions.oldest", {
|
|
2482
|
+
defaultValue: "From oldest"
|
|
2483
|
+
})
|
|
2484
|
+
}], [t]);
|
|
2485
|
+
const handleReset = () => {
|
|
2486
|
+
setFromDate("");
|
|
2487
|
+
setToDate("");
|
|
2488
|
+
setLogType(null);
|
|
2489
|
+
setSortOrder("latest");
|
|
2490
|
+
onReset === null || onReset === void 0 ? void 0 : onReset();
|
|
2491
|
+
};
|
|
2492
|
+
useEffect(function notifyFilterChange() {
|
|
2493
|
+
var _a;
|
|
2494
|
+
(_a = handleFilterChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(handleFilterChangeRef, {
|
|
2495
|
+
fromDate,
|
|
2496
|
+
toDate,
|
|
2497
|
+
logType,
|
|
2498
|
+
sortOrder
|
|
2499
|
+
});
|
|
2500
|
+
}, [fromDate, toDate, logType, sortOrder]);
|
|
2501
|
+
return jsxs(Box, {
|
|
2502
|
+
className: classes.filterSection,
|
|
2503
|
+
children: [jsx(Box, {
|
|
2504
|
+
className: classes.filterInput,
|
|
2505
|
+
children: jsx(VentionTextInput, {
|
|
2506
|
+
size: "xx-large",
|
|
2507
|
+
label: t("logs.filter.from", {
|
|
2508
|
+
defaultValue: "From"
|
|
2509
|
+
}),
|
|
2510
|
+
value: fromDate,
|
|
2511
|
+
onChange: event => setFromDate(event.target.value),
|
|
2512
|
+
type: "date"
|
|
2513
|
+
})
|
|
2514
|
+
}), jsx(Box, {
|
|
2515
|
+
className: classes.filterInput,
|
|
2516
|
+
children: jsx(VentionTextInput, {
|
|
2517
|
+
size: "xx-large",
|
|
2518
|
+
label: t("logs.filter.to", {
|
|
2519
|
+
defaultValue: "To"
|
|
2520
|
+
}),
|
|
2521
|
+
value: toDate,
|
|
2522
|
+
onChange: event => setToDate(event.target.value),
|
|
2523
|
+
type: "date"
|
|
2524
|
+
})
|
|
2525
|
+
}), jsx(Box, {
|
|
2526
|
+
className: classes.filterInput,
|
|
2527
|
+
children: jsx(VentionSelect, {
|
|
2528
|
+
size: "xx-large",
|
|
2529
|
+
variant: "outlined",
|
|
2530
|
+
labelText: t("logs.filter.type", {
|
|
2531
|
+
defaultValue: "Type"
|
|
2532
|
+
}),
|
|
2533
|
+
value: logType !== null && logType !== void 0 ? logType : "",
|
|
2534
|
+
onChange: event => {
|
|
2535
|
+
const value = event.target.value;
|
|
2536
|
+
setLogType(value === "" ? null : value);
|
|
2537
|
+
},
|
|
2538
|
+
placeholder: t("logs.filter.chooseType", {
|
|
2539
|
+
defaultValue: "Choose type"
|
|
2540
|
+
}),
|
|
2541
|
+
menuItems: typeOptions
|
|
2542
|
+
})
|
|
2543
|
+
}), jsx(Box, {
|
|
2544
|
+
className: classes.filterInput,
|
|
2545
|
+
children: jsx(VentionSelect, {
|
|
2546
|
+
size: "xx-large",
|
|
2547
|
+
variant: "outlined",
|
|
2548
|
+
labelText: t("logs.filter.sort", {
|
|
2549
|
+
defaultValue: "Sort"
|
|
2550
|
+
}),
|
|
2551
|
+
value: sortOrder,
|
|
2552
|
+
onChange: event => setSortOrder(event.target.value),
|
|
2553
|
+
menuItems: sortOptions
|
|
2554
|
+
})
|
|
2555
|
+
}), jsx(VentionButton, {
|
|
2556
|
+
size: "x-large",
|
|
2557
|
+
onClick: handleReset,
|
|
2558
|
+
className: classes.resetButton,
|
|
2559
|
+
children: t("logs.filter.reset", {
|
|
2560
|
+
defaultValue: "Reset"
|
|
2561
|
+
})
|
|
2562
|
+
})]
|
|
2563
|
+
});
|
|
2564
|
+
});
|
|
2565
|
+
LogFilterForm.displayName = "LogFilterForm";
|
|
2566
|
+
const useStyles$7 = tss.create(({
|
|
2567
|
+
theme
|
|
2568
|
+
}) => ({
|
|
2569
|
+
filterSection: {
|
|
2570
|
+
display: "flex",
|
|
2571
|
+
alignItems: "flex-end",
|
|
2572
|
+
gap: theme.spacing(4),
|
|
2573
|
+
alignSelf: "stretch",
|
|
2574
|
+
flexWrap: "wrap"
|
|
2575
|
+
},
|
|
2576
|
+
filterInput: {
|
|
2577
|
+
flex: "1 1 200px",
|
|
2578
|
+
minWidth: "200px"
|
|
2579
|
+
},
|
|
2580
|
+
resetButton: {
|
|
2581
|
+
width: "103px",
|
|
2582
|
+
height: "64px",
|
|
2583
|
+
backgroundColor: theme.palette.background.default,
|
|
2584
|
+
color: theme.palette.text.primary,
|
|
2585
|
+
"&:hover": {
|
|
2586
|
+
backgroundColor: theme.palette.background.default
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
}));
|
|
2590
|
+
|
|
2591
|
+
/******************************************************************************
|
|
2592
|
+
Copyright (c) Microsoft Corporation.
|
|
2593
|
+
|
|
2594
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
2595
|
+
purpose with or without fee is hereby granted.
|
|
2596
|
+
|
|
2597
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
2598
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
2599
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
2600
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
2601
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
2602
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2603
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
2604
|
+
***************************************************************************** */
|
|
2605
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
2606
|
+
|
|
2607
|
+
|
|
2608
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
2609
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
2610
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
2611
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
2612
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
2613
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
2614
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
2619
|
+
var e = new Error(message);
|
|
2620
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
const LogsPagination = memo(({
|
|
2624
|
+
currentPage,
|
|
2625
|
+
totalPages,
|
|
2626
|
+
onPageChange
|
|
2627
|
+
}) => {
|
|
2628
|
+
const {
|
|
2629
|
+
classes
|
|
2630
|
+
} = useStyles$6();
|
|
2631
|
+
const {
|
|
2632
|
+
t
|
|
2633
|
+
} = useI18n();
|
|
2634
|
+
const handlePrevious = () => {
|
|
2635
|
+
if (currentPage > 1) {
|
|
2636
|
+
onPageChange(currentPage - 1);
|
|
2637
|
+
}
|
|
2638
|
+
};
|
|
2639
|
+
const handleNext = () => {
|
|
2640
|
+
if (currentPage < totalPages) {
|
|
2641
|
+
onPageChange(currentPage + 1);
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
return jsxs(Box, {
|
|
2645
|
+
className: classes.paginationSection,
|
|
2646
|
+
children: [jsx(VentionButton, {
|
|
2647
|
+
size: "x-large",
|
|
2648
|
+
className: classes.paginationButton,
|
|
2649
|
+
onClick: handlePrevious,
|
|
2650
|
+
disabled: currentPage === 1,
|
|
2651
|
+
children: "\u2190"
|
|
2652
|
+
}), jsxs(Typography, {
|
|
2653
|
+
variant: "heading18SemiBold",
|
|
2654
|
+
children: [t("pagination.page", {
|
|
2655
|
+
defaultValue: "Page"
|
|
2656
|
+
}), " ", currentPage, " ", t("pagination.of", {
|
|
2657
|
+
defaultValue: "of"
|
|
2658
|
+
}), " ", totalPages]
|
|
2659
|
+
}), jsx(VentionButton, {
|
|
2660
|
+
size: "x-large",
|
|
2661
|
+
className: classes.paginationButton,
|
|
2662
|
+
onClick: handleNext,
|
|
2663
|
+
disabled: currentPage === totalPages,
|
|
2664
|
+
children: "\u2192"
|
|
2665
|
+
})]
|
|
2666
|
+
});
|
|
2667
|
+
});
|
|
2668
|
+
LogsPagination.displayName = "LogsPagination";
|
|
2669
|
+
const useStyles$6 = tss.create(({
|
|
2670
|
+
theme
|
|
2671
|
+
}) => ({
|
|
2672
|
+
paginationSection: {
|
|
2673
|
+
display: "flex",
|
|
2674
|
+
justifyContent: "center",
|
|
2675
|
+
alignItems: "center",
|
|
2676
|
+
alignSelf: "stretch",
|
|
2677
|
+
gap: theme.spacing(4)
|
|
2678
|
+
},
|
|
2679
|
+
paginationButton: {
|
|
2680
|
+
width: "64px",
|
|
2681
|
+
height: "64px",
|
|
2682
|
+
backgroundColor: theme.palette.background.default,
|
|
2683
|
+
color: theme.palette.text.primary,
|
|
2684
|
+
"&:hover": {
|
|
2685
|
+
backgroundColor: theme.palette.grey[300]
|
|
2686
|
+
},
|
|
2687
|
+
"&:disabled": {
|
|
2688
|
+
opacity: 0.5,
|
|
2689
|
+
cursor: "not-allowed",
|
|
2690
|
+
backgroundColor: theme.palette.background.slate
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
}));
|
|
2694
|
+
|
|
2695
|
+
const formatDateToInput = date => {
|
|
2696
|
+
return dayjs(date).format("YYYY-MM-DD");
|
|
2697
|
+
};
|
|
2698
|
+
const parseLogDate = dateStr => {
|
|
2699
|
+
const parsed = dayjs(dateStr);
|
|
2700
|
+
return parsed.isValid() ? parsed.valueOf() : 0;
|
|
2701
|
+
};
|
|
2702
|
+
const LogsPanel = forwardRef((props, ref) => {
|
|
2703
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2704
|
+
const {
|
|
2705
|
+
dataFetcher,
|
|
2706
|
+
initialFilters,
|
|
2707
|
+
onError,
|
|
2708
|
+
pagination,
|
|
2709
|
+
onFilterChange,
|
|
2710
|
+
onLogClick,
|
|
2711
|
+
className,
|
|
2712
|
+
tableHeight,
|
|
2713
|
+
emptyStateMessage,
|
|
2714
|
+
emptyStateIcon
|
|
2715
|
+
} = props;
|
|
2716
|
+
const {
|
|
2717
|
+
classes,
|
|
2718
|
+
cx
|
|
2719
|
+
} = useStyles$5();
|
|
2720
|
+
const [logs, setLogs] = useState([]);
|
|
2721
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
2722
|
+
const [error, setError] = useState(null);
|
|
2723
|
+
const [filters, setFilters] = useState({
|
|
2724
|
+
fromDate: (_a = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.fromDate) !== null && _a !== void 0 ? _a : null,
|
|
2725
|
+
toDate: (_b = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.toDate) !== null && _b !== void 0 ? _b : null,
|
|
2726
|
+
logType: (_c = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.logType) !== null && _c !== void 0 ? _c : null,
|
|
2727
|
+
sortOrder: (_d = initialFilters === null || initialFilters === void 0 ? void 0 : initialFilters.sortOrder) !== null && _d !== void 0 ? _d : "latest"
|
|
2728
|
+
});
|
|
2729
|
+
const paginationMode = (_e = pagination === null || pagination === void 0 ? void 0 : pagination.mode) !== null && _e !== void 0 ? _e : "none";
|
|
2730
|
+
const pageSize = (_f = pagination === null || pagination === void 0 ? void 0 : pagination.pageSize) !== null && _f !== void 0 ? _f : 10;
|
|
2731
|
+
const [currentPage, setCurrentPage] = useState((_g = pagination === null || pagination === void 0 ? void 0 : pagination.initialPage) !== null && _g !== void 0 ? _g : 1);
|
|
2732
|
+
const [totalPages, setTotalPages] = useState(1);
|
|
2733
|
+
const [hasMorePages, setHasMorePages] = useState(false);
|
|
2734
|
+
const fetchData = useCallback(function fetchData(page, signal) {
|
|
2735
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2736
|
+
setIsLoading(true);
|
|
2737
|
+
setError(null);
|
|
2738
|
+
try {
|
|
2739
|
+
const result = yield dataFetcher({
|
|
2740
|
+
filters,
|
|
2741
|
+
page,
|
|
2742
|
+
pageSize
|
|
2743
|
+
});
|
|
2744
|
+
if (!(signal === null || signal === void 0 ? void 0 : signal.aborted)) {
|
|
2745
|
+
if (paginationMode === "infinite-scroll" && page > 1) {
|
|
2746
|
+
setLogs(prev => [...prev, ...result.logs]);
|
|
2747
|
+
} else {
|
|
2748
|
+
setLogs(result.logs);
|
|
2749
|
+
}
|
|
2750
|
+
setTotalPages(result.totalPages);
|
|
2751
|
+
setHasMorePages(result.hasMorePages);
|
|
2752
|
+
setCurrentPage(result.currentPage);
|
|
2753
|
+
setIsLoading(false);
|
|
2754
|
+
}
|
|
2755
|
+
} catch (error) {
|
|
2756
|
+
if (!(signal === null || signal === void 0 ? void 0 : signal.aborted)) {
|
|
2757
|
+
const errorMessage = error instanceof Error ? error.message : "Failed to load logs";
|
|
2758
|
+
setError(errorMessage);
|
|
2759
|
+
setIsLoading(false);
|
|
2760
|
+
if (onError) {
|
|
2761
|
+
onError(error);
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
});
|
|
2766
|
+
}, [dataFetcher, filters, pageSize, paginationMode, onError]);
|
|
2767
|
+
useEffect(function fetchDataOnChange() {
|
|
2768
|
+
const controller = new AbortController();
|
|
2769
|
+
fetchData(currentPage, controller.signal);
|
|
2770
|
+
return function cleanup() {
|
|
2771
|
+
controller.abort();
|
|
2772
|
+
};
|
|
2773
|
+
}, [fetchData, currentPage]);
|
|
2774
|
+
const handlePageChange = useCallback(page => {
|
|
2775
|
+
setCurrentPage(page);
|
|
2776
|
+
}, []);
|
|
2777
|
+
const handleLoadMorePages = useCallback(() => {
|
|
2778
|
+
if (hasMorePages) {
|
|
2779
|
+
setCurrentPage(prev => prev + 1);
|
|
2780
|
+
}
|
|
2781
|
+
}, [hasMorePages]);
|
|
2782
|
+
const handleFilterChange = useCallback(next => {
|
|
2783
|
+
setFilters(next);
|
|
2784
|
+
setCurrentPage(1);
|
|
2785
|
+
if (paginationMode === "infinite-scroll") {
|
|
2786
|
+
setLogs([]);
|
|
2787
|
+
}
|
|
2788
|
+
if (onFilterChange) {
|
|
2789
|
+
onFilterChange(next);
|
|
2790
|
+
}
|
|
2791
|
+
}, [onFilterChange, paginationMode]);
|
|
2792
|
+
const handleReset = useCallback(() => {
|
|
2793
|
+
const resetFilters = {
|
|
2794
|
+
fromDate: null,
|
|
2795
|
+
toDate: null,
|
|
2796
|
+
logType: null,
|
|
2797
|
+
sortOrder: "latest"
|
|
2798
|
+
};
|
|
2799
|
+
setFilters(resetFilters);
|
|
2800
|
+
setCurrentPage(1);
|
|
2801
|
+
if (paginationMode === "infinite-scroll") {
|
|
2802
|
+
setLogs([]);
|
|
2803
|
+
}
|
|
2804
|
+
if (onFilterChange) {
|
|
2805
|
+
onFilterChange(resetFilters);
|
|
2806
|
+
}
|
|
2807
|
+
}, [onFilterChange, paginationMode]);
|
|
2808
|
+
const refresh = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
2809
|
+
yield fetchData(currentPage);
|
|
2810
|
+
}), [fetchData, currentPage]);
|
|
2811
|
+
const resetFilters = useCallback(() => {
|
|
2812
|
+
handleReset();
|
|
2813
|
+
}, [handleReset]);
|
|
2814
|
+
const applyFilters = useCallback(newFilters => {
|
|
2815
|
+
const updatedFilters = Object.assign(Object.assign({}, filters), newFilters);
|
|
2816
|
+
setFilters(updatedFilters);
|
|
2817
|
+
if (onFilterChange) {
|
|
2818
|
+
onFilterChange(updatedFilters);
|
|
2819
|
+
}
|
|
2820
|
+
}, [filters, onFilterChange]);
|
|
2821
|
+
const getCurrentFilters = useCallback(() => filters, [filters]);
|
|
2822
|
+
const exportLogs = useCallback(() => logs, [logs]);
|
|
2823
|
+
useImperativeHandle(ref, () => ({
|
|
2824
|
+
refresh,
|
|
2825
|
+
resetFilters,
|
|
2826
|
+
applyFilters,
|
|
2827
|
+
getCurrentFilters,
|
|
2828
|
+
exportLogs
|
|
2829
|
+
}), [refresh, resetFilters, applyFilters, getCurrentFilters, exportLogs]);
|
|
2830
|
+
return jsxs(Box, {
|
|
2831
|
+
className: cx(classes.root, className),
|
|
2832
|
+
children: [jsx(LogFilterForm, {
|
|
2833
|
+
onFilterChange: handleFilterChange,
|
|
2834
|
+
onReset: handleReset,
|
|
2835
|
+
initialFilters: filters
|
|
2836
|
+
}), jsx(LogsTable, {
|
|
2837
|
+
logs: logs,
|
|
2838
|
+
isLoading: isLoading,
|
|
2839
|
+
error: error,
|
|
2840
|
+
onLoadMoreLogs: paginationMode === "infinite-scroll" ? handleLoadMorePages : undefined,
|
|
2841
|
+
hasMoreLogs: paginationMode === "infinite-scroll" ? hasMorePages : undefined,
|
|
2842
|
+
onLogClick: onLogClick,
|
|
2843
|
+
tableHeight: tableHeight,
|
|
2844
|
+
emptyStateMessage: emptyStateMessage,
|
|
2845
|
+
emptyStateIcon: emptyStateIcon
|
|
2846
|
+
}), paginationMode === "pagination" && !isLoading && !error && logs.length > 0 && jsx(LogsPagination, {
|
|
2847
|
+
currentPage: currentPage,
|
|
2848
|
+
totalPages: totalPages,
|
|
2849
|
+
onPageChange: handlePageChange
|
|
2850
|
+
})]
|
|
2851
|
+
});
|
|
2852
|
+
});
|
|
2853
|
+
LogsPanel.displayName = "LogsPanel";
|
|
2854
|
+
const useStyles$5 = tss.create(({
|
|
2855
|
+
theme
|
|
2856
|
+
}) => ({
|
|
2857
|
+
root: {
|
|
2858
|
+
display: "flex",
|
|
2859
|
+
flexDirection: "column",
|
|
2860
|
+
gap: theme.spacing(4),
|
|
2861
|
+
alignSelf: "stretch"
|
|
2862
|
+
}
|
|
2863
|
+
}));
|
|
2864
|
+
|
|
2865
|
+
const SettingsPage = function SettingsPage({
|
|
2866
|
+
sidebarItems,
|
|
2867
|
+
children,
|
|
2868
|
+
sidebarWidth = 320
|
|
2869
|
+
}) {
|
|
2870
|
+
const {
|
|
2871
|
+
classes
|
|
2872
|
+
} = useStyles$4({
|
|
2873
|
+
sidebarWidth
|
|
2874
|
+
});
|
|
2875
|
+
return jsxs(Box, {
|
|
2876
|
+
className: classes.root,
|
|
2877
|
+
children: [jsx(Box, {
|
|
2878
|
+
className: classes.sidebar,
|
|
2879
|
+
children: jsx(Sidebar, {
|
|
2880
|
+
items: sidebarItems
|
|
2881
|
+
})
|
|
2882
|
+
}), jsx(Box, {
|
|
2883
|
+
className: classes.content,
|
|
2884
|
+
children: children
|
|
2885
|
+
})]
|
|
2886
|
+
});
|
|
2887
|
+
};
|
|
2888
|
+
SettingsPage.displayName = "SettingsPage";
|
|
2889
|
+
const useStyles$4 = tss.withParams().create(({
|
|
2890
|
+
theme,
|
|
2891
|
+
sidebarWidth
|
|
2892
|
+
}) => ({
|
|
2893
|
+
root: {
|
|
2894
|
+
display: "flex",
|
|
2895
|
+
flex: 1,
|
|
2896
|
+
height: "100%"
|
|
2897
|
+
},
|
|
2898
|
+
sidebar: {
|
|
2899
|
+
width: sidebarWidth,
|
|
2900
|
+
borderRight: `1px solid ${theme.palette.divider}`,
|
|
2901
|
+
backgroundColor: theme.palette.background.paper
|
|
2902
|
+
},
|
|
2903
|
+
content: {
|
|
2904
|
+
flex: 1,
|
|
2905
|
+
padding: theme.spacing(4),
|
|
2906
|
+
overflow: "auto"
|
|
2907
|
+
}
|
|
2908
|
+
}));
|
|
2909
|
+
|
|
2910
|
+
function formatFileSize(bytes) {
|
|
2911
|
+
if (bytes === 0) return "0 B";
|
|
2912
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
2913
|
+
const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
2914
|
+
const size = (bytes / Math.pow(1024, exponent)).toFixed(1);
|
|
2915
|
+
return `${size} ${units[exponent]}`;
|
|
2916
|
+
}
|
|
2917
|
+
function FileUploadPanel({
|
|
2918
|
+
title,
|
|
2919
|
+
files,
|
|
2920
|
+
onFilesSelect,
|
|
2921
|
+
onFileRemove,
|
|
2922
|
+
onFileRetry,
|
|
2923
|
+
onFileCancel,
|
|
2924
|
+
fileCriteriaDescription,
|
|
2925
|
+
dropzoneTitle,
|
|
2926
|
+
disabled = false,
|
|
2927
|
+
maxHeight
|
|
2928
|
+
}) {
|
|
2929
|
+
const {
|
|
2930
|
+
classes
|
|
2931
|
+
} = useStyles$3({
|
|
2932
|
+
maxHeight
|
|
2933
|
+
});
|
|
2934
|
+
const {
|
|
2935
|
+
t
|
|
2936
|
+
} = useTranslation();
|
|
2937
|
+
const displayTitle = title !== null && title !== void 0 ? title : t("fileUploadPanel.defaultTitle");
|
|
2938
|
+
const displayDropzoneTitle = dropzoneTitle !== null && dropzoneTitle !== void 0 ? dropzoneTitle : t("fileUploadPanel.dropzoneTitle");
|
|
2939
|
+
const displayFileCriteria = fileCriteriaDescription !== null && fileCriteriaDescription !== void 0 ? fileCriteriaDescription : t("fileUploadPanel.defaultFileCriteria");
|
|
2940
|
+
function handleFileRemove(fileId) {
|
|
2941
|
+
onFileRemove(fileId);
|
|
2942
|
+
}
|
|
2943
|
+
function handleFileRetry(fileId) {
|
|
2944
|
+
if (onFileRetry) {
|
|
2945
|
+
onFileRetry(fileId);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
function handleFileCancel(fileId) {
|
|
2949
|
+
if (onFileCancel) {
|
|
2950
|
+
onFileCancel(fileId);
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
return jsxs(Box, {
|
|
2954
|
+
className: classes.container,
|
|
2955
|
+
children: [displayTitle && jsx(Typography, {
|
|
2956
|
+
variant: "heading18SemiBold",
|
|
2957
|
+
className: classes.title,
|
|
2958
|
+
children: displayTitle
|
|
2959
|
+
}), jsx(VentionDropZone, {
|
|
2960
|
+
style: "outline",
|
|
2961
|
+
size: "large",
|
|
2962
|
+
onFilesSelect: onFilesSelect,
|
|
2963
|
+
fileCriteriaDescription: displayFileCriteria,
|
|
2964
|
+
defaultTitle: displayDropzoneTitle,
|
|
2965
|
+
disabled: disabled
|
|
2966
|
+
}), files.length > 0 && jsx(Box, {
|
|
2967
|
+
className: classes.fileList,
|
|
2968
|
+
children: files.map(file => jsx(VentionUploadFile, {
|
|
2969
|
+
fileName: file.name,
|
|
2970
|
+
fileSize: formatFileSize(file.size),
|
|
2971
|
+
state: file.state,
|
|
2972
|
+
errorMessage: file.errorMessage,
|
|
2973
|
+
size: "large",
|
|
2974
|
+
style: "shaded",
|
|
2975
|
+
onRemove: () => handleFileRemove(file.id),
|
|
2976
|
+
onRetry: () => handleFileRetry(file.id),
|
|
2977
|
+
onCancel: () => handleFileCancel(file.id)
|
|
2978
|
+
}, file.id))
|
|
2979
|
+
})]
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
FileUploadPanel.displayName = "FileUploadPanel";
|
|
2983
|
+
const useStyles$3 = tss.withParams().create(({
|
|
2984
|
+
theme,
|
|
2985
|
+
maxHeight
|
|
2986
|
+
}) => ({
|
|
2987
|
+
container: {
|
|
2988
|
+
display: "flex",
|
|
2989
|
+
flexDirection: "column",
|
|
2990
|
+
gap: theme.spacing(2),
|
|
2991
|
+
width: "100%"
|
|
2992
|
+
},
|
|
2993
|
+
title: {
|
|
2994
|
+
marginBottom: theme.spacing(1)
|
|
2995
|
+
},
|
|
2996
|
+
fileList: {
|
|
2997
|
+
display: "flex",
|
|
2998
|
+
flexDirection: "column",
|
|
2999
|
+
gap: theme.spacing(1),
|
|
3000
|
+
maxHeight: maxHeight !== null && maxHeight !== void 0 ? maxHeight : "auto",
|
|
3001
|
+
overflowY: maxHeight ? "auto" : "visible",
|
|
3002
|
+
"& .MuiGrid-container": {
|
|
3003
|
+
width: "100%"
|
|
3004
|
+
},
|
|
3005
|
+
"& .MuiGrid-root:nth-of-type(2)": {
|
|
3006
|
+
flex: "1 1 0",
|
|
3007
|
+
minWidth: 0
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
}));
|
|
3011
|
+
|
|
3012
|
+
/** Padding between the circle edge and the SVG boundary */
|
|
3013
|
+
const CIRCLE_PADDING = 10;
|
|
3014
|
+
function StepProgressCircle({
|
|
3015
|
+
currentStep,
|
|
3016
|
+
totalSteps,
|
|
3017
|
+
title,
|
|
3018
|
+
variant = "default",
|
|
3019
|
+
size = 180,
|
|
3020
|
+
strokeWidth = 12,
|
|
3021
|
+
showTitle = true
|
|
3022
|
+
}) {
|
|
3023
|
+
var _a;
|
|
3024
|
+
const {
|
|
3025
|
+
t
|
|
3026
|
+
} = useTranslation();
|
|
3027
|
+
const {
|
|
3028
|
+
classes
|
|
3029
|
+
} = useStyles$2({
|
|
3030
|
+
size,
|
|
3031
|
+
strokeWidth,
|
|
3032
|
+
variant
|
|
3033
|
+
});
|
|
3034
|
+
const titleKey = (_a = title === null || title === void 0 ? void 0 : title.toLowerCase().replace(/\s/g, "")) !== null && _a !== void 0 ? _a : "progress";
|
|
3035
|
+
const displayTitle = t(`stepProgressCircle.title.${titleKey}`, {
|
|
3036
|
+
defaultValue: title !== null && title !== void 0 ? title : "Progress"
|
|
3037
|
+
});
|
|
3038
|
+
const percentage = totalSteps > 0 ? Math.round(currentStep / totalSteps * 100) : 0;
|
|
3039
|
+
const radius = (size - strokeWidth) / 2 - CIRCLE_PADDING;
|
|
3040
|
+
const circumference = 2 * Math.PI * radius;
|
|
3041
|
+
const strokeDashoffset = circumference - percentage / 100 * circumference;
|
|
3042
|
+
const center = size / 2;
|
|
3043
|
+
const progressText = totalSteps > 0 ? `${currentStep}/${totalSteps}` : "-/-";
|
|
3044
|
+
return jsxs(Box, {
|
|
3045
|
+
className: classes.container,
|
|
3046
|
+
children: [showTitle && jsx(Typography, {
|
|
3047
|
+
variant: "heading18SemiBold",
|
|
3048
|
+
className: classes.title,
|
|
3049
|
+
children: displayTitle
|
|
3050
|
+
}), jsxs(Box, {
|
|
3051
|
+
className: classes.circleContainer,
|
|
3052
|
+
children: [jsxs("svg", {
|
|
3053
|
+
className: classes.svg,
|
|
3054
|
+
width: size,
|
|
3055
|
+
height: size,
|
|
3056
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
3057
|
+
children: [jsx("circle", {
|
|
3058
|
+
cx: center,
|
|
3059
|
+
cy: center,
|
|
3060
|
+
r: radius,
|
|
3061
|
+
className: classes.backgroundCircle,
|
|
3062
|
+
fill: "none"
|
|
3063
|
+
}), jsx("circle", {
|
|
3064
|
+
cx: center,
|
|
3065
|
+
cy: center,
|
|
3066
|
+
r: radius,
|
|
3067
|
+
className: classes.progressCircle,
|
|
3068
|
+
fill: "none",
|
|
3069
|
+
strokeLinecap: "round",
|
|
3070
|
+
transform: `rotate(-90 ${center} ${center})`,
|
|
3071
|
+
strokeDasharray: circumference,
|
|
3072
|
+
strokeDashoffset: strokeDashoffset
|
|
3073
|
+
})]
|
|
3074
|
+
}), jsx(Box, {
|
|
3075
|
+
className: classes.textContainer,
|
|
3076
|
+
children: jsx(Typography, {
|
|
3077
|
+
variant: "heading24SemiBold",
|
|
3078
|
+
className: classes.progressText,
|
|
3079
|
+
children: progressText
|
|
3080
|
+
})
|
|
3081
|
+
})]
|
|
3082
|
+
})]
|
|
3083
|
+
});
|
|
3084
|
+
}
|
|
3085
|
+
StepProgressCircle.displayName = "StepProgressCircle";
|
|
3086
|
+
const useStyles$2 = tss.withParams().create(({
|
|
3087
|
+
theme,
|
|
3088
|
+
size,
|
|
3089
|
+
strokeWidth,
|
|
3090
|
+
variant
|
|
3091
|
+
}) => {
|
|
3092
|
+
const variantColors = {
|
|
3093
|
+
default: theme.palette.primary.main,
|
|
3094
|
+
success: theme.palette.success.main,
|
|
3095
|
+
error: theme.palette.error.main,
|
|
3096
|
+
warning: theme.palette.warning.main
|
|
3097
|
+
};
|
|
3098
|
+
return {
|
|
3099
|
+
container: {
|
|
3100
|
+
display: "flex",
|
|
3101
|
+
flexDirection: "column",
|
|
3102
|
+
alignItems: "center",
|
|
3103
|
+
justifyContent: "center"
|
|
3104
|
+
},
|
|
3105
|
+
title: {
|
|
3106
|
+
marginBottom: theme.spacing(2),
|
|
3107
|
+
color: theme.palette.text.primary
|
|
3108
|
+
},
|
|
3109
|
+
circleContainer: {
|
|
3110
|
+
position: "relative",
|
|
3111
|
+
width: size,
|
|
3112
|
+
height: size
|
|
3113
|
+
},
|
|
3114
|
+
svg: {
|
|
3115
|
+
width: size,
|
|
3116
|
+
height: size
|
|
3117
|
+
},
|
|
3118
|
+
backgroundCircle: {
|
|
3119
|
+
stroke: theme.palette.grey[200],
|
|
3120
|
+
strokeWidth
|
|
3121
|
+
},
|
|
3122
|
+
progressCircle: {
|
|
3123
|
+
stroke: variantColors[variant],
|
|
3124
|
+
strokeWidth,
|
|
3125
|
+
transition: "stroke-dashoffset 0.5s ease-in-out, stroke 0.3s ease-in-out"
|
|
3126
|
+
},
|
|
3127
|
+
textContainer: {
|
|
3128
|
+
position: "absolute",
|
|
3129
|
+
top: "50%",
|
|
3130
|
+
left: "50%",
|
|
3131
|
+
transform: "translate(-50%, -50%)",
|
|
3132
|
+
display: "flex",
|
|
3133
|
+
alignItems: "center",
|
|
3134
|
+
justifyContent: "center"
|
|
3135
|
+
},
|
|
3136
|
+
progressText: {
|
|
3137
|
+
color: theme.palette.text.primary
|
|
3138
|
+
}
|
|
3139
|
+
};
|
|
3140
|
+
});
|
|
3141
|
+
|
|
3142
|
+
const ActionButton = function ActionButton({
|
|
3143
|
+
variant = "primary",
|
|
3144
|
+
onClick,
|
|
3145
|
+
disabled = false,
|
|
3146
|
+
icon,
|
|
3147
|
+
label,
|
|
3148
|
+
size = 96
|
|
3149
|
+
}) {
|
|
3150
|
+
const {
|
|
3151
|
+
classes
|
|
3152
|
+
} = useStyles$1({
|
|
3153
|
+
size
|
|
3154
|
+
});
|
|
3155
|
+
const {
|
|
3156
|
+
t
|
|
3157
|
+
} = useTranslation();
|
|
3158
|
+
const translationKey = label.toLowerCase().replace(/\s+/g, "_");
|
|
3159
|
+
const translatedLabel = t(`actionButton.${translationKey}`, {
|
|
3160
|
+
defaultValue: label
|
|
3161
|
+
});
|
|
3162
|
+
return jsx(VentionIconButton, {
|
|
3163
|
+
onClick: onClick,
|
|
3164
|
+
disabled: disabled,
|
|
3165
|
+
size: "x-large",
|
|
3166
|
+
variant: variant === "destructive" ? "destructive" : "filled",
|
|
3167
|
+
className: classes.button,
|
|
3168
|
+
"data-testid": "action-button",
|
|
3169
|
+
children: jsxs(Box, {
|
|
3170
|
+
className: classes.content,
|
|
3171
|
+
children: [jsx(Box, {
|
|
3172
|
+
className: classes.iconContainer,
|
|
3173
|
+
children: icon
|
|
3174
|
+
}), jsx(Typography, {
|
|
3175
|
+
variant: "uiText14SemiBold",
|
|
3176
|
+
className: classes.label,
|
|
3177
|
+
children: translatedLabel
|
|
3178
|
+
})]
|
|
3179
|
+
})
|
|
3180
|
+
});
|
|
3181
|
+
};
|
|
3182
|
+
ActionButton.displayName = "ActionButton";
|
|
3183
|
+
const useStyles$1 = tss.withParams().create(({
|
|
3184
|
+
theme,
|
|
3185
|
+
size
|
|
3186
|
+
}) => ({
|
|
3187
|
+
button: {
|
|
3188
|
+
height: size,
|
|
3189
|
+
width: size,
|
|
3190
|
+
minWidth: size,
|
|
3191
|
+
padding: theme.spacing(2)
|
|
3192
|
+
},
|
|
3193
|
+
content: {
|
|
3194
|
+
display: "flex",
|
|
3195
|
+
flexDirection: "column",
|
|
3196
|
+
alignItems: "center",
|
|
3197
|
+
justifyContent: "center",
|
|
3198
|
+
gap: theme.spacing(1)
|
|
3199
|
+
},
|
|
3200
|
+
iconContainer: {
|
|
3201
|
+
display: "flex",
|
|
3202
|
+
alignItems: "center",
|
|
3203
|
+
justifyContent: "center"
|
|
3204
|
+
},
|
|
3205
|
+
label: {
|
|
3206
|
+
textAlign: "center"
|
|
3207
|
+
}
|
|
3208
|
+
}));
|
|
3209
|
+
|
|
3210
|
+
function useAutoScrollInput(enabled, options = {}) {
|
|
3211
|
+
const {
|
|
3212
|
+
targetPositionPercent = 25,
|
|
3213
|
+
scrollableContainerSelector = '[role="dialog"] .MuiDialogContent-root',
|
|
3214
|
+
scrollBehavior = "smooth"
|
|
3215
|
+
} = options;
|
|
3216
|
+
useEffect(() => {
|
|
3217
|
+
if (!enabled) return;
|
|
3218
|
+
function findScrollableParent(element) {
|
|
3219
|
+
let parent = element.parentElement;
|
|
3220
|
+
while (parent) {
|
|
3221
|
+
const style = window.getComputedStyle(parent);
|
|
3222
|
+
const hasOverflow = style.overflow === "auto" || style.overflow === "scroll" || style.overflowY === "auto" || style.overflowY === "scroll";
|
|
3223
|
+
if (hasOverflow) {
|
|
3224
|
+
return parent;
|
|
3225
|
+
}
|
|
3226
|
+
if (parent === document.body || parent === document.documentElement) {
|
|
3227
|
+
break;
|
|
3228
|
+
}
|
|
3229
|
+
parent = parent.parentElement;
|
|
3230
|
+
}
|
|
3231
|
+
return null;
|
|
3232
|
+
}
|
|
3233
|
+
function handleFocus(event) {
|
|
3234
|
+
const target = event.target;
|
|
3235
|
+
if (!target || !(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement)) {
|
|
3236
|
+
return;
|
|
3237
|
+
}
|
|
3238
|
+
const targetRect = target.getBoundingClientRect();
|
|
3239
|
+
const viewportHeight = window.innerHeight;
|
|
3240
|
+
const targetY = viewportHeight * (targetPositionPercent / 100);
|
|
3241
|
+
const currentY = targetRect.top;
|
|
3242
|
+
const scrollNeeded = currentY - targetY;
|
|
3243
|
+
let scrollableContainer = null;
|
|
3244
|
+
if (scrollableContainerSelector) {
|
|
3245
|
+
const selectors = scrollableContainerSelector.split(",").map(selector => selector.trim());
|
|
3246
|
+
for (const selector of selectors) {
|
|
3247
|
+
const found = document.querySelector(selector);
|
|
3248
|
+
if (found) {
|
|
3249
|
+
scrollableContainer = found;
|
|
3250
|
+
break;
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
if (!scrollableContainer) {
|
|
3255
|
+
scrollableContainer = findScrollableParent(target);
|
|
3256
|
+
}
|
|
3257
|
+
if (scrollableContainer) {
|
|
3258
|
+
const currentScrollTop = scrollableContainer.scrollTop;
|
|
3259
|
+
const newScrollTop = currentScrollTop + scrollNeeded;
|
|
3260
|
+
scrollableContainer.scrollTo({
|
|
3261
|
+
top: newScrollTop,
|
|
3262
|
+
behavior: scrollBehavior
|
|
3263
|
+
});
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
document.addEventListener("focusin", handleFocus);
|
|
3267
|
+
return () => {
|
|
3268
|
+
document.removeEventListener("focusin", handleFocus);
|
|
3269
|
+
};
|
|
3270
|
+
}, [enabled, targetPositionPercent, scrollableContainerSelector, scrollBehavior]);
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
function ProductFormListComponent({
|
|
3274
|
+
title = "Products",
|
|
3275
|
+
items,
|
|
3276
|
+
onDelete,
|
|
3277
|
+
onSubmit,
|
|
3278
|
+
getItemId,
|
|
3279
|
+
fields,
|
|
3280
|
+
maxHeight = 600
|
|
3281
|
+
}) {
|
|
3282
|
+
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
|
3283
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
3284
|
+
const [deleteId, setDeleteId] = useState(null);
|
|
3285
|
+
const [formData, setFormData] = useState({});
|
|
3286
|
+
const {
|
|
3287
|
+
t
|
|
3288
|
+
} = useTranslation();
|
|
3289
|
+
const {
|
|
3290
|
+
classes
|
|
3291
|
+
} = useStyles({
|
|
3292
|
+
maxHeight
|
|
3293
|
+
});
|
|
3294
|
+
useAutoScrollInput(editDialogOpen);
|
|
3295
|
+
function handleEditClick(item) {
|
|
3296
|
+
setFormData(item);
|
|
3297
|
+
setEditDialogOpen(true);
|
|
3298
|
+
}
|
|
3299
|
+
function handleEditClose() {
|
|
3300
|
+
setEditDialogOpen(false);
|
|
3301
|
+
setFormData({});
|
|
3302
|
+
}
|
|
3303
|
+
function handleDeleteClick(id) {
|
|
3304
|
+
setDeleteId(id);
|
|
3305
|
+
setDeleteDialogOpen(true);
|
|
3306
|
+
}
|
|
3307
|
+
function handleDeleteConfirm() {
|
|
3308
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3309
|
+
if (deleteId) {
|
|
3310
|
+
yield onDelete(deleteId);
|
|
3311
|
+
setDeleteDialogOpen(false);
|
|
3312
|
+
setDeleteId(null);
|
|
3313
|
+
}
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
function handleDeleteCancel() {
|
|
3317
|
+
setDeleteDialogOpen(false);
|
|
3318
|
+
setDeleteId(null);
|
|
3319
|
+
}
|
|
3320
|
+
function handleFieldChange(name, value) {
|
|
3321
|
+
setFormData(prev => Object.assign(Object.assign({}, prev), {
|
|
3322
|
+
[name]: value
|
|
3323
|
+
}));
|
|
3324
|
+
}
|
|
3325
|
+
function getFieldDisplayValue(field, value) {
|
|
3326
|
+
var _a, _b;
|
|
3327
|
+
if (field.type === "select") {
|
|
3328
|
+
return ((_b = (_a = field.options) === null || _a === void 0 ? void 0 : _a.find(opt => opt.value === value)) === null || _b === void 0 ? void 0 : _b.label) || String(value);
|
|
3329
|
+
}
|
|
3330
|
+
return (value === null || value === void 0 ? void 0 : value.toString()) || "";
|
|
3331
|
+
}
|
|
3332
|
+
function renderItemContent(item) {
|
|
3333
|
+
const mainField = fields[0];
|
|
3334
|
+
const secondaryFields = fields.slice(1);
|
|
3335
|
+
return jsxs(Box, {
|
|
3336
|
+
className: classes.itemContent,
|
|
3337
|
+
children: [jsx(Typography, {
|
|
3338
|
+
variant: "heading18SemiBold",
|
|
3339
|
+
className: classes.itemTitle,
|
|
3340
|
+
children: getFieldDisplayValue(mainField, item[mainField.name])
|
|
3341
|
+
}), jsx(Typography, {
|
|
3342
|
+
variant: "uiText14Regular",
|
|
3343
|
+
color: "textSecondary",
|
|
3344
|
+
className: classes.itemSubtitle,
|
|
3345
|
+
children: secondaryFields.map(field => `${field.label}: ${getFieldDisplayValue(field, item[field.name])}`).join(" | ")
|
|
3346
|
+
})]
|
|
3347
|
+
});
|
|
3348
|
+
}
|
|
3349
|
+
function renderField(field) {
|
|
3350
|
+
var _a;
|
|
3351
|
+
const fieldValue = formData[field.name];
|
|
3352
|
+
if (field.type === "select") {
|
|
3353
|
+
const menuItems = ((_a = field.options) === null || _a === void 0 ? void 0 : _a.map(opt => ({
|
|
3354
|
+
value: opt.value,
|
|
3355
|
+
displayText: opt.label
|
|
3356
|
+
}))) || [];
|
|
3357
|
+
return jsx(VentionSelect, {
|
|
3358
|
+
labelText: field.label,
|
|
3359
|
+
value: fieldValue || "",
|
|
3360
|
+
onChange: event => {
|
|
3361
|
+
handleFieldChange(field.name, event.target.value);
|
|
3362
|
+
},
|
|
3363
|
+
menuItems: menuItems,
|
|
3364
|
+
size: "large",
|
|
3365
|
+
variant: "outlined"
|
|
3366
|
+
}, field.name);
|
|
3367
|
+
}
|
|
3368
|
+
return jsx(VentionTextInput, {
|
|
3369
|
+
label: field.label,
|
|
3370
|
+
value: fieldValue !== null && fieldValue !== void 0 ? fieldValue : "",
|
|
3371
|
+
onChange: event => {
|
|
3372
|
+
handleFieldChange(field.name, field.type === "number" ? Number(event.target.value) : event.target.value);
|
|
3373
|
+
},
|
|
3374
|
+
type: field.type === "number" ? "number" : "text",
|
|
3375
|
+
fullWidth: true,
|
|
3376
|
+
size: "large",
|
|
3377
|
+
inputProps: field.type === "number" ? {
|
|
3378
|
+
min: field.min,
|
|
3379
|
+
max: field.max
|
|
3380
|
+
} : undefined
|
|
3381
|
+
}, field.name);
|
|
3382
|
+
}
|
|
3383
|
+
const isEditing = Object.keys(formData).length > 0 && "id" in formData;
|
|
3384
|
+
return jsxs(Box, {
|
|
3385
|
+
className: classes.container,
|
|
3386
|
+
children: [jsxs(Box, {
|
|
3387
|
+
className: classes.header,
|
|
3388
|
+
children: [jsx(Typography, {
|
|
3389
|
+
variant: "heading24SemiBold",
|
|
3390
|
+
children: title
|
|
3391
|
+
}), jsx(VentionButton, {
|
|
3392
|
+
onClick: () => {
|
|
3393
|
+
setFormData({});
|
|
3394
|
+
setEditDialogOpen(true);
|
|
3395
|
+
},
|
|
3396
|
+
size: "large",
|
|
3397
|
+
variant: "filled",
|
|
3398
|
+
startIcon: jsx(VentionIcon, {
|
|
3399
|
+
type: "plus",
|
|
3400
|
+
size: 24,
|
|
3401
|
+
color: "white"
|
|
3402
|
+
}),
|
|
3403
|
+
children: t("productFormList.add")
|
|
3404
|
+
})]
|
|
3405
|
+
}), jsx(Box, {
|
|
3406
|
+
className: classes.listContainer,
|
|
3407
|
+
children: items.length === 0 ? jsx(Box, {
|
|
3408
|
+
className: classes.emptyState,
|
|
3409
|
+
children: jsx(Typography, {
|
|
3410
|
+
variant: "uiText14Regular",
|
|
3411
|
+
color: "textSecondary",
|
|
3412
|
+
children: t("productFormList.emptyState", {
|
|
3413
|
+
defaultValue: "No items yet. Click Add to create one."
|
|
3414
|
+
})
|
|
3415
|
+
})
|
|
3416
|
+
}) : jsx(List, {
|
|
3417
|
+
children: items.map(item => jsxs(ListItem, {
|
|
3418
|
+
className: classes.listItem,
|
|
3419
|
+
children: [renderItemContent(item), jsxs(Box, {
|
|
3420
|
+
className: classes.actions,
|
|
3421
|
+
children: [jsx(IconButton, {
|
|
3422
|
+
onClick: () => handleEditClick(item),
|
|
3423
|
+
size: "medium",
|
|
3424
|
+
children: jsx(VentionIcon, {
|
|
3425
|
+
type: "edit",
|
|
3426
|
+
size: 24
|
|
3427
|
+
})
|
|
3428
|
+
}), jsx(IconButton, {
|
|
3429
|
+
onClick: () => handleDeleteClick(getItemId(item)),
|
|
3430
|
+
size: "medium",
|
|
3431
|
+
children: jsx(VentionIcon, {
|
|
3432
|
+
type: "trash",
|
|
3433
|
+
size: 24
|
|
3434
|
+
})
|
|
3435
|
+
})]
|
|
3436
|
+
})]
|
|
3437
|
+
}, getItemId(item)))
|
|
3438
|
+
})
|
|
3439
|
+
}), jsxs(Dialog, {
|
|
3440
|
+
open: editDialogOpen,
|
|
3441
|
+
onClose: handleEditClose,
|
|
3442
|
+
maxWidth: "sm",
|
|
3443
|
+
fullWidth: true,
|
|
3444
|
+
children: [jsx(DialogTitle, {
|
|
3445
|
+
children: jsx(Typography, {
|
|
3446
|
+
variant: "heading18SemiBold",
|
|
3447
|
+
textAlign: "center",
|
|
3448
|
+
children: isEditing ? t("productFormList.modify") : t("productFormList.new")
|
|
3449
|
+
})
|
|
3450
|
+
}), jsx(DialogContent, {
|
|
3451
|
+
className: classes.dialogContent,
|
|
3452
|
+
children: jsx(Box, {
|
|
3453
|
+
className: classes.dialogForm,
|
|
3454
|
+
children: fields.map(field => renderField(field))
|
|
3455
|
+
})
|
|
3456
|
+
}), jsxs(DialogActions, {
|
|
3457
|
+
className: classes.dialogActions,
|
|
3458
|
+
children: [jsx(VentionButton, {
|
|
3459
|
+
onClick: handleEditClose,
|
|
3460
|
+
variant: "outline",
|
|
3461
|
+
size: "large",
|
|
3462
|
+
children: t("productFormList.cancel")
|
|
3463
|
+
}), jsx(VentionButton, {
|
|
3464
|
+
onClick: () => __awaiter(this, void 0, void 0, function* () {
|
|
3465
|
+
if (yield onSubmit(formData)) {
|
|
3466
|
+
handleEditClose();
|
|
3467
|
+
}
|
|
3468
|
+
}),
|
|
3469
|
+
variant: "filled",
|
|
3470
|
+
size: "large",
|
|
3471
|
+
children: isEditing ? t("productFormList.save") : t("productFormList.create")
|
|
3472
|
+
})]
|
|
3473
|
+
})]
|
|
3474
|
+
}), jsxs(Dialog, {
|
|
3475
|
+
open: deleteDialogOpen,
|
|
3476
|
+
onClose: handleDeleteCancel,
|
|
3477
|
+
maxWidth: "xs",
|
|
3478
|
+
fullWidth: true,
|
|
3479
|
+
children: [jsx(DialogTitle, {
|
|
3480
|
+
children: jsx(Typography, {
|
|
3481
|
+
variant: "heading18SemiBold",
|
|
3482
|
+
textAlign: "center",
|
|
3483
|
+
children: t("productFormList.delete")
|
|
3484
|
+
})
|
|
3485
|
+
}), jsx(DialogContent, {
|
|
3486
|
+
children: jsx(Typography, {
|
|
3487
|
+
variant: "uiText14Regular",
|
|
3488
|
+
className: classes.deleteMessage,
|
|
3489
|
+
children: t("productFormList.deleteConfirmation")
|
|
3490
|
+
})
|
|
3491
|
+
}), jsxs(DialogActions, {
|
|
3492
|
+
className: classes.dialogActions,
|
|
3493
|
+
children: [jsx(VentionButton, {
|
|
3494
|
+
onClick: handleDeleteCancel,
|
|
3495
|
+
variant: "outline",
|
|
3496
|
+
size: "large",
|
|
3497
|
+
children: t("productFormList.cancel")
|
|
3498
|
+
}), jsx(VentionButton, {
|
|
3499
|
+
onClick: handleDeleteConfirm,
|
|
3500
|
+
variant: "destructive",
|
|
3501
|
+
size: "large",
|
|
3502
|
+
children: t("productFormList.delete")
|
|
3503
|
+
})]
|
|
3504
|
+
})]
|
|
3505
|
+
})]
|
|
3506
|
+
});
|
|
3507
|
+
}
|
|
3508
|
+
ProductFormListComponent.displayName = "ProductFormList";
|
|
3509
|
+
const ProductFormList = memo(ProductFormListComponent);
|
|
3510
|
+
const useStyles = tss.withParams().create(({
|
|
3511
|
+
theme,
|
|
3512
|
+
maxHeight
|
|
3513
|
+
}) => ({
|
|
3514
|
+
container: {
|
|
3515
|
+
display: "flex",
|
|
3516
|
+
flexDirection: "column",
|
|
3517
|
+
height: "100%",
|
|
3518
|
+
flex: 1,
|
|
3519
|
+
minWidth: 0
|
|
3520
|
+
},
|
|
3521
|
+
header: {
|
|
3522
|
+
flexShrink: 0,
|
|
3523
|
+
display: "flex",
|
|
3524
|
+
justifyContent: "space-between",
|
|
3525
|
+
alignItems: "center",
|
|
3526
|
+
marginBottom: theme.spacing(3)
|
|
3527
|
+
},
|
|
3528
|
+
listContainer: {
|
|
3529
|
+
flexGrow: 1,
|
|
3530
|
+
overflowY: "auto",
|
|
3531
|
+
maxHeight
|
|
3532
|
+
},
|
|
3533
|
+
listItem: {
|
|
3534
|
+
backgroundColor: theme.palette.background.paper,
|
|
3535
|
+
borderRadius: theme.shape.borderRadius,
|
|
3536
|
+
marginBottom: theme.spacing(2),
|
|
3537
|
+
alignItems: "center",
|
|
3538
|
+
overflow: "hidden",
|
|
3539
|
+
display: "flex",
|
|
3540
|
+
width: "100%"
|
|
3541
|
+
},
|
|
3542
|
+
itemContent: {
|
|
3543
|
+
minWidth: 0,
|
|
3544
|
+
flex: 1,
|
|
3545
|
+
overflow: "hidden",
|
|
3546
|
+
paddingRight: theme.spacing(2)
|
|
3547
|
+
},
|
|
3548
|
+
itemTitle: {
|
|
3549
|
+
overflow: "hidden",
|
|
3550
|
+
textOverflow: "ellipsis",
|
|
3551
|
+
whiteSpace: "nowrap",
|
|
3552
|
+
width: "100%"
|
|
3553
|
+
},
|
|
3554
|
+
itemSubtitle: {
|
|
3555
|
+
overflow: "hidden",
|
|
3556
|
+
textOverflow: "ellipsis",
|
|
3557
|
+
whiteSpace: "nowrap",
|
|
3558
|
+
width: "100%"
|
|
3559
|
+
},
|
|
3560
|
+
actions: {
|
|
3561
|
+
display: "flex",
|
|
3562
|
+
alignItems: "center",
|
|
3563
|
+
flexShrink: 0,
|
|
3564
|
+
gap: theme.spacing(1)
|
|
3565
|
+
},
|
|
3566
|
+
emptyState: {
|
|
3567
|
+
display: "flex",
|
|
3568
|
+
alignItems: "center",
|
|
3569
|
+
justifyContent: "center",
|
|
3570
|
+
padding: theme.spacing(4),
|
|
3571
|
+
flex: 1
|
|
3572
|
+
},
|
|
3573
|
+
dialogContent: {
|
|
3574
|
+
borderTop: `1px solid ${theme.palette.divider}`,
|
|
3575
|
+
borderBottom: `1px solid ${theme.palette.divider}`
|
|
3576
|
+
},
|
|
3577
|
+
dialogForm: {
|
|
3578
|
+
display: "flex",
|
|
3579
|
+
flexDirection: "column",
|
|
3580
|
+
gap: theme.spacing(3),
|
|
3581
|
+
paddingTop: theme.spacing(2)
|
|
3582
|
+
},
|
|
3583
|
+
dialogActions: {
|
|
3584
|
+
padding: theme.spacing(2),
|
|
3585
|
+
gap: theme.spacing(2)
|
|
3586
|
+
},
|
|
3587
|
+
deleteMessage: {
|
|
3588
|
+
paddingTop: theme.spacing(1)
|
|
3589
|
+
}
|
|
3590
|
+
}));
|
|
3591
|
+
|
|
3592
|
+
var UserLevel;
|
|
3593
|
+
(function (UserLevel) {
|
|
3594
|
+
UserLevel[UserLevel["Operator"] = 1] = "Operator";
|
|
3595
|
+
UserLevel[UserLevel["Maintenance"] = 2] = "Maintenance";
|
|
3596
|
+
UserLevel[UserLevel["Admin"] = 3] = "Admin";
|
|
3597
|
+
})(UserLevel || (UserLevel = {}));
|
|
3598
|
+
function hasSufficientLevel(requiredLevel, currentLevel) {
|
|
3599
|
+
return currentLevel >= requiredLevel;
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
/**
|
|
3603
|
+
* This module provides utilities for generating API base URLs for machine apps.
|
|
3604
|
+
* It automatically detects the environment and returns the appropriate URL:
|
|
3605
|
+
* - Local/Edge: http://hostname:8000
|
|
3606
|
+
* - Deployed: Uses passthrough URL for digital twin infrastructure
|
|
3607
|
+
*/
|
|
3608
|
+
/**
|
|
3609
|
+
* Gets the execution engine HTTP URL for deployed environments
|
|
3610
|
+
* @param processName - The name of the process/service
|
|
3611
|
+
* @returns The full URL for the execution engine API
|
|
3612
|
+
*/
|
|
3613
|
+
function getExecutionEngineHttpUrl(processName) {
|
|
3614
|
+
const {
|
|
3615
|
+
href,
|
|
3616
|
+
port,
|
|
3617
|
+
hostname,
|
|
3618
|
+
origin
|
|
3619
|
+
} = window.location;
|
|
3620
|
+
const pathParts = new URL(href).pathname.split("/").filter(Boolean);
|
|
3621
|
+
const passthroughIndex = pathParts.indexOf("passthrough");
|
|
3622
|
+
const hmiIndex = pathParts.indexOf("hmi");
|
|
3623
|
+
const sessionId = passthroughIndex >= 0 && passthroughIndex < pathParts.length - 1 ? pathParts[passthroughIndex + 1] : hmiIndex > 0 ? pathParts[hmiIndex - 1] : "";
|
|
3624
|
+
const basePath = `/digital-twin/machine-motion/passthrough/${sessionId}/80/v1/machineCode/services/${processName}`;
|
|
3625
|
+
const isDev = port === "5173" || hostname === "localhost";
|
|
3626
|
+
const baseOrigin = isDev ? "https://digital-twin.vention.foo" : origin;
|
|
3627
|
+
return `${baseOrigin}${basePath}`;
|
|
3628
|
+
}
|
|
3629
|
+
/**
|
|
3630
|
+
* Checks if the current environment is running on edge (local controller)
|
|
3631
|
+
* @returns true if running on edge, false otherwise
|
|
3632
|
+
*/
|
|
3633
|
+
function isOnEdge() {
|
|
3634
|
+
return window.location.hostname.startsWith("192.168") || window.location.hostname.startsWith("localhost");
|
|
3635
|
+
}
|
|
3636
|
+
/**
|
|
3637
|
+
* Gets the API base URL for the specified process/service
|
|
3638
|
+
* @param options - Configuration options including process name and optional edge port
|
|
3639
|
+
* @returns The API base URL for all backend API calls
|
|
3640
|
+
* @example
|
|
3641
|
+
* ```ts
|
|
3642
|
+
* const apiUrl = getApiBaseUrl({ processName: "ai-operator" })
|
|
3643
|
+
* // Returns: http://192.168.1.100:8000 (on edge)
|
|
3644
|
+
* // or https://digital-twin.../passthrough/.../ai-operator (deployed)
|
|
3645
|
+
* ```
|
|
3646
|
+
*/
|
|
3647
|
+
function getApiBaseUrl(options) {
|
|
3648
|
+
const {
|
|
3649
|
+
processName,
|
|
3650
|
+
edgePort = 8000
|
|
3651
|
+
} = options;
|
|
3652
|
+
if (isOnEdge()) {
|
|
3653
|
+
return `http://${window.location.hostname}:${edgePort}`;
|
|
3654
|
+
}
|
|
3655
|
+
return getExecutionEngineHttpUrl(processName);
|
|
3656
|
+
}
|
|
3657
|
+
|
|
3658
|
+
export { ActionButton, FileUploadPanel, I18nProvider, I18nSettings, LogFilterForm, LogsPagination, LogsPanel, LogsTable, NavigationBar, NavigationConfirmationModal, PasswordProtectionModal, ProductFormList, SettingsPage, Sidebar, StatusTopBar, StepProgressCircle, TimeLabel, UserLevel, Z_INDEX, closeCustomUi, formatDateToInput, getApiBaseUrl, getAvailableTimezones, getLanguageDisplayName, getSupportedLanguages, hasSufficientLevel, isOnEdge, isTouchScreenDevice, navigateControlCenter, parseLogDate, useAutoScrollInput, useI18n };
|