data-primals-engine 1.7.2 → 1.7.3
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 +160 -160
- package/client/package-lock.json +8430 -8430
- package/client/src/APIInfo.jsx +1 -1
- package/client/src/App.jsx +2 -1
- package/client/src/App.scss +1635 -1626
- package/client/src/AssistantChat.jsx +1 -0
- package/client/src/CalendarView.jsx +1 -0
- package/client/src/ContentView.jsx +3 -3
- package/client/src/Dashboard.jsx +5 -2
- package/client/src/DashboardChart.jsx +1 -0
- package/client/src/DashboardFlexViewItem.jsx +1 -0
- package/client/src/DashboardHtmlViewItem.jsx +1 -0
- package/client/src/DashboardView.jsx +2 -0
- package/client/src/DataEditor.jsx +0 -1
- package/client/src/DataImporter.jsx +489 -468
- package/client/src/DataLayout.jsx +6 -3
- package/client/src/DataTable.jsx +4 -3
- package/client/src/Dialog.jsx +92 -90
- package/client/src/Dialog.scss +122 -116
- package/client/src/DisplayFlexNodeRenderer.jsx +1 -0
- package/client/src/FlexBuilderControls.jsx +1 -0
- package/client/src/FlexBuilderPreview.jsx +1 -1
- package/client/src/FlexNode.jsx +1 -1
- package/client/src/HistoryDialog.jsx +3 -2
- package/client/src/KPIWidget.jsx +1 -1
- package/client/src/KanbanView.jsx +1 -0
- package/client/src/ModelCreator.jsx +4 -0
- package/client/src/ModelList.jsx +1 -0
- package/client/src/PackGallery.jsx +5 -4
- package/client/src/RTETrans.jsx +1 -1
- package/client/src/RelationField.jsx +2 -0
- package/client/src/RelationSelectorWidget.jsx +2 -0
- package/client/src/RelationValue.jsx +1 -0
- package/client/src/RestoreDialog.jsx +1 -0
- package/client/src/WorkflowEditor.jsx +3 -0
- package/client/src/contexts/CommandContext.jsx +2 -1
- package/client/src/contexts/ModelContext.jsx +3 -3
- package/client/src/hooks/data.js +1 -0
- package/client/src/hooks/useValidation.js +1 -0
- package/client/src/translations.js +24 -24
- package/doc/AI-assistance.md +87 -63
- package/doc/Concepts.md +122 -0
- package/doc/Custom-Endpoints.md +31 -0
- package/doc/Event-system.md +13 -14
- package/doc/Home.md +33 -0
- package/doc/Modules.md +83 -0
- package/doc/Packs-gallery.md +8 -23
- package/doc/Workflows.md +32 -0
- package/doc/automation-workflows.md +141 -102
- package/doc/dashboards-kpis-charts.md +47 -49
- package/doc/data-management.md +126 -120
- package/doc/data-models.md +68 -75
- package/doc/roles-permissions.md +144 -43
- package/doc/sharding-replication.md +158 -0
- package/doc/users.md +54 -30
- package/package.json +1 -1
- package/server.js +37 -37
- package/src/constants.js +7 -8
- package/src/data.js +521 -520
- package/src/email.js +157 -154
- package/src/engine.js +117 -7
- package/src/gameObject.js +6 -0
- package/src/i18n.js +0 -1
- package/src/modules/auth-google/index.js +53 -50
- package/src/modules/bucket.js +346 -339
- package/src/modules/data/data.backup.js +400 -376
- package/src/modules/data/data.cluster.js +410 -42
- package/src/modules/data/data.operations.js +3666 -3635
- package/src/modules/data/data.replication.js +106 -64
- package/src/modules/data/data.routes.js +87 -64
- package/src/modules/data/data.scheduling.js +2 -1
- package/src/modules/file.js +248 -247
- package/src/modules/user.js +11 -1
- package/src/sso.js +91 -25
- package/test/cluster.test.js +221 -0
- package/test/core.test.js +0 -2
- package/test/replication.test.js +163 -0
- package/doc/core-concepts.md +0 -33
|
@@ -65,6 +65,7 @@ const WorkflowSelectorModal = ({ onClose, onSelectWorkflow }) => {
|
|
|
65
65
|
'activeWorkflowsList',
|
|
66
66
|
() => fetch('/api/data/search?_user='+me.username, {
|
|
67
67
|
method: 'POST',
|
|
68
|
+
credentials: "include",
|
|
68
69
|
headers: { 'Content-Type': 'application/json' },
|
|
69
70
|
body: JSON.stringify({
|
|
70
71
|
model: 'workflow',
|
|
@@ -433,7 +434,8 @@ function DataLayout({refreshUI}, ref) {
|
|
|
433
434
|
///fd.append("files", fd2);
|
|
434
435
|
return fetch(`${url}?lang=${lang}&_user=${encodeURIComponent(getUserId(me))}`, {
|
|
435
436
|
method,
|
|
436
|
-
body: fd
|
|
437
|
+
body: fd,
|
|
438
|
+
credentials: "include",
|
|
437
439
|
}).then(e => e.json());
|
|
438
440
|
} catch (error) {
|
|
439
441
|
console.error('Erreur lors de l\'enregistrement des données:', error);
|
|
@@ -513,7 +515,8 @@ function DataLayout({refreshUI}, ref) {
|
|
|
513
515
|
return fetch(`/api/data/${ids}?lang=${lang}&_user=${encodeURIComponent(getUserId(me))}`, {
|
|
514
516
|
method: 'DELETE', headers: {
|
|
515
517
|
'Content-Type': 'application/json'
|
|
516
|
-
}
|
|
518
|
+
},
|
|
519
|
+
credentials: "include"
|
|
517
520
|
}).then(e => e.json());
|
|
518
521
|
}, [lang, me]);
|
|
519
522
|
|
|
@@ -536,7 +539,7 @@ function DataLayout({refreshUI}, ref) {
|
|
|
536
539
|
return fetch('/api/models/import', { method: 'POST', headers: {
|
|
537
540
|
'Content-Type': 'application/json'
|
|
538
541
|
},
|
|
539
|
-
|
|
542
|
+
credentials: "include",body: JSON.stringify({ models: selectedModels.map(m => m.name) })
|
|
540
543
|
})
|
|
541
544
|
});
|
|
542
545
|
|
package/client/src/DataTable.jsx
CHANGED
|
@@ -6,7 +6,6 @@ import {useAuthContext} from "./contexts/AuthContext.jsx";
|
|
|
6
6
|
import React, {useEffect, useMemo, useRef, useState} from "react";
|
|
7
7
|
import {getUserHash, getUserId} from "../../src/data.js";
|
|
8
8
|
import cronstrue from 'cronstrue/i18n';
|
|
9
|
-
import {Event} from "../../src/events.js";
|
|
10
9
|
|
|
11
10
|
import {
|
|
12
11
|
FaBook,
|
|
@@ -337,6 +336,7 @@ export function DataTable({
|
|
|
337
336
|
return fetch(`/api/data/export?lang=${lang}&${params.toString()}`, {
|
|
338
337
|
method: 'POST',
|
|
339
338
|
body,
|
|
339
|
+
credentials: "include",
|
|
340
340
|
headers: {"Content-Type": "application/json"}
|
|
341
341
|
})
|
|
342
342
|
.then(async resp => {
|
|
@@ -391,8 +391,9 @@ export function DataTable({
|
|
|
391
391
|
const handleConfirmRestore = async () => {
|
|
392
392
|
try {
|
|
393
393
|
// Make the API call to request the restore link
|
|
394
|
-
const response = await fetch('/api/backup/request-restore', {
|
|
394
|
+
const response = await fetch('/api/backup/request-restore?lang='+lang, {
|
|
395
395
|
method: 'POST',
|
|
396
|
+
credentials: "include",
|
|
396
397
|
// ... other options ...
|
|
397
398
|
});
|
|
398
399
|
|
|
@@ -451,7 +452,7 @@ export function DataTable({
|
|
|
451
452
|
<Button onClick={handleImport} title={t("btns.import")}><FaFileImport/><Trans
|
|
452
453
|
i18nKey="btns.import">Importer</Trans></Button>
|
|
453
454
|
<Button disabled={isLoading} onClick={handleExport} title={t("btns.export")}><FaFileExport/><Trans i18nKey="btns.export">Exporter</Trans></Button>
|
|
454
|
-
{
|
|
455
|
+
{(<Button onClick={handleBackup} title={t("btns.backup")}><FaDatabase/><Trans
|
|
455
456
|
i18nKey="btns.backup">Backup</Trans></Button>)}
|
|
456
457
|
|
|
457
458
|
</div>}
|
package/client/src/Dialog.jsx
CHANGED
|
@@ -1,90 +1,92 @@
|
|
|
1
|
-
import Button from "./Button.jsx";
|
|
2
|
-
import { FaWindowClose } from "react-icons/fa";
|
|
3
|
-
|
|
4
|
-
import "./Dialog.scss";
|
|
5
|
-
import { createContext, useContext, useEffect, useState } from "react";
|
|
6
|
-
import {useUI} from "./contexts/UIContext.jsx";
|
|
7
|
-
|
|
8
|
-
const DialogContext = createContext({});
|
|
9
|
-
|
|
10
|
-
export const useDialogContext = () => useContext(DialogContext);
|
|
11
|
-
|
|
12
|
-
export const DialogProvider = ({ children }) => {
|
|
13
|
-
const [dialogs, setDialogs] = useState(0);
|
|
14
|
-
const { locked, setLocked } = useUI()
|
|
15
|
-
const values = {
|
|
16
|
-
addDialog: () => setDialogs((dialogs) => dialogs + 1),
|
|
17
|
-
removeDialog: () =>
|
|
18
|
-
setDialogs((dialogs) => {
|
|
19
|
-
return dialogs > 0 ? dialogs - 1 : 0;
|
|
20
|
-
}),
|
|
21
|
-
};
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
if( dialogs === 0){
|
|
24
|
-
setLocked(false);
|
|
25
|
-
}else{
|
|
26
|
-
setLocked(true);
|
|
27
|
-
}
|
|
28
|
-
}, [dialogs]);
|
|
29
|
-
return (
|
|
30
|
-
<DialogContext.Provider value={values}>
|
|
31
|
-
{dialogs > 0 ? (
|
|
32
|
-
<>
|
|
33
|
-
<div className="dialog-bg"></div>
|
|
34
|
-
{children}
|
|
35
|
-
</>
|
|
36
|
-
) : (
|
|
37
|
-
children
|
|
38
|
-
)}
|
|
39
|
-
</DialogContext.Provider>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
export const Dialog = ({
|
|
43
|
-
title,
|
|
44
|
-
children,
|
|
45
|
-
className,
|
|
46
|
-
onClose,
|
|
47
|
-
isClosable,
|
|
48
|
-
isModal,
|
|
49
|
-
}) => {
|
|
50
|
-
const [showModal, setModalVisible] = useState(true);
|
|
51
|
-
const { addDialog, removeDialog } = useDialogContext();
|
|
52
|
-
const handleClose = () => {
|
|
53
|
-
setModalVisible(false);
|
|
54
|
-
onClose?.();
|
|
55
|
-
removeDialog();
|
|
56
|
-
};
|
|
57
|
-
const clickEvent = (e) => {
|
|
58
|
-
|
|
59
|
-
if( !e.target.closest('.dialog') && !e.target.closest('.notification') ){
|
|
60
|
-
onClose?.();
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
addDialog();
|
|
65
|
-
document.addEventListener('mousedown', clickEvent);
|
|
66
|
-
return () => {
|
|
67
|
-
removeDialog();
|
|
68
|
-
document.removeEventListener('mousedown', clickEvent);
|
|
69
|
-
}
|
|
70
|
-
}, [addDialog, removeDialog]);
|
|
71
|
-
return showModal ? (
|
|
72
|
-
<div
|
|
73
|
-
|
|
74
|
-
aria-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
)
|
|
90
|
-
|
|
1
|
+
import Button from "./Button.jsx";
|
|
2
|
+
import { FaWindowClose } from "react-icons/fa";
|
|
3
|
+
|
|
4
|
+
import "./Dialog.scss";
|
|
5
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
6
|
+
import {useUI} from "./contexts/UIContext.jsx";
|
|
7
|
+
|
|
8
|
+
const DialogContext = createContext({});
|
|
9
|
+
|
|
10
|
+
export const useDialogContext = () => useContext(DialogContext);
|
|
11
|
+
|
|
12
|
+
export const DialogProvider = ({ children }) => {
|
|
13
|
+
const [dialogs, setDialogs] = useState(0);
|
|
14
|
+
const { locked, setLocked } = useUI()
|
|
15
|
+
const values = {
|
|
16
|
+
addDialog: () => setDialogs((dialogs) => dialogs + 1),
|
|
17
|
+
removeDialog: () =>
|
|
18
|
+
setDialogs((dialogs) => {
|
|
19
|
+
return dialogs > 0 ? dialogs - 1 : 0;
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if( dialogs === 0){
|
|
24
|
+
setLocked(false);
|
|
25
|
+
}else{
|
|
26
|
+
setLocked(true);
|
|
27
|
+
}
|
|
28
|
+
}, [dialogs]);
|
|
29
|
+
return (
|
|
30
|
+
<DialogContext.Provider value={values}>
|
|
31
|
+
{dialogs > 0 ? (
|
|
32
|
+
<>
|
|
33
|
+
<div className="dialog-bg"></div>
|
|
34
|
+
{children}
|
|
35
|
+
</>
|
|
36
|
+
) : (
|
|
37
|
+
children
|
|
38
|
+
)}
|
|
39
|
+
</DialogContext.Provider>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
export const Dialog = ({
|
|
43
|
+
title,
|
|
44
|
+
children,
|
|
45
|
+
className,
|
|
46
|
+
onClose,
|
|
47
|
+
isClosable,
|
|
48
|
+
isModal,
|
|
49
|
+
}) => {
|
|
50
|
+
const [showModal, setModalVisible] = useState(true);
|
|
51
|
+
const { addDialog, removeDialog } = useDialogContext();
|
|
52
|
+
const handleClose = () => {
|
|
53
|
+
setModalVisible(false);
|
|
54
|
+
onClose?.();
|
|
55
|
+
removeDialog();
|
|
56
|
+
};
|
|
57
|
+
const clickEvent = (e) => {
|
|
58
|
+
|
|
59
|
+
if( !e.target.closest('.dialog') && !e.target.closest('.notification') ){
|
|
60
|
+
onClose?.();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
addDialog();
|
|
65
|
+
document.addEventListener('mousedown', clickEvent);
|
|
66
|
+
return () => {
|
|
67
|
+
removeDialog();
|
|
68
|
+
document.removeEventListener('mousedown', clickEvent);
|
|
69
|
+
}
|
|
70
|
+
}, [addDialog, removeDialog]);
|
|
71
|
+
return showModal ? (
|
|
72
|
+
<div className="dialog-container">
|
|
73
|
+
<div
|
|
74
|
+
aria-modal={true}
|
|
75
|
+
aria-label={title}
|
|
76
|
+
className={`${className ? className : ""} dialog ${isModal ? "dialog-modal" : ""}`}
|
|
77
|
+
>
|
|
78
|
+
<div className="dialog-header">
|
|
79
|
+
{title && <h2>{title}</h2>}
|
|
80
|
+
{isClosable && (
|
|
81
|
+
<Button className={"btn btn-close"} onClick={handleClose}>
|
|
82
|
+
<FaWindowClose />
|
|
83
|
+
</Button>
|
|
84
|
+
)}
|
|
85
|
+
</div>
|
|
86
|
+
<div className="dialog-content">{children}</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
) : (
|
|
90
|
+
<></>
|
|
91
|
+
);
|
|
92
|
+
};
|
package/client/src/Dialog.scss
CHANGED
|
@@ -1,116 +1,122 @@
|
|
|
1
|
-
|
|
2
|
-
.dialog-bg {
|
|
3
|
-
position: fixed;
|
|
4
|
-
top: 0;
|
|
5
|
-
left: 0;
|
|
6
|
-
width: 100%;
|
|
7
|
-
height: 100%;
|
|
8
|
-
z-index: 10000;
|
|
9
|
-
pointer-events: none;
|
|
10
|
-
background-color: rgba(59, 59, 59, 0.51);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
z-index: 10000;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
1
|
+
|
|
2
|
+
.dialog-bg {
|
|
3
|
+
position: fixed;
|
|
4
|
+
top: 0;
|
|
5
|
+
left: 0;
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 100%;
|
|
8
|
+
z-index: 10000;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
background-color: rgba(59, 59, 59, 0.51);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.dialog-container {
|
|
14
|
+
position: fixed;
|
|
15
|
+
top: 0;
|
|
16
|
+
left: 0;
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
z-index: 10000;
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
pointer-events: none; /* Permet de cliquer "à travers" le conteneur */
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#content .dialog {
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
pointer-events: all;
|
|
29
|
+
background-color: #F8F8F8;
|
|
30
|
+
border: 1px solid #DDDDDD;
|
|
31
|
+
border-radius: 8px;
|
|
32
|
+
color: black;
|
|
33
|
+
width: 90%;
|
|
34
|
+
max-width: 1024px;
|
|
35
|
+
min-width: 320px;
|
|
36
|
+
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.25);
|
|
37
|
+
text-align: left;
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.dialog .actions {
|
|
42
|
+
justify-content: flex-end;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dark .dialog {
|
|
46
|
+
background-color: #191919;
|
|
47
|
+
color: #e3e3e3;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#content .dialog-header {
|
|
51
|
+
display: flex;
|
|
52
|
+
gap: 8px;
|
|
53
|
+
justify-content: flex-start;
|
|
54
|
+
border: none;
|
|
55
|
+
border-bottom: 1px solid #E2E2E2;
|
|
56
|
+
h2 {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex: 1;
|
|
59
|
+
padding: 0;
|
|
60
|
+
align-items: center;
|
|
61
|
+
margin: 8px;
|
|
62
|
+
font-size: 100%;
|
|
63
|
+
line-height: 208%;
|
|
64
|
+
}
|
|
65
|
+
.btn {
|
|
66
|
+
display: flex;
|
|
67
|
+
justify-self: flex-end;
|
|
68
|
+
&.btn-close {
|
|
69
|
+
position: absolute;
|
|
70
|
+
right: 0px;
|
|
71
|
+
z-index: 100;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#ui .dialog-content {
|
|
77
|
+
padding: 16px;
|
|
78
|
+
cursor: auto;
|
|
79
|
+
word-wrap: break-word;
|
|
80
|
+
max-height: 85vh;
|
|
81
|
+
overflow-y: auto;
|
|
82
|
+
.field {
|
|
83
|
+
margin: 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
table {
|
|
87
|
+
width: 100%;
|
|
88
|
+
border: 1px solid #DDDDDD;
|
|
89
|
+
border-collapse: collapse;
|
|
90
|
+
td,th {
|
|
91
|
+
padding: 3px;
|
|
92
|
+
@media only screen and (min-width: 480px) {
|
|
93
|
+
padding: 5px;
|
|
94
|
+
}
|
|
95
|
+
&.mini {
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
min-width: auto;
|
|
98
|
+
width: 40px;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
thead tr {
|
|
102
|
+
background-color: #F1F1F1;
|
|
103
|
+
font-weight: lighter;
|
|
104
|
+
}
|
|
105
|
+
tbody tr {
|
|
106
|
+
}
|
|
107
|
+
@media only screen and (max-width: 480px){
|
|
108
|
+
font-size: 80%;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
.dark table {
|
|
112
|
+
thead tr {
|
|
113
|
+
background-color: #191919;
|
|
114
|
+
color: #e3e3e3;
|
|
115
|
+
}
|
|
116
|
+
tbody tr {
|
|
117
|
+
background-color: #191919;
|
|
118
|
+
}
|
|
119
|
+
td,th {
|
|
120
|
+
border: 1px solid #3f3f3f;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -79,6 +79,7 @@ const CtaNode = ({ node, nodeStyle, dataItem }) => {
|
|
|
79
79
|
|
|
80
80
|
if (method !== 'GET' && method !== 'HEAD' && node.requestBodyTemplate) {
|
|
81
81
|
fetchOptions.body = substituteClientVariables(node.requestBodyTemplate, dataItem);
|
|
82
|
+
fetchOptions.credentials= "include";
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
// 3. Exécuter la requête
|
|
@@ -28,7 +28,7 @@ const FlexBuilderPreview = ({
|
|
|
28
28
|
setIsModalOpen(true);
|
|
29
29
|
|
|
30
30
|
try {
|
|
31
|
-
const response = await fetch(`/api/actions/${node.endpointPath}`, { method: 'GET' });
|
|
31
|
+
const response = await fetch(`/api/actions/${node.endpointPath}`, {credentials: "include", method: 'GET' });
|
|
32
32
|
const data = await response.json();
|
|
33
33
|
setModalContent({ path: node.endpointPath, status: response.status, data });
|
|
34
34
|
} catch (error) {
|
package/client/src/FlexNode.jsx
CHANGED
|
@@ -92,7 +92,7 @@ export const FlexNodeRenderer = React.forwardRef((props, ref) => {
|
|
|
92
92
|
setResult(null);
|
|
93
93
|
|
|
94
94
|
try {
|
|
95
|
-
const response = await fetch(`/api/actions/${endpointPath}`, { method: 'GET' });
|
|
95
|
+
const response = await fetch(`/api/actions/${endpointPath}`, { credentials: "include",method: 'GET' });
|
|
96
96
|
const data = await response.json();
|
|
97
97
|
setResult({ status: response.status, data });
|
|
98
98
|
} catch (error) {
|
|
@@ -153,7 +153,7 @@ export const HistoryDialog = ({ modelName, recordId, onClose }) => {
|
|
|
153
153
|
const params = new URLSearchParams({ page, limit: elementsPerPage, lang: i18n.language });
|
|
154
154
|
if (startDate) params.append('startDate', startDate);
|
|
155
155
|
if (endDate) params.append('endDate', endDate);
|
|
156
|
-
const query = await fetch(`/api/data/history/${modelName}/${recordId}?${params.toString()}
|
|
156
|
+
const query = await fetch(`/api/data/history/${modelName}/${recordId}?${params.toString()}`, {credentials: "include"});
|
|
157
157
|
const response = await query.json();
|
|
158
158
|
if (response.success) {
|
|
159
159
|
setHistory(response.data);
|
|
@@ -185,7 +185,7 @@ export const HistoryDialog = ({ modelName, recordId, onClose }) => {
|
|
|
185
185
|
setPreviewLoading(true);
|
|
186
186
|
setPreviewData(null);
|
|
187
187
|
try {
|
|
188
|
-
const res = await fetch(`/api/data/history/${modelName}/${recordId}/${version}
|
|
188
|
+
const res = await fetch(`/api/data/history/${modelName}/${recordId}/${version}`, {credentials: "include"});
|
|
189
189
|
const response = await res.json();
|
|
190
190
|
if (response.success) {
|
|
191
191
|
setPreviewData(response.data);
|
|
@@ -209,6 +209,7 @@ export const HistoryDialog = ({ modelName, recordId, onClose }) => {
|
|
|
209
209
|
try {
|
|
210
210
|
const res = await fetch(`/api/data/history/${modelName}/${recordId}/revert/${version}`, {
|
|
211
211
|
method: 'POST',
|
|
212
|
+
credentials: "include",
|
|
212
213
|
headers: { 'Content-Type': 'application/json' }
|
|
213
214
|
});
|
|
214
215
|
const response = await res.json();
|
package/client/src/KPIWidget.jsx
CHANGED
|
@@ -9,7 +9,7 @@ import { Tooltip } from 'react-tooltip';
|
|
|
9
9
|
// Fonction pour récupérer la valeur calculée d'un KPI (MODIFIÉE)
|
|
10
10
|
const fetchKpiValue = async (kpiId) => {
|
|
11
11
|
if (!kpiId) return null;
|
|
12
|
-
const response = await fetch(`/api/kpis/calculate/${kpiId}
|
|
12
|
+
const response = await fetch(`/api/kpis/calculate/${kpiId}`, { credentials: "include",});
|
|
13
13
|
if (!response.ok) {
|
|
14
14
|
const errorData = await response.json().catch(() => ({}));
|
|
15
15
|
throw new Error(errorData.error || `Network response was not ok (${response.status})`);
|
|
@@ -62,6 +62,7 @@ const KanbanView = ({ settings, model }) => {
|
|
|
62
62
|
['kanbanData', model.name], // Clé de requête unique pour ce modèle
|
|
63
63
|
() => fetch(`/api/data/search?_user=${me.username}&depth=2`, { // La fonction qui appelle l'API
|
|
64
64
|
method: 'POST',
|
|
65
|
+
credentials: "include",
|
|
65
66
|
headers: { 'Content-Type': 'application/json' },
|
|
66
67
|
// On demande toutes les données pour le modèle spécifié (limit: 0 pour "tout")
|
|
67
68
|
body: JSON.stringify({ model: model.name, page: 1 })
|
|
@@ -94,6 +94,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
94
94
|
const url = `/api/model/${initialModel._id}/renameField?_user=${encodeURIComponent(getUserId(me))}`;
|
|
95
95
|
return fetch(url, {
|
|
96
96
|
method: 'PATCH',
|
|
97
|
+
credentials: "include",
|
|
97
98
|
headers: { 'Content-Type': 'application/json' },
|
|
98
99
|
body: JSON.stringify({ oldFieldName: oldName, newFieldName: newName }),
|
|
99
100
|
}).then((res) => res.json());
|
|
@@ -120,6 +121,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
120
121
|
const method = initialModel?._id ? 'PUT' : 'POST';
|
|
121
122
|
return fetch(url+'?_user='+me.username, {
|
|
122
123
|
method: method,
|
|
124
|
+
credentials: "include",
|
|
123
125
|
headers: { 'Content-Type': 'application/json' },
|
|
124
126
|
body: JSON.stringify(modelData),
|
|
125
127
|
}).then((res) => res.json());
|
|
@@ -173,6 +175,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
173
175
|
(modelName) =>
|
|
174
176
|
fetch(`/api/model?name=${modelName}&_user=${encodeURIComponent(getUserId(me))}`, {
|
|
175
177
|
method: 'DELETE',
|
|
178
|
+
credentials:"include",
|
|
176
179
|
}).then((res) => res.json()),
|
|
177
180
|
{
|
|
178
181
|
onSuccess: () => {
|
|
@@ -386,6 +389,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
386
389
|
|
|
387
390
|
const response = await fetch(`/api/model/generate?lang=${lang}`, {
|
|
388
391
|
method: 'POST',
|
|
392
|
+
credentials:"include",
|
|
389
393
|
headers: { 'Content-Type': 'application/json' },
|
|
390
394
|
body: JSON.stringify(bodyPayload),
|
|
391
395
|
});
|
package/client/src/ModelList.jsx
CHANGED
|
@@ -95,6 +95,7 @@ export function ModelList({ editionMode, onModelSelect, onCreateModel, onImportM
|
|
|
95
95
|
const demoInitMutation = useMutation((profile) => {
|
|
96
96
|
return fetch('/api/demo/initialize', {
|
|
97
97
|
method: 'POST',
|
|
98
|
+
credentials:"include",
|
|
98
99
|
headers: { "Content-Type": "application/json"},
|
|
99
100
|
body: JSON.stringify({profile: profile, packs: profiles[profile].packs}),
|
|
100
101
|
});
|
|
@@ -16,7 +16,7 @@ import {TextField, CheckboxField} from "./Field.jsx";
|
|
|
16
16
|
// --- API Fetching Functions ---
|
|
17
17
|
const fetchPacks = async (sortBy, lang, filterByUser = false, user) => {
|
|
18
18
|
const url = `/api/packs?lang=${lang}&sortBy=${sortBy.field}&order=${sortBy.order}${filterByUser ? '&user='+user.username : ''}`;
|
|
19
|
-
const response = await fetch(url);
|
|
19
|
+
const response = await fetch(url, {credentials:"include"});
|
|
20
20
|
if (!response.ok) {
|
|
21
21
|
throw new Error('Network response was not ok');
|
|
22
22
|
}
|
|
@@ -25,7 +25,7 @@ const fetchPacks = async (sortBy, lang, filterByUser = false, user) => {
|
|
|
25
25
|
|
|
26
26
|
const fetchPackDetails = async (packId, lang) => {
|
|
27
27
|
if (!packId) return null;
|
|
28
|
-
const response = await fetch(`/api/packs/${packId}?lang=${lang}
|
|
28
|
+
const response = await fetch(`/api/packs/${packId}?lang=${lang}`, {credentials:"include"});
|
|
29
29
|
if (!response.ok) {
|
|
30
30
|
throw new Error('Failed to fetch pack details');
|
|
31
31
|
}
|
|
@@ -182,7 +182,7 @@ const PackDetail = ({ packId, onBack }) => {
|
|
|
182
182
|
|
|
183
183
|
const installPackMutationFn = async ({packId, lang}) => {
|
|
184
184
|
const response = await fetch(`/api/packs/${packId}/install?lang=${lang}`, {
|
|
185
|
-
method: 'POST',
|
|
185
|
+
method: 'POST',credentials: "include",
|
|
186
186
|
headers: {
|
|
187
187
|
'Content-Type': 'application/json',
|
|
188
188
|
},
|
|
@@ -196,7 +196,7 @@ const installPackMutationFn = async ({packId, lang}) => {
|
|
|
196
196
|
|
|
197
197
|
const updatePackMutationFn = async ({ packId, updateData }) => {
|
|
198
198
|
const response = await fetch(`/api/packs/${packId}`, {
|
|
199
|
-
method: 'PATCH',
|
|
199
|
+
method: 'PATCH',credentials: "include",
|
|
200
200
|
headers: {
|
|
201
201
|
'Content-Type': 'application/json',
|
|
202
202
|
},
|
|
@@ -241,6 +241,7 @@ const PackGallery = () => {
|
|
|
241
241
|
|
|
242
242
|
const response = await fetch('/api/packs/install', {
|
|
243
243
|
method: 'POST',
|
|
244
|
+
credentials: "include",
|
|
244
245
|
headers: {
|
|
245
246
|
'Content-Type': 'application/json',
|
|
246
247
|
},
|