data-primals-engine 1.3.3 → 1.4.0

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.
Files changed (36) hide show
  1. package/README.md +797 -782
  2. package/client/README.md +20 -0
  3. package/client/package-lock.json +717 -151
  4. package/client/package.json +37 -36
  5. package/client/src/App.jsx +9 -10
  6. package/client/src/App.scss +42 -1
  7. package/client/src/Dashboard.jsx +349 -208
  8. package/client/src/DashboardView.jsx +569 -547
  9. package/client/src/DataEditor.jsx +20 -2
  10. package/client/src/DataLayout.jsx +54 -13
  11. package/client/src/DataTable.jsx +807 -760
  12. package/client/src/DataTable.scss +187 -90
  13. package/client/src/Dialog.scss +0 -3
  14. package/client/src/Field.jsx +1783 -1583
  15. package/client/src/ModelCreator.jsx +25 -3
  16. package/client/src/ModelCreatorField.jsx +906 -804
  17. package/client/src/ModelList.jsx +20 -2
  18. package/client/src/constants.js +16 -4
  19. package/client/src/contexts/UIContext.jsx +19 -10
  20. package/client/src/translations.js +265 -3
  21. package/package.json +4 -3
  22. package/server.js +1 -0
  23. package/src/core.js +18 -0
  24. package/src/defaultModels.js +70 -10
  25. package/src/email.js +2 -1
  26. package/src/filter.js +260 -256
  27. package/src/i18n.js +503 -30
  28. package/src/modules/data/data.core.js +5 -1
  29. package/src/modules/data/data.history.js +489 -489
  30. package/src/modules/data/data.js +76 -10
  31. package/src/modules/data/data.routes.js +3 -20
  32. package/src/modules/user.js +19 -0
  33. package/src/modules/workflow.js +1808 -1817
  34. package/client/public/demo/26899917-d1ba-4df4-bb33-48d09a8778da.jpg +0 -0
  35. package/client/public/demo/4b9894c7-12cd-466d-8fd3-a2757b09ec96.jpg +0 -0
  36. package/client/public/demo/7ed369ac-a1a2-4b45-b0cd-4fd5bcf5a75a.jpg +0 -0
@@ -9,6 +9,17 @@ import useLocalStorage from "./hooks/useLocalStorage.js";
9
9
  import {Tooltip} from "react-tooltip";
10
10
  import {useUI} from "./contexts/UIContext.jsx";
11
11
  import {profiles} from "./constants.js";
12
+ import * as FaIcons from "react-icons/fa";
13
+ import * as Fa6Icons from "react-icons/fa6";
14
+
15
+
16
+ // Fonction pour obtenir le composant icône par son nom
17
+ const getIconComponent = (iconName) => {
18
+ if (!iconName) return null;
19
+ const IconComponent = FaIcons[iconName] || Fa6Icons[iconName];
20
+ return IconComponent ? <IconComponent /> : null; // Retourne l'élément React ou null
21
+ };
22
+
12
23
 
