data-primals-engine 1.7.1 → 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 +9 -9
- package/client/package-lock.json +8430 -8121
- package/client/package.json +7 -4
- 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 +2 -3
- 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 +25 -23
- package/client/src/DataTable.jsx +6 -5
- package/client/src/Dialog.jsx +92 -90
- package/client/src/Dialog.scss +122 -116
- package/client/src/DisplayFlexNodeRenderer.jsx +1 -0
- package/client/src/DocumentationPageLayout.scss +1 -1
- 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/ViewSwitcher.jsx +1 -1
- 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/client/vite.config.js +31 -30
- 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 +27 -17
- package/server.js +37 -37
- package/src/ai.jobs.js +135 -0
- package/src/constants.js +560 -545
- package/src/data.js +521 -518
- package/src/email.js +157 -154
- package/src/engine.js +167 -49
- package/src/gameObject.js +6 -0
- package/src/i18n.js +0 -1
- package/src/modules/assistant/assistant.js +782 -763
- package/src/modules/assistant/constants.js +23 -16
- package/src/modules/assistant/providers.js +77 -37
- package/src/modules/auth-google/index.js +53 -50
- package/src/modules/bucket.js +346 -335
- package/src/modules/data/data.backup.js +400 -376
- package/src/modules/data/data.cluster.js +559 -0
- package/src/modules/data/data.core.js +11 -8
- package/src/modules/data/data.js +311 -311
- package/src/modules/data/data.operations.js +3666 -3555
- package/src/modules/data/data.relations.js +1 -0
- package/src/modules/data/data.replication.js +125 -0
- package/src/modules/data/data.routes.js +2206 -1879
- package/src/modules/data/data.scheduling.js +2 -1
- package/src/modules/file.js +248 -247
- package/src/modules/mongodb.js +76 -73
- package/src/modules/user.js +18 -2
- package/src/modules/worker-script-runner.js +97 -0
- package/src/modules/workflow.js +177 -52
- package/src/packs.js +5701 -5701
- package/src/providers.js +298 -297
- package/src/sso.js +91 -25
- package/test/assistant.test.js +207 -206
- package/test/cluster.test.js +221 -0
- package/test/core.test.js +0 -2
- package/test/data.integration.test.js +1425 -1416
- package/test/import_export.integration.test.js +210 -210
- package/test/replication.test.js +163 -0
- package/test/workflow.actions.integration.test.js +487 -475
- package/test/workflow.integration.test.js +332 -329
- package/doc/core-concepts.md +0 -33
|
@@ -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
|
},
|
package/client/src/RTETrans.jsx
CHANGED
|
@@ -15,7 +15,7 @@ const RTETrans = ({ value, onChange, field }) => {
|
|
|
15
15
|
params.append('model', 'lang');
|
|
16
16
|
params.append("_user", getUserId(me));
|
|
17
17
|
params.append("depth", '1');
|
|
18
|
-
return fetch(`/api/data/search?${params.toString()}`, { signal, method: 'POST',
|
|
18
|
+
return fetch(`/api/data/search?${params.toString()}`, { credentials:"include", signal, method: 'POST', body: JSON.stringify({}), headers: { "Content-Type": "application/json"}})
|
|
19
19
|
.then((res) => res.json())
|
|
20
20
|
.then((data) => {
|
|
21
21
|
setAvailableLangs(data.data || []);
|
|
@@ -49,6 +49,7 @@ const RelationField = ({ field, help, onFocus, onBlur, onChange, value = null })
|
|
|
49
49
|
|
|
50
50
|
const response = await fetch(`/api/data/search?${params.toString()}`, {
|
|
51
51
|
method: 'POST',
|
|
52
|
+
credentials:"include",
|
|
52
53
|
headers: { 'Content-Type': 'application/json' },
|
|
53
54
|
body: JSON.stringify({ filter: {} }) // Le filtre peut être vide quand on cherche par IDs
|
|
54
55
|
});
|
|
@@ -126,6 +127,7 @@ const RelationField = ({ field, help, onFocus, onBlur, onChange, value = null })
|
|
|
126
127
|
body: JSON.stringify({ filter: finalFilter }),
|
|
127
128
|
method: 'POST',
|
|
128
129
|
signal: signal,
|
|
130
|
+
credentials:"include",
|
|
129
131
|
headers: { 'Content-Type': 'application/json' },
|
|
130
132
|
})
|
|
131
133
|
.then(e => e.json())
|
|
@@ -13,6 +13,7 @@ import { useAuthContext } from './contexts/AuthContext.jsx';
|
|
|
13
13
|
const insertDataAPI = async (modelName, data) => {
|
|
14
14
|
const response = await fetch(`/api/data`, {
|
|
15
15
|
method: 'POST',
|
|
16
|
+
credentials:"include",
|
|
16
17
|
headers: { 'Content-Type': 'application/json' },
|
|
17
18
|
body: JSON.stringify({model: modelName,data})
|
|
18
19
|
});
|
|
@@ -27,6 +28,7 @@ const searchDataAPI = async (modelName, filter) => {
|
|
|
27
28
|
const params = new URLSearchParams({ model: modelName, depth: '1' });
|
|
28
29
|
const response = await fetch(`/api/data/search?${params.toString()}`, {
|
|
29
30
|
method: 'POST',
|
|
31
|
+
credentials:"include",
|
|
30
32
|
headers: { 'Content-Type': 'application/json' },
|
|
31
33
|
body: JSON.stringify({ filter })
|
|
32
34
|
});
|
|
@@ -42,6 +42,7 @@ function RestoreDialog() {
|
|
|
42
42
|
try {
|
|
43
43
|
const response = await fetch(apiUrl, {
|
|
44
44
|
method: 'GET', // Ou 'POST' si l'API l'exige, mais GET semble plus probable ici
|
|
45
|
+
credentials:"include",
|
|
45
46
|
headers: {
|
|
46
47
|
'Accept': 'application/json',
|
|
47
48
|
// Ajoute d'autres headers si nécessaire (ex: Authorization si requis)
|
|
@@ -17,7 +17,7 @@ const ViewSwitcher = ({ currentView, onViewChange, configuredViews, onConfigureV
|
|
|
17
17
|
const { t } = useTranslation();
|
|
18
18
|
|
|
19
19
|
return (
|
|
20
|
-
<div className="view-switcher flex items-center gap-1 p-1
|
|
20
|
+
<div className="view-switcher flex items-center gap-1 p-1 rounded-md">
|
|
21
21
|
{viewOptions.map(view => {
|
|
22
22
|
const isConfigured = view.id === 'table' || configuredViews[view.id];
|
|
23
23
|
const isActive = currentView === view.id;
|
|
@@ -84,6 +84,7 @@ const WorkflowEditor = ({ workflowId }) => {
|
|
|
84
84
|
['mainWorkflow', workflowId],
|
|
85
85
|
() => fetch('/api/data/search?_user='+me.username, {
|
|
86
86
|
method: 'POST',
|
|
87
|
+
credentials:"include",
|
|
87
88
|
headers: { 'Content-Type': 'application/json' },
|
|
88
89
|
body: JSON.stringify({
|
|
89
90
|
model: 'workflow',
|
|
@@ -102,6 +103,7 @@ const WorkflowEditor = ({ workflowId }) => {
|
|
|
102
103
|
['workflowSteps', workflowId],
|
|
103
104
|
() => fetch('/api/data/search?_user=' + me.username, {
|
|
104
105
|
method: 'POST',
|
|
106
|
+
credentials:"include",
|
|
105
107
|
headers: { 'Content-Type': 'application/json' },
|
|
106
108
|
body: JSON.stringify({
|
|
107
109
|
model: 'workflowStep',
|
|
@@ -122,6 +124,7 @@ const WorkflowEditor = ({ workflowId }) => {
|
|
|
122
124
|
['workflowActions', workflowId],
|
|
123
125
|
() => fetch('/api/data/search?_user=' + me.username, {
|
|
124
126
|
method: 'POST',
|
|
127
|
+
credentials:"include",
|
|
125
128
|
headers: { 'Content-Type': 'application/json' },
|
|
126
129
|
body: JSON.stringify({
|
|
127
130
|
model: 'workflowAction',
|
|
@@ -116,7 +116,7 @@ export class InsertCommand {
|
|
|
116
116
|
async undo() {
|
|
117
117
|
// On garde une copie de l'item avant de le supprimer pour le redo.
|
|
118
118
|
if (!this.insertedItem?._id) throw new Error("Cannot undo insert: item ID is missing.");
|
|
119
|
-
const response = await fetch(`/api/data/${this.insertedItem._id}`, { method: 'DELETE' });
|
|
119
|
+
const response = await fetch(`/api/data/${this.insertedItem._id}`, { credentials:"include",method: 'DELETE' });
|
|
120
120
|
const result = await response.json();
|
|
121
121
|
if (!response.ok || !result.success) {
|
|
122
122
|
throw new Error(result.error || 'Undo (delete) failed');
|
|
@@ -184,6 +184,7 @@ export class DeleteCommand {
|
|
|
184
184
|
|
|
185
185
|
return fetch('/api/data?_user=system', { // On ajoute _user=system pour tracer l'origine de l'action
|
|
186
186
|
method: 'POST',
|
|
187
|
+
credentials:"include",
|
|
187
188
|
headers: { 'Content-Type': 'application/json' },
|
|
188
189
|
body: JSON.stringify({ model: this.modelName, data: reinsertData }),
|
|
189
190
|
}).then(res => res.json().then(data => {
|
|
@@ -45,7 +45,7 @@ export const ModelProvider = ({ children }) => {
|
|
|
45
45
|
const { data: dataModels = [], isFetched } = useQuery(['api/models', me], () => {
|
|
46
46
|
if(!me)
|
|
47
47
|
return Promise.reject();
|
|
48
|
-
return fetch(`/api/models?lang=${lang}&_user=${encodeURIComponent(getUserId(me))}
|
|
48
|
+
return fetch(`/api/models?lang=${lang}&_user=${encodeURIComponent(getUserId(me))}`, {credentials:"include"}).then((res) => {
|
|
49
49
|
if( !res.ok ){
|
|
50
50
|
return [];
|
|
51
51
|
}
|
|
@@ -118,7 +118,7 @@ export const ModelProvider = ({ children }) => {
|
|
|
118
118
|
if( rel){
|
|
119
119
|
return Promise.resolve(rel);
|
|
120
120
|
}
|
|
121
|
-
return fetch(`/api/data/search?${params.toString()}`, { signal, method: 'POST', headers: { "Content-Type": "application/json"}})
|
|
121
|
+
return fetch(`/api/data/search?${params.toString()}`, { credentials:"include",signal, method: 'POST', headers: { "Content-Type": "application/json"}})
|
|
122
122
|
.then((res) => res.json())
|
|
123
123
|
.then((e) => ({
|
|
124
124
|
count: e.count,
|
|
@@ -204,7 +204,7 @@ export const ModelProvider = ({ children }) => {
|
|
|
204
204
|
const c = pagedFilterToMongoConds(pagedFilters, model)
|
|
205
205
|
const filter= JSON.stringify({filter:{$and:c}});
|
|
206
206
|
|
|
207
|
-
return fetch(`/api/data/search?${params.toString()}`, { signal, method: 'POST', body: filter, headers: { "Content-Type": "application/json"}})
|
|
207
|
+
return fetch(`/api/data/search?${params.toString()}`, { signal, credentials: "include", method: 'POST', body: filter, headers: { "Content-Type": "application/json"}})
|
|
208
208
|
.then((res) => res.json())
|
|
209
209
|
.then((e) => {
|
|
210
210
|
return {
|
package/client/src/hooks/data.js
CHANGED
|
@@ -12,6 +12,7 @@ export const useData = (model, filter, options) => {
|
|
|
12
12
|
return useQuery([options.queryKey || model, filter, me], () => {
|
|
13
13
|
return fetch('/api/data/search?limit='+(options.limit||1)+'&lang='+(options.lang||lang)+'&_user=' + encodeURIComponent(getUserId(me)) + '&model='+model, {
|
|
14
14
|
method: 'POST',
|
|
15
|
+
credentials:"include",
|
|
15
16
|
body: JSON.stringify({filter}),
|
|
16
17
|
headers: { "Content-Type": "application/json"}}
|
|
17
18
|
)
|
|
@@ -457,8 +457,8 @@ export const websiteTranslations = {
|
|
|
457
457
|
"btns.backup": "Restaurer",
|
|
458
458
|
"backup.restore.title": "Envoi de votre lien de restauration",
|
|
459
459
|
"backup.restore.confirm": "Un lien pour restaurer votre sauvegarde vous sera envoyé à votre adresse e-mail. Ce lien expirera dans 30 minutes. Voulez-vous vraiment continuer?",
|
|
460
|
-
"
|
|
461
|
-
"
|
|
460
|
+
"email_backup_restoreRequest_subject": "Votre demande de restauration de sauvegarde",
|
|
461
|
+
"email_backup_restoreRequest_content": `<p>Vous avez demandé une restauration de sauvegarde. Veuillez choisir une option :</p>
|
|
462
462
|
<p><strong>ATTENTION : Toute restauration écrasera vos données actuelles (modèles et/ou données).</strong></p>
|
|
463
463
|
<ul>
|
|
464
464
|
<li><a href="https://{{host}}/backup/restore?token={{modelsToken}}&username={{user}}&type=full">Restauration Complète (Modèles ET Données)</a></li>
|
|
@@ -1570,8 +1570,8 @@ export const websiteTranslations = {
|
|
|
1570
1570
|
"backup.restore.title": "Sending your restore link",
|
|
1571
1571
|
"btns.backup": "Restore",
|
|
1572
1572
|
"backup.restore.confirm": "A link to restore your backup will be sent to your email address. This link will expire in 30 minutes. Are you sure you want to proceed?",
|
|
1573
|
-
"
|
|
1574
|
-
"
|
|
1573
|
+
"email_backup_restoreRequest_subject": "Your Backup restoration request",
|
|
1574
|
+
"email_backup_restoreRequest_content": `<p>You have requested a backup restoration. Please choose an option:</p>
|
|
1575
1575
|
<p><strong>WARNING: Any restoration will overwrite your current data (models and/or data).</strong></p>
|
|
1576
1576
|
<ul>
|
|
1577
1577
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Full Restoration (Models AND Data)</a></li>
|
|
@@ -3046,8 +3046,8 @@ export const websiteTranslations = {
|
|
|
3046
3046
|
"btns.cancel": "Cancelar",
|
|
3047
3047
|
"btns.backup": "Restaurar",
|
|
3048
3048
|
"backup.restore.confirm": "Se enviará un enlace para restaurar su copia de seguridad a su correo electrónico. Este enlace caducará en 30 minutos. ¿Está seguro de que desea continuar?",
|
|
3049
|
-
"
|
|
3050
|
-
"
|
|
3049
|
+
"email_backup_restoreRequest_subject": "Su solicitud de restauración de copia de seguridad",
|
|
3050
|
+
"email_backup_restoreRequest_content": `<p>Has solicitado una restauración de copia de seguridad. Por favor, elige una opción:</p>
|
|
3051
3051
|
<p><strong>ADVERTENCIA: Cualquier restauración sobrescribirá tus datos actuales (modelos y/o datos).</strong></p>
|
|
3052
3052
|
<ul>
|
|
3053
3053
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Restauración completa (Modelos Y Datos)</a></li>
|
|
@@ -4528,8 +4528,8 @@ export const websiteTranslations = {
|
|
|
4528
4528
|
"btns.cancel": "Cancelar",
|
|
4529
4529
|
"btns.backup": "Restaurar",
|
|
4530
4530
|
"backup.restore.confirm": "Será enviado um link para restaurar o seu backup para o seu endereço de e-mail. Este link expirará em 30 minutos. Tem a certeza de que pretende prosseguir?",
|
|
4531
|
-
"
|
|
4532
|
-
"
|
|
4531
|
+
"email_backup_restoreRequest_subject": "O seu pedido de restauro de cópia de segurança",
|
|
4532
|
+
"email_backup_restoreRequest_content": `<p>Solicitou a restauração de uma cópia de segurança. Por favor, escolha uma opção:</p>
|
|
4533
4533
|
<p><strong>ATENÇÃO: Qualquer restauração irá substituir os seus dados atuais (modelos e/ou dados).</strong></p>
|
|
4534
4534
|
<ul>
|
|
4535
4535
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Restauração Completa (Modelos E Dados)</a></li>
|
|
@@ -5984,8 +5984,8 @@ export const websiteTranslations = {
|
|
|
5984
5984
|
"btns.cancel": "Abbrechen",
|
|
5985
5985
|
"btns.backup": "Wiederherstellen",
|
|
5986
5986
|
"backup.restore.confirm": "Ein Link zur Wiederherstellung Ihres Backups wird an Ihre E-Mail-Adresse gesendet. Dieser Link läuft in 30 Minuten ab. Möchten Sie wirklich fortfahren?",
|
|
5987
|
-
"
|
|
5988
|
-
"
|
|
5987
|
+
"email_backup_restoreRequest_subject": "Ihre Anfrage zur Wiederherstellung des Backups",
|
|
5988
|
+
"email_backup_restoreRequest_content": `<p>Sie haben die Wiederherstellung eines Backups angefordert. Bitte wählen Sie eine Option:</p>
|
|
5989
5989
|
<p><strong>ACHTUNG: Jede Wiederherstellung überschreibt Ihre aktuellen Daten (Modelle und/oder Daten).</strong></p>
|
|
5990
5990
|
<ul>
|
|
5991
5991
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Vollständige Wiederherstellung (Modelle UND Daten)</a></li>
|
|
@@ -7463,8 +7463,8 @@ export const websiteTranslations = {
|
|
|
7463
7463
|
"btns.cancel": "Annulla",
|
|
7464
7464
|
"btns.backup": "Ripristina",
|
|
7465
7465
|
"backup.restore.confirm": "Un link per ripristinare il backup verrà inviato al tuo indirizzo email. Questo link scadrà tra 30 minuti. Vuoi procedere?",
|
|
7466
|
-
"
|
|
7467
|
-
"
|
|
7466
|
+
"email_backup_restoreRequest_subject": "La tua richiesta di ripristino del backup",
|
|
7467
|
+
"email_backup_restoreRequest_content": `<p>Hai richiesto il ripristino di un backup. Scegli un'opzione:</p>
|
|
7468
7468
|
<p><strong>ATTENZIONE: Qualsiasi ripristino sovrascriverà i tuoi dati attuali (modelli e/o dati).</strong></p>
|
|
7469
7469
|
<ul>
|
|
7470
7470
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Ripristino Completo (Modelli E Dati)</a></li>
|
|
@@ -8937,8 +8937,8 @@ export const websiteTranslations = {
|
|
|
8937
8937
|
"btns.cancel": "Zrušit",
|
|
8938
8938
|
"btns.backup": "Obnovit",
|
|
8939
8939
|
"backup.restore.confirm": "Na vaši e-mailovou adresu bude odeslán odkaz pro obnovení zálohy. Platnost tohoto odkazu vyprší za 30 minut. Opravdu chcete pokračovat?",
|
|
8940
|
-
"
|
|
8941
|
-
"
|
|
8940
|
+
"email_backup_restoreRequest_subject": "Váš požadavek na obnovení zálohy",
|
|
8941
|
+
"email_backup_restoreRequest_content": `<p>Požádali jste o obnovení ze zálohy. Vyberte prosím možnost:</p>
|
|
8942
8942
|
<p><strong>VAROVÁNÍ: Jakákoli obnova přepíše vaše aktuální data (modely a/nebo data).</strong></p>
|
|
8943
8943
|
<ul>
|
|
8944
8944
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Kompletní obnova (Modely I Data)</a></li>
|
|
@@ -10409,8 +10409,8 @@ export const websiteTranslations = {
|
|
|
10409
10409
|
"btns.cancel": "Отмена",
|
|
10410
10410
|
"btns.backup": "Восстановить",
|
|
10411
10411
|
"backup.restore.confirm": "Ссылка для восстановления резервной копии будет отправлена на ваш адрес электронной почты. Срок действия этой ссылки истекает через 30 минут. Вы уверены, что хотите продолжить?",
|
|
10412
|
-
"
|
|
10413
|
-
"
|
|
10412
|
+
"email_backup_restoreRequest_subject": "Ваш запрос на восстановление резервной копии",
|
|
10413
|
+
"email_backup_restoreRequest_content": `<p>Вы запросили восстановление из резервной копии. Пожалуйста, выберите вариант:</p>
|
|
10414
10414
|
<p><strong>ВНИМАНИЕ: Любое восстановление перезапишет ваши текущие данные (модели и/или данные).</strong></p>
|
|
10415
10415
|
<ul>
|
|
10416
10416
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Полное восстановление (Модели И Данные)</a></li>
|
|
@@ -11900,8 +11900,8 @@ export const websiteTranslations = {
|
|
|
11900
11900
|
"btns.cancel": "إلغاء",
|
|
11901
11901
|
"btns.backup": "استعادة",
|
|
11902
11902
|
"backup.restore.confirm": "سيتم إرسال رابط لاستعادة النسخة الاحتياطية إلى بريدك الإلكتروني. سينتهي هذا الرابط خلال 30 دقيقة. هل أنت متأكد من رغبتك في المتابعة؟",
|
|
11903
|
-
"
|
|
11904
|
-
"
|
|
11903
|
+
"email_backup_restoreRequest_subject": "طلب استعادة النسخة الاحتياطية الخاص بك",
|
|
11904
|
+
"email_backup_restoreRequest_content": `<p>لقد طلبت استعادة نسخة احتياطية. يرجى اختيار خيار:</p>
|
|
11905
11905
|
<p><strong>تحذير: أي عملية استعادة ستستبدل بياناتك الحالية (النماذج و/أو البيانات).</strong></p>
|
|
11906
11906
|
<ul>
|
|
11907
11907
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">استعادة كاملة (النماذج والبيانات)</a></li>
|
|
@@ -13380,8 +13380,8 @@ export const websiteTranslations = {
|
|
|
13380
13380
|
"btns.cancel": "Avbryt",
|
|
13381
13381
|
"btns.backup": "Återställ",
|
|
13382
13382
|
"backup.restore.confirm": "En länk för att återställa din säkerhetskopia kommer att skickas till din e-postadress. Den här länken upphör att gälla om 30 minuter. Är du säker på att du vill fortsätta?",
|
|
13383
|
-
"
|
|
13384
|
-
"
|
|
13383
|
+
"email_backup_restoreRequest_subject": "Din begäran om återställning av säkerhetskopia",
|
|
13384
|
+
"email_backup_restoreRequest_content": `<p>Du har begärt en återställning från backup. Vänligen välj ett alternativ:</p>
|
|
13385
13385
|
<p><strong>OBS: All återställning kommer att skriva över din nuvarande data (modeller och/eller data).</strong></p>
|
|
13386
13386
|
<ul>
|
|
13387
13387
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Fullständig återställning (Modeller OCH Data)</a></li>
|
|
@@ -14854,8 +14854,8 @@ export const websiteTranslations = {
|
|
|
14854
14854
|
"btns.cancel": "Ακύρωση",
|
|
14855
14855
|
"btns.backup": "Επαναφορά",
|
|
14856
14856
|
"backup.restore.confirm": "Ένας σύνδεσμος για την επαναφορά του αντιγράφου ασφαλείας θα σταλεί στη διεύθυνση email σας. Αυτός ο σύνδεσμος θα λήξει σε 30 λεπτά. Είστε βέβαιοι ότι θέλετε να συνεχίσετε;",
|
|
14857
|
-
"
|
|
14858
|
-
"
|
|
14857
|
+
"email_backup_restoreRequest_subject": "Το αίτημα επαναφοράς αντιγράφων ασφαλείας",
|
|
14858
|
+
"email_backup_restoreRequest_content": `<p>Έχετε αιτηθεί επαναφορά από αντίγραφο ασφαλείας. Παρακαλώ επιλέξτε μια επιλογή:</p>
|
|
14859
14859
|
<p><strong>ΠΡΟΣΟΧΗ: Οποιαδήποτε επαναφορά θα αντικαταστήσει τα τρέχοντα δεδομένα σας (μοντέλα και/ή δεδομένα).</strong></p>
|
|
14860
14860
|
<ul>
|
|
14861
14861
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">Πλήρης Επαναφορά (Μοντέλα ΚΑΙ Δεδομένα)</a></li>
|
|
@@ -16283,8 +16283,8 @@ export const websiteTranslations = {
|
|
|
16283
16283
|
"btns.backup": "بازیابی",
|
|
16284
16284
|
"backup.restore.title": "ارسال لینک بازیابی شما",
|
|
16285
16285
|
"backup.restore.confirm": "لینکی برای بازیابی پشتیبانگیری شما به آدرس ایمیل شما ارسال خواهد شد. این لینک پس از 30 دقیقه منقضی میشود. آیا واقعاً میخواهید ادامه دهید؟",
|
|
16286
|
-
"
|
|
16287
|
-
"
|
|
16286
|
+
"email_backup_restoreRequest_subject": "درخواست بازیابی پشتیبانگیری شما",
|
|
16287
|
+
"email_backup_restoreRequest_content": `<p>درخواست بازیابی نسخه پشتیبان را دادهاید. لطفاً یک گزینه انتخاب کنید:</p>
|
|
16288
16288
|
<p><strong>هشدار: هرگونه بازیابی، دادههای فعلی شما (مدلها و/یا دادهها) را بازنویسی خواهد کرد.</strong></p>
|
|
16289
16289
|
<ul>
|
|
16290
16290
|
<li><a href="https://{{host}}/backup/restore?token={{fullToken}}&username={{user}}&type=full">بازیابی کامل (هم مدلها و هم دادهها)</a></li>
|
package/client/vite.config.js
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
import react from '@vitejs/plugin-react'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
import { fileURLToPath, URL } from "node:url";
|
|
4
|
+
|
|
5
|
+
// https://vite.dev/config/
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
plugins: [react()],
|
|
8
|
+
base: "/",
|
|
9
|
+
build: {
|
|
10
|
+
outDir: "dist"
|
|
11
|
+
},
|
|
12
|
+
server : {
|
|
13
|
+
proxy: {
|
|
14
|
+
'/api': {
|
|
15
|
+
target: 'http://localhost:7633',
|
|
16
|
+
secure: false,
|
|
17
|
+
changeOrigin: true,
|
|
18
|
+
// Optionnel mais utile pour le débogage :
|
|
19
|
+
// Affiche les requêtes proxy dans la console de Vite.
|
|
20
|
+
configure: (proxy, options) => {
|
|
21
|
+
proxy.on('proxyReq', (proxyReq, req, res) => {
|
|
22
|
+
console.log(`[Vite Proxy] Forwarding request: ${req.method} ${req.url} -> ${options.target}${proxyReq.path}`);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
fs: {
|
|
29
|
+
allow: ["./src", "../src"]
|
|
30
|
+
}
|
|
31
|
+
})
|