diff --git a/src/config/features.json b/src/config/features.json index dc0df2a..e09d901 100644 --- a/src/config/features.json +++ b/src/config/features.json @@ -1,4 +1,330 @@ { + "translations": { + "en": { + "features": { + "database-crud": { + "name": "Database CRUD Operations", + "description": "Create, read, update, and delete database records" + }, + "table-management": { + "name": "Table Management", + "description": "Create and manage database tables" + }, + "column-management": { + "name": "Column Management", + "description": "Add, modify, and delete table columns" + }, + "sql-query": { + "name": "SQL Query Interface", + "description": "Execute custom SQL queries" + }, + "constraint-management": { + "name": "Constraint Management", + "description": "Add and manage table constraints (PRIMARY KEY, UNIQUE, CHECK)" + }, + "query-builder": { + "name": "Query Builder", + "description": "Visual query builder for creating SELECT queries" + }, + "index-management": { + "name": "Index Management", + "description": "Create and manage database indexes for performance optimization" + } + }, + "actions": { + "create": "Create", + "read": "Read", + "update": "Update", + "delete": "Delete", + "add": "Add", + "modify": "Modify", + "execute": "Execute", + "list": "List", + "build": "Build" + }, + "tables": { + "users": { + "name": "Users", + "description": "User accounts and profiles" + }, + "products": { + "name": "Products", + "description": "Product catalog" + } + }, + "columns": { + "id": "ID", + "name": "Name", + "email": "Email", + "created_at": "Created At", + "updated_at": "Updated At" + } + }, + "fr": { + "features": { + "database-crud": { + "name": "Opérations CRUD de base de données", + "description": "Créer, lire, mettre à jour et supprimer des enregistrements de base de données" + }, + "table-management": { + "name": "Gestion des tables", + "description": "Créer et gérer des tables de base de données" + }, + "column-management": { + "name": "Gestion des colonnes", + "description": "Ajouter, modifier et supprimer des colonnes de table" + }, + "sql-query": { + "name": "Interface de requête SQL", + "description": "Exécuter des requêtes SQL personnalisées" + }, + "constraint-management": { + "name": "Gestion des contraintes", + "description": "Ajouter et gérer les contraintes de table (PRIMARY KEY, UNIQUE, CHECK)" + }, + "query-builder": { + "name": "Constructeur de requêtes", + "description": "Constructeur de requêtes visuel pour créer des requêtes SELECT" + }, + "index-management": { + "name": "Gestion des index", + "description": "Créer et gérer des index de base de données pour l'optimisation des performances" + } + }, + "actions": { + "create": "Créer", + "read": "Lire", + "update": "Mettre à jour", + "delete": "Supprimer", + "add": "Ajouter", + "modify": "Modifier", + "execute": "Exécuter", + "list": "Lister", + "build": "Construire" + }, + "tables": { + "users": { + "name": "Utilisateurs", + "description": "Comptes et profils utilisateur" + }, + "products": { + "name": "Produits", + "description": "Catalogue de produits" + } + }, + "columns": { + "id": "ID", + "name": "Nom", + "email": "E-mail", + "created_at": "Créé le", + "updated_at": "Mis à jour le" + } + } + }, + "actions": { + "database-crud": { + "create": "createRecord", + "read": "readRecords", + "update": "updateRecord", + "delete": "deleteRecord" + }, + "table-management": { + "create": "createTable", + "delete": "dropTable" + }, + "column-management": { + "add": "addColumn", + "modify": "modifyColumn", + "delete": "dropColumn" + }, + "sql-query": { + "execute": "executeQuery" + }, + "constraint-management": { + "list": "listConstraints", + "add": "addConstraint", + "delete": "deleteConstraint" + }, + "query-builder": { + "build": "buildQuery", + "execute": "executeBuiltQuery" + }, + "index-management": { + "list": "listIndexes", + "create": "createIndex", + "delete": "deleteIndex" + } + }, + "tableLayouts": { + "users": { + "columns": ["id", "name", "email", "created_at", "updated_at"], + "columnWidths": { + "id": 80, + "name": 200, + "email": 250, + "created_at": 180, + "updated_at": 180 + }, + "defaultSort": { + "column": "created_at", + "direction": "desc" + }, + "hiddenColumns": [], + "frozenColumns": ["id"] + }, + "products": { + "columns": ["id", "name", "price", "stock", "created_at"], + "columnWidths": { + "id": 80, + "name": 250, + "price": 120, + "stock": 100, + "created_at": 180 + }, + "defaultSort": { + "column": "name", + "direction": "asc" + }, + "hiddenColumns": [], + "frozenColumns": ["id"] + } + }, + "columnLayouts": { + "id": { + "align": "left", + "format": "number", + "editable": false + }, + "name": { + "align": "left", + "format": "text", + "editable": true + }, + "email": { + "align": "left", + "format": "email", + "editable": true + }, + "created_at": { + "align": "left", + "format": "datetime", + "editable": false + }, + "updated_at": { + "align": "left", + "format": "datetime", + "editable": false + }, + "price": { + "align": "right", + "format": "currency", + "editable": true + }, + "stock": { + "align": "right", + "format": "number", + "editable": true + } + }, + "tableFeatures": { + "users": { + "enablePagination": true, + "enableSearch": true, + "enableExport": true, + "enableFilters": true, + "rowsPerPage": 25, + "allowedActions": ["create", "read", "update", "delete"] + }, + "products": { + "enablePagination": true, + "enableSearch": true, + "enableExport": true, + "enableFilters": true, + "rowsPerPage": 50, + "allowedActions": ["create", "read", "update", "delete"] + } + }, + "columnFeatures": { + "id": { + "searchable": true, + "sortable": true, + "filterable": true, + "required": true + }, + "name": { + "searchable": true, + "sortable": true, + "filterable": true, + "required": true + }, + "email": { + "searchable": true, + "sortable": true, + "filterable": true, + "required": true, + "validation": "email" + }, + "created_at": { + "searchable": false, + "sortable": true, + "filterable": true, + "required": false + }, + "updated_at": { + "searchable": false, + "sortable": true, + "filterable": true, + "required": false + }, + "price": { + "searchable": true, + "sortable": true, + "filterable": true, + "required": true, + "validation": "number" + }, + "stock": { + "searchable": true, + "sortable": true, + "filterable": true, + "required": true, + "validation": "number" + } + }, + "componentLayouts": { + "DataGrid": { + "headerHeight": 56, + "rowHeight": 48, + "density": "standard", + "showBorders": true, + "alternateRowColors": false, + "hoverHighlight": true + }, + "FormDialog": { + "width": "md", + "fullScreen": false, + "showCloseButton": true, + "disableBackdropClick": false + }, + "ConfirmDialog": { + "width": "sm", + "showCloseButton": true, + "confirmButtonColor": "primary", + "cancelButtonColor": "default" + }, + "Sidebar": { + "width": 240, + "collapsible": true, + "defaultOpen": true, + "variant": "permanent" + }, + "Toolbar": { + "height": 64, + "showSearch": true, + "showUserMenu": true, + "elevation": 2 + } + }, "features": [ { "id": "database-crud", diff --git a/src/utils/featureConfig.test.ts b/src/utils/featureConfig.test.ts index 45cc3de..41a1865 100644 --- a/src/utils/featureConfig.test.ts +++ b/src/utils/featureConfig.test.ts @@ -6,6 +6,17 @@ import { getFeatureById, getFeatures, getNavItems, + getTranslations, + getFeatureTranslation, + getActionTranslation, + getTableTranslation, + getColumnTranslation, + getActionFunctionName, + getTableLayout, + getColumnLayout, + getTableFeatures, + getColumnFeatures, + getComponentLayout, } from './featureConfig'; describe('FeatureConfig', () => { @@ -385,4 +396,286 @@ describe('FeatureConfig', () => { }); }); }); + + describe('getTranslations', () => { + it('should return English translations by default', () => { + const translations = getTranslations(); + + expect(translations).toBeDefined(); + expect(translations).toHaveProperty('features'); + expect(translations).toHaveProperty('actions'); + expect(translations).toHaveProperty('tables'); + expect(translations).toHaveProperty('columns'); + }); + + it('should return French translations when locale is fr', () => { + const translations = getTranslations('fr'); + + expect(translations).toBeDefined(); + expect(translations).toHaveProperty('features'); + expect(translations).toHaveProperty('actions'); + }); + }); + + describe('getFeatureTranslation', () => { + it('should return English translation for database-crud', () => { + const translation = getFeatureTranslation('database-crud', 'en'); + + expect(translation).toBeDefined(); + expect(translation?.name).toBe('Database CRUD Operations'); + expect(translation?.description).toContain('Create, read, update, and delete'); + }); + + it('should return French translation for database-crud', () => { + const translation = getFeatureTranslation('database-crud', 'fr'); + + expect(translation).toBeDefined(); + expect(translation?.name).toBe('Opérations CRUD de base de données'); + }); + + it('should return undefined for non-existent feature', () => { + const translation = getFeatureTranslation('non-existent', 'en'); + + expect(translation).toBeUndefined(); + }); + }); + + describe('getActionTranslation', () => { + it('should return English translation for create action', () => { + const translation = getActionTranslation('create', 'en'); + + expect(translation).toBe('Create'); + }); + + it('should return French translation for create action', () => { + const translation = getActionTranslation('create', 'fr'); + + expect(translation).toBe('Créer'); + }); + + it('should return English translation for delete action', () => { + const translation = getActionTranslation('delete', 'en'); + + expect(translation).toBe('Delete'); + }); + + it('should return French translation for delete action', () => { + const translation = getActionTranslation('delete', 'fr'); + + expect(translation).toBe('Supprimer'); + }); + }); + + describe('getTableTranslation', () => { + it('should return English translation for users table', () => { + const translation = getTableTranslation('users', 'en'); + + expect(translation).toBeDefined(); + expect(translation?.name).toBe('Users'); + expect(translation?.description).toBe('User accounts and profiles'); + }); + + it('should return French translation for users table', () => { + const translation = getTableTranslation('users', 'fr'); + + expect(translation).toBeDefined(); + expect(translation?.name).toBe('Utilisateurs'); + }); + }); + + describe('getColumnTranslation', () => { + it('should return English translation for name column', () => { + const translation = getColumnTranslation('name', 'en'); + + expect(translation).toBe('Name'); + }); + + it('should return French translation for name column', () => { + const translation = getColumnTranslation('name', 'fr'); + + expect(translation).toBe('Nom'); + }); + + it('should return English translation for email column', () => { + const translation = getColumnTranslation('email', 'en'); + + expect(translation).toBe('Email'); + }); + }); + + describe('getActionFunctionName', () => { + it('should return function name for database-crud create action', () => { + const functionName = getActionFunctionName('database-crud', 'create'); + + expect(functionName).toBe('createRecord'); + }); + + it('should return function name for table-management create action', () => { + const functionName = getActionFunctionName('table-management', 'create'); + + expect(functionName).toBe('createTable'); + }); + + it('should return function name for column-management add action', () => { + const functionName = getActionFunctionName('column-management', 'add'); + + expect(functionName).toBe('addColumn'); + }); + + it('should return undefined for non-existent feature', () => { + const functionName = getActionFunctionName('non-existent', 'create'); + + expect(functionName).toBeUndefined(); + }); + }); + + describe('getTableLayout', () => { + it('should return layout configuration for users table', () => { + const layout = getTableLayout('users'); + + expect(layout).toBeDefined(); + expect(layout?.columns).toContain('id'); + expect(layout?.columns).toContain('name'); + expect(layout?.columns).toContain('email'); + expect(layout?.columnWidths).toHaveProperty('id'); + expect(layout?.defaultSort).toHaveProperty('column'); + expect(layout?.defaultSort).toHaveProperty('direction'); + }); + + it('should return layout configuration for products table', () => { + const layout = getTableLayout('products'); + + expect(layout).toBeDefined(); + expect(layout?.columns).toContain('id'); + expect(layout?.columns).toContain('name'); + expect(layout?.defaultSort.column).toBe('name'); + expect(layout?.defaultSort.direction).toBe('asc'); + }); + + it('should return undefined for non-existent table', () => { + const layout = getTableLayout('non-existent'); + + expect(layout).toBeUndefined(); + }); + }); + + describe('getColumnLayout', () => { + it('should return layout configuration for id column', () => { + const layout = getColumnLayout('id'); + + expect(layout).toBeDefined(); + expect(layout?.align).toBe('left'); + expect(layout?.format).toBe('number'); + expect(layout?.editable).toBe(false); + }); + + it('should return layout configuration for email column', () => { + const layout = getColumnLayout('email'); + + expect(layout).toBeDefined(); + expect(layout?.align).toBe('left'); + expect(layout?.format).toBe('email'); + expect(layout?.editable).toBe(true); + }); + + it('should return layout configuration for price column', () => { + const layout = getColumnLayout('price'); + + expect(layout).toBeDefined(); + expect(layout?.align).toBe('right'); + expect(layout?.format).toBe('currency'); + }); + }); + + describe('getTableFeatures', () => { + it('should return features configuration for users table', () => { + const features = getTableFeatures('users'); + + expect(features).toBeDefined(); + expect(features?.enablePagination).toBe(true); + expect(features?.enableSearch).toBe(true); + expect(features?.enableExport).toBe(true); + expect(features?.enableFilters).toBe(true); + expect(features?.rowsPerPage).toBe(25); + expect(features?.allowedActions).toContain('create'); + expect(features?.allowedActions).toContain('read'); + }); + + it('should return features configuration for products table', () => { + const features = getTableFeatures('products'); + + expect(features).toBeDefined(); + expect(features?.rowsPerPage).toBe(50); + }); + + it('should return undefined for non-existent table', () => { + const features = getTableFeatures('non-existent'); + + expect(features).toBeUndefined(); + }); + }); + + describe('getColumnFeatures', () => { + it('should return features configuration for id column', () => { + const features = getColumnFeatures('id'); + + expect(features).toBeDefined(); + expect(features?.searchable).toBe(true); + expect(features?.sortable).toBe(true); + expect(features?.filterable).toBe(true); + expect(features?.required).toBe(true); + }); + + it('should return features configuration for email column with validation', () => { + const features = getColumnFeatures('email'); + + expect(features).toBeDefined(); + expect(features?.validation).toBe('email'); + expect(features?.required).toBe(true); + }); + + it('should return features configuration for created_at column', () => { + const features = getColumnFeatures('created_at'); + + expect(features).toBeDefined(); + expect(features?.searchable).toBe(false); + expect(features?.sortable).toBe(true); + }); + }); + + describe('getComponentLayout', () => { + it('should return layout configuration for DataGrid component', () => { + const layout = getComponentLayout('DataGrid'); + + expect(layout).toBeDefined(); + expect(layout?.headerHeight).toBe(56); + expect(layout?.rowHeight).toBe(48); + expect(layout?.density).toBe('standard'); + expect(layout?.showBorders).toBe(true); + }); + + it('should return layout configuration for FormDialog component', () => { + const layout = getComponentLayout('FormDialog'); + + expect(layout).toBeDefined(); + expect(layout?.width).toBe('md'); + expect(layout?.fullScreen).toBe(false); + expect(layout?.showCloseButton).toBe(true); + }); + + it('should return layout configuration for Sidebar component', () => { + const layout = getComponentLayout('Sidebar'); + + expect(layout).toBeDefined(); + expect(layout?.width).toBe(240); + expect(layout?.collapsible).toBe(true); + expect(layout?.defaultOpen).toBe(true); + }); + + it('should return undefined for non-existent component', () => { + const layout = getComponentLayout('NonExistentComponent'); + + expect(layout).toBeUndefined(); + }); + }); }); diff --git a/src/utils/featureConfig.ts b/src/utils/featureConfig.ts index 6c583fd..9b2dea4 100644 --- a/src/utils/featureConfig.ts +++ b/src/utils/featureConfig.ts @@ -51,8 +51,73 @@ export type IndexType = { description: string; }; +export type Translation = { + name: string; + description: string; +}; + +export type Translations = { + en: { + features: Record; + actions: Record; + tables: Record; + columns: Record; + }; + fr: { + features: Record; + actions: Record; + tables: Record; + columns: Record; + }; +}; + +export type TableLayout = { + columns: string[]; + columnWidths: Record; + defaultSort: { + column: string; + direction: 'asc' | 'desc'; + }; + hiddenColumns: string[]; + frozenColumns: string[]; +}; + +export type ColumnLayout = { + align: 'left' | 'right' | 'center'; + format: string; + editable: boolean; +}; + +export type TableFeatures = { + enablePagination: boolean; + enableSearch: boolean; + enableExport: boolean; + enableFilters: boolean; + rowsPerPage: number; + allowedActions: string[]; +}; + +export type ColumnFeatures = { + searchable: boolean; + sortable: boolean; + filterable: boolean; + required: boolean; + validation?: string; +}; + +export type ComponentLayout = { + [key: string]: any; +}; + // Type definition for the features config structure type FeaturesConfig = { + translations?: Translations; + actions?: Record>; + tableLayouts?: Record; + columnLayouts?: Record; + tableFeatures?: Record; + columnFeatures?: Record; + componentLayouts?: Record; features: Feature[]; dataTypes: DataType[]; constraintTypes?: ConstraintType[]; @@ -99,3 +164,47 @@ export function getEnabledFeaturesByPriority(priority: string): Feature[] { f => f.enabled && f.priority === priority, ); } + +export function getTranslations(locale: 'en' | 'fr' = 'en'): Translations[typeof locale] | undefined { + return config.translations?.[locale]; +} + +export function getFeatureTranslation(featureId: string, locale: 'en' | 'fr' = 'en'): Translation | undefined { + return config.translations?.[locale]?.features[featureId]; +} + +export function getActionTranslation(actionName: string, locale: 'en' | 'fr' = 'en'): string | undefined { + return config.translations?.[locale]?.actions[actionName]; +} + +export function getTableTranslation(tableName: string, locale: 'en' | 'fr' = 'en'): Translation | undefined { + return config.translations?.[locale]?.tables[tableName]; +} + +export function getColumnTranslation(columnName: string, locale: 'en' | 'fr' = 'en'): string | undefined { + return config.translations?.[locale]?.columns[columnName]; +} + +export function getActionFunctionName(featureId: string, actionName: string): string | undefined { + return config.actions?.[featureId]?.[actionName]; +} + +export function getTableLayout(tableName: string): TableLayout | undefined { + return config.tableLayouts?.[tableName]; +} + +export function getColumnLayout(columnName: string): ColumnLayout | undefined { + return config.columnLayouts?.[columnName]; +} + +export function getTableFeatures(tableName: string): TableFeatures | undefined { + return config.tableFeatures?.[tableName]; +} + +export function getColumnFeatures(columnName: string): ColumnFeatures | undefined { + return config.columnFeatures?.[columnName]; +} + +export function getComponentLayout(componentName: string): ComponentLayout | undefined { + return config.componentLayouts?.[componentName]; +}