data-primals-engine 1.1.8 → 1.2.1
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 +72 -25
- package/client/src/App.scss +11 -6
- package/client/src/AssistantChat.scss +0 -1
- package/client/src/ChartConfigModal.jsx +0 -1
- package/client/src/ConditionBuilder.jsx +0 -2
- package/client/src/ConditionBuilder2.jsx +47 -6
- package/client/src/ContentView.jsx +0 -1
- package/client/src/CronBuilder.scss +0 -1
- package/client/src/CronPartBuilder.jsx +0 -1
- package/client/src/Dashboard.jsx +0 -1
- package/client/src/Dashboard.scss +0 -1
- package/client/src/DashboardChart.jsx +0 -1
- package/client/src/DashboardView.jsx +0 -1
- package/client/src/DataEditor.jsx +0 -4
- package/client/src/DisplayFlexNodeRenderer.jsx +0 -1
- package/client/src/DocumentationPageLayout.jsx +0 -2
- package/client/src/DocumentationPageLayout.scss +0 -1
- package/client/src/Field.jsx +1 -1
- package/client/src/FlexNode.jsx +0 -1
- package/client/src/KanbanView.scss +0 -1
- package/client/src/ModelCreator.jsx +4 -4
- package/client/src/ModelCreator.scss +10 -0
- package/client/src/ModelCreatorField.jsx +34 -34
- package/client/src/RTE.jsx +2 -1
- package/client/src/RestoreDialog.jsx +0 -1
- package/client/src/TourSpotlight.jsx +0 -1
- package/client/src/filter.js +2 -0
- package/client/src/hooks/useDragAndDrop.js +0 -1
- package/issues.txt +0 -0
- package/package.json +3 -2
- package/src/constants.js +6 -0
- package/src/core.js +6 -0
- package/src/data.js +0 -2
- package/src/defaultModels.js +33 -0
- package/src/migrate.js +0 -1
- package/src/modules/assistant.js +211 -133
- package/src/modules/data.js +88 -69
- package/src/modules/user.js +111 -56
- package/src/modules/workflow.js +10 -12
- package/src/providers.js +1 -1
- package/src/workers/crypto-worker.js +0 -1
- package/test/data.integration.test.js +53 -70
- package/test/user.test.js +203 -0
- package/test/workflow.integration.test.js +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
> Whether you're building a CRM, e-commerce site, CMS, or SaaS platform, **data-primals-engine** provides the strong foundations so you can focus on what makes your application unique.
|
|
11
11
|
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://data.primals.net/prez1.jpg" target="_blank"><img alt="Light" src="https://data.primals.net/prez1.jpg" width="35%"></a>
|
|
14
|
+
<a href="https://data.primals.net/prez6.jpg" target="_blank"><img alt="Light" src="https://data.primals.net/prez6.jpg" width="35%"></a>
|
|
15
|
+
<a href="https://data.primals.net/api-docs" target="_blank"><img alt="Dark" src="https://data.primals.net/prez5.jpg" width="25%"></a>
|
|
16
|
+
</p>
|
|
12
17
|
---
|
|
13
18
|
|
|
14
19
|
## 🚀 Key Features
|
|
@@ -23,18 +28,37 @@
|
|
|
23
28
|
- **🌐 i18n support**: Multilingual interfaces, translated validations.
|
|
24
29
|
- **📄 Auto Documentation**: Swagger available at `/api-docs`.
|
|
25
30
|
|
|
31
|
+
|
|
32
|
+
## 🌟 Why Choose data-primals-engine?
|
|
33
|
+
|
|
34
|
+
- **Zero Boilerplate**: Focus on your business logic, not infrastructure
|
|
35
|
+
- **Scalability**: Architecture designed for rapidly growing applications
|
|
36
|
+
- **Modularity**: Enable/disable features as needed
|
|
37
|
+
- **Batteries Included**: Everything you need to get started quickly
|
|
38
|
+
- **Proven Performance**: Handles 50k+ documents efficiently
|
|
39
|
+
- **AI Ready**: Built-in LangChain integration for OpenAI/Gemini
|
|
40
|
+
|
|
26
41
|
---
|
|
27
42
|
|
|
28
43
|
## ⚙️ Requirements
|
|
29
44
|
|
|
30
|
-
- Node.js ≥
|
|
31
|
-
- MongoDB (local or remote)
|
|
45
|
+
- Node.js ≥ 20
|
|
46
|
+
- MongoDB (local or remote), see [installation guide](https://www.mongodb.com/docs/manual/installation/)
|
|
32
47
|
- NPM or Yarn
|
|
33
48
|
|
|
34
49
|
---
|
|
35
50
|
|
|
36
51
|
## ⚡ Quick Start
|
|
37
52
|
|
|
53
|
+
### check
|
|
54
|
+
```bash
|
|
55
|
+
# Verify required versions
|
|
56
|
+
node -v # Must show ≥ v18
|
|
57
|
+
mongod --version # Must be installed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### install
|
|
61
|
+
|
|
38
62
|
```bash
|
|
39
63
|
npm i data-primals-engine
|
|
40
64
|
```
|
|
@@ -44,6 +68,8 @@ git clone https://github.com/anonympins/data-primals-engine.git
|
|
|
44
68
|
cd data-primals-engine
|
|
45
69
|
npm install
|
|
46
70
|
```
|
|
71
|
+
|
|
72
|
+
### configure
|
|
47
73
|
Possibly create a `.env` file:
|
|
48
74
|
```env
|
|
49
75
|
MONGO_DB_URL=mongodb://127.0.0.1:27017
|
|
@@ -64,11 +90,11 @@ MONGO_DB_URL=mongodb://127.0.0.1:27017
|
|
|
64
90
|
| SMTP_USER | Username for SMTP authentication. | user@example.com |
|
|
65
91
|
| SMTP_PASS | Password for SMTP authentication. | password |
|
|
66
92
|
| TLS | Encrypted connection (TLS) mode. Disabled by default | 0/1 false/true |
|
|
67
|
-
|
|
|
68
|
-
|
|
|
93
|
+
| CA_CERT | Path to CA cert file. | certs/ca.crt |
|
|
94
|
+
| CERT | Path to cert file. | certs/cert.pem |
|
|
69
95
|
| CERT_KEY | Path to the key file for your certificate. | certs/key.pem |
|
|
70
96
|
|
|
71
|
-
Start the server
|
|
97
|
+
### Start the server
|
|
72
98
|
```bash
|
|
73
99
|
# Development mode
|
|
74
100
|
npm run devserver
|
|
@@ -77,7 +103,8 @@ npm run devserver
|
|
|
77
103
|
npm run server
|
|
78
104
|
```
|
|
79
105
|
|
|
80
|
-
By default, the app runs on port **7633
|
|
106
|
+
By default, the app runs on port **7633** : http://localhost:7633
|
|
107
|
+
|
|
81
108
|
|
|
82
109
|
---
|
|
83
110
|
|
|
@@ -93,10 +120,22 @@ Define schemas using JSON:
|
|
|
93
120
|
{ "name": "name", "type": "string", "required": true },
|
|
94
121
|
{ "name": "price", "type": "number", "required": true },
|
|
95
122
|
{ "name": "stock", "type": "number", "default": 0 },
|
|
96
|
-
{ "name": "category", "type": "relation", "relation": "taxonomy"
|
|
123
|
+
{ "name": "category", "type": "relation", "relation": "taxonomy",
|
|
124
|
+
"relationFilter": { "$eq": ["$type", "category"] }
|
|
125
|
+
},
|
|
126
|
+
{ "name": "tags", "type": "relation", "relation": "taxonomy", "multiple": true,
|
|
127
|
+
"relationFilter": { "$eq": ["$type", "keyword"] }
|
|
128
|
+
}
|
|
97
129
|
]
|
|
98
130
|
}
|
|
99
131
|
```
|
|
132
|
+
### Smart Relations
|
|
133
|
+
- Handles up to 2,000 direct relations
|
|
134
|
+
- For larger datasets, use intermediate collections
|
|
135
|
+
- Automatic indexing on key fields
|
|
136
|
+
- Custom indexing on fields
|
|
137
|
+
- Custom fields :
|
|
138
|
+
|
|
100
139
|
| Type | Description | Properties/Notes |
|
|
101
140
|
|:------------|:------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
|
|
102
141
|
| string | Character string. | minLength, maxLength |
|
|
@@ -124,10 +163,21 @@ Define schemas using JSON:
|
|
|
124
163
|
Activatable features:
|
|
125
164
|
- `mongodb`, `data`, `user`, `workflow`, `file`, `assistant`, `swagger`
|
|
126
165
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
166
|
+
## 🏗️ Use Case Examples
|
|
167
|
+
|
|
168
|
+
### 🛒 E-Commerce Backoffice
|
|
169
|
+
- Install ecommerce-starter pack
|
|
170
|
+
- Add products via API/UI
|
|
171
|
+
- Customize order workflows
|
|
172
|
+
|
|
173
|
+
### 🎫 Support Ticket System
|
|
174
|
+
- Create ticket model with [open, pending, resolved] statuses
|
|
175
|
+
- Configure notification workflows
|
|
176
|
+
- Add custom endpoints or dashboards/kpi for analytics
|
|
177
|
+
|
|
178
|
+
### 🤖 AI Chatbot
|
|
179
|
+
- Define your model
|
|
180
|
+
- Set up workflow: "When new entry → generate AI content"
|
|
131
181
|
|
|
132
182
|
---
|
|
133
183
|
|
|
@@ -297,7 +347,7 @@ await patchData(
|
|
|
297
347
|
);
|
|
298
348
|
```
|
|
299
349
|
|
|
300
|
-
### deleteData(modelName,
|
|
350
|
+
### deleteData(modelName, filter, user)
|
|
301
351
|
|
|
302
352
|
>Deletes data with cascading relation cleanup.
|
|
303
353
|
|
|
@@ -305,13 +355,13 @@ Examples:
|
|
|
305
355
|
|
|
306
356
|
```javascript
|
|
307
357
|
// Delete by IDs
|
|
308
|
-
await deleteData("comments", ["61d1f1a9e3f1a9e3f1a9e3f1"],
|
|
358
|
+
await deleteData("comments", ["61d1f1a9e3f1a9e3f1a9e3f1"], user);
|
|
309
359
|
|
|
310
360
|
// Delete by filter
|
|
311
|
-
await deleteData("logs",
|
|
361
|
+
await deleteData("logs", { createdAt: { $lt: "2023-01-01" } }, user);
|
|
312
362
|
```
|
|
313
363
|
|
|
314
|
-
### searchData(
|
|
364
|
+
### searchData(query, user)
|
|
315
365
|
|
|
316
366
|
Powerful search with relation expansion and filtering.
|
|
317
367
|
|
|
@@ -326,15 +376,12 @@ Query Options:
|
|
|
326
376
|
Example:
|
|
327
377
|
```javascript
|
|
328
378
|
const results = await searchData({
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
sort: "createdAt:DESC"
|
|
336
|
-
}
|
|
337
|
-
});
|
|
379
|
+
model: "blogPost",
|
|
380
|
+
filter: { status: "published" },
|
|
381
|
+
depth: 2, // Expand author and comments
|
|
382
|
+
limit: 10,
|
|
383
|
+
sort: "createdAt:DESC"
|
|
384
|
+
}, user);
|
|
338
385
|
```
|
|
339
386
|
|
|
340
387
|
## Import/Export
|
|
@@ -574,4 +621,4 @@ Distributed under the **MIT License**. See `LICENSE` file.
|
|
|
574
621
|
|
|
575
622
|
---
|
|
576
623
|
|
|
577
|
-
## [🔼](#) Back to Top
|
|
624
|
+
## [🔼](https://github.com/anonympins/data-primals-engine?tab=readme-ov-file#data-primals-engine) Back to Top
|
package/client/src/App.scss
CHANGED
|
@@ -1083,11 +1083,15 @@ h2.shadow {
|
|
|
1083
1083
|
}
|
|
1084
1084
|
|
|
1085
1085
|
.condition-details {
|
|
1086
|
-
padding-left:
|
|
1086
|
+
padding-left: 4px;
|
|
1087
|
+
margin-left:2px;
|
|
1088
|
+
@media only screen and (min-width: 480px) {
|
|
1089
|
+
padding-left: 20px; // Indentation
|
|
1090
|
+
margin-left: 10px;
|
|
1091
|
+
margin-top: 5px;
|
|
1092
|
+
margin-bottom: 10px;
|
|
1093
|
+
}
|
|
1087
1094
|
border-left: 2px solid #eee; // Ligne visuelle
|
|
1088
|
-
margin-left: 10px;
|
|
1089
|
-
margin-top: 5px;
|
|
1090
|
-
margin-bottom: 10px;
|
|
1091
1095
|
gap: 5px; // Espacement entre les éléments de condition
|
|
1092
1096
|
}
|
|
1093
1097
|
|
|
@@ -1290,9 +1294,10 @@ select[multiple]{
|
|
|
1290
1294
|
}
|
|
1291
1295
|
|
|
1292
1296
|
.datalayout {
|
|
1293
|
-
|
|
1297
|
+
@media only screen and (min-width: 480px) {
|
|
1298
|
+
padding: 0 16px;
|
|
1299
|
+
}
|
|
1294
1300
|
}
|
|
1295
|
-
|
|
1296
1301
|
.main-menu {
|
|
1297
1302
|
padding: 16px 0;
|
|
1298
1303
|
@media only screen and (max-width: 479px) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// C:/Dev/hackersonline-engine/client/src/ConditionBuilder.jsx
|
|
2
1
|
|
|
3
2
|
import React, {useState, useEffect, useRef} from 'react';
|
|
4
3
|
import {
|
|
@@ -567,7 +566,6 @@ const ConditionBuilder = ({ initialValue = null, onChange, models, model = null,
|
|
|
567
566
|
setRoot(p);
|
|
568
567
|
onChange(p);
|
|
569
568
|
};
|
|
570
|
-
// C:/Dev/hackersonline-engine/client/src/ConditionBuilder.jsx
|
|
571
569
|
useEffect(() => {
|
|
572
570
|
let parsedValue = {}; // Valeur par défaut si tout échoue
|
|
573
571
|
|
|
@@ -8,6 +8,30 @@ import {FaRepeat} from "react-icons/fa6";
|
|
|
8
8
|
import {useAuthContext} from "./contexts/AuthContext.jsx";
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
// Déterminer si le champ doit être une date
|
|
12
|
+
const isDateArg = (operator, argIndex) => {
|
|
13
|
+
if (!operator) return false;
|
|
14
|
+
|
|
15
|
+
const opConfig = MONGO_CALC_OPERATORS[operator];
|
|
16
|
+
if (!opConfig) {
|
|
17
|
+
console.warn(`Opérateur non trouvé: ${operator}`);
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Cas spécial pour les opérateurs de date
|
|
22
|
+
if (operator === '$dateAdd' || operator === '$dateSubtract') {
|
|
23
|
+
return argIndex === 0; // Seul le premier argument est une date
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Pour les autres opérateurs marqués isDate (comme $hour, $second, etc.)
|
|
27
|
+
if (opConfig.isDate) {
|
|
28
|
+
return true; // Tous les arguments sont des dates pour ces opérateurs
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
11
35
|
const OperatorSelector = ({ onSelect }) => {
|
|
12
36
|
const [search, setSearch] = useState('');
|
|
13
37
|
|
|
@@ -117,10 +141,12 @@ const ExpressionField = ({ value, onChange, path = [], fieldNames, isRoot = fals
|
|
|
117
141
|
setEditing(false);
|
|
118
142
|
};
|
|
119
143
|
|
|
144
|
+
console.log(path);
|
|
145
|
+
console.log(isDateArg(path[path.length - 1]));
|
|
120
146
|
|
|
121
147
|
const renderArgument = (arg, index, parentOperator, args) => {
|
|
122
148
|
const isSimpleValue = typeof arg !== 'object' || arg === null || Array.isArray(arg);
|
|
123
|
-
|
|
149
|
+
const parentOpConfig = MONGO_CALC_OPERATORS[parentOperator];
|
|
124
150
|
// Fonction pour mettre à jour cet argument spécifique
|
|
125
151
|
const handleArgChange = (newArgValue) => {
|
|
126
152
|
const updatedArgs = [...args];
|
|
@@ -148,8 +174,6 @@ const ExpressionField = ({ value, onChange, path = [], fieldNames, isRoot = fals
|
|
|
148
174
|
onChange({ [parentOperator]: updatedArgs }, path);
|
|
149
175
|
}
|
|
150
176
|
};
|
|
151
|
-
const parentOpConfig = MONGO_CALC_OPERATORS[parentOperator];
|
|
152
|
-
|
|
153
177
|
return (
|
|
154
178
|
<div key={`arg-${index}`} className="expression-arg">
|
|
155
179
|
<div className="arg-content">
|
|
@@ -163,10 +187,11 @@ const ExpressionField = ({ value, onChange, path = [], fieldNames, isRoot = fals
|
|
|
163
187
|
updatedArgs[index] = newValue;
|
|
164
188
|
onChange({ [parentOperator]: updatedArgs }, path);
|
|
165
189
|
}}
|
|
190
|
+
isDate={isDateArg(path[path.length - 1], 0)} // Utilis
|
|
166
191
|
fieldNames={fieldNames}
|
|
167
192
|
isInFindContext={isInFindContext}
|
|
168
193
|
/>
|
|
169
|
-
{!parentOpConfig?.disableAdvancedValue && (<button
|
|
194
|
+
{!parentOpConfig?.disableAdvancedValue && !isDateArg(path[path.length -1]) && (<button
|
|
170
195
|
type="button"
|
|
171
196
|
className="switch-to-expr"
|
|
172
197
|
onClick={() => handleArgChange({ $eq: [arg, ""] })}
|
|
@@ -281,6 +306,7 @@ const ExpressionField = ({ value, onChange, path = [], fieldNames, isRoot = fals
|
|
|
281
306
|
onChange={handleFieldChange}
|
|
282
307
|
fieldNames={fieldNames}
|
|
283
308
|
isFieldName={true}
|
|
309
|
+
isDate={isDateArg(path[path.length - 1])}
|
|
284
310
|
currentModelFields={currentModelFields} // Passer les champs complets
|
|
285
311
|
onlyRelations={true}
|
|
286
312
|
/>
|
|
@@ -607,12 +633,13 @@ const ExpressionField = ({ value, onChange, path = [], fieldNames, isRoot = fals
|
|
|
607
633
|
}}
|
|
608
634
|
fieldNames={fieldNames}
|
|
609
635
|
isInFindContext={isInFindContext}
|
|
636
|
+
isDate={isDateArg(path[path.length - 1])}
|
|
610
637
|
currentModelFields={currentModelFields} // On propage le contexte
|
|
611
638
|
/>
|
|
612
639
|
|
|
613
640
|
{/* --- MODIFICATION --- */}
|
|
614
641
|
{/* On affiche le bouton de conversion uniquement si l'opérateur parent le permet */}
|
|
615
|
-
{parentOpConfig?.disableAdvancedValue !== true && (
|
|
642
|
+
{parentOpConfig?.disableAdvancedValue !== true && !isDateArg(path[path.length - 1]) && (
|
|
616
643
|
<button
|
|
617
644
|
type="button"
|
|
618
645
|
className="switch-to-expr"
|
|
@@ -637,11 +664,13 @@ const FieldInput = ({
|
|
|
637
664
|
isFieldName = false,
|
|
638
665
|
isInFindContext = false,
|
|
639
666
|
currentModelFields = [],
|
|
640
|
-
onlyRelations = false
|
|
667
|
+
onlyRelations = false,
|
|
668
|
+
isDate = false
|
|
641
669
|
}) => {
|
|
642
670
|
const [inputValue, setInputValue] = useState(value);
|
|
643
671
|
const [suggestions, setSuggestions] = useState([]);
|
|
644
672
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
673
|
+
const [showDatePicker, setShowDatePicker] = useState(false);
|
|
645
674
|
|
|
646
675
|
useEffect(() => {
|
|
647
676
|
setInputValue(value);
|
|
@@ -685,6 +714,18 @@ const FieldInput = ({
|
|
|
685
714
|
setShowSuggestions(false);
|
|
686
715
|
};
|
|
687
716
|
|
|
717
|
+
// Si c'est un champ date, on affiche le datepicker
|
|
718
|
+
if (isDate) {
|
|
719
|
+
return (
|
|
720
|
+
<div className="date-input-container">
|
|
721
|
+
<input
|
|
722
|
+
type="datetime-local"
|
|
723
|
+
value={inputValue ? new Date(inputValue).toISOString().slice(0, 16) : ''}
|
|
724
|
+
onChange={(e) => handleDateChange(e.target.value)}
|
|
725
|
+
/>
|
|
726
|
+
</div>
|
|
727
|
+
);
|
|
728
|
+
}
|
|
688
729
|
return (
|
|
689
730
|
<div className="field-input-container">
|
|
690
731
|
<input
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// C:/Dev/hackersonline-engine/client/src/pages/ContentView.jsx
|
|
2
1
|
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
|
3
2
|
import {useParams, Link, useLocation } from 'react-router-dom'; // NavLink supprimé car non utilisé
|
|
4
3
|
import { useQuery } from 'react-query';
|
package/client/src/Dashboard.jsx
CHANGED
|
@@ -52,10 +52,6 @@ const getInputType = (fieldType) => {
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
// C:/Dev/hackersonline-engine/client/src/DataEditor.jsx
|
|
56
|
-
// C:/Dev/hackersonline-engine/client/src/DataEditor.jsx
|
|
57
|
-
|
|
58
|
-
|
|
59
55
|
/**
|
|
60
56
|
* Evaluates a single condition against form data.
|
|
61
57
|
* @param {object} currentModelDef - The definition of the current model.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
// C:/Dev/hackersonline-engine/client/src/DocumentationPageLayout.jsx
|
|
2
1
|
import React from 'react';
|
|
3
2
|
import { Outlet } from 'react-router-dom';
|
|
4
3
|
import './DocumentationPageLayout.scss'; // Nous créerons ce fichier SCSS ensuite
|
|
5
|
-
// C:/Dev/hackersonline-engine/client/src/DocumentationMenu.jsx
|
|
6
4
|
import { NavLink } from 'react-router-dom';
|
|
7
5
|
import { useTranslation } from 'react-i18next';
|
|
8
6
|
import { FaChevronDown, FaChevronRight } from 'react-icons/fa';
|
package/client/src/Field.jsx
CHANGED
|
@@ -493,7 +493,7 @@ const CheckboxField = forwardRef(
|
|
|
493
493
|
};
|
|
494
494
|
return (
|
|
495
495
|
<>
|
|
496
|
-
<div className={cn({field: true, "field-checkbox": true})}>
|
|
496
|
+
<div className={cn({field: true, "field-checkbox": true,"field-bg": true})}>
|
|
497
497
|
<div className="inline"><input
|
|
498
498
|
aria-required={required}
|
|
499
499
|
aria-readonly={readOnly}
|
package/client/src/FlexNode.jsx
CHANGED
|
@@ -526,7 +526,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
526
526
|
{/* Colonne de droite: Formulaire du modèle sélectionné */}
|
|
527
527
|
<div className="model-form-container">
|
|
528
528
|
{/* Le formulaire existant est placé ici */}
|
|
529
|
-
<div className="flex">
|
|
529
|
+
<div className="flex field-bg">
|
|
530
530
|
<label htmlFor="modelName"><Trans i18nKey={"modelcreator.name"}>Nom:</Trans></label>
|
|
531
531
|
</div>
|
|
532
532
|
<TextField
|
|
@@ -539,7 +539,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
539
539
|
required
|
|
540
540
|
/>
|
|
541
541
|
|
|
542
|
-
<div className="flex">
|
|
542
|
+
<div className="flex field-bg">
|
|
543
543
|
<label htmlFor="modelDescription"><Trans i18nKey={"modelcreator.description"}>Description:</Trans></label>
|
|
544
544
|
</div>
|
|
545
545
|
<TextField
|
|
@@ -570,7 +570,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
570
570
|
{/* Affichage du formulaire en mode manuel ou édition */}
|
|
571
571
|
{(!useAI || initialModel) && (
|
|
572
572
|
<div className="model-form-container">
|
|
573
|
-
<div className="flex">
|
|
573
|
+
<div className="flex field-bg">
|
|
574
574
|
<label htmlFor="modelName"><Trans i18nKey={"modelcreator.name"}>Nom:</Trans></label>
|
|
575
575
|
</div>
|
|
576
576
|
<TextField
|
|
@@ -583,7 +583,7 @@ const ModelCreator = forwardRef(({ initialPrompt = '', onModelGenerated, autoGen
|
|
|
583
583
|
required
|
|
584
584
|
/>
|
|
585
585
|
|
|
586
|
-
<div className="flex">
|
|
586
|
+
<div className="flex field-bg">
|
|
587
587
|
<label htmlFor="modelDescription"><Trans i18nKey={"modelcreator.description"}>Description:</Trans></label>
|
|
588
588
|
</div>
|
|
589
589
|
<TextField
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
flex: 1;
|
|
3
3
|
max-width: 720px;
|
|
4
4
|
form {
|
|
5
|
+
padding: 0;
|
|
5
6
|
@media only screen and (min-width: 480px){
|
|
6
7
|
padding: 16px;
|
|
7
8
|
}
|
|
@@ -151,4 +152,13 @@
|
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
154
|
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.field-bg {
|
|
158
|
+
background: #fcfcfc;
|
|
159
|
+
background: linear-gradient(180deg, rgba(252, 252, 252, 1) 0%, rgba(242, 242, 242, 1) 55%, rgba(242, 242, 242, 1) 100%);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.mg-item{
|
|
163
|
+
margin: 10px 0;
|
|
154
164
|
}
|