Skip to content

Commit 86844da

Browse files
authored
Merge pull request #1547 from rocket-admin/backend_table_settings_fixes
fix: remove 'Enum' widget type and filter out foreign key widgets in table settings
2 parents 02f865a + cbb3f7e commit 86844da

File tree

2 files changed

+159
-31
lines changed

2 files changed

+159
-31
lines changed

backend/src/entities/ai/ai.service.ts

Lines changed: 159 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,36 @@ import { TableInformation } from './ai-data-entities/types/ai-module-types.js';
77
import { TableSettingsEntity } from '../table-settings/common-table-settings/table-settings.entity.js';
88
import { AICoreService, AIProviderType, cleanAIJsonResponse } from '../../ai-core/index.js';
99

10+
interface AIGeneratedWidgetParams {
11+
options?: Array<{ value: string; label: string; background_color?: string }>;
12+
allow_null?: boolean;
13+
unit?: string;
14+
threshold_min?: number;
15+
threshold_max?: number;
16+
height?: number;
17+
prefix?: string;
18+
encrypt?: boolean;
19+
algorithm?: string;
20+
min?: number;
21+
max?: number;
22+
step?: number;
23+
formatDistanceWithinHours?: number;
24+
language?: string;
25+
rows?: number;
26+
invert_colors?: boolean;
27+
validate?: string;
28+
regex?: string;
29+
type?: string;
30+
format?: string;
31+
show_flag?: boolean;
32+
preferred_countries?: string[];
33+
enable_placeholder?: boolean;
34+
phone_validation?: boolean;
35+
version?: string;
36+
namespace?: string;
37+
name?: string;
38+
}
39+
1040
interface AIGeneratedTableSettings {
1141
table_name: string;
1242
display_name: string;
@@ -18,6 +48,7 @@ interface AIGeneratedTableSettings {
1848
widgets: Array<{
1949
field_name: string;
2050
widget_type: string;
51+
widget_params?: AIGeneratedWidgetParams;
2152
name: string;
2253
description: string;
2354
}>;
@@ -106,29 +137,96 @@ For each table, provide:
106137
7. widgets: For each column, suggest the best widget type from: ${widgetTypes}
107138
108139
Available widget types and when to use them:
109-
- Password: for password fields
110-
- Boolean: for boolean/bit columns
111-
- Date: for date columns
112-
- Time: for time-only columns
113-
- DateTime: for datetime/timestamp columns
114-
- JSON: for JSON/JSONB columns
115-
- Textarea: for long text fields (description, content, etc.)
116-
- String: for short text fields (name, title, etc.)
117-
- Readonly: for auto-generated fields
118-
- Number: for numeric columns
119-
- Select: for columns with limited options
120-
- UUID: for UUID columns
121-
- Enum: for enum columns
122-
- Foreign_key: for foreign key columns
123-
- File: for file path columns
124-
- Image: for image URL columns
125-
- URL: for URL columns
126-
- Code: for code snippets
127-
- Phone: for phone number columns
128-
- Country: for country columns
129-
- Color: for color columns (hex values)
130-
- Range: for range values
131-
- Timezone: for timezone columns
140+
141+
PASSWORD WIDGET:
142+
- Use for: password, secret, hash columns
143+
- REQUIRED params: {"encrypt": true, "algorithm": "bcrypt"}
144+
- Algorithms: sha1, sha3, sha224, sha256, sha512, sha384, bcrypt (recommended), scrypt, argon2, pbkdf2
145+
- Detect existing hash by pattern:
146+
* bcrypt: starts with "$2a$", "$2b$", or "$2y$" (60 chars)
147+
* argon2: starts with "$argon2"
148+
* scrypt: starts with "$scrypt$"
149+
* pbkdf2: starts with "$pbkdf2"
150+
* sha1: 40 hex characters
151+
* sha256: 64 hex characters (most common)
152+
* sha512: 128 hex characters
153+
154+
BOOLEAN WIDGET:
155+
- Use for: boolean, bit, tinyint(1) columns, is_*, has_*, can_* columns
156+
- Params: {"allow_null": false, "invert_colors": false}
157+
158+
DATE/TIME WIDGETS:
159+
- Date: for date columns (params: {"formatDistanceWithinHours": 24} - shows "2 hours ago" for recent)
160+
- Time: for time-only columns (no params needed)
161+
- DateTime: for datetime/timestamp columns (params: {"formatDistanceWithinHours": 24})
162+
163+
TEXT WIDGETS:
164+
- String: for short text (name, title, email) - params: {"validate": "isEmail"} for email validation
165+
Validators: isEmail, isURL, isUUID, isAlpha, isNumeric, isMobilePhone, isPostalCode, isCreditCard
166+
- Textarea: for long text (description, content, bio) - params: {"rows": 5}
167+
- JSON: for JSON/JSONB columns (no params needed)
168+
- Code: for code/script columns - params: {"language": "html|css|typescript|yaml|markdown|sql"}
169+
- Readonly: for auto-generated, computed fields (no params needed)
170+
171+
NUMBER WIDGET:
172+
- Use for: int, decimal, float columns
173+
- Params: {"unit": "bytes|meters|seconds|kg", "threshold_min": 0, "threshold_max": 1000}
174+
- Unit examples: bytes, KB, MB, meters, km, seconds, minutes, kg, USD
175+
176+
SELECT WIDGET:
177+
- Use for: status, type, category columns with known/limited values
178+
- REQUIRED params: {"allow_null": true, "options": [{"value": "db_value", "label": "Display Label", "background_color": "#hex"}]}
179+
- Infer options from column name (status: active/inactive, type: user/admin, priority: low/medium/high)
180+
181+
RANGE WIDGET:
182+
- Use for: rating, progress, percentage columns
183+
- Params: {"min": 0, "max": 100, "step": 1}
184+
185+
UUID WIDGET:
186+
- Use for: uuid columns
187+
- Params: {"version": "v4"} - versions: v1, v3, v4 (default), v5, v7
188+
189+
IMAGE WIDGET:
190+
- Use for: avatar, photo, image_url, thumbnail columns
191+
- Params: {"height": 100, "prefix": "https://cdn.example.com/"}
192+
193+
FILE WIDGET:
194+
- Use for: file_path, document, attachment columns
195+
- Params: {"type": "file|hex|base64"}
196+
197+
URL WIDGET:
198+
- Use for: website, link, url columns
199+
- Params: {"prefix": "https://"} if values don't include protocol
200+
201+
PHONE WIDGET:
202+
- Use for: phone, mobile, telephone columns
203+
- Params: {"preferred_countries": ["US", "GB"], "phone_validation": true}
204+
205+
COUNTRY WIDGET:
206+
- Use for: country, country_code columns
207+
- Params: {"show_flag": true, "allow_null": false}
208+
209+
COLOR WIDGET:
210+
- Use for: color, hex_color columns
211+
- Params: {"format": "hex_hash"} - formats: hex, hex_hash, rgb, hsl
212+
213+
TIMEZONE WIDGET:
214+
- Use for: timezone, tz columns
215+
- Params: {"allow_null": false}
216+
217+
FOREIGN_KEY WIDGET:
218+
- Use ONLY for columns that reference another table but are NOT detected as foreign keys
219+
- Skip if foreign key is already detected in table structure
220+
- Params: {"column_name": "user_id", "referenced_table_name": "users", "referenced_column_name": "id"}
221+
222+
WIDGET SELECTION RULES:
223+
1. Match widget type to column data type AND column name semantics
224+
2. For password/hash columns: Always use Password with encrypt:true and detect algorithm from hash pattern
225+
3. For status/type/category columns: Use Select with sensible options inferred from column name
226+
4. For columns ending in _id that aren't foreign keys: Consider Foreign_key widget
227+
5. For columns named email, phone, url, etc.: Use specialized widgets (String with isEmail validator, Phone, URL)
228+
6. For auto_increment or primary key columns: Use Readonly
229+
7. Provide widget_params only when the widget type benefits from configuration
132230
133231
Database tables to analyze:
134232
${tablesDescription}
@@ -146,15 +244,39 @@ Respond ONLY with valid JSON in this exact format (no markdown, no explanations)
146244
"ordering_field": "created_at",
147245
"widgets": [
148246
{
149-
"field_name": "column_name",
247+
"field_name": "id",
248+
"widget_type": "Readonly",
249+
"widget_params": {},
250+
"name": "ID",
251+
"description": "Unique identifier"
252+
},
253+
{
254+
"field_name": "email",
150255
"widget_type": "String",
151-
"name": "Column Display Name",
152-
"description": "Description of what this column contains"
256+
"widget_params": {"validate": "isEmail"},
257+
"name": "Email Address",
258+
"description": "User email for login and communication"
259+
},
260+
{
261+
"field_name": "password_hash",
262+
"widget_type": "Password",
263+
"widget_params": {"encrypt": true, "algorithm": "bcrypt"},
264+
"name": "Password",
265+
"description": "Encrypted user password"
266+
},
267+
{
268+
"field_name": "status",
269+
"widget_type": "Select",
270+
"widget_params": {"options": [{"value": "active", "label": "Active"}, {"value": "inactive", "label": "Inactive"}], "allow_null": true},
271+
"name": "Status",
272+
"description": "Current status of the record"
153273
}
154274
]
155275
}
156276
]
157-
}`;
277+
}
278+
279+
IMPORTANT: For each widget, include appropriate widget_params based on the column name, type, and semantics. Use empty {} for widgets that don't need special configuration.`;
158280
}
159281

160282
private parseAIResponse(aiResponse: string, tablesInformation: Array<TableInformation>): AIResponse {
@@ -189,13 +311,21 @@ Respond ONLY with valid JSON in this exact format (no markdown, no explanations)
189311
settings.table_widgets = tableSettings.widgets
190312
.filter((w) => validColumnNames.includes(w.field_name))
191313
.map((widgetData) => {
314+
const widgetType = this.mapWidgetType(widgetData.widget_type);
315+
if (!widgetType || widgetType === WidgetTypeEnum.Foreign_key) {
316+
return null;
317+
}
192318
const widget = new TableWidgetEntity();
193319
widget.field_name = widgetData.field_name;
194-
widget.widget_type = this.mapWidgetType(widgetData.widget_type);
320+
widget.widget_type = widgetType;
195321
widget.name = widgetData.name;
196322
widget.description = widgetData.description;
323+
if (widgetData.widget_params && Object.keys(widgetData.widget_params).length > 0) {
324+
widget.widget_params = JSON.stringify(widgetData.widget_params);
325+
}
197326
return widget;
198-
});
327+
})
328+
.filter((w): w is TableWidgetEntity => w !== null);
199329

200330
return settings;
201331
});
@@ -225,7 +355,6 @@ Respond ONLY with valid JSON in this exact format (no markdown, no explanations)
225355
['Number', WidgetTypeEnum.Number],
226356
['Select', WidgetTypeEnum.Select],
227357
['UUID', WidgetTypeEnum.UUID],
228-
['Enum', WidgetTypeEnum.Enum],
229358
['Foreign_key', WidgetTypeEnum.Foreign_key],
230359
['File', WidgetTypeEnum.File],
231360
['Image', WidgetTypeEnum.Image],

backend/src/enums/widget-type.enum.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export enum WidgetTypeEnum {
1111
Number = 'Number',
1212
Select = 'Select',
1313
UUID = 'UUID',
14-
Enum = 'Enum',
1514
Foreign_key = 'Foreign_key',
1615
File = 'File',
1716
Image = 'Image',

0 commit comments

Comments
 (0)