13
24
  export function ModelList({ onModelSelect, onCreateModel, onImportModel, onEditModel, onAPIInfo, onNewData }) {
14
25
  const {allTourSteps, setIsTourOpen,setCurrentTourSteps, setTourStepIndex, currentTour, setCurrentTour} = useUI();
@@ -34,6 +45,7 @@ export function ModelList({ onModelSelect, onCreateModel, onImportModel, onEditM
34
45
  return models.filter(model => {
35
46
  return (model.name && t('model_' + model.name, model.name).toLowerCase().includes(lowerSearchTerm)) ||
36
47
  (model.fields.some(f =>
48
+ (model.icon && model.icon.toLowerCase().includes(lowerSearchTerm)) ||
37
49
  f.name?.toLowerCase().includes(lowerSearchTerm) ||
38
50
  f.hint?.toLowerCase().includes(lowerSearchTerm)) ||
39
51
  (model.description && model.description.toLowerCase().includes(lowerSearchTerm)))
@@ -51,7 +63,7 @@ export function ModelList({ onModelSelect, onCreateModel, onImportModel, onEditM
51
63
  return fetch('/api/demo/initialize', {
52
64
  method: 'POST',
53
65
  headers: { "Content-Type": "application/json"},
54
- body: JSON.stringify({profile: profile}),
66
+ body: JSON.stringify({profile: profile, packs: profiles[profile].packs}),
55
67
  });
56
68
  });
57
69
 
@@ -169,12 +181,18 @@ export function ModelList({ onModelSelect, onCreateModel, onImportModel, onEditM
169
181
  {filteredModels.sort((a, b) => t('model_' + a.name, a.name).localeCompare(t('model_' + b.name, b.name))).map((model) => {
170
182
  if (model._user !== me.username)
171
183
  return <></>
184
+
185
+
186
+ const IconComponent = getIconComponent(model.icon);
187
+
172
188
  return (
173
189
  <li data-testid={'model_'+model.name} className={`${model.name === selectedModel?.name ? 'active' : ''}`}
174
190
  key={'modelist' + model.name} onClick={() => generatedModels.some(g => g.name === model.name) ? onEditModel(model) : onModelSelect(model)}>
175
191
  <div className="flex flex-center flex-fw">
176
192
  <div
177
- className="flex-1 break-word">{t(`model_${model.name}`, model.name)} {generatedModels.some(f => f.name === model.name) ? '(tmp)' : (mods.some(f => f.mod === model.name) ? `(${mods.find(f => f.mod === model.name).count})` : '')}</div>
193
+ className="flex flex-1 flex-no-wrap break-word">
194
+ <div className={"icon"}>{IconComponent ? IconComponent : <></>}</div>
195
+ <div>{t(`model_${model.name}`, model.name)} {generatedModels.some(f => f.name === model.name) ? '(tmp)' : (mods.some(f => f.mod === model.name) ? `(${mods.find(f => f.mod === model.name).count})` : '')}</div></div>
178
196
  <div className="btns">
179
197
  {!generatedModels.some(g => g.name === model.name) && (<button data-tooltip-id="tooltipML" data-tooltip-content={t('btns.addData')} onClick={(e) => {
180
198
  e.stopPropagation();
@@ -51,10 +51,22 @@ export const MONGO_OPERATORS = {
51
51
  };
52
52
 
53
53
  export const profiles = {
54
- 'personal': ['contact', 'location', 'imageGallery', 'budget', 'currency', 'taxonomy'], // budget,
55
- 'developer': ['alert','endpoint','request','webpage', 'content', 'taxonomy', 'resource', 'translation', 'contact', 'location', 'channel', 'lang', 'token', 'message', 'ticket', 'user', 'permission', 'role'],
56
- 'company': ['alert','request','location', 'order', 'currency', 'product', 'cart', 'cartItem', 'invoice', 'message', 'user', 'role', 'permission', 'token','translation', 'lang', 'webpage', 'content', 'taxonomy', 'contact', 'resource', 'accountingExercise', 'accountingLineItem', 'accountingEntry', 'employee', 'kpi', 'dashboard'],
57
- 'engineer': ['alert','endpoint','request','dashboard', 'kpi', 'user', 'role', 'token', 'permission', 'workflow', 'workflowRun', 'workflowStep', "channel", "message", 'workflowAction', 'workflowTrigger']
54
+ 'personal': {
55
+ "packs": [],
56
+ "models": ['contact', 'location', 'imageGallery', 'budget', 'currency', 'taxonomy']
57
+ }, // budget,
58
+ 'developer': {
59
+ "packs": ["Multilingual starter pack", "Website Starter Pack"],
60
+ "models": ['alert','endpoint','request','webpage', 'content', 'taxonomy', 'resource', 'translation', 'contact', 'location', 'channel', 'lang', 'token', 'message', 'ticket', 'user', 'permission', 'role']
61
+ },
62
+ 'company': {
63
+ "packs": ["E-commerce Starter Kit"],
64
+ "models": ['alert','request','location', 'order', 'currency', 'product', 'cart', 'cartItem', 'invoice', 'message', 'user', 'role', 'permission', 'token','translation', 'lang', 'webpage', 'content', 'taxonomy', 'contact', 'resource', 'accountingExercise', 'accountingLineItem', 'accountingEntry', 'employee', 'kpi', 'dashboard']
65
+ },
66
+ 'engineer': {
67
+ "packs": ["AI Content Generation - Starter Pack"],
68
+ "models":['alert','endpoint','request','dashboard', 'kpi', 'user', 'role', 'token', 'permission', 'workflow', 'workflowRun', 'workflowStep', "channel", "message", 'workflowAction', 'workflowTrigger']
69
+ }
58
70
  }
59
71
 
60
72
  export const OPERAND_TYPES = {
@@ -1,5 +1,5 @@
1
1
  // ModelContext.jsx
2
- import React, {createContext, useContext, useEffect, useMemo, useState} from 'react';
2
+ import React, {createContext, useCallback, useContext, useEffect, useMemo, useState} from 'react';
3
3
  import useLocalStorage from "../hooks/useLocalStorage.js";
4
4
 
5
5
  const UIContext = createContext(null);
@@ -9,22 +9,31 @@ export const UIProvider = ({ children }) => {
9
9
  const [tourStepIndex, setTourStepIndex] = useState(0);
10
10
  const [currentTourSteps, setCurrentTourSteps] = useState([]);
11
11
  const [isTourOpen, setIsTourOpen] = useState(false);
12
- const [allTourSteps, setAllTourSteps] = useState([]);
13
- const [launchedTours, setLaunchedTours] = useState([]);
12
+ const [allTourSteps, setAllTourSteps] = useState({});
14
13
 
15
14
  const [currentTour, setCurrentTour] = useLocalStorage("spotlight-tour", null);
16
- const [finishedTours, setLSTours] = useLocalStorage('launchedTours', []);
17
- useEffect(() =>{
18
- if( launchedTours)
19
- setLSTours(launchedTours);
20
- }, [launchedTours])
15
+ // This is the single source of truth for tours that have been launched.
16
+ // It correctly reads from localStorage on initial load and persists any changes.
17
+ const [launchedTours, setLaunchedTours] = useLocalStorage('launchedTours', []);
18
+
19
+ // A stable helper function to add a tour to the list without overwriting.
20
+ const addLaunchedTour = useCallback((tourName) => {
21
+ setLaunchedTours(prevTours => {
22
+ // Ensure we're working with an array, even if localStorage is empty/corrupted.
23
+ const currentTours = Array.isArray(prevTours) ? prevTours : [];
24
+ if (!currentTours.includes(tourName)) {
25
+ return [...currentTours, tourName];
26
+ }
27
+ return currentTours; // Return unchanged if already present
28
+ });
29
+ }, [setLaunchedTours]); // setLaunchedTours from useLocalStorage is stable
21
30
 
22
31
  const [isLocked, setLocked] = useState(false);
23
32
  const contextValue = useMemo(() => ({
24
33
  isLocked,
25
34
  setLocked,
26
35
  currentTourSteps, setCurrentTourSteps,
27
- launchedTours,setLaunchedTours,
36
+ launchedTours, setLaunchedTours, addLaunchedTour,
28
37
  currentTour, setCurrentTour,
29
38
  isTourOpen, setIsTourOpen, setAllTourSteps, allTourSteps,
30
39
  tourStepIndex, setTourStepIndex
@@ -34,7 +43,7 @@ useEffect(() =>{
34
43
  launchedTours,setLaunchedTours,
35
44
  currentTour, setCurrentTour,
36
45
  isTourOpen, setIsTourOpen, setAllTourSteps, allTourSteps,
37
- tourStepIndex, setTourStepIndex]);
46
+ tourStepIndex, setTourStepIndex, addLaunchedTour]);
38
47
 
39
48
  return (
40
49
  <UIContext.Provider value={contextValue}>
@@ -2,6 +2,28 @@
2
2
  export const websiteTranslations = {
3
3
  fr: {
4
4
  translation: {
5
+ "modelcreator.gauge.hint": "Affiche le champ numérique sous forme de jauge visuelle. Nécessite de définir une valeur minimale et maximale.",
6
+ "modelcreator.percent.hint": "En mode jauge, affiche la valeur sous forme de pourcentage (calculé à partir du min/max) au lieu de la valeur brute.",
7
+
8
+ "duration.unit.days": "jours",
9
+ "duration.unit.hours": "heures",
10
+ "duration.unit.minutes": "minutes",
11
+ "duration.unit.seconds": "secondes",
12
+ "duration.day": "{{count}} jour",
13
+ "duration.day_plural": "{{count}} jours",
14
+ "duration.hour": "{{count}}h",
15
+ "duration.hour_plural": "{{count}}h",
16
+ "duration.minute": "{{count}}min",
17
+ "duration.minute_plural": "{{count}}min",
18
+ "duration.second": "{{count}}s",
19
+ "duration.second_plural": "{{count}}s",
20
+ "views.table": "Tableau",
21
+ "views.kanban": "Kanban",
22
+ "views.calendar": "Calendrier",
23
+ "modelcreator.delay": "Délai ?",
24
+ "modelcreator.delay.hint": "Cette donnée représente un délai en millisecondes.",
25
+ "modelcreator.icon": "Icône",
26
+ "modelcreator.field.icon": "Icône (FontAwesome) associée au modèle",
5
27
  "modelcreator.field.history": "Permet d'afficher et de superviser les modifications effectuées sur vos données. Consomme de l'espace.'",
6
28
  "history": "Historique",
7
29
  "history.op.create": "Création",
@@ -490,7 +512,7 @@ export const websiteTranslations = {
490
512
  "cgu.p.9": "Nous nous réservons le droit de résilier votre accès à notre service à tout moment, avec ou sans motif, et sans préavis. Vous pouvez également résilier votre compte à tout moment en suivant les instructions disponibles sur le Site.",
491
513
  "cgu.h1.10": "10. Loi Applicable",
492
514
  "cgu.p.10": "Ces CGU sont régies par les lois en vigueur en France. Tout litige découlant de ou en relation avec ces CGU sera soumis à la juridiction exclusive des tribunaux compétents de ce pays.",
493
- "seo.title": "Besoin d'une solution API puissante et sécurisée, sans vous ruiner ? Découvrez data.primals.net !",
515
+ "seo.title": "Vos données en ligne - data.primals.net",
494
516
  "modelcreator.field.maxlength.ph": "0: pas de limite, X: nombre de caractères max",
495
517
  "modelcreator.field.unit.ph": "€, cm, kg...",
496
518
  "modelcreator.field.step.ph": "Précision (1, 0.1...)",
@@ -568,6 +590,27 @@ export const websiteTranslations = {
568
590
  },
569
591
  en: {
570
592
  translation: {
593
+ "modelcreator.gauge.hint": "Displays the numeric field as a visual gauge. Requires a minimum and maximum value to be set.",
594
+ "modelcreator.percent.hint": "In gauge mode, displays the value as a percentage (calculated from the min/max) instead of the raw value.",
595
+ "duration.unit.days": "days",
596
+ "duration.unit.hours": "hours",
597
+ "duration.unit.minutes": "minutes",
598
+ "duration.unit.seconds": "seconds",
599
+ "duration.day": "{{count}} day",
600
+ "duration.day_plural": "{{count}} days",
601
+ "duration.hour": "{{count}}h",
602
+ "duration.hour_plural": "{{count}}h",
603
+ "duration.minute": "{{count}}m",
604
+ "duration.minute_plural": "{{count}}m",
605
+ "duration.second": "{{count}}s",
606
+ "duration.second_plural": "{{count}}s",
607
+ "views.table": "Table",
608
+ "views.kanban": "Kanban",
609
+ "views.calendar": "Calendar",
610
+ "modelcreator.delay": "Delay?",
611
+ "modelcreator.delay.hint": "This data represents a delay in seconds.",
612
+ "modelcreator.icon": "Icon",
613
+ "modelcreator.field.icon": "Icon (FontAwesome) associated with the model",
571
614
  "modelcreator.field.history": "Allows you to view and monitor changes made to your data. Consumes space.",
572
615
  "history": "History",
573
616
  "history.op.create": "Creation",
@@ -1588,8 +1631,8 @@ export const websiteTranslations = {
1588
1631
  "cgu.h1.9": "9. Termination",
1589
1632
  "cgu.p.9": "We reserve the right to terminate your access to our service at any time, with or without cause, and without notice. You may also terminate your account at any time by following the instructions available on the Site.",
1590
1633
  "cgu.h1.10": "10. Applicable Law",
1591
- "cgu.p.10": "These TOU are governed by the laws in force in France. Any dispute arising out of or in connection with these TOU will be submitted to the exclusive jurisdiction of the competent courts of that country.",
1592
- "seo.title": "Need a powerful and secure API solution without breaking the bank? Check out data.primals.net!",
1634
+ "cgu.p.10": "TYhese TOU are governed by the laws in force in France. Any dispute arising out of or in connection with these TOU will be submitted to the exclusive jurisdiction of the competent courts of that country.",
1635
+ "seo.title": "Your data comes to life - data.primals.net!",
1593
1636
  "modelcreator.field.maxlength.ph": "0: unlimited, X: maximum number of characters",
1594
1637
  "modelcreator.field.unit.ph": "€, cm, kg...",
1595
1638
  "modelcreator.field.step.ph": "Precision (1, 0.1...)",
@@ -2008,6 +2051,28 @@ export const websiteTranslations = {
2008
2051
  },
2009
2052
  es: {
2010
2053
  translation: {
2054
+ "modelcreator.gauge.hint": "Muestra el campo numérico como un indicador visual. Requiere que se establezcan un valor mínimo y máximo.",
2055
+ "modelcreator.percent.hint": "En modo indicador, muestra el valor como un porcentaje (calculado a partir del mínimo/máximo) en lugar del valor bruto.",
2056
+ "duration.unit.days": "días",
2057
+ "duration.unit.hours": "horas",
2058
+ "duration.unit.minutes": "minutos",
2059
+ "duration.unit.seconds": "segundos",
2060
+ "duration.day": "{{count}} día",
2061
+ "duration.day_plural": "{{count}} días",
2062
+ "duration.hour": "{{count}}h",
2063
+ "duration.hour_plural": "{{count}}h",
2064
+ "duration.minute": "{{count}}min",
2065
+ "duration.minute_plural": "{{count}}min",
2066
+ "duration.second": "{{count}}s",
2067
+ "duration.second_plural": "{{count}}s",
2068
+ "views.table": "Tabla",
2069
+ "views.kanban": "Kanban",
2070
+ "views.calendar": "Calendario",
2071
+ "modelcreator.delay": "¿Retraso?",
2072
+ "modelcreator.delay.hint": "Este dato representa un retraso en segundos.",
2073
+
2074
+ "modelcreator.icon": "Icono",
2075
+ "modelcreator.field.icon": "Icono (FontAwesome) asociado al modelo",
2011
2076
  "modelcreator.field.history": "Permite ver y supervisar los cambios realizados en los datos. Consume espacio.",
2012
2077
  "history": "Historial",
2013
2078
  "history.op.create": "Creación",
@@ -3450,6 +3515,28 @@ export const websiteTranslations = {
3450
3515
  },
3451
3516
  pt: {
3452
3517
  translation: {
3518
+ "modelcreator.gauge.hint": "Exibe o campo numérico como um indicador visual. Requer a definição de um valor mínimo e máximo.",
3519
+ "modelcreator.percent.hint": "No modo de indicador, exibe o valor como uma porcentagem (calculada a partir do mínimo/máximo) em vez do valor bruto.",
3520
+ "duration.unit.days": "dias",
3521
+ "duration.unit.hours": "horas",
3522
+ "duration.unit.minutes": "minutos",
3523
+ "duration.unit.seconds": "segundos",
3524
+ "duration.day": "{{count}} dia",
3525
+ "duration.day_plural": "{{count}} dias",
3526
+ "duration.hour": "{{count}}h",
3527
+ "duration.hour_plural": "{{count}}h",
3528
+ "duration.minute": "{{count}}min",
3529
+ "duration.minute_plural": "{{count}}min",
3530
+ "duration.second": "{{count}}s",
3531
+ "duration.second_plural": "{{count}}s",
3532
+ "views.table": "Tabela",
3533
+ "views.kanban": "Kanban",
3534
+ "views.calendar": "Calendário",
3535
+ "modelcreator.delay": "Atraso?",
3536
+ "modelcreator.delay.hint": "Este dado representa um atraso em segundos.",
3537
+
3538
+ "modelcreator.icon": "Ícone",
3539
+ "modelcreator.field.icon": "Ícone (FontAwesome) associado ao modelo",
3453
3540
  "modelcreator.field.history": "Permite visualizar e monitorar as alterações feitas nos seus dados. Consome espaço.",
3454
3541
  "history": "Histórico",
3455
3542
  "history.op.create": "Criação",
@@ -4887,6 +4974,27 @@ export const websiteTranslations = {
4887
4974
  },
4888
4975
  de: {
4889
4976
  translation: {
4977
+ "modelcreator.gauge.hint": "Zeigt das numerische Feld als visuelle Anzeige an. Erfordert die Festlegung eines Mindest- und Höchstwerts.",
4978
+ "modelcreator.percent.hint": "Im Anzeigemodus wird der Wert als Prozentsatz (berechnet aus Min./Max.) anstelle des Rohwerts angezeigt.",
4979
+ "duration.unit.days": "Tage",
4980
+ "duration.unit.hours": "Stunden",
4981
+ "duration.unit.minutes": "Minuten",
4982
+ "duration.unit.seconds": "Sekunden",
4983
+ "duration.day": "{{count}} Tag",
4984
+ "duration.day_plural": "{{count}} Tage",
4985
+ "duration.hour": "{{count}}h",
4986
+ "duration.hour_plural": "{{count}}h",
4987
+ "duration.minute": "{{count}}min",
4988
+ "duration.minute_plural": "{{count}}min",
4989
+ "duration.second": "{{count}}s",
4990
+ "duration.second_plural": "{{count}}s",
4991
+ "views.table": "Tabelle",
4992
+ "views.kanban": "Kanban",
4993
+ "views.calendar": "Kalender",
4994
+ "modelcreator.delay": "Verzögerung?",
4995
+ "modelcreator.delay.hint": "Dieser Wert stellt eine Verzögerung in sekunden dar.",
4996
+ "modelcreator.icon": "Symbol",
4997
+ "modelcreator.field.icon": "Mit dem Modell verknüpftes Symbol (FontAwesome)",
4890
4998
  "modelcreator.field.history": "Ermöglicht Ihnen, Änderungen an Ihren Daten anzuzeigen und zu überwachen. Verbraucht Speicherplatz.",
4891
4999
  "history": "Verlauf",
4892
5000
 
@@ -6310,6 +6418,28 @@ export const websiteTranslations = {
6310
6418
  },
6311
6419
  it: {
6312
6420
  translation: {
6421
+ "modelcreator.gauge.hint": "Visualizza il campo numerico come indicatore visivo. Richiede l'impostazione di un valore minimo e massimo.",
6422
+ "modelcreator.percent.hint": "In modalità indicatore, visualizza il valore come percentuale (calcolata dal minimo/massimo) anziché come valore grezzo.",
6423
+ "duration.unit.days": "giorni",
6424
+ "duration.unit.hours": "ore",
6425
+ "duration.unit.minutes": "minuti",
6426
+ "duration.unit.seconds": "secondi",
6427
+ "duration.day": "{{count}} giorno",
6428
+ "duration.day_plural": "{{count}} giorni",
6429
+ "duration.hour": "{{count}}h",
6430
+ "duration.hour_plural": "{{count}}h",
6431
+ "duration.minute": "{{count}}min",
6432
+ "duration.minute_plural": "{{count}}min",
6433
+ "duration.second": "{{count}}s",
6434
+ "duration.second_plural": "{{count}}s",
6435
+ "views.table": "Tabella",
6436
+ "views.kanban": "Kanban",
6437
+ "views.calendar": "Calendario",
6438
+ "modelcreator.delay": "Ritardo?",
6439
+ "modelcreator.delay.hint": "Questo dato rappresenta un ritardo in secondi.",
6440
+
6441
+ "modelcreator.icon": "Icona",
6442
+ "modelcreator.field.icon": "Icona (FontAwesome) associata al modello",
6313
6443
  "modelcreator.field.history": "Consente di visualizzare e monitorare le modifiche apportate ai dati. Occupa spazio.",
6314
6444
  "history": "Cronologia",
6315
6445
 
@@ -7745,6 +7875,28 @@ export const websiteTranslations = {
7745
7875
  },
7746
7876
  cs: {
7747
7877
  translation: {
7878
+ "modelcreator.gauge.hint": "Zobrazuje číselné pole jako vizuální měřidlo. Vyžaduje nastavení minimální a maximální hodnoty.",
7879
+ "modelcreator.percent.hint": "V režimu měřidla zobrazuje hodnotu v procentech (vypočtených z min./max.) namísto nezpracované hodnoty.",
7880
+ "duration.unit.days": "dny",
7881
+ "duration.unit.hours": "hodiny",
7882
+ "duration.unit.minutes": "minuty",
7883
+ "duration.unit.seconds": "sekundy",
7884
+ "duration.day": "{{count}} den",
7885
+ "duration.day_plural": "{{count}} dny", // Pour 2,3,4 et pluriel général
7886
+ "duration.hour": "{{count}}h",
7887
+ "duration.hour_plural": "{{count}}h",
7888
+ "duration.minute": "{{count}}min",
7889
+ "duration.minute_plural": "{{count}}min",
7890
+ "duration.second": "{{count}}s",
7891
+ "duration.second_plural": "{{count}}s",
7892
+ "views.table": "Tabulka",
7893
+ "views.kanban": "Kanban",
7894
+ "views.calendar": "Kalendář",
7895
+ "modelcreator.delay": "Zpoždění?",
7896
+ "modelcreator.delay.hint": "Tato data představují zpoždění v sekundách.",
7897
+
7898
+ "modelcreator.icon": "Ikona",
7899
+ "modelcreator.field.icon": "Ikona (FontAwesome) přidružená k modelu",
7748
7900
  "modelcreator.field.history": "Umožňuje zobrazit a sledovat změny provedené ve vašich datech. Spotřebovává místo.",
7749
7901
  "history": "Historie",
7750
7902
  "history.op.create": "Vytvoření",
@@ -9174,6 +9326,28 @@ export const websiteTranslations = {
9174
9326
  },
9175
9327
  ru: {
9176
9328
  translation: {
9329
+ "modelcreator.gauge.hint": "Отображает числовое поле в виде визуальной шкалы. Требуется задать минимальное и максимальное значения.",
9330
+ "modelcreator.percent.hint": "В режиме шкалы отображает значение в процентах (рассчитанных на основе минимального и максимального значений), а не в исходном виде.",
9331
+ "duration.unit.days": "дней",
9332
+ "duration.unit.hours": "часов",
9333
+ "duration.unit.minutes": "минут",
9334
+ "duration.unit.seconds": "секунд",
9335
+ "duration.day": "{{count}} день",
9336
+ "duration.day_plural": "{{count}} дня", // Pour les comptes comme 2,3,4
9337
+ "duration.hour": "{{count}}ч",
9338
+ "duration.hour_plural": "{{count}}ч",
9339
+ "duration.minute": "{{count}}мин",
9340
+ "duration.minute_plural": "{{count}}мин",
9341
+ "duration.second": "{{count}}с",
9342
+ "duration.second_plural": "{{count}}с",
9343
+ "views.table": "Таблица",
9344
+ "views.kanban": "Канбан",
9345
+ "views.calendar": "Календарь",
9346
+ "modelcreator.delay": "Задержка?",
9347
+ "modelcreator.delay.hint": "Эти данные представляют задержку в секундах.",
9348
+
9349
+ "modelcreator.icon": "Значок",
9350
+ "modelcreator.field.icon": "Значок (FontAwesome), связанный с моделью",
9177
9351
  "modelcreator.field.history": "Позволяет просматривать и отслеживать изменения, внесённые в ваши данные. Занимает место.",
9178
9352
  "history": "История",
9179
9353
 
@@ -10615,6 +10789,28 @@ export const websiteTranslations = {
10615
10789
  },
10616
10790
  ar: {
10617
10791
  translation: {
10792
+ "modelcreator.gauge.hint": "يعرض الحقل الرقمي كمقياس مرئي. يتطلب تحديد الحد الأدنى والحد الأقصى للقيمة.",
10793
+ "modelcreator.percent.hint": "في وضع المقياس، يعرض القيمة كنسبة مئوية (محسوبة من الحد الأدنى/الأقصى) بدلاً من القيمة الخام.",
10794
+ "duration.unit.days": "أيام",
10795
+ "duration.unit.hours": "ساعات",
10796
+ "duration.unit.minutes": "دقائق",
10797
+ "duration.unit.seconds": "ثواني",
10798
+ "duration.day": "{{count}} يوم",
10799
+ "duration.day_plural": "{{count}} يوم",
10800
+ "duration.hour": "{{count}}س",
10801
+ "duration.hour_plural": "{{count}}س",
10802
+ "duration.minute": "{{count}}د",
10803
+ "duration.minute_plural": "{{count}}د",
10804
+ "duration.second": "{{count}}ث",
10805
+ "duration.second_plural": "{{count}}ث",
10806
+ "views.table": "جدول",
10807
+ "views.kanban": "كانبان",
10808
+ "views.calendar": "تقويم",
10809
+ "modelcreator.delay": "تأخير؟",
10810
+ "modelcreator.delay.hint": "تمثل هذه البيانات تأخيرًا بالثواني.",
10811
+
10812
+ "modelcreator.icon": "أيقونة",
10813
+ "modelcreator.field.icon": "الأيقونة (FontAwesome) المرتبطة بالنموذج",
10618
10814
  "modelcreator.field.history": "يسمح لك بعرض ومراقبة التغييرات التي أجريتها على بياناتك. يستهلك مساحة.",
10619
10815
  "history": "السجل",
10620
10816
  "history.op.create": "إنشاء",
@@ -12071,6 +12267,28 @@ export const websiteTranslations = {
12071
12267
  },
12072
12268
  sv: {
12073
12269
  translation: {
12270
+ "modelcreator.gauge.hint": "Visar det numeriska fältet som en visuell mätare. Kräver att ett minimum- och maxvärde ställs in.",
12271
+ "modelcreator.percent.hint": "I mätläge visas värdet som en procentandel (beräknat från min/max) istället för det råa värdet.",
12272
+ "duration.unit.days": "dagar",
12273
+ "duration.unit.hours": "timmar",
12274
+ "duration.unit.minutes": "minuter",
12275
+ "duration.unit.seconds": "sekunder",
12276
+ "duration.day": "{{count}} dag",
12277
+ "duration.day_plural": "{{count}} dagar",
12278
+ "duration.hour": "{{count}}h",
12279
+ "duration.hour_plural": "{{count}}h",
12280
+ "duration.minute": "{{count}}min",
12281
+ "duration.minute_plural": "{{count}}min",
12282
+ "duration.second": "{{count}}s",
12283
+ "duration.second_plural": "{{count}}s",
12284
+ "views.table": "Tabell",
12285
+ "views.kanban": "Kanban",
12286
+ "views.calendar": "Kalender",
12287
+ "modelcreator.delay": "Fördröjning?",
12288
+ "modelcreator.delay.hint": "Denna data representerar en fördröjning i sekunder.",
12289
+
12290
+ "modelcreator.icon": "Ikon",
12291
+ "modelcreator.field.icon": "Ikon (FontAwesome) associerad med modellen",
12074
12292
  "modelcreator.field.history": "Låter dig visa och övervaka ändringar som gjorts i dina data. Tar plats.",
12075
12293
  "history": "Historik",
12076
12294
  "history.op.create": "Skapande",
@@ -13500,6 +13718,28 @@ export const websiteTranslations = {
13500
13718
  },
13501
13719
  el: {
13502
13720
  translation: {
13721
+ "modelcreator.gauge.hint": "Εμφανίζει το αριθμητικό πεδίο ως οπτικό μετρητή. Απαιτείται να οριστεί μια ελάχιστη και μια μέγιστη τιμή.",
13722
+ "modelcreator.percent.hint": "Στη λειτουργία μετρητή, εμφανίζει την τιμή ως ποσοστό (υπολογιζόμενο από την ελάχιστη/μέγιστη τιμή) αντί για την ακατέργαστη τιμή.",
13723
+ "duration.unit.days": "ημέρες",
13724
+ "duration.unit.hours": "ώρες",
13725
+ "duration.unit.minutes": "λεπτά",
13726
+ "duration.unit.seconds": "δευτερόλεπτα",
13727
+ "duration.day": "{{count}} ημέρα",
13728
+ "duration.day_plural": "{{count}} ημέρες",
13729
+ "duration.hour": "{{count}}ώ",
13730
+ "duration.hour_plural": "{{count}}ώ",
13731
+ "duration.minute": "{{count}}λ",
13732
+ "duration.minute_plural": "{{count}}λ",
13733
+ "duration.second": "{{count}}δ",
13734
+ "duration.second_plural": "{{count}}δ",
13735
+ "views.table": "Πίνακας",
13736
+ "views.kanban": "Kanban",
13737
+ "views.calendar": "Ημερολόγιο",
13738
+ "modelcreator.delay": "Καθυστέρηση;",
13739
+ "modelcreator.delay.hint": "Αυτά τα δεδομένα αντιπροσωπεύουν μια καθυστέρηση σε δευτερόλεπτα.",
13740
+
13741
+ "modelcreator.icon": "Εικονίδιο",
13742
+ "modelcreator.field.icon": "Εικονίδιο (FontAwesome) που σχετίζεται με το μοντέλο",
13503
13743
  "modelcreator.field.history": "Σας επιτρέπει να βλέπετε και να παρακολουθείτε τις αλλαγές που έγιναν στα δεδομένα σας. Καταλαμβάνει χώρο.",
13504
13744
  "history": "Ιστορικό",
13505
13745
  "history.op.create": "Δημιουργία",
@@ -14938,6 +15178,28 @@ export const websiteTranslations = {
14938
15178
  },
14939
15179
  fa: {
14940
15180
  "translation": {
15181
+ "modelcreator.gauge.hint": "فیلد عددی را به عنوان یک معیار بصری نمایش می‌دهد. نیاز به تنظیم حداقل و حداکثر مقدار دارد.",
15182
+ "modelcreator.percent.hint": "در حالت معیار، مقدار را به صورت درصد (محاسبه شده از حداقل/حداکثر) به جای مقدار خام نمایش می‌دهد.",
15183
+ "duration.unit.days": "روز",
15184
+ "duration.unit.hours": "ساعت",
15185
+ "duration.unit.minutes": "دقیقه",
15186
+ "duration.unit.seconds": "ثانیه",
15187
+ "duration.day": "{{count}} روز",
15188
+ "duration.day_plural": "{{count}} روز",
15189
+ "duration.hour": "{{count}}س",
15190
+ "duration.hour_plural": "{{count}}س",
15191
+ "duration.minute": "{{count}}د",
15192
+ "duration.minute_plural": "{{count}}د",
15193
+ "duration.second": "{{count}}ث",
15194
+ "duration.second_plural": "{{count}}ث",
15195
+ "views.table": "جدول",
15196
+ "views.kanban": "کانبان",
15197
+ "views.calendar": "تقویم",
15198
+ "modelcreator.delay": "تأخیر؟",
15199
+ "modelcreator.delay.hint": "این داده نشان‌دهنده‌ی تأخیر بر حسب ثانیه است.",
15200
+
15201
+ "modelcreator.icon": "آیکون",
15202
+ "modelcreator.field.icon": "آیکون (FontAwesome) مرتبط با مدل",
14941
15203
  "modelcreator.field.history": "به شما امکان می‌دهد تغییرات ایجاد شده در داده‌های خود را مشاهده و نظارت کنید. فضا مصرف می‌کند.",
14942
15204
  "history": "تاریخچه",
14943
15205
  "history.op.create": "ایجاد",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-primals-engine",
3
- "version": "1.3.3",
3
+ "version": "1.4.0",
4
4
  "description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
5
5
  "main": "src/engine.js",
6
6
  "type": "module",
@@ -52,7 +52,8 @@
52
52
  "peerDependencies": {
53
53
  "express": "^5.1.0",
54
54
  "react": "18.3.1",
55
- "react-query": ">=3.0.0"
55
+ "react-query": ">=3.0.0",
56
+ "react-i18next": "^15.6.1"
56
57
  },
57
58
  "dependencies": {
58
59
  "@langchain/anthropic": "^0.3.26",
@@ -88,10 +89,10 @@
88
89
  "process": "^0.11.10",
89
90
  "prop-types": "^15.8.1",
90
91
  "randomcolor": "^0.6.2",
91
- "react-i18next": "^15.6.1",
92
92
  "react-markdown": "^10.1.0",
93
93
  "read-excel-file": "^5.8.8",
94
94
  "request-ip": "^3.3.0",
95
+ "safe-regex": "^2.1.1",
95
96
  "sanitize-html": "^2.17.0",
96
97
  "sirv": "^3.0.1",
97
98
  "stripe": "^18.4.0",
package/server.js CHANGED
@@ -11,6 +11,7 @@ import {port} from "./src/constants.js";
11
11
 
12
12
  Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow","user", "assistant", "swagger"])
13
13
  Config.Set("middlewares", []);
14
+ Config.Set("useDemoAccounts", true);
14
15
 
15
16
  const bench = GameObject.Create("Benchmark");
16
17
  const timer = bench.addComponent(BenchmarkTool);
package/src/core.js CHANGED
@@ -9,6 +9,24 @@ export function escapeRegex(string) {
9
9
  return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
10
10
  }
11
11
 
12
+ export const sequential = async (tasks) => {
13
+ const res = [];
14
+ for (const task of tasks) {
15
+ const r = await task();
16
+ res.push(r);
17
+ }
18
+ return res;
19
+ };
20
+
21
+ export function isValidRegex(s) {
22
+ try {
23
+ const m = s.match(/^([/~@;%#'])(.*?)\1([gimsuy]*)$/);
24
+ return m ? !!new RegExp(m[2],m[3])
25
+ : false;
26
+ } catch (e) {
27
+ return false
28
+ }
29
+ }
12
30
  export function escapeHtml(string){
13
31
  return string.replace(/(javascript|data|vbscript):/gi, '').replace(/[^\w-_. ]/gi, function (c) {
14
32
  return `&#${c.charCodeAt(0)};`;