data-primals-engine 1.3.3-rc.1 → 1.3.4
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/client/package-lock.json +7 -6
- package/client/package.json +1 -1
- package/client/src/App.scss +37 -0
- package/client/src/DataLayout.jsx +38 -9
- package/client/src/Dialog.scss +0 -3
- package/client/src/Field.jsx +75 -2
- package/client/src/ModelCreator.jsx +23 -1
- package/client/src/ModelList.jsx +19 -1
- package/client/src/contexts/UIContext.jsx +19 -10
- package/client/src/translations.js +24 -0
- package/package.json +2 -1
- package/server.js +1 -0
- package/src/core.js +9 -0
- package/src/defaultModels.js +52 -0
- package/src/filter.js +50 -40
- package/src/i18n.js +2 -2
- package/src/modules/data/data.js +6 -3
- package/src/modules/data/data.routes.js +3 -2
- package/src/modules/workflow.js +60 -12
- package/src/packs.js +5461 -5062
package/src/defaultModels.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export const defaultModels = {
|
|
3
3
|
permission: {
|
|
4
4
|
"name": "permission",
|
|
5
|
+
"icon": "FaKey",
|
|
5
6
|
"description": "",
|
|
6
7
|
"fields": [
|
|
7
8
|
{
|
|
@@ -17,6 +18,7 @@ export const defaultModels = {
|
|
|
17
18
|
},
|
|
18
19
|
role: {
|
|
19
20
|
name: 'role',
|
|
21
|
+
"icon": "FaUserTag",
|
|
20
22
|
"description": "",
|
|
21
23
|
fields: [
|
|
22
24
|
{ name: 'name', type: 'string_t', required: true, unique: true, color: '#363636' },
|
|
@@ -26,6 +28,7 @@ export const defaultModels = {
|
|
|
26
28
|
user: {
|
|
27
29
|
name: 'user',
|
|
28
30
|
"description": "",
|
|
31
|
+
"icon": "FaUser",
|
|
29
32
|
locked: true,
|
|
30
33
|
fields: [
|
|
31
34
|
{ name: 'username', type: 'string', required: true, unique: true, color: '#3C7D08' },
|
|
@@ -47,6 +50,7 @@ export const defaultModels = {
|
|
|
47
50
|
]
|
|
48
51
|
},
|
|
49
52
|
userPermission: {
|
|
53
|
+
"icon": "FaUserCheck",
|
|
50
54
|
"name": "userPermission",
|
|
51
55
|
"description": "Gère les exceptions aux permissions des rôles pour un utilisateur (ajouts ou retraits, permanents ou temporaires).",
|
|
52
56
|
"fields": [
|
|
@@ -81,6 +85,7 @@ export const defaultModels = {
|
|
|
81
85
|
},
|
|
82
86
|
token: {
|
|
83
87
|
name: 'token',
|
|
88
|
+
"icon": "FaKey",
|
|
84
89
|
"description": "",
|
|
85
90
|
fields: [
|
|
86
91
|
{ name: 'name', type: 'string' },
|
|
@@ -90,6 +95,7 @@ export const defaultModels = {
|
|
|
90
95
|
},
|
|
91
96
|
translation: {
|
|
92
97
|
name: 'translation',
|
|
98
|
+
"icon": "FaLanguage",
|
|
93
99
|
locked: true,
|
|
94
100
|
"description": "",
|
|
95
101
|
fields: [
|
|
@@ -100,6 +106,7 @@ export const defaultModels = {
|
|
|
100
106
|
},
|
|
101
107
|
lang: {
|
|
102
108
|
name: 'lang',
|
|
109
|
+
"icon": "FaGlobe",
|
|
103
110
|
locked: true,
|
|
104
111
|
"description": "",
|
|
105
112
|
fields: [
|
|
@@ -109,6 +116,7 @@ export const defaultModels = {
|
|
|
109
116
|
},
|
|
110
117
|
currency: {
|
|
111
118
|
name: 'currency',
|
|
119
|
+
"icon": "FaMoneyBill",
|
|
112
120
|
"description": "",
|
|
113
121
|
locked: true,
|
|
114
122
|
fields: [
|
|
@@ -121,6 +129,7 @@ export const defaultModels = {
|
|
|
121
129
|
},
|
|
122
130
|
channel: {
|
|
123
131
|
name: 'channel',
|
|
132
|
+
"icon": "FaComments",
|
|
124
133
|
"description": "",
|
|
125
134
|
fields: [
|
|
126
135
|
{ name: 'name', type: 'string_t', required: true, unique: true }, // Nom du canal (ex: "email", "SMS")
|
|
@@ -130,6 +139,7 @@ export const defaultModels = {
|
|
|
130
139
|
},
|
|
131
140
|
message: {
|
|
132
141
|
name: 'message',
|
|
142
|
+
"icon": "FaEnvelope",
|
|
133
143
|
"description": "",
|
|
134
144
|
locked: true,
|
|
135
145
|
fields: [
|
|
@@ -148,6 +158,7 @@ export const defaultModels = {
|
|
|
148
158
|
},
|
|
149
159
|
alert: {
|
|
150
160
|
name: "alert",
|
|
161
|
+
"icon": "FaBell",
|
|
151
162
|
description: "Définit les règles pour les alertes et les insights automatiques.",
|
|
152
163
|
fields: [
|
|
153
164
|
{ name: "name", type: "string", required: true, asMain: true },
|
|
@@ -186,6 +197,7 @@ export const defaultModels = {
|
|
|
186
197
|
},
|
|
187
198
|
env: {
|
|
188
199
|
name: "env",
|
|
200
|
+
"icon": "FaCog",
|
|
189
201
|
description: "Définit les variables d'environnement qui seront accessibles dans vos scripts et webhooks.",
|
|
190
202
|
fields: [
|
|
191
203
|
{ name: "name", type: "string", required: true, unique: true, asMain: true },
|
|
@@ -194,6 +206,7 @@ export const defaultModels = {
|
|
|
194
206
|
},
|
|
195
207
|
webpage: {
|
|
196
208
|
name: 'webpage',
|
|
209
|
+
"icon": "FaFileAlt",
|
|
197
210
|
locked: true,
|
|
198
211
|
"description": "",
|
|
199
212
|
fields: [
|
|
@@ -210,6 +223,7 @@ export const defaultModels = {
|
|
|
210
223
|
},
|
|
211
224
|
content: {
|
|
212
225
|
name: 'content',
|
|
226
|
+
"icon": "FaFileAlt",
|
|
213
227
|
"description": "",
|
|
214
228
|
fields: [
|
|
215
229
|
{ name: 'lang', type: 'relation', relation: 'lang' },
|
|
@@ -240,6 +254,7 @@ export const defaultModels = {
|
|
|
240
254
|
},
|
|
241
255
|
resource: {
|
|
242
256
|
name: 'resource',
|
|
257
|
+
"icon": "FaBoxOpen",
|
|
243
258
|
"description": "",
|
|
244
259
|
fields: [
|
|
245
260
|
{ name: "source", type: "url"},
|
|
@@ -248,6 +263,7 @@ export const defaultModels = {
|
|
|
248
263
|
},
|
|
249
264
|
taxonomy: {
|
|
250
265
|
name: 'taxonomy',
|
|
266
|
+
"icon": "FaTags",
|
|
251
267
|
"description": "",
|
|
252
268
|
fields: [
|
|
253
269
|
{ name: 'name', type: 'string_t', required: true, color: '#71A314' },
|
|
@@ -261,6 +277,7 @@ export const defaultModels = {
|
|
|
261
277
|
contact: {
|
|
262
278
|
locked: true,
|
|
263
279
|
name: 'contact',
|
|
280
|
+
"icon": "FaAddressBook",
|
|
264
281
|
"description": "",
|
|
265
282
|
fields: [
|
|
266
283
|
{ name: 'legalName', type: 'string', asMain: true, color: '#D9D9D9' },
|
|
@@ -274,6 +291,7 @@ export const defaultModels = {
|
|
|
274
291
|
|
|
275
292
|
location: {
|
|
276
293
|
"name": "location",
|
|
294
|
+
"icon": "FaMapMarkerAlt",
|
|
277
295
|
locked: true,
|
|
278
296
|
"description": "",
|
|
279
297
|
"fields": [
|
|
@@ -332,6 +350,7 @@ export const defaultModels = {
|
|
|
332
350
|
|
|
333
351
|
brand: {
|
|
334
352
|
name: 'brand',
|
|
353
|
+
"icon": "FaTrademark",
|
|
335
354
|
"description": "",
|
|
336
355
|
fields: [
|
|
337
356
|
{ name: 'name', type: 'string', required: true },
|
|
@@ -342,6 +361,7 @@ export const defaultModels = {
|
|
|
342
361
|
|
|
343
362
|
product: {
|
|
344
363
|
name: 'product',
|
|
364
|
+
"icon": "FaShoppingBag",
|
|
345
365
|
"description": "",
|
|
346
366
|
fields: [
|
|
347
367
|
{ name: 'name', type: 'string_t', required: true },
|
|
@@ -359,6 +379,7 @@ export const defaultModels = {
|
|
|
359
379
|
},
|
|
360
380
|
productVariant: {
|
|
361
381
|
name: 'productVariant',
|
|
382
|
+
"icon": "FaBox",
|
|
362
383
|
"description": "",
|
|
363
384
|
fields: [
|
|
364
385
|
{ name: 'product', type: 'relation', relation: 'product', required: true },
|
|
@@ -374,6 +395,7 @@ export const defaultModels = {
|
|
|
374
395
|
},
|
|
375
396
|
cart: {
|
|
376
397
|
name: 'cart',
|
|
398
|
+
"icon": "FaShoppingCart",
|
|
377
399
|
"description": "",
|
|
378
400
|
fields: [
|
|
379
401
|
{ name: 'user', type: 'relation', relation: 'user', required: true },
|
|
@@ -385,6 +407,7 @@ export const defaultModels = {
|
|
|
385
407
|
},
|
|
386
408
|
cartItem: {
|
|
387
409
|
name: 'cartItem',
|
|
410
|
+
"icon": "FaShoppingBasket",
|
|
388
411
|
"description": "",
|
|
389
412
|
fields: [
|
|
390
413
|
{ name: 'product', type: 'relation', relation: 'product', required: true },
|
|
@@ -394,6 +417,7 @@ export const defaultModels = {
|
|
|
394
417
|
},
|
|
395
418
|
discount: {
|
|
396
419
|
name: "discount",
|
|
420
|
+
"icon": "FaTicketAlt",
|
|
397
421
|
locked: true,
|
|
398
422
|
"description": "",
|
|
399
423
|
fields: [
|
|
@@ -411,6 +435,7 @@ export const defaultModels = {
|
|
|
411
435
|
},
|
|
412
436
|
order: {
|
|
413
437
|
name: "order",
|
|
438
|
+
"icon": "FaClipboardList",
|
|
414
439
|
locked: true,
|
|
415
440
|
"description": "",
|
|
416
441
|
fields: [
|
|
@@ -432,6 +457,7 @@ export const defaultModels = {
|
|
|
432
457
|
},
|
|
433
458
|
invoice: {
|
|
434
459
|
name: 'invoice',
|
|
460
|
+
"icon": "FaFileInvoice",
|
|
435
461
|
"description": "",
|
|
436
462
|
fields: [
|
|
437
463
|
{ name: 'order', type: 'relation', relation: 'order', required: true },
|
|
@@ -443,6 +469,7 @@ export const defaultModels = {
|
|
|
443
469
|
},
|
|
444
470
|
userSubscription: {
|
|
445
471
|
name: 'userSubscription',
|
|
472
|
+
"icon": "FaCalendarCheck",
|
|
446
473
|
"description": "",
|
|
447
474
|
locked: true,
|
|
448
475
|
fields: [
|
|
@@ -463,6 +490,7 @@ export const defaultModels = {
|
|
|
463
490
|
},
|
|
464
491
|
stock: {
|
|
465
492
|
name: 'stock',
|
|
493
|
+
"icon": "FaWarehouse",
|
|
466
494
|
"description": "",
|
|
467
495
|
fields: [
|
|
468
496
|
{ name: 'product', type: 'relation', relation: 'product', required: true },
|
|
@@ -474,6 +502,7 @@ export const defaultModels = {
|
|
|
474
502
|
},
|
|
475
503
|
stockAlert: {
|
|
476
504
|
name: 'stockAlert',
|
|
505
|
+
"icon": "FaExclamationTriangle",
|
|
477
506
|
"description": "",
|
|
478
507
|
fields: [
|
|
479
508
|
{ name: 'user', type: 'relation', relation: 'user', required: true },
|
|
@@ -484,6 +513,7 @@ export const defaultModels = {
|
|
|
484
513
|
},
|
|
485
514
|
shipment: {
|
|
486
515
|
name: 'shipment',
|
|
516
|
+
"icon": "FaTruck",
|
|
487
517
|
"description": "",
|
|
488
518
|
fields: [
|
|
489
519
|
{ name: 'order', type: 'relation', relation: 'order', required: true },
|
|
@@ -497,6 +527,7 @@ export const defaultModels = {
|
|
|
497
527
|
warehouse: {
|
|
498
528
|
name: 'warehouse',
|
|
499
529
|
"description": "",
|
|
530
|
+
"icon": "FaWarehouse",
|
|
500
531
|
fields: [
|
|
501
532
|
{ name: 'name', type: 'string_t', required: true },
|
|
502
533
|
{ name: 'location', type: 'relation', relation: 'location' },
|
|
@@ -506,6 +537,7 @@ export const defaultModels = {
|
|
|
506
537
|
'return': {
|
|
507
538
|
name: "return",
|
|
508
539
|
"description": "",
|
|
540
|
+
"icon": "FaUndo",
|
|
509
541
|
fields: [
|
|
510
542
|
{ "name": "order", "type": "relation", "relation": "order", "required": true },
|
|
511
543
|
{ "name": "user", "type": "relation", relation: "user" },
|
|
@@ -519,6 +551,7 @@ export const defaultModels = {
|
|
|
519
551
|
},
|
|
520
552
|
returnItem: {
|
|
521
553
|
name: 'returnItem',
|
|
554
|
+
"icon": "FaBoxOpen",
|
|
522
555
|
"description": "",
|
|
523
556
|
fields: [
|
|
524
557
|
{ name: 'return', type: 'relation', relation: 'return', required: true },
|
|
@@ -530,6 +563,7 @@ export const defaultModels = {
|
|
|
530
563
|
},
|
|
531
564
|
ticket: {
|
|
532
565
|
name: 'ticket',
|
|
566
|
+
"icon": "FaTicketAlt",
|
|
533
567
|
"description": "",
|
|
534
568
|
locked: true,
|
|
535
569
|
fields: [
|
|
@@ -547,6 +581,7 @@ export const defaultModels = {
|
|
|
547
581
|
},
|
|
548
582
|
review: {
|
|
549
583
|
name: "review",
|
|
584
|
+
"icon": "FaStar",
|
|
550
585
|
"description": "",
|
|
551
586
|
fields: [
|
|
552
587
|
{ "name": "user", "type": "relation", relation: "user" },
|
|
@@ -559,6 +594,7 @@ export const defaultModels = {
|
|
|
559
594
|
},
|
|
560
595
|
device: {
|
|
561
596
|
name: "device",
|
|
597
|
+
"icon": "FaMobile",
|
|
562
598
|
"description": "",
|
|
563
599
|
fields: [
|
|
564
600
|
{ "name": "location", "type": "relation", relation: 'location' },
|
|
@@ -568,6 +604,7 @@ export const defaultModels = {
|
|
|
568
604
|
// Modèle pour l'exercice comptable et l'entreprise
|
|
569
605
|
accountingExercise: {
|
|
570
606
|
name: 'accountingExercise',
|
|
607
|
+
"icon": "FaBook",
|
|
571
608
|
description: "Représente un exercice comptable pour une entreprise donnée.",
|
|
572
609
|
fields: [
|
|
573
610
|
{ name: 'name', type: 'string_t', 'required': true, unique: true, hint: "Intitulé de l'exercice comptable" },
|
|
@@ -581,6 +618,7 @@ export const defaultModels = {
|
|
|
581
618
|
// Modèle pour définir la structure des lignes comptables (le "plan")
|
|
582
619
|
accountingLineItem: {
|
|
583
620
|
name: 'accountingLineItem',
|
|
621
|
+
"icon": "FaListAlt",
|
|
584
622
|
description: "Définit une ligne/catégorie dans un document comptable.",
|
|
585
623
|
locked: true, // Probablement géré par l'application, pas par l'utilisateur final
|
|
586
624
|
fields: [
|
|
@@ -610,6 +648,7 @@ export const defaultModels = {
|
|
|
610
648
|
},
|
|
611
649
|
accountingEntry: {
|
|
612
650
|
"name": "accountingEntry",
|
|
651
|
+
"icon": "FaPenAlt",
|
|
613
652
|
"description": "",
|
|
614
653
|
"fields": [
|
|
615
654
|
{
|
|
@@ -679,6 +718,7 @@ export const defaultModels = {
|
|
|
679
718
|
},
|
|
680
719
|
employee: {
|
|
681
720
|
"name": "employee",
|
|
721
|
+
"icon": "FaUserTie",
|
|
682
722
|
"description": "",
|
|
683
723
|
"fields": [
|
|
684
724
|
{
|
|
@@ -819,6 +859,7 @@ export const defaultModels = {
|
|
|
819
859
|
},
|
|
820
860
|
workflow: {
|
|
821
861
|
name: 'workflow',
|
|
862
|
+
"icon": "FaProjectDiagram",
|
|
822
863
|
description: "Defines an automated process.",
|
|
823
864
|
fields: [
|
|
824
865
|
{ name: 'name', type: 'string_t', required: true, hint: "Unique name for the workflow (e.g., 'Order Validation', 'Low Stock Notification')." },
|
|
@@ -828,6 +869,7 @@ export const defaultModels = {
|
|
|
828
869
|
},
|
|
829
870
|
workflowTrigger: {
|
|
830
871
|
name: 'workflowTrigger',
|
|
872
|
+
"icon": "FaPlay",
|
|
831
873
|
description: "Represents an event that can initiate a workflow.",
|
|
832
874
|
fields: [
|
|
833
875
|
{ name: 'workflow', type: 'relation', relation: 'workflow', required: true, hint: "The workflow this step belongs to." },
|
|
@@ -879,6 +921,7 @@ export const defaultModels = {
|
|
|
879
921
|
},
|
|
880
922
|
workflowStep: {
|
|
881
923
|
name: 'workflowStep',
|
|
924
|
+
"icon": "FaStepForward",
|
|
882
925
|
description: "A single step within a workflow process.",
|
|
883
926
|
fields: [
|
|
884
927
|
{ name: 'workflow', type: 'relation', relation: 'workflow', required: true, hint: "The workflow this step belongs to." },
|
|
@@ -892,6 +935,7 @@ export const defaultModels = {
|
|
|
892
935
|
},
|
|
893
936
|
workflowAction: {
|
|
894
937
|
name: 'workflowAction',
|
|
938
|
+
"icon": "FaCogs",
|
|
895
939
|
description: "Defines a specific operation to be performed by a workflow step.",
|
|
896
940
|
fields: [
|
|
897
941
|
{ name: 'name', type: 'string_t', required: true, hint: "Name of the action (e.g., 'Update Order Status', 'Send Email', 'Call Payment API')." },
|
|
@@ -991,6 +1035,7 @@ export const defaultModels = {
|
|
|
991
1035
|
|
|
992
1036
|
workflowRun: {
|
|
993
1037
|
name: 'workflowRun',
|
|
1038
|
+
"icon": "FaRunning",
|
|
994
1039
|
description: "Tracks a specific execution instance of a workflow.",
|
|
995
1040
|
fields: [
|
|
996
1041
|
{ name: 'workflow', type: 'relation', relation: 'workflow', required: true, hint: "The workflow definition that was executed." },
|
|
@@ -1013,6 +1058,7 @@ export const defaultModels = {
|
|
|
1013
1058
|
},
|
|
1014
1059
|
dashboard:{
|
|
1015
1060
|
name: 'dashboard', // Nom technique du modèle
|
|
1061
|
+
"icon": "FaTachometerAlt",
|
|
1016
1062
|
description: "Configuration d'un tableau de bord personnalisé par l'utilisateur.", // Description du modèle
|
|
1017
1063
|
locked: false, // Indique si le modèle peut être modifié par l'utilisateur (false = modifiable)
|
|
1018
1064
|
fields: [
|
|
@@ -1052,6 +1098,7 @@ export const defaultModels = {
|
|
|
1052
1098
|
},
|
|
1053
1099
|
'request': {
|
|
1054
1100
|
name: 'request',
|
|
1101
|
+
"icon": "FaExchangeAlt",
|
|
1055
1102
|
description: "Journal des requêtes reçues par l'API.",
|
|
1056
1103
|
locked: true, // Géré par le système, non modifiable directement par l'utilisateur via l'UI standard
|
|
1057
1104
|
fields: [
|
|
@@ -1137,6 +1184,7 @@ export const defaultModels = {
|
|
|
1137
1184
|
|
|
1138
1185
|
kpi : {
|
|
1139
1186
|
name: 'kpi',
|
|
1187
|
+
"icon": "FaChartLine",
|
|
1140
1188
|
description: "Configuration d'un Indicateur Clé de Performance (KPI)",
|
|
1141
1189
|
fields: [
|
|
1142
1190
|
{ name: 'name', type: 'string_t', required: true, hint: "Nom affiché du KPI (ex: Chiffre d'affaires total)" },
|
|
@@ -1200,6 +1248,7 @@ export const defaultModels = {
|
|
|
1200
1248
|
},
|
|
1201
1249
|
imageGallery: {
|
|
1202
1250
|
name: 'imageGallery',
|
|
1251
|
+
"icon": "FaImages",
|
|
1203
1252
|
description: "Représente une galerie d'images avec un titre et une description.",
|
|
1204
1253
|
locked: false, // Les utilisateurs peuvent créer/gérer leurs galeries
|
|
1205
1254
|
fields: [
|
|
@@ -1241,6 +1290,7 @@ export const defaultModels = {
|
|
|
1241
1290
|
},
|
|
1242
1291
|
budget: {
|
|
1243
1292
|
name: 'budget',
|
|
1293
|
+
"icon": "FaMoneyCheck",
|
|
1244
1294
|
description: "Un budget permet de lister vos transactions personnelles.",
|
|
1245
1295
|
fields: [
|
|
1246
1296
|
{
|
|
@@ -1312,6 +1362,7 @@ export const defaultModels = {
|
|
|
1312
1362
|
},
|
|
1313
1363
|
event: {
|
|
1314
1364
|
"name": "event",
|
|
1365
|
+
"icon": "FaCalendar",
|
|
1315
1366
|
"description": "A model for managing events, conferences, meetups, and gatherings.",
|
|
1316
1367
|
"fields": [
|
|
1317
1368
|
{
|
|
@@ -1424,6 +1475,7 @@ export const defaultModels = {
|
|
|
1424
1475
|
},
|
|
1425
1476
|
endpoint: {
|
|
1426
1477
|
name: "endpoint",
|
|
1478
|
+
"icon": "FaCode",
|
|
1427
1479
|
description: "Defines custom API endpoints that execute a server-side script.",
|
|
1428
1480
|
fields: [
|
|
1429
1481
|
{
|
package/src/filter.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import safeRegex from 'safe-regex';
|
|
1
2
|
/**
|
|
2
3
|
* Evaluates a single condition against form data.
|
|
3
4
|
* @param {object} currentModelDef - The definition of the current model.
|
|
@@ -139,8 +140,8 @@ const evaluateSingleCondition = (currentModelDef, condition, formData, allModels
|
|
|
139
140
|
function evaluateComparison(operator, targetValue, processedConditionValue, condition) {
|
|
140
141
|
try {
|
|
141
142
|
switch (typeof operator === 'object' ? Object.keys(operator)[0] : null) {
|
|
142
|
-
case '$eq': return targetValue
|
|
143
|
-
case '$ne': return targetValue
|
|
143
|
+
case '$eq': return targetValue === processedConditionValue;
|
|
144
|
+
case '$ne': return targetValue !== processedConditionValue;
|
|
144
145
|
case '$gt': return targetValue > processedConditionValue;
|
|
145
146
|
case '$lt': return targetValue < processedConditionValue;
|
|
146
147
|
case '$gte': return targetValue >= processedConditionValue;
|
|
@@ -149,8 +150,11 @@ const evaluateSingleCondition = (currentModelDef, condition, formData, allModels
|
|
|
149
150
|
if (typeof targetValue !== 'string') return false;
|
|
150
151
|
if (typeof processedConditionValue !== 'string') return false;
|
|
151
152
|
try {
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
if( safeRegex(processedConditionValue)) {
|
|
154
|
+
const regex = new RegExp(processedConditionValue, 'i');
|
|
155
|
+
return regex.test(targetValue);
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
154
158
|
} catch (e) {
|
|
155
159
|
logClientEvalWarning(`Invalid regex pattern: ${processedConditionValue}`, condition);
|
|
156
160
|
return false;
|
|
@@ -175,63 +179,70 @@ export const isConditionMet = (model, cond, formData, allModels, user) => {
|
|
|
175
179
|
|
|
176
180
|
if (!condition) return true;
|
|
177
181
|
|
|
178
|
-
// Cas 0: Condition est une valeur primitive (string, number, boolean)
|
|
179
|
-
// On la considère comme toujours vraie (comportement de searchData)
|
|
180
182
|
if (typeof condition !== 'object' || condition === null) {
|
|
181
183
|
return true;
|
|
182
184
|
}
|
|
183
185
|
|
|
184
|
-
// Cas
|
|
185
|
-
|
|
186
|
+
// Cas spécial: Évaluation sans modèle (ex: pour les webhooks où la condition est déjà résolue)
|
|
187
|
+
// Dans ce mode, la condition doit être un objet avec un seul opérateur.
|
|
188
|
+
if (!model) {
|
|
186
189
|
const keys = Object.keys(condition);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
typeof condition[keys[0]] !== 'object') {
|
|
191
|
-
const fieldName = keys[0];
|
|
192
|
-
const value = condition[fieldName];
|
|
193
|
-
|
|
194
|
-
// Si la valeur est null/undefined, on vérifie simplement l'existence
|
|
195
|
-
if (value === null || value === undefined) {
|
|
196
|
-
return formData[fieldName] === value;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Sinon on fait une comparaison d'égalité simple
|
|
200
|
-
return formData[fieldName] == value;
|
|
190
|
+
if (keys.length !== 1 || !keys[0].startsWith('$')) {
|
|
191
|
+
console.warn('[isConditionMet] Condition invalide pour une évaluation sans modèle. Attendu : { "$opérateur": [...] }. Reçu :', condition);
|
|
192
|
+
return false; // Plus sûr que true pour éviter les faux positifs
|
|
201
193
|
}
|
|
202
194
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
195
|
+
const operator = keys[0];
|
|
196
|
+
const operands = condition[operator];
|
|
197
|
+
|
|
198
|
+
switch (operator) {
|
|
199
|
+
// Opérateurs logiques (récursifs)
|
|
200
|
+
case '$and':
|
|
201
|
+
return Array.isArray(operands) && operands.every(sub => isConditionMet(null, sub, formData, allModels, user));
|
|
202
|
+
case '$or':
|
|
203
|
+
return Array.isArray(operands) && operands.some(sub => isConditionMet(null, sub, formData, allModels, user));
|
|
204
|
+
case '$not':
|
|
205
|
+
return !isConditionMet(null, operands, formData, allModels, user);
|
|
206
|
+
case '$nor':
|
|
207
|
+
return Array.isArray(operands) && !operands.some(sub => isConditionMet(null, sub, formData, allModels, user));
|
|
208
|
+
|
|
209
|
+
// Opérateurs de comparaison (terminaux)
|
|
210
|
+
case '$eq':
|
|
211
|
+
return Array.isArray(operands) && operands[0] === operands[1];
|
|
212
|
+
case '$ne':
|
|
213
|
+
return Array.isArray(operands) && operands[0] !== operands[1];
|
|
214
|
+
case '$in':
|
|
215
|
+
return Array.isArray(operands) && Array.isArray(operands[1]) && operands[1].includes(operands[0]);
|
|
216
|
+
case '$nin':
|
|
217
|
+
return Array.isArray(operands) && Array.isArray(operands[1]) && !operands[1].includes(operands[0]);
|
|
218
|
+
case '$gt':
|
|
219
|
+
return Array.isArray(operands) && operands[0] > operands[1];
|
|
220
|
+
case '$gte':
|
|
221
|
+
return Array.isArray(operands) && operands[0] >= operands[1];
|
|
222
|
+
case '$lt':
|
|
223
|
+
return Array.isArray(operands) && operands[0] < operands[1];
|
|
224
|
+
case '$lte':
|
|
225
|
+
return Array.isArray(operands) && operands[0] <= operands[1];
|
|
214
226
|
|
|
215
|
-
|
|
216
|
-
|
|
227
|
+
default:
|
|
228
|
+
console.warn(`[isConditionMet] Opérateur non supporté '${operator}' pour une évaluation sans modèle.`);
|
|
229
|
+
return false;
|
|
217
230
|
}
|
|
218
231
|
}
|
|
219
232
|
|
|
220
|
-
//
|
|
233
|
+
// --- Logique existante pour l'évaluation AVEC modèle ---
|
|
234
|
+
|
|
221
235
|
if (condition.$and && Array.isArray(condition.$and)) {
|
|
222
236
|
if (condition.$and.length === 0) return true;
|
|
223
237
|
return condition.$and.every(sub => isConditionMet(model, sub, formData, allModels, user));
|
|
224
238
|
}
|
|
225
|
-
|
|
226
239
|
if (condition.$or && Array.isArray(condition.$or)) {
|
|
227
240
|
if (condition.$or.length === 0) return false;
|
|
228
241
|
return condition.$or.some(sub => isConditionMet(model, sub, formData, allModels, user));
|
|
229
242
|
}
|
|
230
|
-
|
|
231
243
|
if (condition.$not) {
|
|
232
244
|
return !isConditionMet(model, condition.$not, formData, allModels, user);
|
|
233
245
|
}
|
|
234
|
-
|
|
235
246
|
if (condition.$nor && Array.isArray(condition.$nor)) {
|
|
236
247
|
if (condition.$nor.length === 0) return true;
|
|
237
248
|
return !condition.$nor.some(sub => isConditionMet(model, sub, formData, allModels, user));
|
|
@@ -246,6 +257,5 @@ export const isConditionMet = (model, cond, formData, allModels, user) => {
|
|
|
246
257
|
}
|
|
247
258
|
}
|
|
248
259
|
|
|
249
|
-
// Cas 4: Tous les autres cas (conditions normales avec opérateurs)
|
|
250
260
|
return evaluateSingleCondition(model, condition, formData, allModels, user);
|
|
251
261
|
};
|
package/src/i18n.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import i18n from "i18next";
|
|
2
|
-
import {Trans, useTranslation, initReactI18next} from "react-i18next";
|
|
2
|
+
import {Trans, useTranslation,I18nextProvider, initReactI18next} from "react-i18next";
|
|
3
3
|
import LanguageDetector from "i18next-browser-languagedetector";
|
|
4
4
|
|
|
5
5
|
export const translations = {
|
|
@@ -12441,5 +12441,5 @@ i18n
|
|
|
12441
12441
|
}
|
|
12442
12442
|
});
|
|
12443
12443
|
|
|
12444
|
-
export {Trans, useTranslation};
|
|
12444
|
+
export {Trans, useTranslation, I18nextProvider};
|
|
12445
12445
|
export default i18n;
|
package/src/modules/data/data.js
CHANGED
|
@@ -1075,7 +1075,8 @@ export const editModel = async (user, id, data) => {
|
|
|
1075
1075
|
export async function middlewareEndpointAuthenticator(req, res, next) {
|
|
1076
1076
|
const { path } = req.params;
|
|
1077
1077
|
const method = req.method.toUpperCase();
|
|
1078
|
-
const
|
|
1078
|
+
const user = await engine.userProvider.findUserByUsername(req.query._user || req.params.user || req.me.username);
|
|
1079
|
+
const datasCollection = await getCollectionForUser(user);
|
|
1079
1080
|
|
|
1080
1081
|
try {
|
|
1081
1082
|
const endpointDef = await datasCollection.findOne({
|
|
@@ -1137,7 +1138,9 @@ export async function handleCustomEndpointRequest(req, res) {
|
|
|
1137
1138
|
// 2. Préparer le contexte pour le script
|
|
1138
1139
|
const contextData = {
|
|
1139
1140
|
request: {
|
|
1140
|
-
|
|
1141
|
+
// MODIFICATION: Utiliser req.body si disponible (pour les requêtes JSON comme les webhooks Stripe),
|
|
1142
|
+
// sinon, utiliser req.fields (pour les données de formulaire).
|
|
1143
|
+
body: (req.body && Object.keys(req.body).length > 0) ? req.body : (req.fields || {}),
|
|
1141
1144
|
query: req.query,
|
|
1142
1145
|
params: req.params,
|
|
1143
1146
|
headers: req.headers
|
|
@@ -1276,7 +1279,7 @@ export async function onInit(defaultEngine) {
|
|
|
1276
1279
|
|
|
1277
1280
|
const objectKeys = Object.keys(modelStructure);
|
|
1278
1281
|
|
|
1279
|
-
if( objectKeys.find(o => !["name", "_user", "history", "locked", "_id", "description", "maxRequestData", "fields"].includes(o)) ){
|
|
1282
|
+
if( objectKeys.find(o => !["name", "_user", "icon", "history", "locked", "_id", "description", "maxRequestData", "fields"].includes(o)) ){
|
|
1280
1283
|
throw new Error(i18n.t('api.model.invalidStructure'));
|
|
1281
1284
|
}
|
|
1282
1285
|
|
|
@@ -161,7 +161,8 @@ export async function registerRoutes(engine){
|
|
|
161
161
|
|
|
162
162
|
logger = engine.getComponent(Logger);
|
|
163
163
|
|
|
164
|
-
engine.all('/api/actions/:path', [middlewareEndpointAuthenticator, userInitiator], handleCustomEndpointRequest);
|
|
164
|
+
engine.all('/api/actions/:user/:path', [middlewareEndpointAuthenticator, userInitiator], handleCustomEndpointRequest);
|
|
165
|
+
engine.all('/api/actions/:path', [middlewareAuthenticator, middlewareEndpointAuthenticator, userInitiator], handleCustomEndpointRequest);
|
|
165
166
|
engine.post('/api/demo/initialize', [middlewareAuthenticator, userInitiator], handleDemoInitialization);
|
|
166
167
|
|
|
167
168
|
engine.post('/api/magnets', [middlewareAuthenticator, userInitiator], async (req, res) => {
|
|
@@ -872,7 +873,7 @@ export async function registerRoutes(engine){
|
|
|
872
873
|
await cancelAlerts(req.me);
|
|
873
874
|
|
|
874
875
|
await getPromise();
|
|
875
|
-
await Event.Trigger('
|
|
876
|
+
await Event.Trigger('OnDemoUserAdded', req.me.username);
|
|
876
877
|
}else{
|
|
877
878
|
await getPromise();
|
|
878
879
|
}
|