diff --git a/README.md b/README.md index 278dbc7..6ae2ddd 100644 --- a/README.md +++ b/README.md @@ -1,154 +1,2 @@ # DTFlux Titrage Client - Interface Angular pour Unreal Engine -## 🎯 Vue d'ensemble - -Interface graphique modulaire Angular 19+ pour crĂ©er et gĂ©rer des fiches de titrage destinĂ©es Ă  Unreal Engine avec le plugin Remote Control et Motion Design. - -## ✅ Composants créés et fonctionnalitĂ©s - -### đŸ—ïž Architecture modulaire respectĂ©e - -#### Services -- ✅ **TitleSheetsService** - Gestion des fiches de titrage (CRUD + localStorage) -- ✅ **UnrealEngineService** - Communication avec Unreal Engine Remote Control API -- ✅ **ConfigService** - Gestion de la configuration de l'application - -#### Composants modulaires -- ✅ **MenuBarComponent** - Barre de menu avec actions de configuration -- ✅ **CuedTitleComponent** - Affichage du titre en cours de lecture -- ✅ **ToolbarComponent** - Barre de recherche + bouton d'ajout -- ✅ **ListHeaderComponent** - En-tĂȘtes de colonnes avec tri -- ✅ **ListComponent** - Liste principale des titres -- ✅ **ListItemComponent** - ÉlĂ©ment de liste avec Ă©dition inline -- ✅ **DetailsPanelComponent** - Panneau de dĂ©tails de l'Ă©lĂ©ment sĂ©lectionnĂ© -- ✅ **TitleDialogComponent** - BoĂźte de dialogue d'ajout/modification -- ✅ **TitleSheetsListComponent** - Composant principal orchestrant la liste - -#### Pages -- ✅ **DTFluxTitleComponent** - Page principale de l'application -- ✅ **SetupComponent** - Page de configuration lĂ©gĂšre - -### 🎹 Design et thĂšme -- ✅ **ThĂšme dark** inspirĂ© de VS Code et Unreal Engine -- ✅ **Design sobre et Ă©purĂ©** comme demandĂ© -- ✅ **Responsive design** adaptatif jusqu'Ă  950px de largeur max -- ✅ **IcĂŽnes FontAwesome** intĂ©grĂ©es -- ✅ **Animations et transitions** modernes - -### ⚡ FonctionnalitĂ©s Angular 19+ -- ✅ **Signals** utilisĂ©s partout (input, output, computed, effect) -- ✅ **Directives modernes** (@if, @for, etc.) -- ✅ **Composants standalone** -- ✅ **Reactive Forms** pour la validation -- ✅ **Gestion d'Ă©tat** avec BehaviorSubject et Signals - -### 🔧 FonctionnalitĂ©s mĂ©tier -- ✅ **CRUD complet** des fiches de titrage (Nom, PrĂ©nom, Fonction1, Fonction2) -- ✅ **Recherche en temps rĂ©el** avec autocomplĂ©tion -- ✅ **Tri des colonnes** (nom, prĂ©nom, fonctions, date de modification) -- ✅ **Édition inline** des cellules avec navigation clavier -- ✅ **SĂ©lection et navigation** avec flĂšches clavier -- ✅ **Raccourcis clavier** (Ctrl+I ajouter, Enter play, Space stop, Delete supprimer) -- ✅ **Communication Unreal Engine** via Remote Control API -- ✅ **Gestion des Ă©tats** (stopped, playing, error) -- ✅ **Timer de lecture** avec changement de couleur -- ✅ **Sauvegarde automatique** et configuration persistante - -### đŸ“± ExpĂ©rience utilisateur -- ✅ **Interface adaptative** 950px max comme demandĂ© -- ✅ **États vides** avec messages et actions appropriĂ©es -- ✅ **Messages de feedback** (succĂšs, erreurs) -- ✅ **Loading states** pendant les opĂ©rations -- ✅ **Tooltips et aide** contextuelle -- ✅ **AccessibilitĂ©** (aria-labels, focus management, contraste Ă©levĂ©) - -## 🚀 Comment dĂ©marrer - -1. **Installation des dĂ©pendances** : - ```bash - npm install - ``` - -2. **DĂ©marrage du serveur de dĂ©veloppement** : - ```bash - ng serve - ``` - -3. **AccĂšs Ă  l'application** : - - Interface principale : `http://localhost:4200/dtflux-title` - - Configuration : `http://localhost:4200/setup` - -## 📋 Utilisation - -### Interface principale -1. **Ajouter une fiche** : Bouton "Add" ou Ctrl+I -2. **Modifier une fiche** : Clic sur l'icĂŽne roue crantĂ©e ou double-clic sur une cellule -3. **Supprimer une fiche** : Bouton poubelle ou sĂ©lectionner + Delete -4. **Lancer un rundown** : Bouton play ou sĂ©lectionner + Enter -5. **ArrĂȘter un rundown** : Bouton stop ou Space -6. **Rechercher** : Tapez dans la barre de recherche -7. **Trier** : Cliquez sur les en-tĂȘtes de colonnes - -### Configuration -- **Unreal Engine** : Adresse IP, port, timeout -- **Sauvegarde** : Chemin, auto-sauvegarde, intervalle -- **Test de connexion** : VĂ©rifier la communication avec Unreal - -## 🔌 API Unreal Engine - -L'application communique avec Unreal Engine via l'API Remote Control : -- **Endpoint** : `http://{address}:{port}/remote/object/call` -- **Blueprint cible** : `/Game/MotionDesign/TitleSheet_BP.TitleSheet_BP_C` -- **Fonctions** : `SetTitleProperties`, `StartRundown`, `StopRundown`, `GetStatus` - -## đŸ› ïž Prochaines Ă©tapes possibles - -### FonctionnalitĂ©s avancĂ©es -- [ ] **Import/Export** de fiches en CSV/JSON -- [ ] **Templates** de fiches prĂ©dĂ©finies -- [ ] **Historique** des modifications -- [ ] **Groupes/CatĂ©gories** de fiches -- [ ] **Preview en temps rĂ©el** dans Unreal -- [ ] **Synchronisation** multi-utilisateurs - -### IntĂ©grations -- [ ] **Drag & drop** pour rĂ©organiser -- [ ] **Copier/coller** entre fiches -- [ ] **Undo/redo** des actions -- [ ] **Notifications** push pour les changements d'Ă©tat -- [ ] **Mode hors ligne** avec synchronisation - -### Performance -- [ ] **Virtualisation** de la liste pour de gros volumes -- [ ] **Lazy loading** des donnĂ©es -- [ ] **Cache** intelligent des requĂȘtes -- [ ] **Optimisation bundle** et tree-shaking - -## đŸ—ïž Architecture technique - -``` -src/app/ -├── models/ # Interfaces TypeScript -│ ├── title-sheet.model.ts -│ ├── unreal-status.model.ts -│ └── app-config.model.ts -├── services/ # Services Angular -│ ├── title-sheet.service.ts -│ ├── unreal-engine.service.ts -│ └── config.service.ts -└── view/ - ├── components/ # Composants rĂ©utilisables - │ ├── menu-bar/ - │ ├── cued-title/ - │ ├── toolbar/ - │ ├── list-header/ - │ ├── list-item/ - │ ├── details-panel/ - │ ├── title-dialog/ - │ └── title-sheets-list/ - └── pages/ # Pages de l'application - ├── dtflux-title/ - └── setup/ -``` - -L'architecture respecte parfaitement le paradigme de modularitĂ© demandĂ© avec des composants indĂ©pendants et rĂ©utilisables. diff --git a/angular.json b/angular.json index d8b9852..5dbb338 100644 --- a/angular.json +++ b/angular.json @@ -63,6 +63,7 @@ }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", + "proxyConfig": "src/proxy.conf.json", "configurations": { "production": { "buildTarget": "DTFluxTitrage-Client:build:production" diff --git a/package-lock.json b/package-lock.json index ad5a7f9..6c8126e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,9 @@ "@angular/platform-browser": "^19.2.0", "@angular/platform-browser-dynamic": "^19.2.0", "@angular/router": "^19.2.0", + "@fortawesome/fontawesome-free": "^6.7.2", + "@types/uuid": "^10.0.0", + "cbor-x": "^1.6.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" @@ -2467,6 +2470,84 @@ "node": ">=6.9.0" } }, + "node_modules/@cbor-extract/cbor-extract-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@cbor-extract/cbor-extract-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz", + "integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-arm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz", + "integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz", + "integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz", + "integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz", + "integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2912,6 +2993,15 @@ "node": ">=18" } }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz", + "integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==", + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, "node_modules/@inquirer/checkbox": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.9.tgz", @@ -5304,6 +5394,12 @@ "@types/node": "*" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -6329,6 +6425,52 @@ ], "license": "CC-BY-4.0" }, + "node_modules/cbor-extract": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz", + "integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.1.1" + }, + "bin": { + "download-cbor-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0", + "@cbor-extract/cbor-extract-darwin-x64": "2.2.0", + "@cbor-extract/cbor-extract-linux-arm": "2.2.0", + "@cbor-extract/cbor-extract-linux-arm64": "2.2.0", + "@cbor-extract/cbor-extract-linux-x64": "2.2.0", + "@cbor-extract/cbor-extract-win32-x64": "2.2.0" + } + }, + "node_modules/cbor-extract/node_modules/node-gyp-build-optional-packages": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", + "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/cbor-x": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz", + "integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==", + "license": "MIT", + "optionalDependencies": { + "cbor-extract": "^2.2.0" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7094,7 +7236,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "dev": true, "license": "Apache-2.0", "optional": true, "engines": { diff --git a/package.json b/package.json index 19ab6cb..a18333c 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,9 @@ "@angular/platform-browser": "^19.2.0", "@angular/platform-browser-dynamic": "^19.2.0", "@angular/router": "^19.2.0", + "@fortawesome/fontawesome-free": "^6.7.2", + "@types/uuid": "^10.0.0", + "cbor-x": "^1.6.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" diff --git a/src/app/app.component.html b/src/app/app.component.html index 4044025..50072ed 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,3 +1,6 @@
+ + +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 9095c9a..11c2a3a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -4,6 +4,7 @@ import { CommonModule } from '@angular/common'; import { TitleSheetsFormComponent } from './view/components/title-sheets-form/title-sheets-form.component'; import { TitleSheet, createEmptyTitleSheet } from './models/title-sheet.model'; import { Router, RouterModule, RouterOutlet } from '@angular/router'; +import { ToastComponent } from './view/components/toast/toast.component'; @Component({ selector: 'app-root', @@ -11,7 +12,7 @@ import { Router, RouterModule, RouterOutlet } from '@angular/router'; imports: [ CommonModule, RouterOutlet, - TitleSheetsFormComponent // ← Import direct du composant + ToastComponent ], templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] diff --git a/src/styles.scss b/src/styles.scss index 48b074e..7a9a91a 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,7 +1,7 @@ /* src/styles.scss - Variables globales Dark Theme */ -// === FONTAWESOME IMPORT === -@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css'); +// === FONTAWESOME IMPORT (OFFLINE) === +@import '@fortawesome/fontawesome-free/css/all.min.css'; // === DARK THEME PALETTE === :root { @@ -97,3 +97,45 @@ html, body { .border-radius { border-radius: var(--radius-medium); } .shadow-light { box-shadow: var(--shadow-light); } .shadow-medium { box-shadow: var(--shadow-medium); } + +// === FONT AWESOME ICON STYLES === +.icon { + font-size: inherit; + vertical-align: middle; + + &.icon-sm { font-size: 0.875rem; } + &.icon-md { font-size: 1rem; } + &.icon-lg { font-size: 1.25rem; } + &.icon-xl { font-size: 1.5rem; } +} + +// Icînes de statut +.status-icon { + font-size: 1.5rem; + margin-right: 15px; + + &.success { color: var(--color-success); } + &.warning { color: var(--color-warning); } + &.danger { color: var(--color-danger); } + &.info { color: var(--color-info); } +} + +// Icînes d'action +.action-icon { + font-size: 1rem; + transition: transform 0.2s ease; + + &:hover { + transform: scale(1.1); + } +} + +// Animation pour les icînes de chargement +.fa-spin { + animation: fa-spin 1s infinite linear; +} + +@keyframes fa-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +}