fix: Correction de l'architecture - modules/ contient uniquement les Dockerfiles
This commit is contained in:
parent
9953a161e6
commit
dbd53136c8
@ -13,9 +13,9 @@ TAG="latest"
|
||||
build_module() {
|
||||
local module=$1
|
||||
local dockerfile=$2
|
||||
|
||||
|
||||
echo "🔨 Construction de $module..."
|
||||
|
||||
|
||||
if [ -f "$dockerfile" ]; then
|
||||
cd modules/$module && docker build -t "$REGISTRY-$module:$TAG" . && cd ../../
|
||||
echo "✅ $module construit avec succès"
|
||||
@ -30,19 +30,11 @@ echo "📦 Construction des modules..."
|
||||
|
||||
# sdk_signer
|
||||
if [ -d "../sdk_signer" ]; then
|
||||
echo "📁 Copie du code sdk_signer depuis docker-support-v2..."
|
||||
echo "🔨 Construction de sdk_signer depuis docker-support-v2..."
|
||||
cd ../sdk_signer
|
||||
git checkout docker-support-v2
|
||||
git pull origin docker-support-v2
|
||||
cd ../4NK_node
|
||||
cp -r ../sdk_signer/* modules/sdk_signer/
|
||||
build_module "sdk_signer" "modules/sdk_signer/Dockerfile"
|
||||
else
|
||||
echo "⚠️ Répertoire sdk_signer non trouvé"
|
||||
fi
|
||||
if [ -d "../sdk_signer" ]; then
|
||||
echo "📁 Copie du code sdk_signer..."
|
||||
cp -r ../sdk_signer/* modules/sdk_signer/
|
||||
build_module "sdk_signer" "modules/sdk_signer/Dockerfile"
|
||||
else
|
||||
echo "⚠️ Répertoire sdk_signer non trouvé"
|
||||
@ -50,8 +42,11 @@ fi
|
||||
|
||||
# sdk_storage
|
||||
if [ -d "../sdk_storage" ]; then
|
||||
echo "📁 Copie du code sdk_storage..."
|
||||
cp -r ../sdk_storage/* modules/sdk_storage/
|
||||
echo "🔨 Construction de sdk_storage depuis docker-support-v2..."
|
||||
cd ../sdk_storage
|
||||
git checkout docker-support-v2
|
||||
git pull origin docker-support-v2
|
||||
cd ../4NK_node
|
||||
build_module "sdk_storage" "modules/sdk_storage/Dockerfile"
|
||||
else
|
||||
echo "⚠️ Répertoire sdk_storage non trouvé"
|
||||
@ -59,22 +54,53 @@ fi
|
||||
|
||||
# ihm_client
|
||||
if [ -d "../ihm_client" ]; then
|
||||
echo "📁 Copie du code ihm_client..."
|
||||
cp -r ../ihm_client/* modules/ihm_client/
|
||||
echo "🔨 Construction de ihm_client depuis docker-support-v2..."
|
||||
cd ../ihm_client
|
||||
git checkout docker-support-v2
|
||||
git pull origin docker-support-v2
|
||||
cd ../4NK_node
|
||||
build_module "ihm_client" "modules/ihm_client/Dockerfile"
|
||||
else
|
||||
echo "⚠️ Répertoire ihm_client non trouvé"
|
||||
fi
|
||||
|
||||
# sdk_relay
|
||||
# sdk_relay1, sdk_relay2, sdk_relay3
|
||||
if [ -d "../sdk_relay" ]; then
|
||||
echo "📁 Copie du code sdk_relay..."
|
||||
cp -r ../sdk_relay/* modules/sdk_relay/
|
||||
build_module "sdk-relay" "modules/sdk_relay/Dockerfile"
|
||||
echo "🔨 Construction des relays depuis docker-support-v2..."
|
||||
cd ../sdk_relay
|
||||
git checkout docker-support-v2
|
||||
git pull origin docker-support-v2
|
||||
cd ../4NK_node
|
||||
|
||||
# Construire les 3 instances de relay
|
||||
for i in 1 2 3; do
|
||||
echo "🔨 Construction de sdk_relay$i..."
|
||||
build_module "sdk_relay$i" "modules/sdk_relay$i/Dockerfile"
|
||||
done
|
||||
else
|
||||
echo "⚠️ Répertoire sdk_relay non trouvé"
|
||||
fi
|
||||
|
||||
# bitcoin
|
||||
echo "🔨 Construction de bitcoin..."
|
||||
build_module "bitcoin" "modules/bitcoin/Dockerfile"
|
||||
|
||||
# blindbit
|
||||
if [ -d "../blindbit" ]; then
|
||||
echo "🔨 Construction de blindbit depuis docker-support-v2..."
|
||||
cd ../blindbit
|
||||
git checkout docker-support-v2
|
||||
git pull origin docker-support-v2
|
||||
cd ../4NK_node
|
||||
build_module "blindbit" "modules/blindbit/Dockerfile"
|
||||
else
|
||||
echo "⚠️ Répertoire blindbit non trouvé"
|
||||
fi
|
||||
|
||||
# tor
|
||||
echo "🔨 Construction de tor..."
|
||||
build_module "tor" "modules/tor/Dockerfile"
|
||||
|
||||
echo "🎉 Construction de tous les modules terminée !"
|
||||
echo ""
|
||||
echo "📋 Images construites :"
|
||||
|
1
modules/bitcoin/Dockerfile
Normal file
1
modules/bitcoin/Dockerfile
Normal file
@ -0,0 +1 @@
|
||||
FROM bitcoin/bitcoin-core:25.0
|
1
modules/blindbit/Dockerfile
Normal file
1
modules/blindbit/Dockerfile
Normal file
@ -0,0 +1 @@
|
||||
FROM rust:1.75-alpine AS builder
|
@ -1,357 +0,0 @@
|
||||
# AGENTS.md - ihm_client
|
||||
|
||||
## Table des matières
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Agents fondamentaux](#agents-fondamentaux)
|
||||
- [Agents spécialisés frontend](#agents-spécialisés-frontend)
|
||||
- [Agents spécialisés WASM](#agents-spécialisés-wasm)
|
||||
- [Agents spécialisés tests](#agents-spécialisés-tests)
|
||||
- [Agents documentation](#agents-documentation)
|
||||
- [Agents open source et CI](#agents-open-source-et-ci)
|
||||
- [Agents complémentaires](#agents-complémentaires)
|
||||
- [Matrice de coordination](#matrice-de-coordination)
|
||||
- [Conclusion](#conclusion)
|
||||
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Ce document définit les agents, leurs rôles et leurs responsabilités dans le projet `ihm_client`.
|
||||
Chaque agent est assigné à un périmètre clair (frontend, WASM, tests, documentation, CI, gouvernance open source).
|
||||
L'objectif est d'assurer une maintenance cohérente de l'interface utilisateur, une traçabilité complète et une exécution fiable des bonnes pratiques.
|
||||
Les règles détaillées de réalisation et de contrôle sont précisées dans `.cursor/rules/`.
|
||||
|
||||
---
|
||||
|
||||
## Agents fondamentaux
|
||||
|
||||
### Agent Fondation
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Garantir que toute production est en français.
|
||||
- Vérifier l'absence d'exemples de code applicatif dans la base de code.
|
||||
- Imposer l'introduction et/ou conclusion dans chaque contenu.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- Tous fichiers.
|
||||
|
||||
---
|
||||
|
||||
### Agent Structure
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir l'arborescence canonique du projet.
|
||||
- Déplacer les documents obsolètes vers `archive/`.
|
||||
- Bloquer toute suppression non documentée.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `archive/`, `docs/`, `tests/`, `.gitea/`, `CHANGELOG.md`.
|
||||
|
||||
---
|
||||
|
||||
## Agents spécialisés frontend
|
||||
|
||||
### Agent Vue.js
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la qualité du code Vue.js.
|
||||
- Assurer la cohérence des composants.
|
||||
- Optimiser les performances de l'interface.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/components/`, `src/pages/`, `src/services/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent TypeScript
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la qualité du code TypeScript.
|
||||
- Assurer la cohérence des types.
|
||||
- Optimiser la compilation TypeScript.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/types/`, `tsconfig.json`, `vite.config.ts`.
|
||||
|
||||
---
|
||||
|
||||
### Agent UI/UX
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la cohérence de l'interface utilisateur.
|
||||
- Assurer l'accessibilité.
|
||||
- Optimiser l'expérience utilisateur.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/components/`, `src/pages/`, `src/assets/`.
|
||||
|
||||
---
|
||||
|
||||
## Agents spécialisés WASM
|
||||
|
||||
### Agent Rust
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la qualité du code Rust.
|
||||
- Assurer la sécurité de la mémoire.
|
||||
- Optimiser les performances WASM.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `temp-deps/sdk_client/`, `temp-deps/sdk_common/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent WASM
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la compilation WASM.
|
||||
- Assurer l'intégration avec le frontend.
|
||||
- Optimiser la taille du bundle WASM.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `pkg/`, `scripts/setup-remote-deps.sh`.
|
||||
|
||||
---
|
||||
|
||||
### Agent Silent Payments
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir l'intégration des Silent Payments.
|
||||
- Assurer la sécurité des transactions.
|
||||
- Optimiser les performances de paiement.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/services/`, `src/types/sdk_client.d.ts`.
|
||||
|
||||
---
|
||||
|
||||
## Agents spécialisés tests
|
||||
|
||||
### Agent Tests Frontend
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la couverture des tests frontend.
|
||||
- Assurer la qualité des tests Vue.js.
|
||||
- Optimiser l'exécution des tests.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `tests/unit/`, `tests/integration/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent Tests WASM
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la couverture des tests WASM.
|
||||
- Assurer la qualité des tests Rust.
|
||||
- Optimiser l'exécution des tests WASM.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `temp-deps/sdk_client/tests/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent Tests E2E
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la couverture des tests end-to-end.
|
||||
- Assurer la qualité des tests d'intégration.
|
||||
- Optimiser l'exécution des tests E2E.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `tests/e2e/`, `tests/performance/`.
|
||||
|
||||
---
|
||||
|
||||
## Agents documentation
|
||||
|
||||
### Agent Documentation
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Mettre à jour les fichiers de `docs/` selon l'impact des changements.
|
||||
- Maintenir `README.md` comme documentation principale.
|
||||
- Produire des REX techniques dans `archive/`.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `docs/`, `README.md`, `CHANGELOG.md`.
|
||||
|
||||
---
|
||||
|
||||
### Agent API Documentation
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la documentation des APIs.
|
||||
- Assurer la cohérence des types TypeScript.
|
||||
- Optimiser la documentation des interfaces.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `docs/API.md`, `src/types/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent User Documentation
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la documentation utilisateur.
|
||||
- Assurer la clarté des guides.
|
||||
- Optimiser l'expérience de lecture.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `docs/USAGE.md`, `docs/INSTALLATION.md`.
|
||||
|
||||
---
|
||||
|
||||
## Agents open source et CI
|
||||
|
||||
### Agent Open Source
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la conformité open source.
|
||||
- Assurer la qualité des licences.
|
||||
- Optimiser la gouvernance open source.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `LICENSE`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`.
|
||||
|
||||
---
|
||||
|
||||
### Agent CI/CD
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la pipeline CI/CD.
|
||||
- Assurer la qualité des builds.
|
||||
- Optimiser l'automatisation.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `.gitea/workflows/`, `scripts/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent Security
|
||||
|
||||
**Rôle (Responsable)** :
|
||||
|
||||
- Maintenir la sécurité du code.
|
||||
- Assurer la qualité des audits de sécurité.
|
||||
- Optimiser la gestion des vulnérabilités.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `SECURITY.md`, `docs/SECURITY_AUDIT.md`.
|
||||
|
||||
---
|
||||
|
||||
## Agents complémentaires
|
||||
|
||||
### Agent Performance
|
||||
|
||||
**Rôle (Consulté)** :
|
||||
|
||||
- Optimiser les performances frontend.
|
||||
- Assurer la qualité des métriques.
|
||||
- Optimiser l'expérience utilisateur.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/`, `dist/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent Accessibility
|
||||
|
||||
**Rôle (Consulté)** :
|
||||
|
||||
- Maintenir l'accessibilité de l'interface.
|
||||
- Assurer la conformité WCAG.
|
||||
- Optimiser l'expérience pour tous les utilisateurs.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/components/`, `src/pages/`.
|
||||
|
||||
---
|
||||
|
||||
### Agent Internationalization
|
||||
|
||||
**Rôle (Consulté)** :
|
||||
|
||||
- Maintenir l'internationalisation.
|
||||
- Assurer la qualité des traductions.
|
||||
- Optimiser l'expérience multilingue.
|
||||
|
||||
**Artefacts :**
|
||||
|
||||
- `src/locales/`, `src/i18n/`.
|
||||
|
||||
---
|
||||
|
||||
## Matrice de coordination
|
||||
|
||||
| Agent | Frontend | WASM | Tests | Docs | CI/CD | Security |
|
||||
|-------|----------|------|-------|------|-------|----------|
|
||||
| **Fondation** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| **Structure** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| **Vue.js** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
|
||||
| **TypeScript** | 🔴 | ⚪ | 🔴 | ⚪ | ⚪ | ⚪ |
|
||||
| **UI/UX** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
|
||||
| **Rust** | ⚪ | 🔴 | ⚪ | ⚪ | ⚪ | 🔴 |
|
||||
| **WASM** | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ |
|
||||
| **Silent Payments** | 🔴 | 🔴 | 🔴 | ⚪ | ⚪ | 🔴 |
|
||||
| **Tests Frontend** | 🔴 | ⚪ | 🔴 | ⚪ | ⚪ | ⚪ |
|
||||
| **Tests WASM** | ⚪ | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ |
|
||||
| **Tests E2E** | 🔴 | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ |
|
||||
| **Documentation** | ⚪ | ⚪ | ⚪ | 🔴 | ⚪ | ⚪ |
|
||||
| **API Documentation** | 🔴 | 🔴 | ⚪ | 🔴 | ⚪ | ⚪ |
|
||||
| **User Documentation** | 🔴 | ⚪ | ⚪ | 🔴 | ⚪ | ⚪ |
|
||||
| **Open Source** | ⚪ | ⚪ | ⚪ | ⚪ | 🔴 | ⚪ |
|
||||
| **CI/CD** | 🔴 | 🔴 | 🔴 | ⚪ | 🔴 | ⚪ |
|
||||
| **Security** | 🔴 | 🔴 | 🔴 | ⚪ | ⚪ | 🔴 |
|
||||
| **Performance** | 🔴 | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ |
|
||||
| **Accessibility** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
|
||||
| **Internationalization** | 🔴 | ⚪ | ⚪ | ⚪ | ⚪ | ⚪ |
|
||||
|
||||
**Légende :**
|
||||
- 🔴 **Responsable** - Agent principal pour ce domaine
|
||||
- ⚪ **Consulté** - Agent consulté si nécessaire
|
||||
- ✅ **Tous** - Applicable à tous les domaines
|
||||
|
||||
## Conclusion
|
||||
|
||||
Cette organisation des agents assure une couverture complète du projet `ihm_client` avec des responsabilités claires et une coordination efficace. Chaque agent contribue à maintenir la qualité, la sécurité et la performance de l'interface utilisateur pour les Silent Payments.
|
||||
|
||||
---
|
||||
|
||||
**Objectif** : Maintenir `ihm_client` comme une interface utilisateur moderne, sécurisée et performante pour les Silent Payments. 🚀
|
@ -1,179 +0,0 @@
|
||||
# Changelog - ihm_client
|
||||
|
||||
Tous les changements notables de ce projet seront documentés dans ce fichier.
|
||||
|
||||
Le format est basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/),
|
||||
et ce projet adhère au [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
## [1.1.0] - 2025-08-26
|
||||
|
||||
### Added
|
||||
- Intégration complète avec l'infrastructure 4NK_node
|
||||
- Compilation WASM réussie avec sdk_client et sdk_common
|
||||
- Interface utilisateur moderne avec Vue.js et TypeScript
|
||||
- Système de notifications en temps réel
|
||||
- Gestion des Silent Payments via WASM
|
||||
- Scanner QR Code intégré
|
||||
- Système de pairing entre utilisateurs
|
||||
- Gestion des documents et signatures
|
||||
- Tests unitaires pour les fonctions de conversion hex
|
||||
- Documentation d'intégration avec 4NK_node
|
||||
- Tests unitaires pour `sp-address.utils` et `html.utils`
|
||||
- Documentation: `docs/API.md`, `docs/TESTING.md`, `docs/CONFIGURATION.md`
|
||||
- Documentation fonctionnelle: `docs/FONCTIONNEL.md` et index mis à jour
|
||||
- Spécification d’intégration iframe: `docs/INTEGRATION_IFRAME.md` et index mis à jour
|
||||
- Tests pour `TokenService` et fallback d’environnement pour tests
|
||||
|
||||
### Changed
|
||||
- Suppression des vues `chat`, `process`, `process-element`, `signature`; routeur limité à `home` et `account`
|
||||
- Nettoyage de `src/main.ts` et `src/utils/notification.store.ts` pour retirer les dépendances aux vues supprimées
|
||||
- Stabilisation des tests unitaires de canal en conditionnant l'émission `LISTENING` au mode E2E en iframe
|
||||
- Documentation mise à jour: `docs/USAGE.md`, `docs/INDEX.md`
|
||||
- Migration vers la branche `docker-support`
|
||||
- Optimisation du build Docker multi-stage
|
||||
- Amélioration des performances de compilation
|
||||
- Modernisation de l'interface utilisateur
|
||||
- Amélioration du script de démarrage pour une meilleure robustesse
|
||||
- Suppression des dépendances critiques pour permettre le démarrage même si certains services ne sont pas prêts
|
||||
- Ajout de vérifications WebSocket pour les relays
|
||||
- `tsconfig.build.json` en module `ES2022` pour supporter `import.meta` et top-level `await`
|
||||
- Import dynamique des services dans `sp-address.utils` pour alléger les tests
|
||||
|
||||
### Fixed
|
||||
- Correction de la configuration Vite pour générer correctement index.html
|
||||
- Suppression de la configuration lib qui causait des conflits
|
||||
- Amélioration de la configuration Jest (moduleNameMapper, transform)
|
||||
- Création de tests unitaires fonctionnels pour les conversions hex
|
||||
- Suppression du fichier de test problématique avec dépendances complexes
|
||||
- Tests de conversion hex passent avec succès (8/8 tests)
|
||||
- Stabilisation des tests Jest (mock `jose`, polyfills Web APIs dans `tests/setup.ts`)
|
||||
- Correction de l’index de documentation (liens API et SSH)
|
||||
|
||||
## [1.0.1] - 2025-08-25
|
||||
|
||||
### Fixed
|
||||
- Correction de la configuration Vite pour générer correctement index.html
|
||||
- Suppression de la configuration lib qui causait des conflits
|
||||
- Amélioration de la configuration Jest (moduleNameMapper, transform)
|
||||
- Création de tests unitaires fonctionnels pour les conversions hex
|
||||
- Suppression du fichier de test problématique avec dépendances complexes
|
||||
- Tests de conversion hex passent avec succès (8/8 tests)
|
||||
|
||||
### Technical
|
||||
- Correction de la configuration build pour éviter les conflits entre lib et application
|
||||
- Amélioration de la configuration Jest pour une meilleure compatibilité
|
||||
- Tests unitaires robustes pour les fonctions de conversion hex
|
||||
- Suppression des dépendances complexes dans les tests
|
||||
|
||||
### Changed
|
||||
- Migration vers la branche `docker-support`
|
||||
- Optimisation du build Docker multi-stage
|
||||
- Amélioration des performances de compilation
|
||||
- Modernisation de l'interface utilisateur
|
||||
- Amélioration du script de démarrage pour une meilleure robustesse
|
||||
- Suppression des dépendances critiques pour permettre le démarrage même si certains services ne sont pas prêts
|
||||
- Ajout de vérifications WebSocket pour les relays
|
||||
|
||||
### Fixed
|
||||
- Correction des erreurs de compilation WASM
|
||||
- Résolution des problèmes de dépendances TypeScript
|
||||
- Correction des imports manquants dans sdk_client
|
||||
- Amélioration de la gestion des erreurs
|
||||
- Correction de la fonction `hexToBlob` pour gérer correctement les types ArrayBuffer
|
||||
- Amélioration de la gestion des erreurs de connexion
|
||||
- Correction des timeouts de démarrage
|
||||
|
||||
### Technical
|
||||
- Ajout de tests pour les fonctions de conversion hex
|
||||
- Mise à jour de la documentation d'intégration
|
||||
- Amélioration des logs de démarrage
|
||||
|
||||
## [1.0.0] - 2025-08-25
|
||||
|
||||
### Added
|
||||
- Interface utilisateur complète pour les Silent Payments
|
||||
- Intégration WASM avec sdk_client et sdk_common
|
||||
- Architecture Vue.js + TypeScript + Vite
|
||||
- Système de routing et navigation
|
||||
- Gestion des profils utilisateurs
|
||||
- Système de pairing avec QR codes
|
||||
- Gestion des processus et documents
|
||||
- Système de signatures électroniques
|
||||
- Chat en temps réel
|
||||
- Notifications push
|
||||
- Gestion des wallets Silent Payments
|
||||
- Interface responsive et moderne
|
||||
|
||||
### Features
|
||||
- **Interface utilisateur** : Vue.js avec TypeScript
|
||||
- **WASM** : Intégration complète avec sdk_client
|
||||
- **Pairing** : Connexion avec QR codes
|
||||
- **Documents** : Gestion et signature
|
||||
- **Chat** : Communication temps réel
|
||||
- **Notifications** : Système de notifications
|
||||
- **Wallet** : Gestion des Silent Payments
|
||||
|
||||
### Technical
|
||||
- Architecture frontend moderne avec Vue.js
|
||||
- Compilation WASM avec Rust et wasm-pack
|
||||
- Build optimisé avec Vite
|
||||
- Docker multi-stage pour la production
|
||||
- Intégration complète avec 4NK_node
|
||||
- Variables d'environnement configurées
|
||||
- Scripts d'automatisation
|
||||
|
||||
## [0.9.0] - 2025-08-20
|
||||
|
||||
### Added
|
||||
- Version initiale de l'interface utilisateur
|
||||
- Configuration de base Vue.js + TypeScript
|
||||
- Premiers composants d'interface
|
||||
- Tests de compilation WASM
|
||||
|
||||
### Changed
|
||||
- Configuration initiale du projet
|
||||
- Premiers tests d'intégration WASM
|
||||
|
||||
### Fixed
|
||||
- Problèmes de compilation TypeScript
|
||||
- Configuration des dépendances
|
||||
|
||||
## [0.8.0] - 2025-08-15
|
||||
|
||||
### Added
|
||||
- Support de l'intégration WASM
|
||||
- Configuration des dépendances distantes
|
||||
- Scripts d'automatisation
|
||||
- Documentation technique
|
||||
|
||||
### Changed
|
||||
- Amélioration de l'architecture WASM
|
||||
- Optimisation des performances
|
||||
|
||||
### Fixed
|
||||
- Correction des problèmes de compilation
|
||||
- Amélioration de la stabilité
|
||||
|
||||
## [0.7.0] - 2025-08-10
|
||||
|
||||
### Added
|
||||
- Support des Silent Payments
|
||||
- Intégration avec sdk_client
|
||||
- Tests de fonctionnalités
|
||||
- Documentation des APIs
|
||||
|
||||
### Changed
|
||||
- Amélioration de l'architecture
|
||||
- Optimisation des performances
|
||||
|
||||
### Fixed
|
||||
- Correction des bugs d'intégration
|
||||
- Amélioration de la stabilité
|
@ -1,93 +0,0 @@
|
||||
# Code de Conduite - ihm_client
|
||||
|
||||
## Notre Engagement
|
||||
|
||||
Dans l'intérêt de favoriser un environnement ouvert et accueillant, nous, en tant que contributeurs et mainteneurs, nous engageons à faire de la participation à notre projet et à notre communauté une expérience sans harcèlement pour tous, peu importe l'âge, la taille, le handicap, l'ethnicité, les caractéristiques sexuelles, l'identité et l'expression de genre, le niveau d'expérience, l'éducation, le statut socio-économique, la nationalité, l'apparence personnelle, la race, la religion ou l'identité et l'orientation sexuelles.
|
||||
|
||||
## Nos Standards
|
||||
|
||||
Exemples de comportements qui contribuent à créer un environnement positif :
|
||||
|
||||
* Utiliser un langage accueillant et inclusif
|
||||
* Respecter les différents points de vue et expériences
|
||||
* Accepter gracieusement les critiques constructives
|
||||
* Se concentrer sur ce qui est le mieux pour la communauté
|
||||
* Faire preuve d'empathie envers les autres membres de la communauté
|
||||
|
||||
Exemples de comportements inacceptables :
|
||||
|
||||
* L'utilisation de langage ou d'imagerie sexualisés et d'attention ou d'avances sexuelles non désirées
|
||||
* Le trolling, les commentaires insultants/désobligeants et les attaques personnelles ou politiques
|
||||
* Le harcèlement public ou privé
|
||||
* Publier les informations privées d'autres personnes, telles que des adresses physiques ou électroniques, sans permission explicite
|
||||
* Autres comportements qui pourraient raisonnablement être considérés comme inappropriés dans un contexte professionnel
|
||||
|
||||
## Nos Responsabilités
|
||||
|
||||
Les mainteneurs du projet sont responsables de clarifier les standards de comportement acceptable et sont censés prendre des mesures correctives appropriées et équitables en réponse à tout cas de comportement inacceptable.
|
||||
|
||||
Les mainteneurs du projet ont le droit et la responsabilité de supprimer, modifier ou rejeter les commentaires, commits, code, modifications de wiki, questions et autres contributions qui ne sont pas alignés avec ce Code de Conduite, et de bannir temporairement ou définitivement tout contributeur pour d'autres comportements qu'ils jugent inappropriés, menaçants, offensants ou nuisibles.
|
||||
|
||||
## Portée
|
||||
|
||||
Ce Code de Conduite s'applique à la fois dans les espaces du projet et dans les espaces publics lorsqu'un individu représente le projet ou sa communauté. Des exemples de représentation du projet ou de la communauté incluent l'utilisation d'une adresse email officielle du projet, la publication via un compte de média social officiel, ou l'action en tant que représentant désigné lors d'un événement en ligne ou hors ligne. La représentation du projet peut être davantage définie et clarifiée par les mainteneurs du projet.
|
||||
|
||||
## Application
|
||||
|
||||
Les cas de comportement abusif, harcelant ou autrement inacceptable peuvent être signalés en contactant l'équipe du projet à contact@4nkweb5.com. Toutes les plaintes seront examinées et enquêtées et se traduiront par une réponse jugée nécessaire et appropriée aux circonstances. L'équipe du projet est obligée de maintenir la confidentialité concernant le rapporteur d'un incident. Plus de détails sur les politiques d'application spécifiques peuvent être publiés séparément.
|
||||
|
||||
Les mainteneurs du projet qui ne suivent pas ou n'appliquent pas le Code de Conduite de bonne foi peuvent faire face à des répercussions temporaires ou permanentes déterminées par d'autres membres de la direction du projet.
|
||||
|
||||
## Attribution
|
||||
|
||||
Ce Code de Conduite est adapté du [Contributor Covenant](https://www.contributor-covenant.org), version 2.0, disponible à https://www.contributor-covenant.org/fr/version/2/0/code_of_conduct.html.
|
||||
|
||||
## Contact
|
||||
|
||||
Pour signaler un problème ou poser des questions concernant ce Code de Conduite, vous pouvez :
|
||||
|
||||
* Créer une issue privée sur le repository
|
||||
* Contacter l'équipe de maintenance via les canaux officiels
|
||||
* Utiliser les canaux de discussion du projet
|
||||
|
||||
## Équipe de Modération
|
||||
|
||||
L'équipe de modération est composée des mainteneurs principaux du projet qui s'engagent à :
|
||||
|
||||
* Traiter tous les signalements avec impartialité
|
||||
* Maintenir la confidentialité des rapports
|
||||
* Prendre des mesures appropriées et équitables
|
||||
* Documenter les décisions prises
|
||||
* Améliorer continuellement le processus
|
||||
|
||||
## Processus de Signalement
|
||||
|
||||
1. **Signalement** : Contactez l'équipe via les canaux appropriés
|
||||
2. **Accusé de réception** : Vous recevrez une confirmation dans les 48h
|
||||
3. **Enquête** : L'équipe examinera le signalement
|
||||
4. **Décision** : Une décision sera prise et communiquée
|
||||
5. **Appel** : Possibilité de faire appel de la décision
|
||||
|
||||
## Mesures Correctives
|
||||
|
||||
Les mesures correctives peuvent inclure :
|
||||
|
||||
* Avertissement privé
|
||||
* Avertissement public
|
||||
* Suspension temporaire
|
||||
* Bannissement permanent
|
||||
* Suppression de contenu inapproprié
|
||||
|
||||
## Engagement envers l'Amélioration
|
||||
|
||||
Nous nous engageons à :
|
||||
|
||||
* Réviser régulièrement ce Code de Conduite
|
||||
* Solliciter les retours de la communauté
|
||||
* Améliorer les processus de modération
|
||||
* Former l'équipe de modération
|
||||
* Maintenir un environnement sain et inclusif
|
||||
|
||||
---
|
||||
|
||||
**Merci de contribuer à maintenir ihm_client comme un projet accueillant et inclusif !** 🌟
|
@ -1,311 +0,0 @@
|
||||
# Guide de Contribution - ihm_client
|
||||
|
||||
Merci de votre intérêt pour contribuer au projet ihm_client ! Ce guide vous aidera à comprendre comment participer au développement de cette interface utilisateur pour les Silent Payments.
|
||||
|
||||
## 📋 Table des Matières
|
||||
|
||||
- [🎯 Comment Contribuer](#-comment-contribuer)
|
||||
- [🚀 Premiers Pas](#-premiers-pas)
|
||||
- [🔧 Environnement de Développement](#️-environnement-de-développement)
|
||||
- [📝 Processus de Contribution](#-processus-de-contribution)
|
||||
- [🧪 Tests](#-tests)
|
||||
- [📚 Documentation](#-documentation)
|
||||
- [🐛 Signaler un Bug](#-signaler-un-bug)
|
||||
- [💡 Proposer une Fonctionnalité](#-proposer-une-fonctionnalité)
|
||||
- [🔍 Code Review](#-code-review)
|
||||
- [📦 Release](#-release)
|
||||
|
||||
## 🎯 Comment Contribuer
|
||||
|
||||
### Types de Contributions
|
||||
|
||||
Nous accueillons différents types de contributions :
|
||||
|
||||
- **🐛 Bug fixes** - Correction de bugs et problèmes
|
||||
- **✨ Nouvelles fonctionnalités** - Ajout de nouvelles capacités
|
||||
- **📚 Documentation** - Amélioration de la documentation
|
||||
- **🧪 Tests** - Ajout ou amélioration des tests
|
||||
- **🔧 Outils** - Amélioration des scripts et outils
|
||||
- **🌐 Traductions** - Traduction de la documentation
|
||||
- **📊 Performance** - Optimisations de performance
|
||||
- **🔒 Sécurité** - Améliorations de sécurité
|
||||
|
||||
### Niveaux de Contribution
|
||||
|
||||
- **Débutant** - Documentation, tests, petits bugs
|
||||
- **Intermédiaire** - Nouvelles fonctionnalités, améliorations UI
|
||||
- **Avancé** - Architecture WASM, optimisations majeures
|
||||
|
||||
## 🚀 Premiers Pas
|
||||
|
||||
### Prérequis
|
||||
|
||||
- **Node.js 18+** et **npm**
|
||||
- **Git** configuré
|
||||
- **Rust** (pour le développement WASM)
|
||||
- **Docker** (pour l'intégration 4NK_node)
|
||||
- **Connexion Internet** stable
|
||||
|
||||
### Fork et Clone
|
||||
|
||||
```bash
|
||||
# 1. Fork le repository sur Gitea
|
||||
# 2. Clone votre fork
|
||||
git clone https://git.4nkweb.com/votre-username/ihm_client.git
|
||||
cd ihm_client
|
||||
|
||||
# 3. Ajouter le repository original comme upstream
|
||||
git remote add upstream https://git.4nkweb.com/4nk/ihm_client.git
|
||||
```
|
||||
|
||||
### Branches
|
||||
|
||||
```bash
|
||||
# Créer une branche pour votre contribution
|
||||
git checkout -b feature/nom-de-votre-feature
|
||||
# ou
|
||||
git checkout -b fix/nom-du-bug
|
||||
```
|
||||
|
||||
## 🔧 Environnement de Développement
|
||||
|
||||
### Installation Locale
|
||||
|
||||
```bash
|
||||
# 1. Cloner le repository
|
||||
git clone https://git.4nkweb.com/4nk/ihm_client.git
|
||||
cd ihm_client
|
||||
|
||||
# 2. Installer les dépendances
|
||||
npm install
|
||||
|
||||
# 3. Configurer les dépendances WASM
|
||||
./scripts/setup-remote-deps.sh
|
||||
|
||||
# 4. Démarrer le serveur de développement
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Configuration de Développement
|
||||
|
||||
```bash
|
||||
# Variables d'environnement pour le développement
|
||||
export NODE_ENV=development
|
||||
export VITE_DEV_SERVER_PORT=3000
|
||||
export VITE_API_URL=http://localhost:8091
|
||||
```
|
||||
|
||||
### Outils de Développement
|
||||
|
||||
```bash
|
||||
# Tests
|
||||
npm run test
|
||||
|
||||
# Build de production
|
||||
npm run build
|
||||
|
||||
# Linting
|
||||
npm run lint
|
||||
|
||||
# Type checking
|
||||
npm run type-check
|
||||
```
|
||||
|
||||
## 📝 Processus de Contribution
|
||||
|
||||
### 1. Préparation
|
||||
|
||||
```bash
|
||||
# Mettre à jour votre branche
|
||||
git checkout main
|
||||
git pull upstream main
|
||||
|
||||
# Créer votre branche de feature
|
||||
git checkout -b feature/votre-feature
|
||||
```
|
||||
|
||||
### 2. Développement
|
||||
|
||||
- Suivez les conventions de code
|
||||
- Écrivez des tests pour les nouvelles fonctionnalités
|
||||
- Mettez à jour la documentation si nécessaire
|
||||
- Vérifiez que les tests passent
|
||||
|
||||
### 3. Commit
|
||||
|
||||
```bash
|
||||
# Ajouter vos changements
|
||||
git add .
|
||||
|
||||
# Créer un commit descriptif
|
||||
git commit -m "feat: ajout de la fonctionnalité X
|
||||
|
||||
- Description détaillée des changements
|
||||
- Impact sur l'interface utilisateur
|
||||
- Tests ajoutés"
|
||||
```
|
||||
|
||||
### 4. Push et Pull Request
|
||||
|
||||
```bash
|
||||
# Pousser votre branche
|
||||
git push origin feature/votre-feature
|
||||
|
||||
# Créer une Pull Request sur Gitea
|
||||
```
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
### Types de Tests
|
||||
|
||||
- **Unit Tests** - Tests des composants individuels
|
||||
- **Integration Tests** - Tests d'intégration WASM
|
||||
- **E2E Tests** - Tests end-to-end de l'interface
|
||||
- **Performance Tests** - Tests de performance
|
||||
|
||||
### Exécution des Tests
|
||||
|
||||
```bash
|
||||
# Tous les tests
|
||||
npm run test
|
||||
|
||||
# Tests unitaires uniquement
|
||||
npm run test:unit
|
||||
|
||||
# Tests d'intégration
|
||||
npm run test:integration
|
||||
|
||||
# Tests avec couverture
|
||||
npm run test:coverage
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Mise à Jour de la Documentation
|
||||
|
||||
- **README.md** - Documentation principale
|
||||
- **docs/** - Documentation technique détaillée
|
||||
- **CHANGELOG.md** - Historique des changements
|
||||
- **API.md** - Documentation des APIs
|
||||
|
||||
### Standards de Documentation
|
||||
|
||||
- Écrire en français
|
||||
- Utiliser des exemples concrets
|
||||
- Inclure des captures d'écran pour l'UI
|
||||
- Maintenir la cohérence du style
|
||||
|
||||
## 🐛 Signaler un Bug
|
||||
|
||||
### Template de Bug Report
|
||||
|
||||
```markdown
|
||||
**Description du bug**
|
||||
Description claire et concise du problème.
|
||||
|
||||
**Étapes pour reproduire**
|
||||
1. Aller à '...'
|
||||
2. Cliquer sur '...'
|
||||
3. Voir l'erreur
|
||||
|
||||
**Comportement attendu**
|
||||
Description de ce qui devrait se passer.
|
||||
|
||||
**Captures d'écran**
|
||||
Si applicable, ajouter des captures d'écran.
|
||||
|
||||
**Environnement**
|
||||
- OS: [ex: Windows 10, macOS, Linux]
|
||||
- Navigateur: [ex: Chrome, Firefox, Safari]
|
||||
- Version: [ex: 1.0.0]
|
||||
|
||||
**Informations supplémentaires**
|
||||
Contexte supplémentaire sur le problème.
|
||||
```
|
||||
|
||||
## 💡 Proposer une Fonctionnalité
|
||||
|
||||
### Template de Feature Request
|
||||
|
||||
```markdown
|
||||
**Problème à résoudre**
|
||||
Description claire du problème que cette fonctionnalité résoudrait.
|
||||
|
||||
**Solution proposée**
|
||||
Description de la solution souhaitée.
|
||||
|
||||
**Alternatives considérées**
|
||||
Autres solutions envisagées.
|
||||
|
||||
**Contexte supplémentaire**
|
||||
Informations supplémentaires, captures d'écran, etc.
|
||||
```
|
||||
|
||||
## 🔍 Code Review
|
||||
|
||||
### Critères de Review
|
||||
|
||||
- **Fonctionnalité** - Le code fait-il ce qu'il doit faire ?
|
||||
- **Qualité** - Le code est-il propre et maintenable ?
|
||||
- **Tests** - Y a-t-il des tests appropriés ?
|
||||
- **Documentation** - La documentation est-elle mise à jour ?
|
||||
- **Performance** - L'impact sur les performances est-il acceptable ?
|
||||
|
||||
### Processus de Review
|
||||
|
||||
1. **Automatique** - Tests et linting
|
||||
2. **Review** - Review par un mainteneur
|
||||
3. **Approbation** - Approbation requise pour merge
|
||||
4. **Merge** - Intégration dans la branche principale
|
||||
|
||||
## 📦 Release
|
||||
|
||||
### Processus de Release
|
||||
|
||||
1. **Préparation** - Mise à jour du CHANGELOG
|
||||
2. **Versioning** - Incrémentation de la version
|
||||
3. **Build** - Build de production
|
||||
4. **Tests** - Tests de validation
|
||||
5. **Tag** - Création du tag de release
|
||||
6. **Déploiement** - Déploiement en production
|
||||
|
||||
### Versioning
|
||||
|
||||
Nous suivons le [Semantic Versioning](https://semver.org/) :
|
||||
|
||||
- **MAJOR** - Changements incompatibles
|
||||
- **MINOR** - Nouvelles fonctionnalités compatibles
|
||||
- **PATCH** - Corrections de bugs compatibles
|
||||
|
||||
## 🤝 Code de Conduite
|
||||
|
||||
### Nos Standards
|
||||
|
||||
- Être respectueux et inclusif
|
||||
- Utiliser un langage accueillant
|
||||
- Accepter les critiques constructives
|
||||
- Se concentrer sur ce qui est le mieux pour la communauté
|
||||
|
||||
### Nos Responsabilités
|
||||
|
||||
- Clarifier les standards de comportement acceptable
|
||||
- Prendre des mesures correctives appropriées
|
||||
- Supprimer, éditer ou rejeter les commentaires inappropriés
|
||||
|
||||
## 📞 Support
|
||||
|
||||
### Obtenir de l'Aide
|
||||
|
||||
- **Issues** - [Git.4nkweb.com](https://git.4nkweb.com/4nk/ihm_client/issues)
|
||||
- **Documentation** - [docs/](docs/)
|
||||
- **Discussions** - [Git.4nkweb.com](https://git.4nkweb.com/4nk/ihm_client)
|
||||
|
||||
### Ressources
|
||||
|
||||
- [Documentation Vue.js](https://vuejs.org/guide/)
|
||||
- [Documentation TypeScript](https://www.typescriptlang.org/docs/)
|
||||
- [Documentation WASM](https://webassembly.org/docs/)
|
||||
|
||||
---
|
||||
|
||||
Merci de contribuer à ihm_client ! 🚀
|
@ -1,53 +0,0 @@
|
||||
# Dockerfile optimisé pour l'intégration dans 4NK_node
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Installation des dépendances système
|
||||
RUN apk update && apk add --no-cache \
|
||||
git \
|
||||
build-base \
|
||||
python3 \
|
||||
make \
|
||||
g++
|
||||
|
||||
# Copie des fichiers de dépendances
|
||||
COPY package*.json ./
|
||||
|
||||
# Installation des dépendances
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Copie du code source
|
||||
COPY . .
|
||||
|
||||
# Build de l'application
|
||||
RUN npm run build
|
||||
|
||||
# Image de production
|
||||
FROM nginx:alpine
|
||||
|
||||
# Installation de Node.js pour les scripts de démarrage
|
||||
RUN apk update && apk add --no-cache nodejs npm
|
||||
|
||||
# Copie des fichiers buildés
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/package*.json /app/
|
||||
|
||||
# Copie de la configuration nginx optimisée pour 4NK_node
|
||||
COPY nginx.4nk-node.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Script de démarrage
|
||||
COPY start-4nk-node.sh /start-4nk-node.sh
|
||||
RUN chmod +x /start-4nk-node.sh
|
||||
|
||||
# Exposition des ports
|
||||
EXPOSE 80 3003
|
||||
|
||||
# Variables d'environnement pour 4NK_node
|
||||
ENV SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
|
||||
ENV SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
|
||||
ENV BITCOIN_RPC_URL=http://bitcoin:18443
|
||||
ENV BLINDBIT_URL=http://blindbit:8000
|
||||
|
||||
# Point d'entrée
|
||||
CMD ["/start-4nk-node.sh"]
|
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 4NK Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,86 +0,0 @@
|
||||
# ihm_client
|
||||
|
||||
Interface utilisateur moderne pour les Silent Payments - Intégrée dans l'infrastructure 4NK_node
|
||||
|
||||
## 🚀 Statut actuel
|
||||
|
||||
**✅ OPÉRATIONNEL ET PRÊT POUR LA PRODUCTION**
|
||||
|
||||
- **Branche** : `docker-support`
|
||||
- **Compilation WASM** : ✅ Réussie
|
||||
- **Compilation TypeScript** : ✅ Réussie
|
||||
- **Intégration 4NK_node** : ✅ Configurée
|
||||
|
||||
## 📋 Fonctionnalités
|
||||
|
||||
### Interface utilisateur
|
||||
- 🌐 **Accueil** - Vue d'ensemble et navigation
|
||||
- 👤 **Compte** - Gestion du profil utilisateur
|
||||
- 📄 **Processus** - Création et gestion des processus
|
||||
- ✍️ **Signature** - Signatures de documents
|
||||
- 💬 **Chat** - Communication entre membres
|
||||
|
||||
### Fonctionnalités techniques
|
||||
- 🔗 **Pairing** - Connexion avec d'autres utilisateurs
|
||||
- 💰 **Wallet** - Gestion des Silent Payments
|
||||
- 📋 **Documents** - Validation et signature
|
||||
- 🔔 **Notifications** - Système temps réel
|
||||
- 📱 **QR Code** - Scanner et génération
|
||||
- ⚡ **WASM** - Intégration complète avec sdk_client
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
- **Frontend** : TypeScript + Vite + Vue.js
|
||||
- **WASM** : Rust + wasm-pack
|
||||
- **Build** : Vite + TypeScript Compiler
|
||||
- **Docker** : Build artefacts dist/ (Nginx géré par 4NK_node)
|
||||
|
||||
## 🔗 Intégration 4NK_node
|
||||
|
||||
L'interface est intégrée dans l'infrastructure 4NK_node et accessible sur :
|
||||
- **URL** : http://localhost:8080
|
||||
- **Service** : `ihm_client` dans docker-compose.yml
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- [Référence rapide](docs/QUICK_REFERENCE.md) - Points d’entrée et commandes
|
||||
- [Intégration iframe](docs/INTEGRATION_IFRAME.md) - Messagerie d’intégration
|
||||
- [Configuration SSH](docs/SSH_USAGE.md) - SSH automatisé
|
||||
- [Architecture](docs/ARCHITECTURE.md) - Architecture technique
|
||||
- [API](docs/API.md) - Documentation des APIs
|
||||
- [Tests E2E](docs/TESTING.md) - Playwright (smoke tests)
|
||||
|
||||
## 🛠️ Développement
|
||||
|
||||
```bash
|
||||
# Installation
|
||||
npm install
|
||||
|
||||
# Développement local
|
||||
npm run dev
|
||||
|
||||
# Build de production
|
||||
npm run build
|
||||
|
||||
# Configuration des dépendances distantes
|
||||
./scripts/setup-remote-deps.sh
|
||||
```
|
||||
|
||||
## 📊 Métriques
|
||||
|
||||
- **WASM** : 3.3 MB
|
||||
- **CSS** : 711 KB (gzippé)
|
||||
- **JavaScript** : 4.5 MB (gzippé)
|
||||
- **Temps de compilation** : ~25s
|
||||
|
||||
## 🎯 Prochaines étapes
|
||||
|
||||
1. Test complet de l'infrastructure 4NK_node
|
||||
2. Validation des fonctionnalités en production
|
||||
3. Optimisation des performances
|
||||
|
||||
---
|
||||
|
||||
**État** : ✅ **PRÊT POUR LA PRODUCTION**
|
||||
**Version** : docker-support
|
||||
**Dernière mise à jour** : 25 août 2025
|
@ -1,217 +0,0 @@
|
||||
# Politique de Sécurité - ihm_client
|
||||
|
||||
## 🛡️ Signalement de Vulnérabilités
|
||||
|
||||
Nous prenons la sécurité très au sérieux. Si vous découvrez une vulnérabilité de sécurité, nous vous demandons de la signaler de manière responsable.
|
||||
|
||||
### Comment Signaler une Vulnérabilité
|
||||
|
||||
**NE PAS** créer d'issue publique pour les vulnérabilités de sécurité.
|
||||
|
||||
**À la place :**
|
||||
1. Envoyez un email à [security@4nkweb.com](mailto:security@4nkweb.com)
|
||||
2. Incluez "SECURITY VULNERABILITY" dans l'objet
|
||||
3. Décrivez la vulnérabilité de manière détaillée
|
||||
4. Incluez les étapes pour reproduire le problème
|
||||
5. Proposez une solution si possible
|
||||
|
||||
### Ce que nous attendons
|
||||
|
||||
- **Confidentialité** : Ne divulguez pas la vulnérabilité publiquement
|
||||
- **Détails** : Fournissez suffisamment d'informations pour reproduire le problème
|
||||
- **Patience** : Nous examinerons et répondrons dans les 48h
|
||||
- **Coopération** : Nous pouvons avoir besoin de clarifications
|
||||
|
||||
### Ce que vous pouvez attendre
|
||||
|
||||
- **Réponse rapide** : Accusé de réception dans les 48h
|
||||
- **Évaluation** : Analyse de la vulnérabilité
|
||||
- **Mise à jour** : Statut de la correction
|
||||
- **Reconnaissance** : Mention dans les remerciements (si souhaité)
|
||||
|
||||
## 🔒 Bonnes Pratiques de Sécurité
|
||||
|
||||
### Pour les Contributeurs
|
||||
|
||||
#### Code Frontend
|
||||
- Validez toutes les entrées utilisateur côté client et serveur
|
||||
- Utilisez des requêtes préparées pour les APIs
|
||||
- Évitez les injections XSS et CSRF
|
||||
- Implémentez l'authentification appropriée
|
||||
- Utilisez HTTPS pour toutes les communications
|
||||
|
||||
#### WASM et Rust
|
||||
- Validez les entrées dans le code Rust
|
||||
- Évitez les vulnérabilités de mémoire
|
||||
- Utilisez des types sûrs
|
||||
- Testez les cas limites
|
||||
- Maintenez les dépendances à jour
|
||||
|
||||
#### Configuration
|
||||
- Ne committez jamais de secrets
|
||||
- Utilisez des variables d'environnement pour les données sensibles
|
||||
- Vérifiez les permissions des fichiers
|
||||
- Maintenez les dépendances à jour
|
||||
|
||||
#### Tests
|
||||
- Incluez des tests de sécurité
|
||||
- Testez les cas limites
|
||||
- Validez les entrées malveillantes
|
||||
- Vérifiez les fuites de mémoire
|
||||
|
||||
### Pour les Utilisateurs
|
||||
|
||||
#### Installation
|
||||
- Utilisez des sources officielles
|
||||
- Vérifiez les checksums
|
||||
- Maintenez le système à jour
|
||||
- Utilisez un pare-feu
|
||||
|
||||
#### Configuration
|
||||
- Changez les mots de passe par défaut
|
||||
- Utilisez des clés SSH fortes
|
||||
- Limitez l'accès réseau
|
||||
- Surveillez les logs
|
||||
|
||||
#### Opération
|
||||
- Surveillez les connexions
|
||||
- Sauvegardez régulièrement
|
||||
- Testez les sauvegardes
|
||||
- Documentez les incidents
|
||||
|
||||
## 🔍 Audit de Sécurité
|
||||
|
||||
### Composants Principaux
|
||||
|
||||
#### Interface Utilisateur (Vue.js)
|
||||
- **Validation** : Validation côté client et serveur
|
||||
- **Authentification** : Gestion sécurisée des sessions
|
||||
- **XSS Protection** : Échappement des données
|
||||
- **CSRF Protection** : Tokens de sécurité
|
||||
|
||||
#### WASM (sdk_client)
|
||||
- **Mémoire** : Gestion sûre de la mémoire
|
||||
- **Entrées** : Validation des paramètres
|
||||
- **Cryptographie** : Utilisation de bibliothèques sûres
|
||||
- **Silent Payments** : Protection des clés privées
|
||||
|
||||
#### Communication
|
||||
- **WebSocket** : Validation des messages
|
||||
- **HTTPS** : Chiffrement des communications
|
||||
- **APIs** : Authentification et autorisation
|
||||
- **CORS** : Configuration sécurisée
|
||||
|
||||
#### Stockage
|
||||
- **Local Storage** : Pas de données sensibles
|
||||
- **Session Storage** : Données temporaires sécurisées
|
||||
- **Cookies** : Configuration sécurisée
|
||||
- **Cache** : Pas d'informations sensibles
|
||||
|
||||
## 🚨 Vulnérabilités Connues
|
||||
|
||||
### Vulnérabilités Résolues
|
||||
|
||||
#### [CVE-2024-XXXX] - Injection XSS
|
||||
- **Statut** : Résolu
|
||||
- **Version** : 1.0.0
|
||||
- **Description** : Vulnérabilité d'injection XSS dans les champs de saisie
|
||||
- **Solution** : Validation et échappement des entrées utilisateur
|
||||
|
||||
#### [CVE-2024-XXXX] - Fuite de Mémoire WASM
|
||||
- **Statut** : Résolu
|
||||
- **Version** : 1.0.0
|
||||
- **Description** : Fuite de mémoire dans le module WASM
|
||||
- **Solution** : Gestion correcte de la mémoire Rust
|
||||
|
||||
### Vulnérabilités Actives
|
||||
|
||||
Aucune vulnérabilité active connue.
|
||||
|
||||
## 🔧 Mesures de Sécurité
|
||||
|
||||
### Authentification
|
||||
|
||||
- **JWT** : Tokens sécurisés avec expiration
|
||||
- **Refresh Tokens** : Rotation automatique
|
||||
- **Multi-Factor** : Support pour l'authentification à deux facteurs
|
||||
- **Session Management** : Gestion sécurisée des sessions
|
||||
|
||||
### Autorisation
|
||||
|
||||
- **RBAC** : Contrôle d'accès basé sur les rôles
|
||||
- **Permissions** : Permissions granulaires
|
||||
- **Audit** : Logs d'audit complets
|
||||
- **Validation** : Validation des permissions côté serveur
|
||||
|
||||
### Chiffrement
|
||||
|
||||
- **HTTPS** : Chiffrement en transit
|
||||
- **WASM** : Chiffrement des données sensibles
|
||||
- **Local Storage** : Chiffrement des données locales
|
||||
- **APIs** : Chiffrement des communications
|
||||
|
||||
### Monitoring
|
||||
|
||||
- **Logs** : Logs de sécurité complets
|
||||
- **Alertes** : Alertes automatiques
|
||||
- **Audit** : Audit de sécurité régulier
|
||||
- **Incidents** : Gestion des incidents de sécurité
|
||||
|
||||
## 📋 Checklist de Sécurité
|
||||
|
||||
### Développement
|
||||
|
||||
- [ ] Validation des entrées utilisateur
|
||||
- [ ] Protection contre XSS
|
||||
- [ ] Protection contre CSRF
|
||||
- [ ] Authentification sécurisée
|
||||
- [ ] Autorisation appropriée
|
||||
- [ ] Chiffrement des données sensibles
|
||||
- [ ] Gestion sûre des erreurs
|
||||
- [ ] Tests de sécurité
|
||||
|
||||
### Déploiement
|
||||
|
||||
- [ ] Configuration HTTPS
|
||||
- [ ] Headers de sécurité
|
||||
- [ ] Variables d'environnement sécurisées
|
||||
- [ ] Permissions de fichiers appropriées
|
||||
- [ ] Monitoring de sécurité
|
||||
- [ ] Sauvegarde sécurisée
|
||||
- [ ] Documentation de sécurité
|
||||
|
||||
### Maintenance
|
||||
|
||||
- [ ] Mise à jour des dépendances
|
||||
- [ ] Audit de sécurité régulier
|
||||
- [ ] Monitoring des vulnérabilités
|
||||
- [ ] Tests de pénétration
|
||||
- [ ] Formation à la sécurité
|
||||
- [ ] Plan de réponse aux incidents
|
||||
|
||||
## 📞 Contact Sécurité
|
||||
|
||||
### Équipe de Sécurité
|
||||
|
||||
- **Email** : [security@4nkweb.com](mailto:security@4nkweb.com)
|
||||
- **PGP** : [Clé publique PGP](https://4nkweb.com/security.asc)
|
||||
- **Signalement** : [Formulaire de signalement](https://4nkweb.com/security)
|
||||
|
||||
### Réponse aux Incidents
|
||||
|
||||
1. **Détection** : Identification de l'incident
|
||||
2. **Containment** : Limitation de l'impact
|
||||
3. **Éradication** : Suppression de la cause
|
||||
4. **Récupération** : Retour à la normale
|
||||
5. **Post-mortem** : Analyse et amélioration
|
||||
|
||||
### Communication
|
||||
|
||||
- **Interne** : Communication avec l'équipe
|
||||
- **Utilisateurs** : Notification des utilisateurs
|
||||
- **Public** : Communication publique si nécessaire
|
||||
- **Autorités** : Notification des autorités si requis
|
||||
|
||||
---
|
||||
|
||||
**La sécurité est une responsabilité partagée. Merci de contribuer à maintenir ihm_client sécurisé !** 🔒
|
@ -1 +0,0 @@
|
||||
v2025.08.5
|
Binary file not shown.
@ -1,43 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
ihm_client:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.4nk-node
|
||||
container_name: 4nk-ihm-client
|
||||
ports:
|
||||
- "8080:80"
|
||||
- "3003:3003"
|
||||
environment:
|
||||
- SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
|
||||
- SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
|
||||
- BITCOIN_RPC_URL=http://bitcoin:18443
|
||||
- BLINDBIT_URL=http://blindbit:8000
|
||||
- NODE_ENV=production
|
||||
volumes:
|
||||
- ihm_client_logs:/var/log/nginx
|
||||
- ihm_client_data:/usr/share/nginx/html/data
|
||||
networks:
|
||||
- btcnet
|
||||
depends_on:
|
||||
- sdk_relay_1
|
||||
- sdk_relay_2
|
||||
- sdk_relay_3
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--timeout=5", "--spider", "http://localhost"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
ihm_client_logs:
|
||||
driver: local
|
||||
ihm_client_data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
btcnet:
|
||||
external: true
|
@ -1,6 +0,0 @@
|
||||
# Intégration des agents 4NK_template
|
||||
|
||||
- Hooks centralisés: pre-commit / pre-push via ../4NK_template (Docker).
|
||||
- Pré-requis: ~/.4nk_template/.env monté en RO dans le conteneur.
|
||||
- Exécution: scripts/local/precommit.sh ou git push (déclenche pre-push).
|
||||
- Rapports: tests/reports/agents/.
|
@ -1,49 +0,0 @@
|
||||
# API - ihm_client
|
||||
|
||||
Ce document décrit les interfaces publiques significatives exposées par l’interface `ihm_client`. Il ne contient aucun exemple d’usage exécutable et sert de référence de contrat.
|
||||
|
||||
## Types et modules principaux
|
||||
|
||||
- Services applicatifs
|
||||
- `src/services/service.ts` (classe `Services`) : opérations d’app, gestion des relays, pairing, processus, stockage, conversions hex/blob.
|
||||
- `src/services/token.ts` (classe `TokenService`) : génération/validation/refresh de jetons de session.
|
||||
- Utilitaires
|
||||
- `src/utils/sp-address.utils.ts` : conversions adresse → empreinte d’emojis, gestion du flux d’affichage, QR code.
|
||||
- `src/utils/html.utils.ts` : résolution du DOM racine ou `shadowRoot`.
|
||||
|
||||
## Contrats clés
|
||||
|
||||
- `Services.getInstance(): Promise<Services>`: retour singleton initialisé.
|
||||
- Pairing et processus
|
||||
- `createPairingProcess(userName: string, pairWith: string[]): Promise<ApiReturn>`
|
||||
- `confirmPairing(): Promise<void>`
|
||||
- `createProcess(...)`, `updateProcess(...)` : gestion des états/processus.
|
||||
- Données chiffrées
|
||||
- `getHashForFile(commitedIn: string, label: string, fileBlob: { type: string; data: Uint8Array }): string`
|
||||
- `getMerkleProofForFile(processState, attributeName): MerkleProofResult`
|
||||
- `validateMerkleProof(proof, hash): boolean`
|
||||
- Conversion binaire
|
||||
- `hexToBlob(hex: string): Blob`
|
||||
- `hexToUInt8Array(hex: string): Uint8Array`
|
||||
- `blobToHex(blob: Blob): Promise<string>`
|
||||
- Tokens
|
||||
- `TokenService.getInstance(): Promise<TokenService>`
|
||||
- `generateSessionToken(origin: string): Promise<{ accessToken: string; refreshToken: string }>`
|
||||
- `validateToken(token: string, origin: string): Promise<boolean>`
|
||||
- `refreshAccessToken(refreshToken: string, origin: string): Promise<string | null>`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Les méthodes de `Services` supposent l’initialisation du module WASM (`pkg/sdk_client`) lors du `init()`.
|
||||
- `TokenService` requiert une clé de signature via `VITE_JWT_SECRET_KEY` (Vite ou environnement Node en test).
|
||||
- Les conversions hex/binaire doivent préserver l’intégrité des octets (longueur paire pour l’hex).
|
||||
|
||||
## Erreurs et retours
|
||||
|
||||
- Les méthodes renvoient des erreurs typées via `throw new Error(message)` si un invariant n’est pas respecté (ex. adresse manquante, état introuvable).
|
||||
- Les fonctions de token retournent `false`/`null` pour les validations/refresh non valides.
|
||||
|
||||
## Compatibilité
|
||||
|
||||
- Environnement navigateur moderne (WebCrypto, `Blob`, `TextEncoder`).
|
||||
- Tests sous Jest avec polyfills contrôlés dans `tests/setup.ts`.
|
@ -1,570 +0,0 @@
|
||||
# 🏗️ Architecture Technique - ihm_client
|
||||
|
||||
Documentation technique détaillée de l'architecture de l'interface utilisateur ihm_client.
|
||||
|
||||
## 📋 Vue d'Ensemble
|
||||
|
||||
### Architecture Générale
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ihm_client │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Frontend (Vue.js + TypeScript) │
|
||||
│ ├── Components Vue.js │
|
||||
│ ├── Services TypeScript │
|
||||
│ ├── Types et Interfaces │
|
||||
│ └── Utilitaires │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ WASM (Rust + sdk_client) │
|
||||
│ ├── Module WebAssembly │
|
||||
│ ├── Fonctions Silent Payments │
|
||||
│ └── Interface JavaScript │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Build System (Vite) │
|
||||
│ ├── Compilation TypeScript │
|
||||
│ ├── Bundling et Optimisation │
|
||||
│ └── Hot Module Replacement │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Stack Technologique
|
||||
|
||||
| Couche | Technologie | Version | Rôle |
|
||||
|--------|-------------|---------|------|
|
||||
| **Frontend** | Vue.js | 3.x | Framework UI |
|
||||
| **Language** | TypeScript | 5.x | Typage statique |
|
||||
| **Build** | Vite | 5.x | Build tool |
|
||||
| **WASM** | Rust | 1.70+ | Logique métier |
|
||||
| **WASM Build** | wasm-pack | 0.12+ | Compilation WASM |
|
||||
| **Styling** | CSS3 | - | Styles |
|
||||
| **Package Manager** | npm | 8.x+ | Gestion dépendances |
|
||||
|
||||
## 🏛️ Architecture Frontend
|
||||
|
||||
### Structure des Composants
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/ # Composants réutilisables
|
||||
│ ├── header/ # En-tête de l'application
|
||||
│ ├── modal/ # Modales et popups
|
||||
│ ├── qrcode-scanner/ # Scanner QR code
|
||||
│ └── validation-modal/ # Modales de validation
|
||||
├── pages/ # Pages de l'application
|
||||
│ ├── home/ # Page d'accueil
|
||||
│ ├── account/ # Gestion du compte
|
||||
│ ├── signature/ # Signatures de documents
|
||||
│ └── process-element/ # Gestion des processus
|
||||
├── services/ # Services et APIs
|
||||
│ ├── service.ts # Service principal
|
||||
│ ├── modal.service.ts # Gestion des modales
|
||||
│ ├── storage.service.ts # Gestion du stockage
|
||||
│ └── token.ts # Gestion des tokens
|
||||
├── types/ # Types TypeScript
|
||||
│ ├── sdk_client.d.ts # Types WASM
|
||||
│ └── raw-imports.d.ts # Types d'imports
|
||||
└── utils/ # Utilitaires
|
||||
├── document.utils.ts # Utilitaires documents
|
||||
├── html.utils.ts # Utilitaires HTML
|
||||
└── sp-address.utils.ts # Utilitaires Silent Payments
|
||||
```
|
||||
|
||||
### Architecture Vue.js
|
||||
|
||||
#### Composants Principaux
|
||||
|
||||
##### Header Component
|
||||
```typescript
|
||||
interface HeaderProps {
|
||||
user: User;
|
||||
notifications: Notification[];
|
||||
onLogout: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
**Responsabilités :**
|
||||
- Navigation principale
|
||||
- Affichage du profil utilisateur
|
||||
- Gestion des notifications
|
||||
- Menu de déconnexion
|
||||
|
||||
##### Modal Components
|
||||
```typescript
|
||||
interface ModalProps {
|
||||
isOpen: boolean;
|
||||
title: string;
|
||||
content: string;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
**Types de modales :**
|
||||
- **Confirmation** : Actions critiques
|
||||
- **Validation** : Validation de données
|
||||
- **QR Scanner** : Scanner de codes QR
|
||||
- **Profile** : Édition du profil
|
||||
|
||||
##### QR Code Scanner
|
||||
```typescript
|
||||
interface QRScannerProps {
|
||||
onScan: (data: string) => void;
|
||||
onError: (error: Error) => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
**Fonctionnalités :**
|
||||
- Accès à la caméra
|
||||
- Détection de QR codes
|
||||
- Validation des données
|
||||
- Gestion des erreurs
|
||||
|
||||
### Services et Communication
|
||||
|
||||
#### Service Principal
|
||||
```typescript
|
||||
class Service {
|
||||
// Communication avec sdk_client WASM
|
||||
async generateWallet(): Promise<Wallet>;
|
||||
async lockUTXOs(wallet: Wallet, utxos: UTXO[]): Promise<boolean>;
|
||||
|
||||
// Communication avec les APIs
|
||||
async sendMessage(message: Message): Promise<void>;
|
||||
async uploadDocument(file: File): Promise<Document>;
|
||||
|
||||
// Gestion des données
|
||||
async saveData(key: string, data: any): Promise<void>;
|
||||
async loadData(key: string): Promise<any>;
|
||||
}
|
||||
```
|
||||
|
||||
#### Gestion des États
|
||||
|
||||
```typescript
|
||||
// Store global (Vuex/Pinia)
|
||||
interface AppState {
|
||||
user: User | null;
|
||||
wallet: Wallet | null;
|
||||
processes: Process[];
|
||||
notifications: Notification[];
|
||||
settings: Settings;
|
||||
}
|
||||
```
|
||||
|
||||
## ⚡ Architecture WASM
|
||||
|
||||
### Module sdk_client
|
||||
|
||||
#### Structure du Module
|
||||
```
|
||||
pkg/
|
||||
├── sdk_client_bg.wasm # Module WASM principal (3.3 MB)
|
||||
├── sdk_client.d.ts # Types TypeScript (12.6 KB)
|
||||
├── sdk_client.js # Wrapper JavaScript (182 B)
|
||||
├── sdk_client_bg.js # Code JavaScript généré (38 KB)
|
||||
└── package.json # Métadonnées du package
|
||||
```
|
||||
|
||||
#### Fonctions Principales
|
||||
|
||||
##### Gestion des Wallets
|
||||
```rust
|
||||
// Rust (sdk_client)
|
||||
pub fn generate_sp_wallet() -> Wallet {
|
||||
// Génération d'un nouveau wallet Silent Payment
|
||||
}
|
||||
|
||||
pub fn lock_freezed_utxos(wallet: Wallet, utxos: Vec<UTXO>) -> bool {
|
||||
// Verrouillage des UTXOs gelés
|
||||
}
|
||||
```
|
||||
|
||||
##### Interface JavaScript
|
||||
```typescript
|
||||
// TypeScript (ihm_client)
|
||||
import { generate_sp_wallet, lock_freezed_utxos } from 'pkg/sdk_client';
|
||||
|
||||
const wallet = generate_sp_wallet();
|
||||
const success = lock_freezed_utxos(wallet, utxos);
|
||||
```
|
||||
|
||||
### Intégration WASM-Frontend
|
||||
|
||||
#### Initialisation
|
||||
```typescript
|
||||
// Initialisation du module WASM
|
||||
import init from 'pkg/sdk_client';
|
||||
|
||||
async function initializeWASM() {
|
||||
try {
|
||||
await init();
|
||||
console.log('WASM module initialized');
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize WASM:', error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Communication
|
||||
```typescript
|
||||
// Appel de fonctions WASM
|
||||
async function createWallet() {
|
||||
try {
|
||||
const wallet = generate_sp_wallet();
|
||||
return wallet;
|
||||
} catch (error) {
|
||||
console.error('WASM error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Architecture Build
|
||||
|
||||
### Configuration Vite
|
||||
|
||||
```typescript
|
||||
// vite.config.ts
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import wasm from 'vite-plugin-wasm';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
wasm(),
|
||||
],
|
||||
optimizeDeps: {
|
||||
exclude: ['pkg/sdk_client']
|
||||
},
|
||||
build: {
|
||||
target: 'es2020',
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
'sdk-client': ['pkg/sdk_client']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Processus de Build
|
||||
|
||||
#### Développement
|
||||
```bash
|
||||
# Serveur de développement
|
||||
npm run dev
|
||||
|
||||
# Hot Module Replacement activé
|
||||
# Compilation TypeScript en temps réel
|
||||
# Chargement WASM à la demande
|
||||
```
|
||||
|
||||
#### Production
|
||||
```bash
|
||||
# Build optimisé
|
||||
npm run build
|
||||
|
||||
# Optimisations :
|
||||
# - Tree shaking
|
||||
# - Code splitting
|
||||
# - Minification
|
||||
# - Compression gzip
|
||||
```
|
||||
|
||||
### Optimisations
|
||||
|
||||
#### Code Splitting
|
||||
```typescript
|
||||
// Chargement à la demande des composants
|
||||
const SignatureComponent = () => import('./pages/signature/signature-component.vue');
|
||||
const AccountComponent = () => import('./pages/account/account-component.vue');
|
||||
```
|
||||
|
||||
#### Lazy Loading WASM
|
||||
```typescript
|
||||
// Chargement différé du module WASM
|
||||
const loadWASM = async () => {
|
||||
if (!wasmModule) {
|
||||
wasmModule = await import('pkg/sdk_client');
|
||||
await wasmModule.default();
|
||||
}
|
||||
return wasmModule;
|
||||
};
|
||||
```
|
||||
|
||||
## 🔄 Flux de Données
|
||||
|
||||
### Flux Principal
|
||||
|
||||
```
|
||||
1. Utilisateur → Interface Vue.js
|
||||
2. Interface → Services TypeScript
|
||||
3. Services → Module WASM (sdk_client)
|
||||
4. WASM → APIs externes (si nécessaire)
|
||||
5. Réponse → Services → Interface → Utilisateur
|
||||
```
|
||||
|
||||
### Gestion des États
|
||||
|
||||
#### État Local (Composants)
|
||||
```typescript
|
||||
// État local d'un composant
|
||||
const componentState = reactive({
|
||||
loading: false,
|
||||
data: null,
|
||||
error: null
|
||||
});
|
||||
```
|
||||
|
||||
#### État Global (Store)
|
||||
```typescript
|
||||
// Store global de l'application
|
||||
const appStore = {
|
||||
user: ref<User | null>(null),
|
||||
wallet: ref<Wallet | null>(null),
|
||||
processes: ref<Process[]>([]),
|
||||
notifications: ref<Notification[]>([])
|
||||
};
|
||||
```
|
||||
|
||||
#### Persistance
|
||||
```typescript
|
||||
// Sauvegarde locale
|
||||
localStorage.setItem('user-data', JSON.stringify(userData));
|
||||
|
||||
// Synchronisation avec le serveur
|
||||
await service.syncData(userData);
|
||||
```
|
||||
|
||||
## 🔒 Architecture de Sécurité
|
||||
|
||||
### Sécurité Frontend
|
||||
|
||||
#### Validation des Entrées
|
||||
```typescript
|
||||
// Validation côté client
|
||||
function validateUserInput(input: string): boolean {
|
||||
return input.length > 0 && input.length < 100;
|
||||
}
|
||||
|
||||
// Sanitisation HTML
|
||||
function sanitizeHTML(html: string): string {
|
||||
return DOMPurify.sanitize(html);
|
||||
}
|
||||
```
|
||||
|
||||
#### Protection XSS
|
||||
```typescript
|
||||
// Échappement des données
|
||||
function escapeHTML(text: string): string {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
```
|
||||
|
||||
### Sécurité WASM
|
||||
|
||||
#### Gestion de la Mémoire
|
||||
```rust
|
||||
// Rust - Gestion sûre de la mémoire
|
||||
pub fn process_data(data: Vec<u8>) -> Result<Vec<u8>, Error> {
|
||||
// Validation des données d'entrée
|
||||
if data.len() > MAX_SIZE {
|
||||
return Err(Error::DataTooLarge);
|
||||
}
|
||||
|
||||
// Traitement sécurisé
|
||||
let result = process_secure(data)?;
|
||||
Ok(result)
|
||||
}
|
||||
```
|
||||
|
||||
#### Protection des Clés
|
||||
```rust
|
||||
// Protection des clés privées
|
||||
pub struct SecureWallet {
|
||||
private_key: SecureString,
|
||||
public_key: String,
|
||||
}
|
||||
|
||||
impl SecureWallet {
|
||||
pub fn new() -> Self {
|
||||
let private_key = generate_secure_key();
|
||||
let public_key = derive_public_key(&private_key);
|
||||
|
||||
Self {
|
||||
private_key: SecureString::new(private_key),
|
||||
public_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Architecture de Performance
|
||||
|
||||
### Métriques de Performance
|
||||
|
||||
#### Temps de Chargement
|
||||
- **Premier rendu** : < 2s
|
||||
- **Interactivité** : < 3s
|
||||
- **Chargement complet** : < 5s
|
||||
|
||||
#### Optimisations
|
||||
|
||||
##### Bundle Size
|
||||
```bash
|
||||
# Taille des bundles
|
||||
dist/
|
||||
├── index.js # ~300 KB (gzippé)
|
||||
├── sdk_client.wasm # ~3.3 MB (gzippé)
|
||||
└── vendor.js # ~200 KB (gzippé)
|
||||
```
|
||||
|
||||
##### Lazy Loading
|
||||
```typescript
|
||||
// Chargement à la demande
|
||||
const routes = [
|
||||
{
|
||||
path: '/signature',
|
||||
component: () => import('./pages/signature.vue')
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
##### Caching
|
||||
```typescript
|
||||
// Cache du module WASM
|
||||
const wasmCache = new Map();
|
||||
|
||||
async function getWASMModule() {
|
||||
if (wasmCache.has('sdk_client')) {
|
||||
return wasmCache.get('sdk_client');
|
||||
}
|
||||
|
||||
const module = await loadWASMModule();
|
||||
wasmCache.set('sdk_client', module);
|
||||
return module;
|
||||
}
|
||||
```
|
||||
|
||||
## 🔍 Monitoring et Observabilité
|
||||
|
||||
### Logs et Debugging
|
||||
|
||||
#### Logs Frontend
|
||||
```typescript
|
||||
// Logging structuré
|
||||
const logger = {
|
||||
info: (message: string, data?: any) => {
|
||||
console.log(`[INFO] ${message}`, data);
|
||||
},
|
||||
error: (message: string, error?: Error) => {
|
||||
console.error(`[ERROR] ${message}`, error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### Logs WASM
|
||||
```rust
|
||||
// Logging Rust
|
||||
use log::{info, error};
|
||||
|
||||
pub fn process_wallet() -> Result<Wallet, Error> {
|
||||
info!("Starting wallet processing");
|
||||
|
||||
match process_secure() {
|
||||
Ok(wallet) => {
|
||||
info!("Wallet processed successfully");
|
||||
Ok(wallet)
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Wallet processing failed: {}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Métriques
|
||||
|
||||
#### Métriques Frontend
|
||||
- **Temps de rendu** : Performance des composants
|
||||
- **Temps de réponse** : Réactivité de l'interface
|
||||
- **Utilisation mémoire** : Consommation RAM
|
||||
- **Erreurs JavaScript** : Stabilité de l'application
|
||||
|
||||
#### Métriques WASM
|
||||
- **Temps d'initialisation** : Chargement du module
|
||||
- **Temps d'exécution** : Performance des fonctions
|
||||
- **Utilisation mémoire** : Gestion de la mémoire
|
||||
- **Erreurs Rust** : Stabilité du module
|
||||
|
||||
## 🚀 Déploiement
|
||||
|
||||
### Environnements
|
||||
|
||||
#### Développement
|
||||
```bash
|
||||
# Serveur de développement
|
||||
npm run dev
|
||||
|
||||
# Variables d'environnement
|
||||
NODE_ENV=development
|
||||
VITE_API_URL=http://localhost:8091
|
||||
VITE_WS_URL=ws://localhost:8090
|
||||
```
|
||||
|
||||
#### Production
|
||||
```bash
|
||||
# Build de production
|
||||
npm run build
|
||||
|
||||
# Variables d'environnement
|
||||
NODE_ENV=production
|
||||
VITE_API_URL=https://api.4nkweb.com
|
||||
VITE_WS_URL=wss://ws.4nkweb.com
|
||||
```
|
||||
|
||||
### Intégration 4NK_node
|
||||
|
||||
#### Artefacts et serveur
|
||||
- Le Dockerfile de `ihm_client` produit uniquement les artefacts `dist/`.
|
||||
- Le serveur (Nginx) est géré par `4NK_node` qui consomme `dist/`.
|
||||
|
||||
#### Variables d'Environnement
|
||||
```bash
|
||||
# Configuration pour 4NK_node
|
||||
SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
|
||||
SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
|
||||
BITCOIN_RPC_URL=http://bitcoin:18443
|
||||
BLINDBIT_URL=http://blindbit:8000
|
||||
```
|
||||
|
||||
## 🔮 Évolutions Futures
|
||||
|
||||
### Améliorations Planifiées
|
||||
|
||||
#### Performance
|
||||
- **Web Workers** : Traitement en arrière-plan
|
||||
- **Service Workers** : Cache et offline
|
||||
- **WebAssembly SIMD** : Optimisations vectorielles
|
||||
|
||||
#### Fonctionnalités
|
||||
- **PWA** : Application web progressive
|
||||
- **Offline Mode** : Fonctionnement hors ligne
|
||||
- **Real-time Sync** : Synchronisation temps réel
|
||||
|
||||
#### Sécurité
|
||||
- **Hardware Security** : Intégration TPM/SE
|
||||
- **Multi-factor Auth** : Authentification à deux facteurs
|
||||
- **Audit Trail** : Traçabilité complète
|
||||
|
||||
---
|
||||
|
||||
**🏗️ Architecture ihm_client - Conçue pour la performance et la sécurité** 🚀
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 1.9 MiB |
@ -1,5 +0,0 @@
|
||||
# Guide de la communauté - ihm_client
|
||||
|
||||
- Comment contribuer (issues, PR, revues)
|
||||
- Standards de code et de documentation
|
||||
- Processus de release et de support
|
@ -1,34 +0,0 @@
|
||||
# Configuration - ihm_client
|
||||
|
||||
Ce document synthétise la configuration de l’application et des outils. Il complète `INSTALLATION.md`.
|
||||
|
||||
## Variables d’environnement
|
||||
|
||||
- Variables Vite (navigateur)
|
||||
- `VITE_API_URL`: URL HTTP du relais/API.
|
||||
- `VITE_WS_URL`: URL WS du relais.
|
||||
- `VITE_WASM_PATH`: chemin vers `pkg/sdk_client_bg.wasm`.
|
||||
- `VITE_JWT_SECRET_KEY`: clé de signature des JWT (utilisée par `TokenService`).
|
||||
- Intégration 4NK_node (serveur géré côté 4NK_node, artefacts `dist/` produits ici)
|
||||
- `SDK_RELAY_WS_URL`, `SDK_RELAY_HTTP_URL`, `BITCOIN_RPC_URL`, `BLINDBIT_URL`.
|
||||
|
||||
## Build
|
||||
|
||||
- Outil: Vite 5 + TypeScript 5.
|
||||
- Ciblage: `es2020`+.
|
||||
- WASM: `vite-plugin-wasm`, bundle différé conseillé.
|
||||
|
||||
## Tests
|
||||
|
||||
- Jest 29 + `ts-jest`.
|
||||
- `tests/setup.ts` injecte polyfills et mocks.
|
||||
|
||||
## Résolution des modules
|
||||
|
||||
- Aliases: `~/*` → `src/*` (cf. `tsconfig.json`).
|
||||
- Mapper: `jest.config.js` mappe `pkg/` vers `pkg/` local.
|
||||
|
||||
## CI/CD
|
||||
|
||||
- Étapes minimales: install, tests, build, artefacts.
|
||||
- Audit dépendances à intégrer selon politique sécurité.
|
@ -1,99 +0,0 @@
|
||||
# Documentation fonctionnelle - ihm_client
|
||||
|
||||
Cette documentation décrit ce que fait fonctionnellement l’interface `ihm_client`, les parcours utilisateurs, les règles de gestion et les contraintes associées. Aucun exemple de code applicatif n’est inclus.
|
||||
|
||||
## Objectif produit
|
||||
|
||||
- Proposer une interface moderne pour la gestion de processus collaboratifs autour des Silent Payments.
|
||||
- Faciliter le pairing sécurisé entre appareils/utilisateurs et la gestion des transactions associées.
|
||||
- Offrir un espace unifié pour la gestion des membres, documents, signatures et échanges (chat/notifications).
|
||||
|
||||
## Personas et rôles
|
||||
|
||||
- Utilisateur standard: initie/participe à des processus, signe des documents, échange des messages.
|
||||
- Administrateur de processus: configure les rôles, vérifie les validations, déclenche des mises à jour.
|
||||
- Observateur (lecture seule): consulte les informations publiques/partagées sans intervenir.
|
||||
|
||||
## Parcours principaux
|
||||
|
||||
### Accueil
|
||||
- Accès rapide aux sections clés (Compte, Processus, Signature, Chat, Pairing).
|
||||
- Indicateurs d’activité: processus actifs, notifications récentes, métriques succinctes.
|
||||
|
||||
### Pairing (mise en relation)
|
||||
- Objectif: établir une relation de confiance entre appareils via adresse Silent Payment.
|
||||
- Étapes:
|
||||
1. Saisir ou scanner l’adresse SP distante (ou URL contenant `sp_address`).
|
||||
2. Vérifier l’empreinte visuelle (emojis) dérivée de l’adresse pour confirmer l’identité.
|
||||
3. Créer et confirmer le processus de pairing (flux guidé, confirmation finale).
|
||||
- Résultat: l’appareil local est appairé; les échanges sécurisés sont possibles.
|
||||
|
||||
### Wallet et relays
|
||||
- Visualiser l’état du wallet (montant disponible, synchro via relays).
|
||||
- Interagir avec le réseau via relays (mise à jour des membres/états, échange de messages techniques).
|
||||
- Disposer d’un mécanisme de “faucet” en environnement de test pour provisionner le wallet.
|
||||
|
||||
### Processus
|
||||
- Créer un nouveau processus (données publiques et privées, rôles, règles de validation).
|
||||
- Mettre à jour un processus existant (évolution des états, validations, preuves).
|
||||
- Consulter l’historique (états validés, états en attente/non committés).
|
||||
|
||||
### Membres et rôles
|
||||
- Gérer les membres impliqués (par adresse SP).
|
||||
- Définir des rôles et règles de validation (quorum, champs soumis à contrôle, seuils).
|
||||
- Vérifier l’appartenance de l’utilisateur à un rôle (autorisation implicite des actions).
|
||||
|
||||
### Documents et signatures
|
||||
- Associer des documents aux processus (hashés et stockés via mécanismes dédiés).
|
||||
- Déclencher des demandes de signature, suivre leur statut (en attente, signé, expiré).
|
||||
- Vérifier/valider les preuves (ex. Merkle) liées aux documents échangés.
|
||||
|
||||
### Chat et notifications
|
||||
- Échanger des messages dans le contexte des processus.
|
||||
- Recevoir des notifications liées aux événements (nouvelle transaction, demande de signature, mise à jour de processus).
|
||||
|
||||
## Règles de gestion clés
|
||||
|
||||
- Pairing
|
||||
- Une empreinte visuelle (emojis) dérivée de l’adresse SP aide à la confirmation utilisateur.
|
||||
- Un processus de pairing doit inclure l’adresse de l’appareil local.
|
||||
- Validation
|
||||
- Les règles de validation (quorum, seuils) s’appliquent aux champs déclarés.
|
||||
- Une mise à jour de processus peut être refusée si les preuves/validations sont insuffisantes.
|
||||
- Données
|
||||
- Les données volumineuses (blobs) sont stockées séparément et référencées par hash.
|
||||
- Les attributs chiffrés nécessitent clés/permissions pour être déchiffrés.
|
||||
- Sécurité
|
||||
- Les échanges sont consolidés via relays; l’appairage conditionne l’accès aux données privées.
|
||||
- Les tokens de session sont temporaires et régénérables (Access/Refresh).
|
||||
|
||||
## Contraintes et limites
|
||||
|
||||
- Dépendance au module WASM pour les opérations de bas niveau (Silent Payments, encodages, preuves).
|
||||
- Nécessité d’un ou plusieurs relays disponibles pour la synchronisation et l’échange d’informations.
|
||||
- Performance dépendant du contexte (navigateur, réseau, taille des données).
|
||||
|
||||
## Indicateurs et métriques
|
||||
|
||||
- Disponibilité des relays et latence observée.
|
||||
- État de synchronisation (hauteur de bloc, mises à jour reçues).
|
||||
- Taille et temps de manipulation des documents.
|
||||
- Taux de succès des signatures et validations.
|
||||
|
||||
## Gestion des erreurs et non-régression
|
||||
|
||||
- Messages d’erreur explicites pour états manquants, adresses invalides, clés indisponibles, connexions relays.
|
||||
- Tests unitaires couvrant conversions (hex/blob), DOM utilitaire et tokens.
|
||||
- Stratégie de test documentée (voir `docs/TESTING.md`).
|
||||
|
||||
## Confidentialité et conformité
|
||||
|
||||
- Pas de stockage permanent de secrets en clair côté client.
|
||||
- Utilisation stricte de variables d’environnement pour les secrets runtime.
|
||||
- Revue régulière des dépendances et audits sécurité (voir `docs/SECURITY_AUDIT.md`).
|
||||
|
||||
## Support et usage
|
||||
|
||||
- Guides d’installation et d’utilisation (voir `docs/INSTALLATION.md`, `docs/USAGE.md`).
|
||||
- Référentiel contractuel des API (voir `docs/API.md`).
|
||||
- Intégration dans un site via iframe (voir `docs/INTEGRATION_IFRAME.md`).
|
@ -1,17 +0,0 @@
|
||||
# Configuration Gitea - ihm_client
|
||||
|
||||
## Repository
|
||||
- Création du dépôt sur `git.4nkweb.com`
|
||||
- Droits d’écriture/lecture selon rôle
|
||||
|
||||
## SSH
|
||||
- Ajout de la clé dans Settings > SSH Keys
|
||||
- Scripts: `scripts/init-ssh-env.sh`, `scripts/auto-ssh-push.sh`
|
||||
|
||||
## CI/CD
|
||||
- Workflows dans `.gitea/workflows/` (à définir selon pipeline)
|
||||
- Politique de branche: protection de `main`/`docker-support`
|
||||
|
||||
## Permissions
|
||||
- Maintainers: merge + tags
|
||||
- Contributeurs: PRs avec validation
|
@ -1,219 +0,0 @@
|
||||
# 📚 Index de Documentation - ihm_client
|
||||
|
||||
Index complet de la documentation de l'interface utilisateur ihm_client pour les Silent Payments.
|
||||
|
||||
## 📖 Guides Principaux
|
||||
|
||||
### 🚀 [Guide d'Installation](INSTALLATION.md)
|
||||
Guide complet pour installer et configurer l'interface utilisateur ihm_client.
|
||||
- **Prérequis système et logiciels**
|
||||
- **Installation de Node.js et dépendances**
|
||||
- **Configuration Rust et WASM**
|
||||
- **Configuration des dépendances distantes**
|
||||
- **Tests post-installation**
|
||||
- **Dépannage et monitoring**
|
||||
|
||||
### 📖 [Guide d'Utilisation](USAGE.md)
|
||||
### 🧭 [Documentation fonctionnelle](FONCTIONNEL.md)
|
||||
Description fonctionnelle complète (parcours, règles de gestion, contraintes).
|
||||
Guide complet pour utiliser l'interface utilisateur ihm_client au quotidien.
|
||||
- **Démarrage du serveur de développement**
|
||||
- **Utilisation de l'interface utilisateur**
|
||||
- **Navigation Accueil et Compte**
|
||||
- **Opérations de pairing et wallet**
|
||||
- **Tests et validation**
|
||||
|
||||
### ⚙️ [Guide de Configuration](CONFIGURATION.md)
|
||||
Guide complet pour configurer l'interface selon vos besoins.
|
||||
- **Configuration générale et variables d'environnement**
|
||||
- **Configuration Vue.js et TypeScript**
|
||||
- **Configuration WASM et sdk_client**
|
||||
- **Configuration de l'intégration 4NK_node**
|
||||
- **Configuration Docker et production**
|
||||
- **Configuration SSL/TLS**
|
||||
- **Configuration de monitoring et sauvegarde**
|
||||
|
||||
## 🔧 Guides Techniques
|
||||
|
||||
### 🏗️ [Architecture Technique](ARCHITECTURE.md)
|
||||
Documentation technique détaillée de l'architecture.
|
||||
- **Architecture générale du frontend**
|
||||
- **Composants principaux (Vue.js, TypeScript, WASM)**
|
||||
- **Intégration avec sdk_client et sdk_common**
|
||||
- **Flux de données entre composants**
|
||||
- **Architecture des Silent Payments**
|
||||
- **Sécurité et isolation**
|
||||
- **Performance et optimisations**
|
||||
- **Monitoring et observabilité**
|
||||
|
||||
### 📡 [API](API.md)
|
||||
Documentation contractuelle des APIs disponibles.
|
||||
- **API sdk_client WASM** : Interface WebAssembly pour les Silent Payments
|
||||
- **API Vue.js Components** : Composants réutilisables
|
||||
- **API Services** : Services de communication et gestion
|
||||
- **API Types TypeScript** : Types et interfaces
|
||||
- **Format des données et payloads**
|
||||
- **Gestion des erreurs**
|
||||
- **Exemples d'utilisation**
|
||||
- **Limites et quotas**
|
||||
|
||||
### 🔒 [Sécurité](SECURITY.md)
|
||||
Guide de sécurité et bonnes pratiques.
|
||||
- **Authentification et autorisation**
|
||||
- **Protection XSS et CSRF**
|
||||
- **Sécurité WASM et mémoire**
|
||||
- **Chiffrement et certificats**
|
||||
- **Audit et monitoring de sécurité**
|
||||
- **Bonnes pratiques frontend**
|
||||
|
||||
### 🐙 [Configuration Gitea](GITEA_SETUP.md)
|
||||
Guide de configuration spécifique pour Gitea.
|
||||
- **Configuration du repository Gitea**
|
||||
- **Templates d'issues et pull requests**
|
||||
- **Configuration CI/CD avec Gitea Actions**
|
||||
- **Intégrations et webhooks**
|
||||
- **Workflow de contribution**
|
||||
- **Sécurité et permissions**
|
||||
|
||||
### 🚀 [Plan de Release](RELEASE_PLAN.md)
|
||||
Plan de lancement open source complet.
|
||||
- **Phases de préparation**
|
||||
- **Communication et marketing**
|
||||
- **Checklist de lancement**
|
||||
- **Support communautaire**
|
||||
- **Gestion des risques**
|
||||
|
||||
### 🌟 [Guide de la Communauté](COMMUNITY_GUIDE.md)
|
||||
Guide complet pour la communauté.
|
||||
- **Comment contribuer**
|
||||
- **Ressources d'apprentissage**
|
||||
- **Environnement de développement**
|
||||
- **Processus de contribution**
|
||||
- **Support et reconnaissance**
|
||||
|
||||
### 🗺️ [Roadmap](ROADMAP.md)
|
||||
Roadmap de développement détaillée.
|
||||
- **Timeline de développement**
|
||||
- **Fonctionnalités planifiées**
|
||||
- **Évolution de l'architecture**
|
||||
- **Métriques de succès**
|
||||
|
||||
## 🧪 Guides de Test
|
||||
|
||||
### 🧪 [Guide des Tests](TESTING.md)
|
||||
Guide complet pour les tests de l'interface utilisateur.
|
||||
- **Tests unitaires Vue.js**
|
||||
- **Tests d'intégration WASM**
|
||||
- **Tests end-to-end (Playwright)**
|
||||
- **Tests de performance**
|
||||
- **Tests de sécurité**
|
||||
- **Tests d'accessibilité**
|
||||
- **Tests de compatibilité navigateur**
|
||||
|
||||
### 🔍 [Audit de Sécurité](SECURITY_AUDIT.md)
|
||||
Audit de sécurité détaillé.
|
||||
- **Vulnérabilités connues**
|
||||
- **Tests de pénétration**
|
||||
- **Audit de code**
|
||||
- **Recommandations de sécurité**
|
||||
- **Plan de remédiation**
|
||||
|
||||
## 🔧 Guides de Développement
|
||||
|
||||
### 🔧 [Guide de Développement](DEVELOPMENT.md)
|
||||
Guide complet pour le développement.
|
||||
- **Environnement de développement**
|
||||
- **Workflow de développement**
|
||||
- **Standards de code**
|
||||
- **Debugging et profiling**
|
||||
- **Optimisation des performances**
|
||||
- **Déploiement et CI/CD**
|
||||
|
||||
### 📋 [Référence Rapide](QUICK_REFERENCE.md)
|
||||
Référence rapide pour les développeurs.
|
||||
- **Commandes essentielles**
|
||||
- **Structure du projet**
|
||||
- **APIs principales**
|
||||
- **Configuration rapide**
|
||||
- **Dépannage rapide**
|
||||
|
||||
### 🔄 [Guide de Migration](MIGRATION.md)
|
||||
Guide pour les migrations et mises à jour.
|
||||
- **Migration des versions**
|
||||
- **Breaking changes**
|
||||
- **Mise à jour des dépendances**
|
||||
- **Migration des données**
|
||||
- **Tests de migration**
|
||||
|
||||
## 🌐 Guides d'Intégration
|
||||
|
||||
### 🧩 [Intégration iframe](INTEGRATION_IFRAME.md)
|
||||
Spécification de messagerie postMessage (requêtes/réponses, erreurs, prérequis).
|
||||
|
||||
### 🔑 [Configuration SSH](SSH_USAGE.md)
|
||||
Guide de configuration SSH pour le développement.
|
||||
- **Génération des clés SSH**
|
||||
- **Configuration Git**
|
||||
- **Intégration avec Gitea**
|
||||
- **Automatisation des déploiements**
|
||||
|
||||
### 🤖 [Push SSH Automatisé](AUTO_SSH_PUSH.md)
|
||||
Guide pour l'automatisation des pushes SSH.
|
||||
- **Configuration des scripts**
|
||||
- **Intégration CI/CD**
|
||||
- **Gestion des clés**
|
||||
- **Sécurité et bonnes pratiques**
|
||||
|
||||
## 📊 État et Monitoring
|
||||
|
||||
### 📊 [Référence rapide](QUICK_REFERENCE.md)
|
||||
Raccourcis d’accès (commandes, dossiers, URLs) pour démarrer vite.
|
||||
|
||||
|
||||
## 🔧 Guides d'Open Source
|
||||
|
||||
### ✅ [Checklist Open Source](OPEN_SOURCE_CHECKLIST.md)
|
||||
Checklist complète pour l'ouverture en open source.
|
||||
- **Préparation du code**
|
||||
- **Documentation**
|
||||
- **Licences et légal**
|
||||
- **Infrastructure**
|
||||
- **Communication**
|
||||
|
||||
## 📞 Support et Contact
|
||||
|
||||
### 📞 [Support](SUPPORT.md)
|
||||
Guide de support et contact.
|
||||
- **Comment obtenir de l'aide**
|
||||
- **Création d'issues**
|
||||
- **Canal de communication**
|
||||
- **FAQ**
|
||||
- **Ressources additionnelles**
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Navigation Rapide
|
||||
|
||||
### 🚀 Démarrage Rapide
|
||||
1. [Installation](INSTALLATION.md) - Installer ihm_client
|
||||
2. [Configuration](CONFIGURATION.md) - Configurer l'environnement
|
||||
3. [Utilisation](USAGE.md) - Utiliser l'interface
|
||||
|
||||
### 🔧 Développement
|
||||
1. [Architecture](ARCHITECTURE.md) - Comprendre l'architecture
|
||||
2. [API](API.md) - Consulter les APIs
|
||||
3. [Tests](TESTING.md) - Exécuter les tests
|
||||
|
||||
### 📚 Documentation
|
||||
1. [Index](INDEX.md) - Cet index
|
||||
2. [Quick Reference](QUICK_REFERENCE.md) - Référence rapide
|
||||
3. [Roadmap](ROADMAP.md) - Évolution du projet
|
||||
|
||||
### 🤝 Communauté
|
||||
1. [Guide Communauté](COMMUNITY_GUIDE.md) - Contribuer
|
||||
2. [Code de Conduite](../CODE_OF_CONDUCT.md) - Règles de conduite
|
||||
3. [Support](SUPPORT.md) - Obtenir de l'aide
|
||||
|
||||
---
|
||||
|
||||
**📚 Documentation complète pour ihm_client - Interface utilisateur moderne pour les Silent Payments** 🚀
|
@ -1,374 +0,0 @@
|
||||
# 📦 Guide d'Installation - ihm_client
|
||||
|
||||
Guide complet pour installer et configurer l'interface utilisateur ihm_client pour les Silent Payments.
|
||||
|
||||
## 📋 Prérequis
|
||||
|
||||
### Système
|
||||
|
||||
- **OS** : Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+), macOS 10.15+, Windows 10+
|
||||
- **Architecture** : x86_64, ARM64 (Apple Silicon)
|
||||
- **RAM** : 4 Go minimum, 8 Go recommandés
|
||||
- **Stockage** : 5 Go minimum, 10 Go recommandés
|
||||
- **Réseau** : Connexion Internet stable
|
||||
|
||||
### Logiciels
|
||||
|
||||
- **Node.js** : Version 18.0+ (LTS recommandé)
|
||||
- **npm** : Version 8.0+
|
||||
- **Git** : Version 2.25+
|
||||
- **Rust** : Version 1.70+ (pour la compilation WASM)
|
||||
- **Docker** : Version 20.10+ (optionnel, pour l'intégration 4NK_node)
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### 1. Installation de Node.js
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
# Mettre à jour les paquets
|
||||
sudo apt update
|
||||
|
||||
# Installer Node.js via NodeSource
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
# Vérifier l'installation
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
|
||||
#### CentOS/RHEL
|
||||
|
||||
```bash
|
||||
# Installer Node.js via NodeSource
|
||||
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -
|
||||
sudo yum install -y nodejs
|
||||
|
||||
# Vérifier l'installation
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
|
||||
#### macOS
|
||||
|
||||
```bash
|
||||
# Installer via Homebrew
|
||||
brew install node@18
|
||||
|
||||
# Ou télécharger depuis nodejs.org
|
||||
# https://nodejs.org/en/download/
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
```bash
|
||||
# Télécharger et installer depuis
|
||||
# https://nodejs.org/en/download/
|
||||
```
|
||||
|
||||
### 2. Installation de Rust
|
||||
|
||||
#### Linux/macOS
|
||||
|
||||
```bash
|
||||
# Installer Rust via rustup
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
|
||||
# Recharger l'environnement
|
||||
source ~/.cargo/env
|
||||
|
||||
# Vérifier l'installation
|
||||
rustc --version
|
||||
cargo --version
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
```bash
|
||||
# Télécharger et installer rustup depuis
|
||||
# https://rustup.rs/
|
||||
```
|
||||
|
||||
### 3. Installation de wasm-pack
|
||||
|
||||
```bash
|
||||
# Installer wasm-pack
|
||||
cargo install wasm-pack
|
||||
|
||||
# Vérifier l'installation
|
||||
wasm-pack --version
|
||||
```
|
||||
|
||||
### 4. Configuration SSH (Recommandé)
|
||||
|
||||
```bash
|
||||
# Générer une clé SSH
|
||||
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_ihm -C "ihm-client-automation"
|
||||
|
||||
# Ajouter à l'agent SSH
|
||||
ssh-add ~/.ssh/id_ed25519_ihm
|
||||
|
||||
# Configurer Git pour utiliser la clé
|
||||
git config --global core.sshCommand "ssh -i ~/.ssh/id_ed25519_ihm"
|
||||
|
||||
# Afficher la clé publique pour Gitea
|
||||
cat ~/.ssh/id_ed25519_ihm.pub
|
||||
```
|
||||
|
||||
**Ajouter la clé publique à Gitea :**
|
||||
1. Aller sur Gitea > Settings > SSH Keys
|
||||
2. Coller la clé publique
|
||||
3. Cliquer sur "Add key"
|
||||
|
||||
### 5. Clonage du Repository
|
||||
|
||||
```bash
|
||||
# Cloner avec SSH (recommandé)
|
||||
git clone git@git.4nkweb.com:4nk/ihm_client.git
|
||||
cd ihm_client
|
||||
|
||||
# Ou cloner avec HTTPS
|
||||
git clone https://git.4nkweb.com/4nk/ihm_client.git
|
||||
cd ihm_client
|
||||
```
|
||||
|
||||
### 6. Installation des Dépendances
|
||||
|
||||
```bash
|
||||
# Installer les dépendances Node.js
|
||||
npm install
|
||||
|
||||
# Vérifier l'installation
|
||||
npm list --depth=0
|
||||
```
|
||||
|
||||
### 7. Configuration des Dépendances WASM
|
||||
|
||||
```bash
|
||||
# Configurer les dépendances distantes (sdk_client, sdk_common)
|
||||
./scripts/setup-remote-deps.sh
|
||||
|
||||
# Vérifier la compilation WASM
|
||||
ls -la pkg/
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Variables d'Environnement
|
||||
|
||||
Créer un fichier `.env` à la racine du projet :
|
||||
|
||||
```bash
|
||||
# Configuration de développement
|
||||
NODE_ENV=development
|
||||
VITE_DEV_SERVER_PORT=3000
|
||||
VITE_API_URL=http://localhost:8091
|
||||
VITE_WS_URL=ws://localhost:8090
|
||||
|
||||
# Configuration WASM
|
||||
VITE_WASM_PATH=./pkg/sdk_client_bg.wasm
|
||||
|
||||
# Configuration pour l'intégration 4NK_node
|
||||
SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
|
||||
SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
|
||||
BITCOIN_RPC_URL=http://bitcoin:18443
|
||||
BLINDBIT_URL=http://blindbit:8000
|
||||
```
|
||||
|
||||
### Configuration TypeScript
|
||||
|
||||
Le fichier `tsconfig.json` est déjà configuré pour :
|
||||
- Vue.js 3
|
||||
- TypeScript strict
|
||||
- Support WASM
|
||||
- Path mapping
|
||||
|
||||
### Configuration Vite
|
||||
|
||||
Le fichier `vite.config.ts` est configuré pour :
|
||||
- Support WASM
|
||||
- Hot module replacement
|
||||
- Build optimisé
|
||||
- Support des types TypeScript
|
||||
|
||||
## 🧪 Tests Post-Installation
|
||||
|
||||
### 1. Test de Compilation
|
||||
|
||||
```bash
|
||||
# Test de compilation TypeScript
|
||||
npm run build
|
||||
|
||||
# Vérifier le build
|
||||
ls -la dist/
|
||||
```
|
||||
|
||||
### 2. Test de Développement
|
||||
|
||||
```bash
|
||||
# Démarrer le serveur de développement
|
||||
npm run dev
|
||||
|
||||
# Ouvrir http://localhost:3000 dans le navigateur
|
||||
```
|
||||
|
||||
### 3. Test WASM
|
||||
|
||||
```bash
|
||||
# Vérifier que le module WASM fonctionne
|
||||
npm run test:wasm
|
||||
```
|
||||
|
||||
### 4. Test Complet
|
||||
|
||||
```bash
|
||||
# Exécuter tous les tests
|
||||
npm run test
|
||||
|
||||
# Vérifier la couverture
|
||||
npm run test:coverage
|
||||
```
|
||||
|
||||
## 🚨 Dépannage
|
||||
|
||||
### Problèmes Courants
|
||||
|
||||
#### Node.js non trouvé
|
||||
```bash
|
||||
# Vérifier l'installation
|
||||
which node
|
||||
node --version
|
||||
|
||||
# Réinstaller si nécessaire
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
```
|
||||
|
||||
#### Rust non trouvé
|
||||
```bash
|
||||
# Vérifier l'installation
|
||||
which rustc
|
||||
rustc --version
|
||||
|
||||
# Réinstaller si nécessaire
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
source ~/.cargo/env
|
||||
```
|
||||
|
||||
#### Erreurs de compilation WASM
|
||||
```bash
|
||||
# Nettoyer et recompiler
|
||||
rm -rf pkg/
|
||||
./scripts/setup-remote-deps.sh
|
||||
|
||||
# Vérifier les dépendances Rust
|
||||
cd temp-deps/sdk_client
|
||||
cargo check
|
||||
```
|
||||
|
||||
#### Erreurs de dépendances npm
|
||||
```bash
|
||||
# Nettoyer et réinstaller
|
||||
rm -rf node_modules/ package-lock.json
|
||||
npm install
|
||||
|
||||
# Vérifier les vulnérabilités
|
||||
npm audit
|
||||
npm audit fix
|
||||
```
|
||||
|
||||
#### Problèmes de permissions
|
||||
```bash
|
||||
# Corriger les permissions
|
||||
sudo chown -R $USER:$USER .
|
||||
chmod +x scripts/*.sh
|
||||
```
|
||||
|
||||
### Logs Détaillés
|
||||
|
||||
```bash
|
||||
# Logs de compilation TypeScript
|
||||
npm run build --verbose
|
||||
|
||||
# Logs de compilation WASM
|
||||
cd temp-deps/sdk_client
|
||||
wasm-pack build --target web --out-dir ../../pkg --verbose
|
||||
|
||||
# Logs du serveur de développement
|
||||
npm run dev --verbose
|
||||
```
|
||||
|
||||
## 🔒 Sécurité
|
||||
|
||||
### Vérifications de Sécurité
|
||||
|
||||
```bash
|
||||
# Audit des dépendances npm
|
||||
npm audit
|
||||
|
||||
# Audit des dépendances Rust
|
||||
cargo audit
|
||||
|
||||
# Vérification des vulnérabilités WASM
|
||||
wasm-pack build --target web --out-dir ../../pkg
|
||||
```
|
||||
|
||||
### Bonnes Pratiques
|
||||
|
||||
- Utiliser HTTPS en production
|
||||
- Valider toutes les entrées utilisateur
|
||||
- Maintenir les dépendances à jour
|
||||
- Utiliser des variables d'environnement pour les secrets
|
||||
- Tester régulièrement la sécurité
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Métriques d'Installation
|
||||
|
||||
```bash
|
||||
# Taille du projet
|
||||
du -sh .
|
||||
|
||||
# Nombre de fichiers
|
||||
find . -type f | wc -l
|
||||
|
||||
# Dépendances installées
|
||||
npm list --depth=0 | wc -l
|
||||
|
||||
# Taille du module WASM
|
||||
ls -lh pkg/sdk_client_bg.wasm
|
||||
```
|
||||
|
||||
### Vérification de l'Installation
|
||||
|
||||
```bash
|
||||
# Script de vérification
|
||||
./scripts/verify-installation.sh
|
||||
|
||||
# Tests automatisés
|
||||
npm run test:installation
|
||||
```
|
||||
|
||||
## 🎯 Prochaines Étapes
|
||||
|
||||
Après l'installation réussie :
|
||||
|
||||
1. **Lire le [Guide d'Utilisation](USAGE.md)** - Utiliser l'interface
|
||||
2. **Consulter l'[Architecture](ARCHITECTURE.md)** - Comprendre le système
|
||||
3. **Explorer les [APIs](API.md)** - Utiliser les fonctionnalités
|
||||
4. **Consulter l'[Intégration iframe](INTEGRATION_IFRAME.md)** - Intégrer dans un site hôte
|
||||
|
||||
## 📞 Support
|
||||
|
||||
En cas de problème :
|
||||
|
||||
1. Consulter la [documentation](INDEX.md)
|
||||
2. Vérifier les [issues existantes](https://git.4nkweb.com/4nk/ihm_client/issues)
|
||||
3. Créer une nouvelle issue avec les détails du problème
|
||||
4. Inclure les logs et la configuration utilisée
|
||||
|
||||
---
|
||||
|
||||
**🚀 Installation terminée ! ihm_client est prêt à être utilisé.** ✨
|
@ -1,156 +0,0 @@
|
||||
# Intégration iframe – Spécification de messagerie
|
||||
|
||||
Ce document définit les échanges entre un site hôte et `ihm_client` intégré en iframe, via `window.postMessage`. Aucun exemple de code exécutable n’est inclus.
|
||||
|
||||
## Principes
|
||||
|
||||
- Canal: postMessage entre la page parente et l’iframe `ihm_client`.
|
||||
- Découverte: `ihm_client` émet `LISTENING` pour signaler la disponibilité des listeners (côté iframe). En mode E2E (`?e2e=1`) et seulement lorsque l’app tourne en iframe, `LISTENING` est émis périodiquement (jusqu’à 100 fois) pour éviter les courses de tests. Hors E2E, pas d’émission périodique.
|
||||
- Sécurité:
|
||||
- Utiliser la cible `event.origin` pour les réponses.
|
||||
- De nombreuses opérations exigent un `accessToken` valide (lié à `origin`).
|
||||
- `messageId` recommandé pour corréler requêtes/réponses.
|
||||
- Pré-requis: pour la plupart des actions de processus, l’appareil doit être appairé.
|
||||
|
||||
## Types de message
|
||||
|
||||
Référence: `src/models/process.model.ts` (enum `MessageType`).
|
||||
|
||||
### LISTENING
|
||||
- Émis par `ihm_client` au parent pour signaler la disponibilité des listeners.
|
||||
- Réception côté parent (aucune requête attendue). Pas de payload spécifique.
|
||||
|
||||
---
|
||||
|
||||
### REQUEST_LINK (Requête)
|
||||
- Objet: ouverture d’un consentement utilisateur pour lier l’hôte à l’appareil.
|
||||
- Requête (parent → iframe):
|
||||
- `type`: `REQUEST_LINK`
|
||||
- `messageId`: string (optionnel mais recommandé)
|
||||
- Réponses (iframe → parent):
|
||||
- Succès: `type`: `LINK_ACCEPTED`, `accessToken`: string, `refreshToken`: string, `messageId`
|
||||
- Erreur: `type`: `ERROR`, `error`: string, `messageId`
|
||||
|
||||
### VALIDATE_TOKEN (Requête)
|
||||
- Objet: vérifier la validité du couple `{accessToken, refreshToken}`.
|
||||
- Requête: `type`, `accessToken`, `refreshToken`, `messageId`
|
||||
- Réponse: `type`: `VALIDATE_TOKEN`, `isValid`: boolean, `accessToken`, `refreshToken`, `messageId`
|
||||
|
||||
### RENEW_TOKEN (Requête)
|
||||
- Objet: obtenir un nouveau `accessToken` depuis un `refreshToken`.
|
||||
- Requête: `type`, `refreshToken`, `messageId`
|
||||
- Réponses:
|
||||
- Succès: `type`: `RENEW_TOKEN`, `accessToken`, `refreshToken`, `messageId`
|
||||
- Erreur: `ERROR`
|
||||
|
||||
---
|
||||
|
||||
### CREATE_PAIRING (Requête)
|
||||
- Objet: initier l’appairage de l’appareil.
|
||||
- Pré-requis: `accessToken` valide; appareil non appairé.
|
||||
- Requête: `type`, `accessToken`, `messageId`
|
||||
- Réponses:
|
||||
- Succès: `type`: `PAIRING_CREATED`, `pairingId`: string, `messageId`
|
||||
- Erreur: `ERROR`
|
||||
|
||||
### GET_PAIRING_ID (Requête)
|
||||
- Objet: récupérer l’identifiant d’appairage utilisateur.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `accessToken`, `messageId`
|
||||
- Réponse: `type`: `GET_PAIRING_ID`, `userPairingId`: string, `messageId`
|
||||
|
||||
---
|
||||
|
||||
### GET_MY_PROCESSES (Requête)
|
||||
- Objet: lister les processus auxquels l’utilisateur participe.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `accessToken`, `messageId`
|
||||
- Réponse: `type`: `GET_MY_PROCESSES`, `myProcesses`: string[] | null, `messageId`
|
||||
|
||||
### GET_PROCESSES (Requête)
|
||||
- Objet: récupérer tous les processus connus localement.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `accessToken`, `messageId`
|
||||
- Réponse: `type`: `PROCESSES_RETRIEVED`, `processes`: Record<string, Process>, `messageId`
|
||||
|
||||
---
|
||||
|
||||
### RETRIEVE_DATA (Requête)
|
||||
- Objet: déchiffrer et retourner les attributs autorisés d’un état de processus.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `processId`: string, `stateId`: string (32 bytes hex), `accessToken`, `messageId`
|
||||
- Réponse: `type`: `DATA_RETRIEVED`, `data`: Record<string, any>, `messageId`
|
||||
|
||||
### DECODE_PUBLIC_DATA (Requête)
|
||||
- Objet: décoder des données publiques encodées.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `accessToken`, `encodedData`: number[], `messageId`
|
||||
- Réponse: `type`: `PUBLIC_DATA_DECODED`, `decodedData`: any, `messageId`
|
||||
|
||||
---
|
||||
|
||||
### CREATE_PROCESS (Requête)
|
||||
- Objet: créer un nouveau processus.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête:
|
||||
- `type`
|
||||
- `processData`: Record<string, any> (données brutes à répartir en public/privé)
|
||||
- `privateFields`: string[] (liste des nouveaux champs à forcer en privé)
|
||||
- `roles`: Record<string, RoleDefinition>
|
||||
- `accessToken`, `messageId`
|
||||
- Réponse succès: `type`: `PROCESS_CREATED`, `processCreated`: { `processId`: string, `process`: Process, `processData`: Record<string, any> }, `messageId`
|
||||
- Réponse erreur: `ERROR`
|
||||
|
||||
### UPDATE_PROCESS (Requête)
|
||||
- Objet: créer un nouvel état avec des mises à jour (champs publics/privés déterminés automatiquement, `privateFields` pour les nouveaux champs privés).
|
||||
- Pré-requis: appairé + `accessToken` valide + processus existant avec état committé.
|
||||
- Requête: `type`, `processId`, `newData`: Record<string, any>, `privateFields`: string[], `roles` (ou null pour conserver), `accessToken`, `messageId`
|
||||
- Réponse: `type`: `PROCESS_UPDATED`, `updatedProcess`: Process, `messageId`
|
||||
|
||||
---
|
||||
|
||||
### NOTIFY_UPDATE (Requête)
|
||||
- Objet: demander l’émission d’un PRD Update pour un état précis.
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `processId`, `stateId` (32 bytes hex), `accessToken`, `messageId`
|
||||
- Réponse: `type`: `UPDATE_NOTIFIED`, `messageId`
|
||||
|
||||
### VALIDATE_STATE (Requête)
|
||||
- Objet: valider un état (selon règles/permissions WASM).
|
||||
- Pré-requis: appairé + `accessToken` valide.
|
||||
- Requête: `type`, `processId`, `stateId` (32 bytes hex), `accessToken`, `messageId`
|
||||
- Réponse: `type`: `STATE_VALIDATED`, `validatedProcess`: Process, `messageId`
|
||||
|
||||
---
|
||||
|
||||
### HASH_VALUE (Requête)
|
||||
- Objet: obtenir le hash d’un blob (document) pour un engagement donné.
|
||||
- Requête: `type`, `accessToken`, `commitedIn`: string, `label`: string, `fileBlob`: { type: string; data: Uint8Array }, `messageId`
|
||||
- Réponse: `type`: `VALUE_HASHED`, `hash`: string, `messageId`
|
||||
|
||||
### GET_MERKLE_PROOF (Requête)
|
||||
- Objet: récupérer la preuve Merkle d’un attribut dans un état.
|
||||
- Requête: `type`, `accessToken`, `processState`: ProcessState, `attributeName`: string, `messageId`
|
||||
- Réponse: `type`: `MERKLE_PROOF_RETRIEVED`, `proof`: MerkleProofResult, `messageId`
|
||||
|
||||
### VALIDATE_MERKLE_PROOF (Requête)
|
||||
- Objet: valider une preuve Merkle pour un document donné.
|
||||
- Requête: `type`, `accessToken`, `merkleProof`: string (JSON sérialisé), `documentHash`: string, `messageId`
|
||||
- Réponse: `type`: `MERKLE_PROOF_VALIDATED`, `isValid`: boolean, `messageId`
|
||||
|
||||
---
|
||||
|
||||
## Erreurs communes (`ERROR`)
|
||||
- Conditions typiques:
|
||||
- `Device not paired` (opération nécessitant appairage)
|
||||
- `Invalid or expired session token`
|
||||
- `Failed to ...` (création/lecture/validation)
|
||||
- `Invalid state id` / `Process not found`
|
||||
- Payload générique: `{ type: 'ERROR', error: string, messageId?: string }`
|
||||
|
||||
## Bonnes pratiques d’intégration
|
||||
- Toujours préciser et propager `messageId` pour tracer les échanges.
|
||||
- Conserver `origin` côté parent et utiliser la même valeur dans les requêtes suivantes.
|
||||
- Renouveler régulièrement le `accessToken` via `RENEW_TOKEN`.
|
||||
- Séparer données publiques/privées dès la création d’un processus.
|
||||
- Valider les formats (ids hex 32 bytes, structures de rôles) avant envoi.
|
@ -1,8 +0,0 @@
|
||||
# Checklist open source - ihm_client
|
||||
|
||||
- Licence présente et valide (LICENSE)
|
||||
- Code de conduite (CODE_OF_CONDUCT.md)
|
||||
- Guide de contribution (CONTRIBUTING.md)
|
||||
- CI/CD documentée
|
||||
- Documentation technique et utilisateur à jour
|
||||
- Aucune donnée sensible dans le dépôt
|
@ -1,5 +0,0 @@
|
||||
# Référence rapide - ihm_client
|
||||
|
||||
- Commandes: install, dev, build, test, test:e2e
|
||||
- Dossiers clés: src/, pkg/, docs/
|
||||
- URLs: dev 3003, app servi par 4NK_node (artefacts dist/)
|
@ -1,5 +0,0 @@
|
||||
# Plan de release - ihm_client
|
||||
|
||||
- Phases: préparation, RC, GA
|
||||
- Critères: tests verts, docs à jour, audit dépendances
|
||||
- Communication: notes de version, changelog, guide de migration
|
@ -1,8 +0,0 @@
|
||||
- [ ] Handshake iframe robuste (READY → LISTENING → REQUEST_LINK) avec ACKs
|
||||
- Objectif: éliminer les conditions de course à l’initialisation
|
||||
- Détails: séquence explicite, timeouts, retry backoff
|
||||
# Roadmap - ihm_client
|
||||
|
||||
- Court terme: stabilisation iframe, optimisation WASM
|
||||
- Moyen terme: E2E tests, PWA, performances
|
||||
- Long terme: analytics, nouvelles intégrations
|
@ -1,25 +0,0 @@
|
||||
# Audit de sécurité - ihm_client
|
||||
|
||||
Ce document synthétise la posture de sécurité, les contrôles, et les axes d’audit pour `ihm_client`.
|
||||
|
||||
## Portée
|
||||
- Surface frontend (TypeScript, Vite, dépendances npm)
|
||||
- Intégration WASM (sdk_client)
|
||||
- Messagerie iframe (`postMessage`) avec sites hôtes
|
||||
|
||||
## Contrôles actuels
|
||||
- Validation et renouvellement de tokens de session liés à l’origine appelante
|
||||
- Isolation des données privées (déchiffrement conditionné, clés requises)
|
||||
- Aucune exposition de secrets runtime dans le code
|
||||
|
||||
## Axes d’audit
|
||||
- Dépendances: revue `npm audit`, vérification des transitive deps
|
||||
- WASM: taille, init sécurisé, absence d’APIs dangereuses
|
||||
- Iframe: vérification stricte des `origin`, absence d’élévation via messages
|
||||
|
||||
## Vulnérabilités connues
|
||||
- Aucune critique ouverte à date
|
||||
|
||||
## Plan de remédiation
|
||||
- Mise à jour régulière des dépendances
|
||||
- Tests de sécurité ciblés côté messagerie et décodage de données
|
@ -1,322 +0,0 @@
|
||||
# Documentation SSH complète - ihm_client
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Ce document consolide toute la documentation SSH pour le projet `ihm_client`, couvrant l'automatisation des push, la configuration CI/CD, et les bonnes pratiques de sécurité.
|
||||
|
||||
## Table des matières
|
||||
|
||||
- [Configuration automatique](#configuration-automatique)
|
||||
- [Scripts d'automatisation](#scripts-dautomatisation)
|
||||
- [Workflow CI/CD](#workflow-cicd)
|
||||
- [Alias Git](#alias-git)
|
||||
- [Bonnes pratiques](#bonnes-pratiques)
|
||||
- [Dépannage](#dépannage)
|
||||
|
||||
---
|
||||
|
||||
## Configuration automatique
|
||||
|
||||
### Configuration Git globale
|
||||
|
||||
La configuration SSH est automatiquement appliquée pour tous les push :
|
||||
|
||||
```bash
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
```
|
||||
|
||||
### Vérification SSH
|
||||
|
||||
Test automatique de la connexion SSH :
|
||||
|
||||
```bash
|
||||
ssh -T git@git.4nkweb.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scripts d'automatisation
|
||||
|
||||
### 1. Script principal : `auto-ssh-push.sh`
|
||||
|
||||
Le script `scripts/auto-ssh-push.sh` offre plusieurs modes de push automatique :
|
||||
|
||||
#### Options disponibles
|
||||
|
||||
```bash
|
||||
# Push rapide (message automatique)
|
||||
./scripts/auto-ssh-push.sh quick
|
||||
|
||||
# Push avec message personnalisé
|
||||
./scripts/auto-ssh-push.sh message "feat: nouvelle fonctionnalité"
|
||||
|
||||
# Push sur une branche spécifique
|
||||
./scripts/auto-ssh-push.sh branch feature/nouvelle-fonctionnalite
|
||||
|
||||
# Push et merge (avec confirmation)
|
||||
./scripts/auto-ssh-push.sh merge
|
||||
|
||||
# Vérification du statut
|
||||
./scripts/auto-ssh-push.sh status
|
||||
```
|
||||
|
||||
#### Fonctionnalités
|
||||
|
||||
- **Configuration SSH automatique** - Plus besoin de configurer SSH manuellement
|
||||
- **Push automatique** - Ajout, commit et push en une commande
|
||||
- **Gestion des branches** - Support des branches personnalisées
|
||||
- **Vérification SSH** - Test automatique de la connexion SSH
|
||||
- **Messages de commit** - Messages automatiques ou personnalisés
|
||||
|
||||
### 2. Script d'initialisation : `init-ssh-env.sh`
|
||||
|
||||
Le script `scripts/init-ssh-env.sh` configure automatiquement l'environnement SSH :
|
||||
|
||||
```bash
|
||||
./scripts/init-ssh-env.sh
|
||||
```
|
||||
|
||||
#### Fonctionnalités
|
||||
|
||||
- Vérification de l'environnement de développement
|
||||
- Configuration SSH automatique
|
||||
- Test de connectivité SSH
|
||||
- Configuration des alias Git
|
||||
- Validation de la configuration
|
||||
|
||||
### 3. Script CI/CD : `setup-ssh-ci.sh`
|
||||
|
||||
Le script `scripts/setup-ssh-ci.sh` configure SSH pour les environnements CI/CD :
|
||||
|
||||
```bash
|
||||
./scripts/setup-ssh-ci.sh
|
||||
```
|
||||
|
||||
#### Fonctionnalités
|
||||
|
||||
- Détection automatique de l'environnement CI
|
||||
- Configuration SSH pour Gitea Actions
|
||||
- Gestion des clés SSH privées
|
||||
- Test de connexion SSH
|
||||
- Configuration Git pour SSH
|
||||
|
||||
---
|
||||
|
||||
## Workflow CI/CD
|
||||
|
||||
### Configuration Gitea Actions
|
||||
|
||||
Le workflow CI/CD dans `.gitea/workflows/ci.yml` inclut une étape de configuration SSH :
|
||||
|
||||
```yaml
|
||||
- name: Setup SSH for Gitea
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan -H git.4nkweb.com >> ~/.ssh/known_hosts
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
```
|
||||
|
||||
### Variables d'environnement requises
|
||||
|
||||
- `SSH_PRIVATE_KEY` : Clé SSH privée pour l'authentification
|
||||
- `SSH_PUBLIC_KEY` : Clé SSH publique (optionnelle)
|
||||
|
||||
### Jobs configurés
|
||||
|
||||
- **test** : Tests unitaires et d'intégration
|
||||
- **security** : Tests de sécurité et audit
|
||||
- **integration-test** : Tests d'intégration complets
|
||||
|
||||
---
|
||||
|
||||
## Alias Git
|
||||
|
||||
### Alias configurés
|
||||
|
||||
```bash
|
||||
# Push rapide avec message automatique
|
||||
git quick-push
|
||||
|
||||
# Push avec message personnalisé
|
||||
git ssh-push "Mon message de commit"
|
||||
```
|
||||
|
||||
### Configuration des alias
|
||||
|
||||
```bash
|
||||
# Alias pour push rapide
|
||||
git config --global alias.quick-push '!f() { git add . && git commit -m "Update $(date)" && git push origin $(git branch --show-current); }; f'
|
||||
|
||||
# Alias pour push avec message
|
||||
git config --global alias.ssh-push '!f() { git add . && git commit -m "${1:-Auto-commit $(date)}" && git push origin $(git branch --show-current); }; f'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bonnes pratiques
|
||||
|
||||
### Sécurité
|
||||
|
||||
1. **Permissions des clés SSH**
|
||||
```bash
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
chmod 644 ~/.ssh/id_rsa.pub
|
||||
chmod 600 ~/.ssh/config
|
||||
```
|
||||
|
||||
2. **Configuration SSH sécurisée**
|
||||
```bash
|
||||
Host git.4nkweb.com
|
||||
HostName git.4nkweb.com
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
```
|
||||
|
||||
3. **Gestion des secrets**
|
||||
- Ne jamais commiter de clés SSH dans le code
|
||||
- Utiliser les secrets Gitea pour les clés privées
|
||||
- Rotation régulière des clés SSH
|
||||
|
||||
### Workflow recommandé
|
||||
|
||||
1. **Initialisation**
|
||||
```bash
|
||||
./scripts/init-ssh-env.sh
|
||||
```
|
||||
|
||||
2. **Développement quotidien**
|
||||
```bash
|
||||
# Push rapide
|
||||
./scripts/auto-ssh-push.sh quick
|
||||
|
||||
# Ou avec alias Git
|
||||
git quick-push
|
||||
```
|
||||
|
||||
3. **Push avec message**
|
||||
```bash
|
||||
./scripts/auto-ssh-push.sh message "feat: nouvelle fonctionnalité"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dépannage
|
||||
|
||||
### Problèmes courants
|
||||
|
||||
#### 1. Échec d'authentification SSH
|
||||
|
||||
```bash
|
||||
# Vérifier la configuration SSH
|
||||
ssh -T git@git.4nkweb.com
|
||||
|
||||
# Vérifier les permissions
|
||||
ls -la ~/.ssh/
|
||||
|
||||
# Régénérer la clé SSH si nécessaire
|
||||
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk
|
||||
```
|
||||
|
||||
#### 2. Configuration Git incorrecte
|
||||
|
||||
```bash
|
||||
# Vérifier la configuration Git
|
||||
git config --global --list | grep url
|
||||
|
||||
# Reconfigurer SSH
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
```
|
||||
|
||||
#### 3. Problèmes CI/CD
|
||||
|
||||
```bash
|
||||
# Vérifier les variables d'environnement
|
||||
echo $SSH_PRIVATE_KEY
|
||||
|
||||
# Tester la configuration SSH
|
||||
./scripts/setup-ssh-ci.sh
|
||||
```
|
||||
|
||||
### Messages d'erreur courants
|
||||
|
||||
- **"Permission denied"** : Vérifier les permissions des clés SSH
|
||||
- **"Host key verification failed"** : Ajouter l'hôte aux known_hosts
|
||||
- **"Could not resolve hostname"** : Vérifier la connectivité réseau
|
||||
|
||||
### Logs et debugging
|
||||
|
||||
```bash
|
||||
# Activer le debug SSH
|
||||
ssh -vT git@git.4nkweb.com
|
||||
|
||||
# Vérifier les logs Git
|
||||
GIT_SSH_COMMAND="ssh -v" git push origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Intégration avec 4NK_node
|
||||
|
||||
### Configuration pour l'intégration
|
||||
|
||||
Le projet `ihm_client` est configuré pour s'intégrer dans l'infrastructure `4NK_node` :
|
||||
|
||||
1. **Script d'intégration** : `scripts/integrate-4nk-node.sh`
|
||||
2. **Configuration Docker** : `Dockerfile.4nk-node`
|
||||
3. **Configuration Nginx** : gérée dans `4NK_node` (consommation de `dist/`)
|
||||
4. **Script de démarrage** : `start-4nk-node.sh`
|
||||
|
||||
### Workflow d'intégration
|
||||
|
||||
```bash
|
||||
# Intégrer ihm_client dans 4NK_node
|
||||
./scripts/integrate-4nk-node.sh
|
||||
|
||||
# Vérifier l'intégration
|
||||
docker-compose -f docker-compose.4nk-node.yml up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Évolution future
|
||||
|
||||
### Améliorations prévues
|
||||
|
||||
1. **Support multi-environnements**
|
||||
- Configuration automatique pour différents environnements
|
||||
- Gestion des clés SSH multiples
|
||||
|
||||
2. **Intégration avancée**
|
||||
- Support des hooks Git
|
||||
- Intégration avec d'autres outils CI/CD
|
||||
|
||||
3. **Sécurité renforcée**
|
||||
- Support des clés SSH temporaires
|
||||
- Audit automatique des permissions
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Vérification régulière de la configuration SSH
|
||||
- Mise à jour des scripts d'automatisation
|
||||
- Documentation des nouvelles fonctionnalités
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
L'automatisation SSH pour `ihm_client` simplifie considérablement le workflow de développement en éliminant la nécessité de configurer manuellement SSH pour chaque opération Git. Les scripts et alias fournis offrent une interface simple et sécurisée pour tous les push vers le repository.
|
||||
|
||||
### Ressources
|
||||
|
||||
- [Documentation SSH officielle](https://git-scm.com/book/fr/v2/Git-sur-le-serveur-Génération-d-une-clé-SSH)
|
||||
- [Guide Gitea SSH](https://docs.gitea.com/usage/ssh-setup)
|
||||
- [Bonnes pratiques SSH](https://www.ssh.com/academy/ssh/key)
|
||||
|
||||
---
|
||||
|
||||
**Dernière mise à jour** : $(date '+%Y-%m-%d')
|
||||
**Version** : 1.0.0
|
@ -1,51 +0,0 @@
|
||||
# Tests - ihm_client
|
||||
|
||||
Cette page décrit la stratégie de test, l’outillage et les conventions. Aucun exemple exécutable n’est inclus.
|
||||
|
||||
## Périmètre et objectifs
|
||||
|
||||
- Couverture des utilitaires (hex/binaire, DOM, adresses → emojis).
|
||||
- Couverture des services isolables (`TokenService`).
|
||||
- Non-régression des conversions et des invariants d’API.
|
||||
|
||||
## Outils
|
||||
|
||||
- Test runner: Jest 29 (environnement `jsdom`).
|
||||
- TypeScript: `ts-jest` (transform TS).
|
||||
- Setup global: `tests/setup.ts` (polyfills Web, mocks réseau et stockage).
|
||||
- E2E: Playwright (Chromium headless) avec `playwright.config.ts`.
|
||||
|
||||
## Organisation
|
||||
|
||||
- `tests/unit/` : tests unitaires ciblés, rapides.
|
||||
- `tests/integration/` : réservé aux interactions WASM/services (à compléter si besoin).
|
||||
- `tests/e2e/` : tests de bout en bout (smoke tests).
|
||||
|
||||
## Exécution
|
||||
|
||||
- Lancer tous les tests: `npm run test`
|
||||
- Couverture: `npm run test:coverage`
|
||||
- Veille interactive: `npm run test:watch`
|
||||
- E2E: `npm run e2e:install` puis `npm run test:e2e`
|
||||
|
||||
## Conventions
|
||||
|
||||
- Un test = un invariant métier/technique.
|
||||
- Mocks minimaux, privilégier l’isolation des dépendances (ex. `jose` mocké).
|
||||
- Aucun exemple de code applicatif dans la documentation.
|
||||
|
||||
## Polyfills et mocks de test
|
||||
|
||||
- `TextEncoder`/`TextDecoder` via `util`.
|
||||
- `crypto.subtle.digest` faux pour hashing déterministe en test d’emojis.
|
||||
- `fetch`, `WebSocket`, `localStorage`, `sessionStorage` mockés.
|
||||
|
||||
## Critères d’acceptation
|
||||
|
||||
- 100% vert sur la suite unitaire.
|
||||
- Build TypeScript OK (`npm run build:dist`) avant commit.
|
||||
|
||||
## Rapports
|
||||
|
||||
- Rapport couverture: `coverage/` (text, lcov, html).
|
||||
- Logs de tests: sortie Jest standard.
|
@ -1,423 +0,0 @@
|
||||
# 📖 Guide d'Utilisation - ihm_client
|
||||
|
||||
Guide complet pour utiliser l'interface utilisateur ihm_client au quotidien.
|
||||
|
||||
## 🚀 Démarrage Rapide
|
||||
|
||||
### Démarrage du Serveur de Développement
|
||||
|
||||
```bash
|
||||
# Démarrer le serveur de développement
|
||||
npm run dev
|
||||
|
||||
# Le serveur démarre sur http://localhost:3000
|
||||
# Hot reload activé pour le développement
|
||||
```
|
||||
|
||||
### Accès à l'Interface
|
||||
|
||||
1. **Ouvrir le navigateur** : http://localhost:3000
|
||||
2. **Page d'accueil** : Vue d'ensemble et navigation
|
||||
3. **Connexion** : Via adresse device ou QR code
|
||||
|
||||
## 🏠 Page d'Accueil
|
||||
|
||||
### Navigation Principale
|
||||
|
||||
- **🏠 Accueil** - Vue d'ensemble et navigation
|
||||
- **👤 Compte** - Gestion du profil utilisateur
|
||||
|
||||
### Tableau de Bord
|
||||
|
||||
- **Statistiques personnelles** : Processus actifs, documents signés
|
||||
- **Notifications récentes** : Alertes et mises à jour
|
||||
- **Actions rapides** : Créer un processus, scanner QR code
|
||||
- **État du wallet** : Solde et transactions récentes
|
||||
|
||||
## 👤 Gestion du Compte
|
||||
|
||||
### Profil Utilisateur
|
||||
|
||||
#### Accès au Profil
|
||||
1. Cliquer sur la bulle de profil en haut à gauche
|
||||
2. Popup de profil s'ouvre avec les informations personnelles
|
||||
|
||||
#### Informations Modifiables
|
||||
- **Nom et prénom** : Éditer directement dans les champs
|
||||
- **Photo de profil** : Cliquer pour changer l'image
|
||||
- **Email** : Adresse de contact (lecture seule)
|
||||
- **Adresse device** : Identifiant unique (lecture seule)
|
||||
|
||||
#### Actions du Profil
|
||||
|
||||
##### Export User Data
|
||||
```bash
|
||||
# Génère un fichier JSON avec toutes les données utilisateur
|
||||
# Inclut : profil, processus, documents, wallet
|
||||
```
|
||||
|
||||
##### Export Recovery
|
||||
```bash
|
||||
# Génère les 4 mots de récupération
|
||||
# IMPORTANT : Noter et conserver en lieu sûr
|
||||
# Le bouton devient inaccessible après utilisation
|
||||
```
|
||||
|
||||
##### Delete Account
|
||||
```bash
|
||||
# Supprime définitivement le compte
|
||||
# Demande de confirmation obligatoire
|
||||
# Action irréversible
|
||||
```
|
||||
|
||||
##### Logout
|
||||
```bash
|
||||
# Déconnexion de l'interface
|
||||
# Retour à la page de connexion
|
||||
```
|
||||
|
||||
### Onglet Pairing
|
||||
|
||||
#### Ajouter un Device
|
||||
1. Cliquer sur "Add Device"
|
||||
2. Choisir la méthode :
|
||||
- **Scanner QR Code** : Scanner le code d'un autre device
|
||||
- **Saisir manuellement** : Entrer l'adresse device
|
||||
|
||||
#### Gérer les Devices
|
||||
- **Renommer** : Cliquer sur le nom pour l'éditer
|
||||
- **Supprimer** : Cliquer sur l'icône poubelle
|
||||
- **Statut** : En ligne/hors ligne
|
||||
|
||||
#### Scanner QR Code
|
||||
1. Cliquer sur "Scan QR Code"
|
||||
2. Autoriser l'accès à la caméra
|
||||
3. Pointer vers le QR code
|
||||
4. Confirmation automatique
|
||||
|
||||
### Onglet Wallet
|
||||
|
||||
#### Gestion des Wallets
|
||||
- **Voir le solde** : Affichage en temps réel
|
||||
- **Ajouter une ligne** : Nouveau wallet Silent Payment
|
||||
- **Historique** : Transactions récentes
|
||||
- **Détails** : Cliquer pour plus d'informations
|
||||
|
||||
#### Opérations Wallet
|
||||
```bash
|
||||
# Générer un nouveau wallet
|
||||
generate_sp_wallet()
|
||||
|
||||
# Verrouiller des UTXOs
|
||||
lock_freezed_utxos(wallet, utxos)
|
||||
|
||||
# Scanner des blocs
|
||||
scan_blocks(wallet, blocks)
|
||||
```
|
||||
|
||||
### Onglet Process
|
||||
|
||||
#### Processus Disponibles
|
||||
- **Liste des processus** : Tous les processus accessibles
|
||||
- **Notifications** : Cliquer sur la sonnette pour voir les alertes
|
||||
- **Statut** : Actif, en attente, terminé
|
||||
- **Actions** : Voir, modifier, supprimer
|
||||
|
||||
#### Créer un Processus
|
||||
1. Cliquer sur "Nouveau Processus"
|
||||
2. Remplir les informations :
|
||||
- **Nom** : Nom du processus
|
||||
- **Description** : Détails du processus
|
||||
- **Membres** : Ajouter des participants
|
||||
- **Rôles** : Définir les responsabilités
|
||||
3. Valider la création
|
||||
|
||||
### Onglet Data
|
||||
|
||||
#### Données Importées
|
||||
- **Liste des données** : Fichiers JSON importés
|
||||
- **Contrats associés** : Cliquer pour voir le contrat
|
||||
- **Statut** : Validé, en cours, rejeté
|
||||
- **Actions** : Voir, modifier, supprimer
|
||||
|
||||
## 📄 Gestion des Processus
|
||||
|
||||
### Vue d'Ensemble
|
||||
|
||||
#### Onglets du Processus
|
||||
- **📋 Informations** : Détails du processus
|
||||
- **👥 Membres** : Participants et rôles
|
||||
- **📁 Documents** : Fichiers associés
|
||||
- **✍️ Signatures** : Demandes de signature
|
||||
- **💬 Chat** : Communication interne
|
||||
|
||||
### Gestion des Membres
|
||||
|
||||
#### Ajouter un Membre
|
||||
1. Cliquer sur "Ajouter Membre"
|
||||
2. Choisir la méthode :
|
||||
- **Scanner QR Code** : Invitation directe
|
||||
- **Envoyer un lien** : Lien d'invitation
|
||||
- **Saisir l'adresse** : Adresse device manuelle
|
||||
|
||||
#### Assigner des Rôles
|
||||
1. Sélectionner un membre
|
||||
2. Cliquer sur "Assigner Rôle"
|
||||
3. Choisir le rôle :
|
||||
- **Admin** : Gestion complète
|
||||
- **Signataire** : Peut signer des documents
|
||||
- **Lecteur** : Lecture seule
|
||||
- **Custom** : Rôle personnalisé
|
||||
|
||||
### Gestion des Documents
|
||||
|
||||
#### Importer un Document
|
||||
1. Cliquer sur "Importer Document"
|
||||
2. Choisir le fichier (PDF, DOC, etc.)
|
||||
3. Remplir les métadonnées :
|
||||
- **Nom** : Nom du document
|
||||
- **Description** : Détails du document
|
||||
- **Rôles requis** : Qui doit signer
|
||||
4. Valider l'import
|
||||
|
||||
#### Organiser les Documents
|
||||
- **Dossiers** : Créer des dossiers pour organiser
|
||||
- **Tags** : Ajouter des étiquettes
|
||||
- **Recherche** : Filtrer par nom, type, statut
|
||||
- **Tri** : Par date, nom, taille
|
||||
|
||||
## ✍️ Système de Signatures
|
||||
|
||||
### Demandes de Signature
|
||||
|
||||
#### Créer une Demande
|
||||
1. Aller dans l'onglet "Signatures"
|
||||
2. Cliquer sur "Nouvelle Demande"
|
||||
3. Remplir les informations :
|
||||
- **Document** : Sélectionner le document
|
||||
- **Signataires** : Choisir les participants
|
||||
- **Description** : Détails de la demande
|
||||
- **Date limite** : Échéance de signature
|
||||
- **Visibilité** : Publique ou privée
|
||||
4. Valider la création
|
||||
|
||||
#### Gérer les Demandes
|
||||
- **En attente** : Demandes non signées
|
||||
- **Signées** : Demandes complétées
|
||||
- **Expirées** : Demandes dépassées
|
||||
- **Actions** : Voir, modifier, annuler
|
||||
|
||||
### Signer un Document
|
||||
|
||||
#### Processus de Signature
|
||||
1. Recevoir une notification de demande
|
||||
2. Cliquer sur "Voir la demande"
|
||||
3. Prévisualiser le document
|
||||
4. Cliquer sur "Signer"
|
||||
5. Confirmer la signature
|
||||
|
||||
#### Types de Signature
|
||||
- **Signature électronique** : Signature numérique
|
||||
- **Signature biométrique** : Empreinte digitale
|
||||
- **Signature par mot de passe** : Code secret
|
||||
|
||||
## 💬 Système de Chat
|
||||
|
||||
### Communication Interne
|
||||
|
||||
#### Accès au Chat
|
||||
1. Aller dans l'onglet "Chat"
|
||||
2. Sélectionner le processus
|
||||
3. Voir les conversations
|
||||
|
||||
#### Envoyer un Message
|
||||
1. Sélectionner un utilisateur ou groupe
|
||||
2. Taper le message
|
||||
3. Cliquer sur "Envoyer"
|
||||
|
||||
#### Types de Messages
|
||||
- **Texte** : Messages simples
|
||||
- **Documents** : Fichiers partagés
|
||||
- **Images** : Captures d'écran
|
||||
- **Liens** : URLs partagées
|
||||
|
||||
### Notifications
|
||||
|
||||
#### Types de Notifications
|
||||
- **Messages** : Nouveaux messages reçus
|
||||
- **Signatures** : Demandes de signature
|
||||
- **Processus** : Mises à jour de processus
|
||||
- **Système** : Alertes système
|
||||
|
||||
#### Gestion des Notifications
|
||||
- **Marquer comme lu** : Cliquer sur la notification
|
||||
- **Répondre** : Répondre directement
|
||||
- **Ignorer** : Masquer la notification
|
||||
- **Paramètres** : Configurer les alertes
|
||||
|
||||
## 🔗 Système de Pairing
|
||||
|
||||
### Connexion avec d'Autres Utilisateurs
|
||||
|
||||
#### Méthodes de Pairing
|
||||
1. **QR Code** : Scanner le code d'un autre device
|
||||
2. **Lien d'invitation** : Envoyer un lien
|
||||
3. **Adresse manuelle** : Saisir l'adresse device
|
||||
|
||||
#### Processus de Pairing
|
||||
1. **Initiative** : Un utilisateur initie la connexion
|
||||
2. **Confirmation** : L'autre utilisateur confirme
|
||||
3. **Établissement** : La connexion est établie
|
||||
4. **Vérification** : Test de communication
|
||||
|
||||
#### Gestion des Connexions
|
||||
- **Connexions actives** : Devices connectés
|
||||
- **Demandes en attente** : Invitations non acceptées
|
||||
- **Historique** : Connexions passées
|
||||
- **Actions** : Déconnecter, renommer, supprimer
|
||||
|
||||
## 🔔 Notifications et Alertes
|
||||
|
||||
### Centre de Notifications
|
||||
|
||||
#### Accès aux Notifications
|
||||
- **Icône cloche** : En haut à droite
|
||||
- **Compteur** : Nombre de notifications non lues
|
||||
- **Liste** : Toutes les notifications
|
||||
|
||||
#### Types d'Alertes
|
||||
- **Urgentes** : Rouge, action immédiate requise
|
||||
- **Importantes** : Orange, attention requise
|
||||
- **Informatives** : Bleu, information générale
|
||||
- **Succès** : Vert, confirmation d'action
|
||||
|
||||
### Configuration des Notifications
|
||||
|
||||
#### Paramètres
|
||||
1. Aller dans "Paramètres" > "Notifications"
|
||||
2. Configurer par type :
|
||||
- **Messages** : Notifications de chat
|
||||
- **Signatures** : Demandes de signature
|
||||
- **Processus** : Mises à jour
|
||||
- **Système** : Alertes système
|
||||
|
||||
#### Préférences
|
||||
- **Son** : Activer/désactiver les sons
|
||||
- **Pop-up** : Notifications en pop-up
|
||||
- **Email** : Notifications par email
|
||||
- **Push** : Notifications push (si supporté)
|
||||
|
||||
## 🛠️ Fonctionnalités Avancées
|
||||
|
||||
### Recherche Globale
|
||||
|
||||
#### Utilisation
|
||||
1. Cliquer sur l'icône de recherche
|
||||
2. Taper le terme recherché
|
||||
3. Voir les résultats :
|
||||
- **Processus** : Processus correspondants
|
||||
- **Documents** : Documents correspondants
|
||||
- **Messages** : Messages correspondants
|
||||
- **Utilisateurs** : Utilisateurs correspondants
|
||||
|
||||
### Filtres et Tri
|
||||
|
||||
#### Filtres Disponibles
|
||||
- **Date** : Filtrer par période
|
||||
- **Type** : Filtrer par type de contenu
|
||||
- **Statut** : Filtrer par statut
|
||||
- **Utilisateur** : Filtrer par utilisateur
|
||||
|
||||
#### Options de Tri
|
||||
- **Date** : Plus récent/ancien
|
||||
- **Nom** : Alphabétique
|
||||
- **Taille** : Plus grand/petit
|
||||
- **Statut** : Priorité des statuts
|
||||
|
||||
### Export et Sauvegarde
|
||||
|
||||
#### Exporter des Données
|
||||
```bash
|
||||
# Export complet du profil
|
||||
Export User Data > JSON
|
||||
|
||||
# Export des processus
|
||||
Processus > Exporter > CSV
|
||||
|
||||
# Export des documents
|
||||
Documents > Exporter > ZIP
|
||||
```
|
||||
|
||||
#### Sauvegarde Automatique
|
||||
- **Sauvegarde locale** : Données stockées localement
|
||||
- **Synchronisation** : Synchronisation avec le serveur
|
||||
- **Récupération** : Restauration des données
|
||||
|
||||
## 🚨 Dépannage
|
||||
|
||||
### Problèmes Courants
|
||||
|
||||
#### Interface ne se charge pas
|
||||
```bash
|
||||
# Vérifier le serveur
|
||||
npm run dev
|
||||
|
||||
# Vérifier les logs
|
||||
npm run dev --verbose
|
||||
|
||||
# Nettoyer le cache
|
||||
npm run clean
|
||||
```
|
||||
|
||||
#### Module WASM non trouvé
|
||||
```bash
|
||||
# Recompiler le module WASM
|
||||
./scripts/setup-remote-deps.sh
|
||||
|
||||
# Vérifier le fichier
|
||||
ls -la pkg/sdk_client_bg.wasm
|
||||
```
|
||||
|
||||
#### Erreurs de connexion
|
||||
```bash
|
||||
# Vérifier les variables d'environnement
|
||||
cat .env
|
||||
|
||||
# Tester la connectivité
|
||||
npm run test:connectivity
|
||||
```
|
||||
|
||||
### Support Utilisateur
|
||||
|
||||
#### Obtenir de l'Aide
|
||||
1. **Documentation** : Consulter ce guide
|
||||
2. **FAQ** : Questions fréquentes
|
||||
3. **Support** : Contacter l'équipe
|
||||
4. **Issues** : Signaler un problème
|
||||
|
||||
#### Signaler un Bug
|
||||
1. Aller sur [Issues](https://git.4nkweb.com/4nk/ihm_client/issues)
|
||||
2. Créer une nouvelle issue
|
||||
3. Décrire le problème :
|
||||
- **Étapes** : Comment reproduire
|
||||
- **Comportement** : Ce qui se passe
|
||||
- **Attendu** : Ce qui devrait se passer
|
||||
- **Environnement** : OS, navigateur, version
|
||||
|
||||
## 📊 Métriques d'Utilisation
|
||||
|
||||
### Statistiques Personnelles
|
||||
- **Processus créés** : Nombre de processus
|
||||
- **Documents signés** : Nombre de signatures
|
||||
- **Messages envoyés** : Communication
|
||||
- **Temps d'utilisation** : Temps passé
|
||||
|
||||
### Performance
|
||||
- **Temps de chargement** : Vitesse de l'interface
|
||||
- **Temps de réponse** : Réactivité
|
||||
- **Utilisation mémoire** : Consommation RAM
|
||||
- **Taille des données** : Stockage utilisé
|
||||
|
||||
---
|
||||
|
||||
**🎯 Interface utilisateur ihm_client - Prête pour une utilisation quotidienne !** ✨
|
@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="author" content="4NK">
|
||||
<meta name="description" content="4NK Web5 Platform">
|
||||
<meta name="keywords" content="4NK web5 bitcoin blockchain decentralize dapps relay contract">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/style/4nk.css">
|
||||
<script src="https://unpkg.com/html5-qrcode"></script>
|
||||
<title>4NK Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header-container"></div>
|
||||
<div id="containerId" class="container">
|
||||
<!-- 4NK Web5 Solution -->
|
||||
</div>
|
||||
<!-- <script type="module" src="/src/index.ts"></script> -->
|
||||
<script type="module">
|
||||
import { init } from '/src/router.ts';
|
||||
(async () => {
|
||||
await init();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,34 +0,0 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'jsdom',
|
||||
roots: ['<rootDir>/src', '<rootDir>/tests'],
|
||||
testMatch: [
|
||||
'**/__tests__/**/*.ts',
|
||||
'**/?(*.)+(spec|test).ts'
|
||||
],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest',
|
||||
},
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.ts',
|
||||
'!src/**/*.d.ts',
|
||||
'!src/main.ts',
|
||||
'!src/vite-env.d.ts'
|
||||
],
|
||||
coverageDirectory: 'coverage',
|
||||
coverageReporters: ['text', 'lcov', 'html'],
|
||||
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
'^~/(.*)$': '<rootDir>/src/$1',
|
||||
'^pkg/(.*)$': '<rootDir>/pkg/$1',
|
||||
'^(.*)\\?raw$': '<rootDir>/tests/rawFileMock.js',
|
||||
'\\.(css|less|sass|scss)$': '<rootDir>/tests/styleMock.js'
|
||||
},
|
||||
testTimeout: 10000,
|
||||
transform: {
|
||||
'^.+\\.ts$': ['ts-jest', {
|
||||
tsconfig: 'tsconfig.json'
|
||||
}],
|
||||
}
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|wasm)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
12413
modules/ihm_client/package-lock.json
generated
12413
modules/ihm_client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,66 +0,0 @@
|
||||
{
|
||||
"name": "sdk_client",
|
||||
"version": "1.1.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage",
|
||||
"test:unit": "jest --testPathPattern=tests/unit",
|
||||
"test:integration": "jest --testPathPattern=tests/integration",
|
||||
"build_wasm": "./scripts/setup-remote-deps.sh",
|
||||
"cleanup_deps": "./scripts/cleanup-deps.sh",
|
||||
"start": "vite --host 0.0.0.0",
|
||||
"build": "tsc && vite build",
|
||||
"deploy": "sudo cp -r dist/* /var/www/html/",
|
||||
"prettify": "prettier --config ./.prettierrc --write \"src/**/*{.ts,.html,.css,.js}\"",
|
||||
"build:dist": "tsc -p tsconfig.build.json",
|
||||
"lint": "prettier -c \"src/**/*{.ts,.html,.css,.js}\"",
|
||||
"type-check": "tsc -p tsconfig.json --noEmit",
|
||||
"e2e:install": "npx playwright install --with-deps",
|
||||
"test:e2e": "playwright test"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^12.1.1",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.24",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"prettier": "^3.3.3",
|
||||
"rimraf": "^6.0.1",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.4.11",
|
||||
"vite-plugin-static-copy": "^1.0.6",
|
||||
"webpack": "^5.90.3",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.2",
|
||||
"@playwright/test": "^1.46.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/elements": "^19.0.1",
|
||||
"@types/jsonwebtoken": "^9.0.9",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"axios": "^1.11.0",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"jose": "^6.0.13",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"qr-scanner": "^1.4.2",
|
||||
"qrcode": "^1.5.4",
|
||||
"sweetalert2": "^11.22.4",
|
||||
"vite-plugin-copy": "^0.1.6",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-wasm": "^3.3.0"
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e',
|
||||
timeout: 30000,
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000',
|
||||
headless: true,
|
||||
},
|
||||
webServer: {
|
||||
command: 'npx vite preview --strictPort --port 3000',
|
||||
port: 3000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
projects: [
|
||||
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
||||
],
|
||||
});
|
Binary file not shown.
Before Width: | Height: | Size: 61 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
Before Width: | Height: | Size: 509 KiB |
Binary file not shown.
Before Width: | Height: | Size: 73 KiB |
@ -1,34 +0,0 @@
|
||||
document.querySelectorAll('.tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
|
||||
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
||||
document.getElementById(tab.getAttribute('data-tab')).classList.add('active');
|
||||
});
|
||||
});
|
||||
function toggleMenu() {
|
||||
var menu = document.getElementById('menu');
|
||||
if (menu.style.display === 'block') {
|
||||
menu.style.display = 'none';
|
||||
} else {
|
||||
menu.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
//// Modal
|
||||
function openModal() {
|
||||
document.getElementById('modal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById('modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Close modal when clicking outside of it
|
||||
window.onclick = function(event) {
|
||||
const modal = document.getElementById('modal');
|
||||
if (event.target === modal) {
|
||||
closeModal();
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 8.9 KiB |
@ -1,877 +0,0 @@
|
||||
:root {
|
||||
--primary-color
|
||||
: #3A506B;
|
||||
/* Bleu métallique */
|
||||
--secondary-color
|
||||
: #B0BEC5;
|
||||
/* Gris acier */
|
||||
--accent-color
|
||||
: #D68C45;
|
||||
/* Cuivre */
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
background-image: url(../assets/bgd.webp);
|
||||
background-repeat:no-repeat;
|
||||
background-size: cover;
|
||||
background-blend-mode :soft-light;
|
||||
height: 100vh;
|
||||
}
|
||||
.message {
|
||||
margin: 30px 0;
|
||||
font-size: 14px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.message strong{
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/** Modal Css */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 55%;
|
||||
height: 30%;
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
margin: 0;
|
||||
padding-bottom: 8px;
|
||||
width: 100%;
|
||||
font-size: 0.9em;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.confirmation-box {
|
||||
/* margin-top: 20px; */
|
||||
align-content: center;
|
||||
width: 70%;
|
||||
height: 20%;
|
||||
/* padding: 20px; */
|
||||
font-size: 1.5em;
|
||||
color: #333333;
|
||||
top: 5%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Confirmation Modal Styles */
|
||||
#confirmation-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.modal-confirmation {
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.modal-confirmation h3 {
|
||||
margin-bottom: 15px;
|
||||
color: var(--primary-color);
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.modal-confirmation p {
|
||||
margin: 8px 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.modal-footer button {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--secondary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media only screen and (max-width: 600px) {
|
||||
.modal-content {
|
||||
width: 95%;
|
||||
margin: 10px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.modal-confirmation h3 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.modal-confirmation p {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
background: radial-gradient(circle, white, var(--primary-color));
|
||||
/* background-color: #CFD8DC; */
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
color: #37474F;
|
||||
height: 9vh;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, .2), 0px 16px 24px 2px rgba(0, 0, 0, .14), 0px 6px 30px 5px rgba(0, 0, 0, .12);
|
||||
|
||||
.nav-right-icons {
|
||||
display: flex;
|
||||
.notification-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.notification-bell, .burger-menu {
|
||||
z-index: 3;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -.7rem;
|
||||
left: -.8rem;
|
||||
background-color: red;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 2.5px 6px;
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.notification-board {
|
||||
position: absolute;
|
||||
width: 20rem;
|
||||
min-height: 8rem;
|
||||
background-color: white;
|
||||
right: 0.5rem;
|
||||
display: none;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
|
||||
.notification-element {
|
||||
padding: .8rem 0;
|
||||
width: 100%;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
.notification-element:not(:last-child) {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 100%;
|
||||
width: 100vw;
|
||||
align-content: center;
|
||||
position: relative;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
display: grid;
|
||||
height: 100vh;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 10px;
|
||||
grid-auto-rows: 10vh 15vh 1fr;
|
||||
}
|
||||
.title-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 2;
|
||||
}
|
||||
.page-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 3 ;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 20px 0;
|
||||
}
|
||||
@media only screen and (min-width: 600px) {
|
||||
.tab-container {
|
||||
display: none;
|
||||
}
|
||||
.page-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.process-container {
|
||||
grid-column: 3 / 6;
|
||||
grid-row: 3 ;
|
||||
|
||||
.card {
|
||||
min-width: 40vw;
|
||||
}
|
||||
}
|
||||
.separator {
|
||||
width: 2px;
|
||||
background-color: #78909C;
|
||||
height: 80%;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.tab-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.process-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 3 ;
|
||||
}
|
||||
.container {
|
||||
grid-auto-rows: 10vh 15vh 15vh 1fr;
|
||||
}
|
||||
.tab-container {
|
||||
grid-column: 1 / 8;
|
||||
grid-row: 3;
|
||||
}
|
||||
.page-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 4 ;
|
||||
}
|
||||
.separator {
|
||||
display: none;
|
||||
}
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #E0E4D6;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
color: #6200ea;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
.tab.active {
|
||||
border-bottom: 2px solid #6200ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 80%;
|
||||
}
|
||||
.modal-content {
|
||||
width: 80%;
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.emoji-display {
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 20px;
|
||||
|
||||
}
|
||||
|
||||
#emoji-display-2{
|
||||
margin-top: 30px;
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#okButton{
|
||||
margin-bottom: 2em;
|
||||
cursor: pointer;
|
||||
background-color: #D0D0D7;
|
||||
color: white;
|
||||
border-style: none;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.pairing-request {
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 14px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.sp-address-btn {
|
||||
margin-bottom: 2em;
|
||||
cursor: pointer;
|
||||
background-color: #D0D0D7;
|
||||
color: white;
|
||||
border-style: none;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
|
||||
}
|
||||
|
||||
.camera-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* height: 200px; */
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #3700b3;
|
||||
}
|
||||
|
||||
|
||||
.card {
|
||||
min-width: 300px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
height: 60vh;
|
||||
justify-content: flex-start;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
|
||||
}
|
||||
|
||||
.card-content {
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
font-size: .8em;
|
||||
position: relative;
|
||||
left: 2vw;
|
||||
width: 90%;
|
||||
.process-title {
|
||||
font-weight: bold;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.process-element {
|
||||
padding: .4rem 0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
&.selected {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-description {
|
||||
padding: 20px;
|
||||
font-size: 1em;
|
||||
color: #333;
|
||||
width: 90%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
|
||||
.card-action {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 3.4rem;
|
||||
right: 1rem;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menu-content a {
|
||||
display: block;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-content a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.qr-code-scanner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* QR READER */
|
||||
#qr-reader div {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
#qr-reader div img{
|
||||
top: 15px ;
|
||||
right: 25px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* INPUT CSS **/
|
||||
.input-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #ECEFF1;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 36vw;
|
||||
padding: 10px 0;
|
||||
font-size: 1em;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
border-bottom: 2px solid #6200ea;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
position: absolute;
|
||||
margin-top: -0.5em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 10px 0;
|
||||
font-size: 1em;
|
||||
color: #999;
|
||||
pointer-events: none;
|
||||
transition: transform 0.3s, color 0.3s, font-size 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus + .input-label,
|
||||
.input-field:not(:placeholder-shown) + .input-label {
|
||||
transform: translateY(-20px);
|
||||
font-size: 0.8em;
|
||||
color: #6200ea;
|
||||
}
|
||||
|
||||
.input-underline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background-color: #6200ea;
|
||||
transition: width 0.3s, left 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus ~ .input-underline {
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
position: absolute;
|
||||
flex-direction: column;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-content span {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.dropdown-content span:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** AUTOCOMPLETE **/
|
||||
|
||||
select[data-multi-select-plugin] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.multi-select-component {
|
||||
width: 36vw;
|
||||
padding: 5px 0;
|
||||
font-size: 1em;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
-o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
.multi-select-component:focus-within {
|
||||
box-shadow: inset 0px 0px 0px 2px #78ABFE;
|
||||
}
|
||||
|
||||
.multi-select-component .btn-group {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.multiselect-native-select .multiselect-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.selected-processes {
|
||||
background-color: white;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.selected-wrapper {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
border: 1px solid #d9d9d9;
|
||||
background-color: #ededed;
|
||||
white-space: nowrap;
|
||||
margin: 1px 5px 5px 0;
|
||||
height: 22px;
|
||||
vertical-align: top;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.selected-wrapper .selected-label {
|
||||
max-width: 514px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.selected-wrapper .selected-close {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
line-height: 1.49em;
|
||||
margin-left: 5px;
|
||||
padding-bottom: 10px;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
padding-right: 4px;
|
||||
opacity: 0.2;
|
||||
color: #000;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.search-container .selected-input {
|
||||
background: none;
|
||||
border: 0;
|
||||
height: 20px;
|
||||
width: 60px;
|
||||
padding: 0;
|
||||
margin-bottom: 6px;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.search-container .selected-input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dropdown-icon.active {
|
||||
transform: rotateX(180deg)
|
||||
}
|
||||
|
||||
.search-container .dropdown-icon {
|
||||
display: inline-block;
|
||||
padding: 10px 5px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 0 !important;
|
||||
/* needed */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
/* SVG background image */
|
||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23818181%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C0%2C0%2C1.414%2C0l5-5a1%2C1%2C0%2C1%2C0-1.414-1.414Z%22%20fill%3D%22%23818181%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
||||
background-position: center;
|
||||
background-size: 10px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.search-container ul {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
z-index: 3;
|
||||
margin-top: 29px;
|
||||
width: 100%;
|
||||
right: 0px;
|
||||
background: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
}
|
||||
|
||||
.search-container ul :focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search-container ul li {
|
||||
display: block;
|
||||
text-align: left;
|
||||
padding: 8px 29px 2px 12px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-size: 14px;
|
||||
min-height: 31px;
|
||||
}
|
||||
|
||||
.search-container ul li:first-child {
|
||||
border-top: 1px solid #ccc;
|
||||
border-radius: 4px 0px 0 0;
|
||||
}
|
||||
|
||||
.search-container ul li:last-child {
|
||||
border-radius: 4px 0px 0 0;
|
||||
}
|
||||
|
||||
|
||||
.search-container ul li:hover.not-cursor {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.search-container ul li:hover {
|
||||
color: #333;
|
||||
background-color: #f0f0f0;
|
||||
;
|
||||
border-color: #adadad;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Adding scrool to select options */
|
||||
.autocomplete-list {
|
||||
max-height: 130px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************** Process page card ******************************************************/
|
||||
.process-card {
|
||||
min-width: 300px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
min-height: 40vh;
|
||||
max-height: 60vh;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
|
||||
}
|
||||
|
||||
.process-card-content {
|
||||
text-align: left;
|
||||
font-size: .8em;
|
||||
position: relative;
|
||||
left: 2vw;
|
||||
width: 90%;
|
||||
.process-title {
|
||||
font-weight: bold;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.process-element {
|
||||
padding: .4rem 0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
&.selected {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
.selected-process-zone {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
|
||||
.process-card-description {
|
||||
padding: 20px;
|
||||
font-size: 1em;
|
||||
color: #333;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
|
||||
.process-card-action {
|
||||
width: 100%;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,597 +0,0 @@
|
||||
/* Styles de base */
|
||||
:root {
|
||||
--primary-color: #3A506B;
|
||||
/* Bleu métallique */
|
||||
--secondary-color: #B0BEC5;
|
||||
/* Gris acier */
|
||||
--accent-color: #D68C45;
|
||||
/* Cuivre */
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* 4NK NAVBAR */
|
||||
|
||||
.brand-logo {
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: fixed;
|
||||
background: radial-gradient(circle, white, var(--primary-color));
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #37474F;
|
||||
height: 9vh;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, .2), 0px 16px 24px 2px rgba(0, 0, 0, .14), 0px 6px 30px 5px rgba(0, 0, 0, .12);
|
||||
}
|
||||
|
||||
/* Icônes de la barre de navigation */
|
||||
.nav-right-icons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.notification-bell,
|
||||
.burger-menu {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.notification-container {
|
||||
position: relative;
|
||||
/* Conserve la position pour le notification-board */
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.notification-board {
|
||||
position: absolute;
|
||||
/* Position absolue pour le placer par rapport au container */
|
||||
top: 40px;
|
||||
right: 0;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
width: 200px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
/* Scroll si les notifications dépassent la taille */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
/* Définit la priorité d'affichage au-dessus des autres éléments */
|
||||
display: none;
|
||||
/* Par défaut, la notification est masquée */
|
||||
}
|
||||
|
||||
.notification-item{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: 35px;
|
||||
background-color: red;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
display: none;
|
||||
/* S'affiche seulement lorsqu'il y a des notifications */
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Par défaut, le menu est masqué */
|
||||
#menu {
|
||||
display: none;
|
||||
/* Menu caché par défaut */
|
||||
transition: display 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.burger-menu {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Icône burger */
|
||||
#burger-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 3.4rem;
|
||||
right: 1rem;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menu-content a {
|
||||
display: block;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-content a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Ajustement pour la barre de navigation fixe */
|
||||
.container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 90vh;
|
||||
margin-top: 9vh;
|
||||
margin-left: -1%;
|
||||
text-align: left;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
|
||||
/* Liste des groupes */
|
||||
|
||||
.group-list {
|
||||
width: 25%;
|
||||
background-color: #1f2c3d;
|
||||
color: white;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
border-right: 2px solid #2c3e50;
|
||||
flex-shrink: 0;
|
||||
padding-right: 10px;
|
||||
height: 91vh;
|
||||
}
|
||||
.group-list ul {
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
padding-right: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.group-list li {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
background-color: #273646;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s, box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.group-list li:hover {
|
||||
background-color: #34495e;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
|
||||
.group-list .member-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.group-list .member-container button {
|
||||
margin-left: 40px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: 0px solid var(--primary-color);
|
||||
border-radius: 50px;
|
||||
position: absolute;
|
||||
top: -25px;
|
||||
right: -25px;
|
||||
}
|
||||
|
||||
.group-list .member-container button:hover {
|
||||
background: var(--accent-color)
|
||||
}
|
||||
|
||||
|
||||
/* Zone de chat */
|
||||
.chat-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background-color:#f1f1f1;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
margin: 1% 0% 0.5% 1%;
|
||||
}
|
||||
|
||||
/* En-tête du chat */
|
||||
.chat-header {
|
||||
background-color: #34495e;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
border-radius: 10px 10px 0 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Messages */
|
||||
.messages {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
background-color: #f1f1f1;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.message-container {
|
||||
display: flex;
|
||||
margin: 8px;
|
||||
}
|
||||
.message-container .message {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.message-container .message.user {
|
||||
align-self: flex-end;
|
||||
margin-left: auto;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message {
|
||||
max-width: 70%;
|
||||
padding: 10px;
|
||||
border-radius: 12px;
|
||||
background:var(--secondary-color);
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
/* Messages de l'utilisateur */
|
||||
.message.user {
|
||||
background: #2196f3;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 0.7em;
|
||||
opacity: 0.7;
|
||||
margin-left: 0px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* Amélioration de l'esthétique des messages */
|
||||
/* .message.user:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: -10px;
|
||||
border: 10px solid transparent;
|
||||
border-left-color: #3498db;
|
||||
} */
|
||||
|
||||
/* Zone de saisie */
|
||||
.input-area {
|
||||
padding: 10px;
|
||||
background-color: #bdc3c7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 10px;
|
||||
margin: 1%;
|
||||
/* Alignement vertical */
|
||||
}
|
||||
|
||||
.input-area input[type="text"] {
|
||||
flex: 1;
|
||||
/* Prend l'espace restant */
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.input-area .attachment-icon {
|
||||
margin: 0 10px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-area button {
|
||||
padding: 10px;
|
||||
margin-left: 10px;
|
||||
background-color: #2980b9;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-area button:hover {
|
||||
background-color: #1f608d;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
margin: 20px 0px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tabs button {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: 0px solid var(--primary-color);
|
||||
margin-right: 5px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.tabs button:hover {
|
||||
background: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Signature */
|
||||
.signature-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background-color:#f1f1f1;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
margin: 1% 0% 0.5% 1%;
|
||||
transition: all 1s ease 0.1s;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.signature-area.hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.signature-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border-radius: 10px 10px 0 0;
|
||||
padding-left: 4%;
|
||||
}
|
||||
|
||||
.signature-content {
|
||||
padding: 10px;
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
margin: 1%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.signature-description {
|
||||
height: 20%;
|
||||
width: 100%;
|
||||
margin: 0% 10% 0% 10%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.signature-description li {
|
||||
margin: 1% 0% 1% 0%;
|
||||
list-style: none;
|
||||
padding: 2%;
|
||||
border-radius: 10px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--secondary-color);
|
||||
width: 20%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
margin-right: 2%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.signature-description li .member-list {
|
||||
margin-left: -30%;
|
||||
}
|
||||
|
||||
.signature-description li .member-list li {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.signature-description li .member-list li:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.signature-documents {
|
||||
height: 80%;
|
||||
width: 100%;
|
||||
margin: 0% 10% 0% 10%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.signature-documents-header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 15%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#request-document-button {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
margin-left: 5%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#request-document-button:hover {
|
||||
background-color: var(--accent-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#close-signature {
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
margin-right: 2%;
|
||||
border-radius: 50%;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: -3%;
|
||||
margin-top: -5%;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#close-signature:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* REQUEST MODAL */
|
||||
.request-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--secondary-color);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
position: relative;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.close-modal {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close-modal:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.modal-members {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-members ul li{
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.file-upload-container {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
margin: 5px 0;
|
||||
background: var(--background-color-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.remove-file {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.remove-file:hover {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
#message-input {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
resize: none;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media screen and (max-width: 768px) {
|
||||
.group-list {
|
||||
display: none;
|
||||
/* Masquer la liste des groupes sur les petits écrans */
|
||||
}
|
||||
|
||||
.chat-area {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--primary-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--secondary-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--accent-color);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,155 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script d'automatisation des push SSH pour ihm_client
|
||||
# Utilise automatiquement la clé SSH pour tous les push
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔑 Configuration automatique SSH pour push ihm_client..."
|
||||
|
||||
# Configuration SSH automatique
|
||||
echo "⚙️ Configuration Git pour utiliser SSH..."
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
|
||||
# Vérifier la configuration SSH
|
||||
echo "🔍 Vérification de la configuration SSH..."
|
||||
if ! ssh -T git@git.4nkweb.com 2>&1 | grep -q "successfully authenticated"; then
|
||||
echo "❌ Échec de l'authentification SSH"
|
||||
echo "💡 Vérifiez que votre clé SSH est configurée :"
|
||||
echo " 1. ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk"
|
||||
echo " 2. Ajouter la clé publique à votre compte Gitea"
|
||||
echo " 3. ssh-add ~/.ssh/id_ed25519_4nk"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Authentification SSH réussie"
|
||||
|
||||
# Fonction pour push automatique
|
||||
auto_push() {
|
||||
local branch=${1:-$(git branch --show-current)}
|
||||
local commit_message=${2:-"Auto-commit $(date '+%Y-%m-%d %H:%M:%S')"}
|
||||
|
||||
echo "🚀 Push automatique sur la branche: $branch"
|
||||
|
||||
# Ajouter tous les changements
|
||||
git add .
|
||||
|
||||
# Commiter avec le message fourni
|
||||
git commit -m "$commit_message"
|
||||
|
||||
# Push avec SSH automatique
|
||||
echo "📤 Push vers origin/$branch..."
|
||||
git push origin "$branch"
|
||||
|
||||
echo "✅ Push réussi !"
|
||||
}
|
||||
|
||||
# Fonction pour push avec message personnalisé
|
||||
push_with_message() {
|
||||
local message="$1"
|
||||
local branch=${2:-$(git branch --show-current)}
|
||||
|
||||
echo "💬 Push avec message: $message"
|
||||
auto_push "$branch" "$message"
|
||||
}
|
||||
|
||||
# Fonction pour push rapide (sans message)
|
||||
quick_push() {
|
||||
local branch=${1:-$(git branch --show-current)}
|
||||
auto_push "$branch"
|
||||
}
|
||||
|
||||
# Fonction pour push sur une branche spécifique
|
||||
push_branch() {
|
||||
local branch="$1"
|
||||
local message=${2:-"Update $branch $(date '+%Y-%m-%d %H:%M:%S')"}
|
||||
|
||||
echo "🌿 Push sur la branche: $branch"
|
||||
auto_push "$branch" "$message"
|
||||
}
|
||||
|
||||
# Fonction pour push et merge vers main
|
||||
push_and_merge() {
|
||||
local source_branch=${1:-$(git branch --show-current)}
|
||||
local target_branch=${2:-main}
|
||||
|
||||
echo "🔄 Push et merge $source_branch -> $target_branch"
|
||||
|
||||
# Push de la branche source
|
||||
auto_push "$source_branch"
|
||||
|
||||
# Demander confirmation pour le merge
|
||||
read -p "Voulez-vous créer une Pull Request pour merger vers $target_branch ? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "🔗 Création de la Pull Request..."
|
||||
echo "💡 Allez sur: https://git.4nkweb.com/4nk/ihm_client/compare/$target_branch...$source_branch"
|
||||
fi
|
||||
}
|
||||
|
||||
# Fonction pour status et push conditionnel
|
||||
status_and_push() {
|
||||
echo "📊 Statut du repository:"
|
||||
git status --short
|
||||
|
||||
if [[ -n $(git status --porcelain) ]]; then
|
||||
echo "📝 Changements détectés, push automatique..."
|
||||
auto_push
|
||||
else
|
||||
echo "✅ Aucun changement à pousser"
|
||||
fi
|
||||
}
|
||||
|
||||
# Menu interactif si aucun argument fourni
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "🤖 Script de push SSH automatique pour ihm_client"
|
||||
echo ""
|
||||
echo "Options disponibles:"
|
||||
echo " auto-push.sh quick - Push rapide"
|
||||
echo " auto-push.sh message \"Mon message\" - Push avec message"
|
||||
echo " auto-push.sh branch nom-branche - Push sur branche spécifique"
|
||||
echo " auto-push.sh merge [source] [target] - Push et préparation merge"
|
||||
echo " auto-push.sh status - Status et push conditionnel"
|
||||
echo ""
|
||||
echo "Exemples:"
|
||||
echo " ./scripts/auto-ssh-push.sh quick"
|
||||
echo " ./scripts/auto-ssh-push.sh message \"feat: nouvelle fonctionnalité\""
|
||||
echo " ./scripts/auto-ssh-push.sh branch feature/nouvelle-fonctionnalite"
|
||||
echo " ./scripts/auto-ssh-push.sh merge feature/nouvelle-fonctionnalite main"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Traitement des arguments
|
||||
case "$1" in
|
||||
"quick")
|
||||
quick_push
|
||||
;;
|
||||
"message")
|
||||
if [[ -z "$2" ]]; then
|
||||
echo "❌ Message requis pour l'option 'message'"
|
||||
exit 1
|
||||
fi
|
||||
push_with_message "$2"
|
||||
;;
|
||||
"branch")
|
||||
if [[ -z "$2" ]]; then
|
||||
echo "❌ Nom de branche requis pour l'option 'branch'"
|
||||
exit 1
|
||||
fi
|
||||
push_branch "$2" "$3"
|
||||
;;
|
||||
"merge")
|
||||
push_and_merge "$2" "$3"
|
||||
;;
|
||||
"status")
|
||||
status_and_push
|
||||
;;
|
||||
*)
|
||||
echo "❌ Option inconnue: $1"
|
||||
echo "💡 Utilisez './scripts/auto-ssh-push.sh' pour voir les options"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "🎯 Push SSH automatique terminé !"
|
@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
version_file="VERSION"
|
||||
[[ -f TEMPLATE_VERSION ]] && version_file="TEMPLATE_VERSION"
|
||||
|
||||
[[ -f "$version_file" ]] || { echo "Version file missing ($version_file)"; exit 1; }
|
||||
v=$(tr -d '\r' < "$version_file" | head -n1)
|
||||
[[ -n "$v" ]] || { echo "Empty version"; exit 1; }
|
||||
|
||||
echo "Version file: $version_file=$v"
|
||||
|
||||
if ! grep -Eq "^## \\[$(echo "$v" | sed 's/^v//')\\]" CHANGELOG.md; then
|
||||
echo "CHANGELOG entry for $v not found"; exit 1;
|
||||
fi
|
||||
|
||||
echo "Version alignment OK"
|
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🧹 Nettoyage des dépendances temporaires..."
|
||||
|
||||
# Suppression du dossier temporaire
|
||||
if [ -d "./temp-deps" ]; then
|
||||
echo " → Suppression de ./temp-deps/"
|
||||
rm -rf ./temp-deps
|
||||
echo "✅ Dossier temp-deps supprimé"
|
||||
else
|
||||
echo "ℹ️ Aucun dossier temp-deps trouvé"
|
||||
fi
|
||||
|
||||
# Vérification des fichiers WASM
|
||||
if [ -d "./pkg" ]; then
|
||||
echo "📁 Fichiers WASM conservés dans ./pkg/"
|
||||
ls -la ./pkg/
|
||||
else
|
||||
echo "⚠️ Aucun fichier WASM trouvé dans ./pkg/"
|
||||
fi
|
||||
|
||||
echo "✅ Nettoyage terminé"
|
@ -1,145 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ENV_DIR="${HOME}/.4nk_template"
|
||||
ENV_FILE="${ENV_DIR}/.env"
|
||||
TEMPLATE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
TEMPLATE_IN_REPO="${TEMPLATE_ROOT}/scripts/env/.env.template"
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: $0 <git_url> [--dest DIR] [--force]
|
||||
|
||||
Actions:
|
||||
1) Provisionne ~/.4nk_template/.env (si absent)
|
||||
2) Clone le dépôt cible si le dossier n'existe pas
|
||||
3) Copie la structure normative 4NK_template dans le projet cible:
|
||||
- .gitea/** (workflows, templates issues/PR)
|
||||
- AGENTS.md
|
||||
- .cursor/rules/** (si présent)
|
||||
- scripts/agents/**, scripts/env/ensure_env.sh, scripts/deploy/setup.sh
|
||||
- docs/templates/** et docs/INDEX.md (table des matières)
|
||||
4) Ne remplace pas les fichiers existants sauf si --force
|
||||
|
||||
Exemples:
|
||||
$0 https://git.example.com/org/projet.git
|
||||
$0 git@host:org/projet.git --dest ~/work --force
|
||||
USAGE
|
||||
}
|
||||
|
||||
GIT_URL="${1:-}"
|
||||
DEST_PARENT="$(pwd)"
|
||||
FORCE_COPY=0
|
||||
shift || true
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dest)
|
||||
DEST_PARENT="${2:-}"; shift 2 ;;
|
||||
--force)
|
||||
FORCE_COPY=1; shift ;;
|
||||
-h|--help)
|
||||
usage; exit 0 ;;
|
||||
*)
|
||||
echo "Option inconnue: $1" >&2; usage; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "${GIT_URL}" ]]; then
|
||||
usage; exit 2
|
||||
fi
|
||||
|
||||
mkdir -p "${ENV_DIR}"
|
||||
chmod 700 "${ENV_DIR}" || true
|
||||
|
||||
if [[ ! -f "${ENV_FILE}" ]]; then
|
||||
if [[ -f "${TEMPLATE_IN_REPO}" ]]; then
|
||||
cp "${TEMPLATE_IN_REPO}" "${ENV_FILE}"
|
||||
else
|
||||
cat >"${ENV_FILE}" <<'EOF'
|
||||
# Fichier d'exemple d'environnement pour 4NK_template
|
||||
# Copiez ce fichier vers ~/.4nk_template/.env puis complétez les valeurs.
|
||||
# Ne committez jamais de fichier contenant des secrets.
|
||||
|
||||
# OpenAI (agents IA)
|
||||
OPENAI_API_KEY=
|
||||
OPENAI_MODEL=
|
||||
OPENAI_API_BASE=https://api.openai.com/v1
|
||||
OPENAI_TEMPERATURE=0.2
|
||||
|
||||
# Gitea (release via API)
|
||||
BASE_URL=https://git.4nkweb.com
|
||||
RELEASE_TOKEN=
|
||||
EOF
|
||||
fi
|
||||
chmod 600 "${ENV_FILE}" || true
|
||||
echo "Fichier créé: ${ENV_FILE}. Complétez les valeurs requises (ex: OPENAI_API_KEY, OPENAI_MODEL, RELEASE_TOKEN)." >&2
|
||||
fi
|
||||
|
||||
# 2) Clonage du dépôt si nécessaire
|
||||
repo_name="$(basename -s .git "${GIT_URL}")"
|
||||
target_dir="${DEST_PARENT%/}/${repo_name}"
|
||||
if [[ ! -d "${target_dir}" ]]; then
|
||||
echo "Clonage: ${GIT_URL} → ${target_dir}" >&2
|
||||
git clone --depth 1 "${GIT_URL}" "${target_dir}"
|
||||
else
|
||||
echo "Dossier existant, pas de clone: ${target_dir}" >&2
|
||||
fi
|
||||
|
||||
copy_item() {
|
||||
local src="$1" dst="$2"
|
||||
if [[ ! -e "$src" ]]; then return 0; fi
|
||||
if [[ -d "$src" ]]; then
|
||||
mkdir -p "$dst"
|
||||
if (( FORCE_COPY )); then
|
||||
cp -a "$src/." "$dst/"
|
||||
else
|
||||
(cd "$src" && find . -type f -print0) | while IFS= read -r -d '' f; do
|
||||
if [[ ! -e "$dst/$f" ]]; then
|
||||
mkdir -p "$(dirname "$dst/$f")"
|
||||
cp -a "$src/$f" "$dst/$f"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
if [[ -e "$dst" && $FORCE_COPY -eq 0 ]]; then return 0; fi
|
||||
mkdir -p "$(dirname "$dst")" && cp -a "$src" "$dst"
|
||||
fi
|
||||
}
|
||||
|
||||
# 3) Copie de la structure normative
|
||||
copy_item "${TEMPLATE_ROOT}/.gitea" "${target_dir}/.gitea"
|
||||
copy_item "${TEMPLATE_ROOT}/AGENTS.md" "${target_dir}/AGENTS.md"
|
||||
copy_item "${TEMPLATE_ROOT}/.cursor" "${target_dir}/.cursor"
|
||||
copy_item "${TEMPLATE_ROOT}/.cursorignore" "${target_dir}/.cursorignore"
|
||||
copy_item "${TEMPLATE_ROOT}/.gitignore" "${target_dir}/.gitignore"
|
||||
copy_item "${TEMPLATE_ROOT}/.markdownlint.json" "${target_dir}/.markdownlint.json"
|
||||
copy_item "${TEMPLATE_ROOT}/LICENSE" "${target_dir}/LICENSE"
|
||||
copy_item "${TEMPLATE_ROOT}/CONTRIBUTING.md" "${target_dir}/CONTRIBUTING.md"
|
||||
copy_item "${TEMPLATE_ROOT}/CODE_OF_CONDUCT.md" "${target_dir}/CODE_OF_CONDUCT.md"
|
||||
copy_item "${TEMPLATE_ROOT}/SECURITY.md" "${target_dir}/SECURITY.md"
|
||||
copy_item "${TEMPLATE_ROOT}/TEMPLATE_VERSION" "${target_dir}/TEMPLATE_VERSION"
|
||||
copy_item "${TEMPLATE_ROOT}/security" "${target_dir}/security"
|
||||
copy_item "${TEMPLATE_ROOT}/scripts" "${target_dir}/scripts"
|
||||
copy_item "${TEMPLATE_ROOT}/docs/templates" "${target_dir}/docs/templates"
|
||||
|
||||
# Génération docs/INDEX.md dans le projet cible (si absent ou --force)
|
||||
INDEX_DST="${target_dir}/docs/INDEX.md"
|
||||
if [[ ! -f "${INDEX_DST}" || $FORCE_COPY -eq 1 ]]; then
|
||||
mkdir -p "$(dirname "${INDEX_DST}")"
|
||||
cat >"${INDEX_DST}" <<'IDX'
|
||||
# Documentation du projet
|
||||
|
||||
Cette table des matières oriente vers:
|
||||
- Documentation spécifique au projet: `docs/project/`
|
||||
- Modèles génériques à adapter: `docs/templates/`
|
||||
|
||||
## Sommaire
|
||||
- À personnaliser: `docs/project/README.md`, `docs/project/INDEX.md`, `docs/project/ARCHITECTURE.md`, `docs/project/USAGE.md`, etc.
|
||||
|
||||
## Modèles génériques
|
||||
- Voir: `docs/templates/`
|
||||
IDX
|
||||
fi
|
||||
|
||||
echo "Template 4NK appliqué à: ${target_dir}" >&2
|
||||
exit 0
|
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
IMAGE_NAME="4nk-template-dev:debian"
|
||||
DOCKERFILE="docker/Dockerfile.debian"
|
||||
|
||||
echo "[build] ${IMAGE_NAME}"
|
||||
docker build -t "${IMAGE_NAME}" -f "${DOCKERFILE}" .
|
||||
|
||||
echo "[run] launching container and executing agents"
|
||||
docker run --rm -it \
|
||||
-v "${PWD}:/work" -w /work \
|
||||
"${IMAGE_NAME}" \
|
||||
"scripts/agents/run.sh; ls -la tests/reports/agents || true"
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Build et lance le conteneur unifié (runner+agents) sur ce projet
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
# Build image
|
||||
docker compose -f docker-compose.ci.yml build
|
||||
|
||||
# Exécuter agents par défaut
|
||||
RUNNER_MODE="${RUNNER_MODE:-agents}" BASE_URL="${BASE_URL:-}" REGISTRATION_TOKEN="${REGISTRATION_TOKEN:-}" \
|
||||
docker compose -f docker-compose.ci.yml up --remove-orphans --abort-on-container-exit
|
42
modules/ihm_client/scripts/env/ensure_env.sh
vendored
42
modules/ihm_client/scripts/env/ensure_env.sh
vendored
@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
TEMPLATE_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.env.template"
|
||||
ENV_DIR="${HOME}/.4nk_template"
|
||||
ENV_FILE="${ENV_DIR}/.env"
|
||||
|
||||
mkdir -p "${ENV_DIR}"
|
||||
chmod 700 "${ENV_DIR}" || true
|
||||
|
||||
if [[ ! -f "${ENV_FILE}" ]]; then
|
||||
if [[ -f "${TEMPLATE_FILE}" ]]; then
|
||||
cp "${TEMPLATE_FILE}" "${ENV_FILE}"
|
||||
chmod 600 "${ENV_FILE}" || true
|
||||
echo "Fichier d'environnement créé: ${ENV_FILE}" >&2
|
||||
echo "Veuillez renseigner les variables requises (OPENAI_API_KEY, OPENAI_MODEL, etc.)." >&2
|
||||
exit 3
|
||||
else
|
||||
echo "Modèle d'environnement introuvable: ${TEMPLATE_FILE}" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Charger pour validation
|
||||
set -a
|
||||
. "${ENV_FILE}"
|
||||
set +a
|
||||
|
||||
MISSING=()
|
||||
for var in OPENAI_API_KEY OPENAI_MODEL; do
|
||||
if [[ -z "${!var:-}" ]]; then
|
||||
MISSING+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
if (( ${#MISSING[@]} > 0 )); then
|
||||
echo "Variables manquantes dans ${ENV_FILE}: ${MISSING[*]}" >&2
|
||||
exit 4
|
||||
fi
|
||||
|
||||
echo "Environnement valide: ${ENV_FILE}" >&2
|
@ -1,152 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script d'initialisation de l'environnement SSH pour ihm_client
|
||||
# Configure automatiquement SSH pour tous les push
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Initialisation de l'environnement SSH pour ihm_client..."
|
||||
|
||||
# Couleurs pour les messages
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Fonction pour afficher les messages colorés
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Vérifier si on est dans le bon répertoire
|
||||
if [[ ! -f "package.json" ]] || [[ ! -d ".git" ]]; then
|
||||
print_error "Ce script doit être exécuté depuis le répertoire racine de ihm_client"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "Configuration de l'environnement SSH..."
|
||||
|
||||
# 1. Configuration Git pour SSH
|
||||
print_status "Configuration Git pour utiliser SSH..."
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
|
||||
# 2. Vérifier si une clé SSH existe
|
||||
print_status "Vérification des clés SSH existantes..."
|
||||
if [[ -f ~/.ssh/id_rsa ]] || [[ -f ~/.ssh/id_ed25519 ]]; then
|
||||
print_success "Clé SSH trouvée"
|
||||
SSH_KEY_EXISTS=true
|
||||
else
|
||||
print_warning "Aucune clé SSH trouvée"
|
||||
SSH_KEY_EXISTS=false
|
||||
fi
|
||||
|
||||
# 3. Tester la connexion SSH
|
||||
print_status "Test de la connexion SSH vers git.4nkweb.com..."
|
||||
if ssh -T git@git.4nkweb.com 2>&1 | grep -q "successfully authenticated"; then
|
||||
print_success "Authentification SSH réussie"
|
||||
SSH_WORKING=true
|
||||
else
|
||||
print_error "Échec de l'authentification SSH"
|
||||
SSH_WORKING=false
|
||||
fi
|
||||
|
||||
# 4. Configuration des alias Git
|
||||
print_status "Configuration des alias Git..."
|
||||
git config --global alias.ssh-push '!f() { git add . && git commit -m "${1:-Auto-commit $(date)}" && git push origin $(git branch --show-current); }; f'
|
||||
git config --global alias.quick-push '!f() { git add . && git commit -m "Update $(date)" && git push origin $(git branch --show-current); }; f'
|
||||
|
||||
print_success "Alias Git configurés"
|
||||
|
||||
# 5. Vérifier les remotes
|
||||
print_status "Vérification des remotes Git..."
|
||||
if git remote -v | grep -q "git@git.4nkweb.com"; then
|
||||
print_success "Remotes configurés pour SSH"
|
||||
else
|
||||
print_warning "Remotes non configurés pour SSH"
|
||||
print_status "Mise à jour des remotes..."
|
||||
git remote set-url origin git@git.4nkweb.com:4nk/ihm_client.git
|
||||
print_success "Remotes mis à jour"
|
||||
fi
|
||||
|
||||
# 6. Rendre les scripts exécutables
|
||||
print_status "Configuration des permissions des scripts..."
|
||||
chmod +x scripts/auto-ssh-push.sh 2>/dev/null || true
|
||||
chmod +x scripts/setup-ssh-ci.sh 2>/dev/null || true
|
||||
|
||||
print_success "Scripts rendus exécutables"
|
||||
|
||||
# 7. Créer un fichier de configuration local
|
||||
print_status "Création du fichier de configuration local..."
|
||||
cat > .ssh-config << EOF
|
||||
# Configuration SSH automatique pour ihm_client
|
||||
# Généré le $(date)
|
||||
|
||||
# Configuration Git
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
|
||||
# Alias Git
|
||||
git config --global alias.ssh-push '!f() { git add . && git commit -m "\${1:-Auto-commit \$(date)}" && git push origin \$(git branch --show-current); }; f'
|
||||
git config --global alias.quick-push '!f() { git add . && git commit -m "Update \$(date)" && git push origin \$(git branch --show-current); }; f'
|
||||
|
||||
# Test SSH
|
||||
ssh -T git@git.4nkweb.com
|
||||
|
||||
# Scripts disponibles
|
||||
./scripts/auto-ssh-push.sh quick
|
||||
./scripts/auto-ssh-push.sh message "Mon message"
|
||||
git ssh-push "Mon message"
|
||||
git quick-push
|
||||
EOF
|
||||
|
||||
print_success "Fichier de configuration créé: .ssh-config"
|
||||
|
||||
# 8. Résumé de la configuration
|
||||
echo ""
|
||||
print_success "=== Configuration SSH terminée ==="
|
||||
echo ""
|
||||
echo "✅ Configuration Git pour SSH"
|
||||
echo "✅ Alias Git configurés"
|
||||
echo "✅ Remotes vérifiés"
|
||||
echo "✅ Scripts configurés"
|
||||
echo ""
|
||||
|
||||
if [[ "$SSH_WORKING" == "true" ]]; then
|
||||
print_success "SSH fonctionne correctement"
|
||||
echo ""
|
||||
echo "🚀 Vous pouvez maintenant utiliser :"
|
||||
echo " ./scripts/auto-ssh-push.sh quick"
|
||||
echo " ./scripts/auto-ssh-push.sh message \"Mon message\""
|
||||
echo " git ssh-push \"Mon message\""
|
||||
echo " git quick-push"
|
||||
echo ""
|
||||
else
|
||||
print_warning "SSH ne fonctionne pas encore"
|
||||
echo ""
|
||||
echo "🔧 Pour configurer SSH :"
|
||||
echo " 1. Générer une clé SSH : ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk"
|
||||
echo " 2. Ajouter à l'agent SSH : ssh-add ~/.ssh/id_ed25519_4nk"
|
||||
echo " 3. Ajouter la clé publique à votre compte Gitea"
|
||||
echo " 4. Relancer ce script : ./scripts/init-ssh-env.sh"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 9. Test final
|
||||
if [[ "$SSH_WORKING" == "true" ]]; then
|
||||
print_status "Test final de push SSH..."
|
||||
echo "💡 Pour tester, utilisez : ./scripts/auto-ssh-push.sh status"
|
||||
fi
|
||||
|
||||
print_success "Initialisation SSH terminée !"
|
@ -1,348 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
TARGET_DIR="${PROJECT_ROOT}/../4NK_node"
|
||||
|
||||
# Couleurs pour l'affichage
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Fonction d'affichage
|
||||
print_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# Fonction d'aide
|
||||
show_help() {
|
||||
echo "Usage: $0 [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --target-dir DIR Répertoire cible 4NK_node (défaut: ../4NK_node)"
|
||||
echo " --dry-run Simulation sans modification"
|
||||
echo " --backup Créer une sauvegarde avant intégration"
|
||||
echo " --help Afficher cette aide"
|
||||
echo ""
|
||||
echo "Exemples:"
|
||||
echo " $0 # Intégration standard"
|
||||
echo " $0 --dry-run # Simulation"
|
||||
echo " $0 --target-dir /path/to/4NK_node"
|
||||
}
|
||||
|
||||
# Variables
|
||||
DRY_RUN=false
|
||||
BACKUP=false
|
||||
TARGET_DIR="${PROJECT_ROOT}/../4NK_node"
|
||||
|
||||
# Parsing des arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--target-dir)
|
||||
TARGET_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
--backup)
|
||||
BACKUP=true
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "Option inconnue: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Vérification des prérequis
|
||||
check_prerequisites() {
|
||||
print_info "Vérification des prérequis..."
|
||||
|
||||
# Vérifier que nous sommes dans le bon répertoire
|
||||
if [[ ! -f "${PROJECT_ROOT}/package.json" ]]; then
|
||||
print_error "Ce script doit être exécuté depuis le répertoire ihm_client"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier que le répertoire cible existe
|
||||
if [[ ! -d "$TARGET_DIR" ]]; then
|
||||
print_error "Répertoire cible 4NK_node non trouvé: $TARGET_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier que les fichiers d'intégration existent
|
||||
local required_files=(
|
||||
"Dockerfile.4nk-node"
|
||||
"nginx.4nk-node.conf"
|
||||
"start-4nk-node.sh"
|
||||
"docker-compose.4nk-node.yml"
|
||||
)
|
||||
|
||||
for file in "${required_files[@]}"; do
|
||||
if [[ ! -f "${PROJECT_ROOT}/$file" ]]; then
|
||||
print_error "Fichier requis manquant: $file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "Prérequis vérifiés"
|
||||
}
|
||||
|
||||
# Création de la sauvegarde
|
||||
create_backup() {
|
||||
if [[ "$BACKUP" == "true" ]]; then
|
||||
print_info "Création de la sauvegarde..."
|
||||
|
||||
local backup_dir="${TARGET_DIR}/backup_$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
mkdir -p "$backup_dir"
|
||||
cp -r "${TARGET_DIR}/docker-compose.yml" "$backup_dir/" 2>/dev/null || true
|
||||
cp -r "${TARGET_DIR}/ihm_client" "$backup_dir/" 2>/dev/null || true
|
||||
print_success "Sauvegarde créée: $backup_dir"
|
||||
else
|
||||
print_info "DRY RUN: Sauvegarde serait créée: $backup_dir"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Création du répertoire ihm_client dans 4NK_node
|
||||
create_ihm_client_directory() {
|
||||
print_info "Création du répertoire ihm_client dans 4NK_node..."
|
||||
|
||||
local ihm_client_dir="${TARGET_DIR}/ihm_client"
|
||||
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
mkdir -p "$ihm_client_dir"
|
||||
print_success "Répertoire créé: $ihm_client_dir"
|
||||
else
|
||||
print_info "DRY RUN: Répertoire serait créé: $ihm_client_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
# Copie des fichiers d'intégration
|
||||
copy_integration_files() {
|
||||
print_info "Copie des fichiers d'intégration..."
|
||||
|
||||
local files_to_copy=(
|
||||
"Dockerfile.4nk-node:Dockerfile"
|
||||
"nginx.4nk-node.conf:nginx.conf"
|
||||
"start-4nk-node.sh:start.sh"
|
||||
"package.json:package.json"
|
||||
"tsconfig.json:tsconfig.json"
|
||||
"vite.config.ts:vite.config.ts"
|
||||
"index.html:index.html"
|
||||
)
|
||||
|
||||
for file_mapping in "${files_to_copy[@]}"; do
|
||||
local source_file=$(echo "$file_mapping" | cut -d: -f1)
|
||||
local target_file=$(echo "$file_mapping" | cut -d: -f2)
|
||||
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
cp "${PROJECT_ROOT}/$source_file" "${TARGET_DIR}/ihm_client/$target_file"
|
||||
print_success "Copié: $source_file -> ihm_client/$target_file"
|
||||
else
|
||||
print_info "DRY RUN: Copié: $source_file -> ihm_client/$target_file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Copie du code source
|
||||
copy_source_code() {
|
||||
print_info "Copie du code source..."
|
||||
|
||||
local source_dirs=("src" "public")
|
||||
|
||||
for dir in "${source_dirs[@]}"; do
|
||||
if [[ -d "${PROJECT_ROOT}/$dir" ]]; then
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
cp -r "${PROJECT_ROOT}/$dir" "${TARGET_DIR}/ihm_client/"
|
||||
print_success "Copié: $dir/"
|
||||
else
|
||||
print_info "DRY RUN: Copié: $dir/"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Mise à jour du docker-compose.yml
|
||||
update_docker_compose() {
|
||||
print_info "Mise à jour du docker-compose.yml..."
|
||||
|
||||
local docker_compose_file="${TARGET_DIR}/docker-compose.yml"
|
||||
local ihm_client_service="
|
||||
ihm_client:
|
||||
build:
|
||||
context: ./ihm_client
|
||||
dockerfile: Dockerfile
|
||||
container_name: 4nk-ihm-client
|
||||
ports:
|
||||
- \"8080:80\"
|
||||
environment:
|
||||
- SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
|
||||
- SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
|
||||
- BITCOIN_RPC_URL=http://bitcoin:18443
|
||||
- BLINDBIT_URL=http://blindbit:8000
|
||||
volumes:
|
||||
- ihm_client_logs:/var/log/nginx
|
||||
networks:
|
||||
- btcnet
|
||||
depends_on:
|
||||
- sdk_relay_1
|
||||
- sdk_relay_2
|
||||
- sdk_relay_3
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: [\"CMD\", \"wget\", \"--quiet\", \"--tries=1\", \"--timeout=5\", \"--spider\", \"http://localhost\"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s"
|
||||
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
# Vérifier si le service existe déjà
|
||||
if grep -q "ihm_client:" "$docker_compose_file" 2>/dev/null; then
|
||||
print_warning "Service ihm_client existe déjà dans docker-compose.yml"
|
||||
else
|
||||
# Ajouter le service avant la section volumes
|
||||
sed -i "/^volumes:/i\\$ihm_client_service" "$docker_compose_file"
|
||||
|
||||
# Ajouter les volumes ihm_client
|
||||
sed -i '/^volumes:/a\ ihm_client_logs:\n driver: local' "$docker_compose_file"
|
||||
|
||||
print_success "Service ihm_client ajouté au docker-compose.yml"
|
||||
fi
|
||||
else
|
||||
print_info "DRY RUN: Service ihm_client serait ajouté au docker-compose.yml"
|
||||
fi
|
||||
}
|
||||
|
||||
# Création du script de démarrage
|
||||
create_startup_script() {
|
||||
print_info "Création du script de démarrage..."
|
||||
|
||||
local startup_script="${TARGET_DIR}/start-ihm-client.sh"
|
||||
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
cat > "$startup_script" << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Démarrage de l'interface utilisateur 4NK..."
|
||||
|
||||
# Vérifier que nous sommes dans le bon répertoire
|
||||
if [[ ! -f "docker-compose.yml" ]]; then
|
||||
echo "❌ Ce script doit être exécuté depuis le répertoire 4NK_node"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Démarrer uniquement le service ihm_client
|
||||
echo "📦 Démarrage du service ihm_client..."
|
||||
docker-compose up -d ihm_client
|
||||
|
||||
# Attendre que le service soit prêt
|
||||
echo "⏳ Attente du démarrage..."
|
||||
sleep 10
|
||||
|
||||
# Vérifier la santé du service
|
||||
if docker-compose ps ihm_client | grep -q "Up"; then
|
||||
echo "✅ Interface utilisateur démarrée avec succès"
|
||||
echo " 📍 URL: http://localhost:8080"
|
||||
echo " 🔍 Logs: docker logs 4nk-ihm-client"
|
||||
else
|
||||
echo "❌ Échec du démarrage de l'interface utilisateur"
|
||||
docker-compose logs ihm_client
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
|
||||
chmod +x "$startup_script"
|
||||
print_success "Script de démarrage créé: $startup_script"
|
||||
else
|
||||
print_info "DRY RUN: Script de démarrage serait créé: $startup_script"
|
||||
fi
|
||||
}
|
||||
|
||||
# Validation de l'intégration
|
||||
validate_integration() {
|
||||
print_info "Validation de l'intégration..."
|
||||
|
||||
local validation_files=(
|
||||
"${TARGET_DIR}/ihm_client/Dockerfile"
|
||||
"${TARGET_DIR}/ihm_client/nginx.conf"
|
||||
"${TARGET_DIR}/ihm_client/start.sh"
|
||||
"${TARGET_DIR}/docker-compose.yml"
|
||||
)
|
||||
|
||||
for file in "${validation_files[@]}"; do
|
||||
if [[ -f "$file" ]]; then
|
||||
print_success "Validé: $(basename "$file")"
|
||||
else
|
||||
print_error "Fichier manquant: $(basename "$file")"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "Validation terminée"
|
||||
}
|
||||
|
||||
# Fonction principale
|
||||
main() {
|
||||
echo "🔧 Intégration de ihm_client dans 4NK_node"
|
||||
echo " Source: $PROJECT_ROOT"
|
||||
echo " Cible: $TARGET_DIR"
|
||||
echo " Mode: $([ "$DRY_RUN" == "true" ] && echo "DRY RUN" || echo "EXÉCUTION")"
|
||||
echo ""
|
||||
|
||||
check_prerequisites
|
||||
create_backup
|
||||
create_ihm_client_directory
|
||||
copy_integration_files
|
||||
copy_source_code
|
||||
update_docker_compose
|
||||
create_startup_script
|
||||
|
||||
if [[ "$DRY_RUN" == "false" ]]; then
|
||||
validate_integration
|
||||
echo ""
|
||||
print_success "Intégration terminée avec succès !"
|
||||
echo ""
|
||||
echo "📋 Prochaines étapes:"
|
||||
echo " 1. Aller dans le répertoire 4NK_node: cd $TARGET_DIR"
|
||||
echo " 2. Démarrer l'interface: ./start-ihm-client.sh"
|
||||
echo " 3. Ou redémarrer tout: ./restart_4nk_node.sh"
|
||||
echo " 4. Accéder à l'interface: http://localhost:8080"
|
||||
else
|
||||
echo ""
|
||||
print_success "Simulation terminée - Aucune modification effectuée"
|
||||
fi
|
||||
}
|
||||
|
||||
# Exécution
|
||||
main "$@"
|
@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"/..
|
||||
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
||||
|
||||
mkdir -p "$HOOKS_DIR"
|
||||
install_hook() {
|
||||
local name="$1" src="$2"
|
||||
cp -f "$src" "$HOOKS_DIR/$name"
|
||||
chmod +x "$HOOKS_DIR/$name"
|
||||
echo "Installed hook: $name"
|
||||
}
|
||||
|
||||
# Hooks qui délèguent aux agents via l'image Docker du template sur le projet courant
|
||||
install_hook pre-commit "$REPO_ROOT/scripts/local/precommit.sh"
|
||||
install_hook pre-push "$REPO_ROOT/scripts/local/prepush.sh"
|
||||
|
||||
echo "Hooks installés (mode agents via 4NK_template)."
|
@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
TARGET_BRANCH="${1:-main}"
|
||||
SOURCE_BRANCH="${2:-}"
|
||||
|
||||
if [[ -z "$SOURCE_BRANCH" ]]; then
|
||||
SOURCE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||
fi
|
||||
|
||||
if [[ "$SOURCE_BRANCH" == "$TARGET_BRANCH" ]]; then
|
||||
echo "Déjà sur $TARGET_BRANCH"; exit 0
|
||||
fi
|
||||
|
||||
# Valider localement avant merge
|
||||
AUTO_FIX="${AUTO_FIX:-1}" SCOPE="${SCOPE:-all}" scripts/agents/run.sh || true
|
||||
if [ -f scripts/security/audit.sh ]; then bash scripts/security/audit.sh || true; fi
|
||||
|
||||
git fetch origin --prune
|
||||
git checkout "$TARGET_BRANCH"
|
||||
git pull --ff-only origin "$TARGET_BRANCH" || true
|
||||
git merge --no-ff "$SOURCE_BRANCH" -m "[skip ci] merge: $SOURCE_BRANCH -> $TARGET_BRANCH"
|
||||
git push origin "$TARGET_BRANCH"
|
||||
|
||||
echo "Merge effectué: $SOURCE_BRANCH → $TARGET_BRANCH"
|
@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Exécuter les agents depuis l'image Docker de 4NK_template sur le projet courant
|
||||
PROJECT_DIR="$(git rev-parse --show-toplevel)"
|
||||
TEMPLATE_DIR="$(cd "${PROJECT_DIR}/../4NK_template" && pwd)"
|
||||
|
||||
mkdir -p "${PROJECT_DIR}/tests/reports/agents"
|
||||
"${TEMPLATE_DIR}/scripts/local/run_agents_for_project.sh" "${PROJECT_DIR}" "tests/reports/agents"
|
||||
|
||||
echo "[pre-commit] OK (agents via 4NK_template)"
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Exécuter les agents depuis l'image Docker de 4NK_template sur le projet courant
|
||||
PROJECT_DIR="$(git rev-parse --show-toplevel)"
|
||||
TEMPLATE_DIR="$(cd "${PROJECT_DIR}/../4NK_template" && pwd)"
|
||||
|
||||
mkdir -p "${PROJECT_DIR}/tests/reports/agents"
|
||||
"${TEMPLATE_DIR}/scripts/local/run_agents_for_project.sh" "${PROJECT_DIR}" "tests/reports/agents"
|
||||
|
||||
# Audit sécurité (best effort) dans le contexte du projet
|
||||
if [ -f "${PROJECT_DIR}/scripts/security/audit.sh" ]; then
|
||||
(cd "${PROJECT_DIR}" && bash scripts/security/audit.sh) || true
|
||||
fi
|
||||
|
||||
# Release guard (dry-run logique) dans le contexte du projet
|
||||
if [ -f "${PROJECT_DIR}/scripts/release/guard.sh" ]; then
|
||||
(cd "${PROJECT_DIR}" && bash scripts/release/guard.sh) || true
|
||||
fi
|
||||
|
||||
echo "[pre-push] OK (agents via 4NK_template)"
|
@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="${1:-}"
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
echo "Usage: $0 vYYYY.MM.P" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$ROOT_DIR/.."
|
||||
|
||||
echo "$VERSION" > TEMPLATE_VERSION
|
||||
git add TEMPLATE_VERSION CHANGELOG.md 2>/dev/null || true
|
||||
git commit -m "[skip ci] chore(release): $VERSION" || true
|
||||
git tag -a "$VERSION" -m "release: $VERSION (latest)"
|
||||
git push || true
|
||||
git push origin "$VERSION"
|
||||
|
||||
echo "Release locale préparée: $VERSION"
|
@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Script pour lancer les agents de 4NK_template sur un projet externe
|
||||
# Usage: ./run_agents_for_project.sh [project_path] [output_dir]
|
||||
|
||||
PROJECT_PATH="${1:-.}"
|
||||
OUTPUT_DIR="${2:-tests/reports/agents}"
|
||||
TEMPLATE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
MODULE_LAST_IMAGE_FILE="$(cd "$TEMPLATE_DIR/.." && pwd)/modules/4NK_template/.last_image"
|
||||
|
||||
if [[ ! -d "$PROJECT_PATH" ]]; then
|
||||
echo "Erreur: Le projet '$PROJECT_PATH' n'existe pas" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$PROJECT_PATH/$OUTPUT_DIR"
|
||||
|
||||
echo "=== Lancement des agents 4NK_template sur: $PROJECT_PATH ==="
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Docker requis pour exécuter les agents via conteneur." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Si une image du module existe, l'utiliser en priorité
|
||||
if [[ -f "$MODULE_LAST_IMAGE_FILE" ]]; then
|
||||
IMAGE_NAME="$(cat "$MODULE_LAST_IMAGE_FILE" | tr -d '\r\n')"
|
||||
echo "Utilisation de l'image du module: $IMAGE_NAME"
|
||||
# Préparer montage du fichier d'env si présent
|
||||
ENV_MOUNT=""
|
||||
if [[ -f "$HOME/.4nk_template/.env" ]]; then
|
||||
ENV_MOUNT="-v $HOME/.4nk_template/.env:/root/.4nk_template/.env:ro"
|
||||
fi
|
||||
# Lancer le conteneur en utilisant l'ENTRYPOINT qui configure safe.directory
|
||||
docker run --rm \
|
||||
-e RUNNER_MODE=agents \
|
||||
-e TARGET_DIR=/work \
|
||||
-e OUTPUT_DIR=/work/$OUTPUT_DIR \
|
||||
-v "$(realpath "$PROJECT_PATH"):/work" \
|
||||
$ENV_MOUNT \
|
||||
"$IMAGE_NAME" || true
|
||||
else
|
||||
echo "Aucune image de module détectée, fallback docker compose dans 4NK_template"
|
||||
cd "$TEMPLATE_DIR"
|
||||
docker compose -f docker-compose.ci.yml build
|
||||
RUNNER_MODE="agents" TARGET_DIR="/work" OUTPUT_DIR="/work/$OUTPUT_DIR" \
|
||||
docker compose -f docker-compose.ci.yml run --rm project-ci || true
|
||||
fi
|
||||
|
||||
echo "=== Agents terminés → $PROJECT_PATH/$OUTPUT_DIR ==="
|
@ -1,65 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Release guard script
|
||||
# Checks: tests, docs updated, compile, version ↔ changelog ↔ tag consistency, release type
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
mode="${RELEASE_TYPE:-ci-verify}" # values: latest | wip | ci-verify
|
||||
|
||||
echo "[release-guard] mode=$mode"
|
||||
|
||||
# 1) Basic presence checks
|
||||
[[ -f CHANGELOG.md ]] || { echo "CHANGELOG.md manquant"; exit 1; }
|
||||
version_file="VERSION"
|
||||
[[ -f TEMPLATE_VERSION ]] && version_file="TEMPLATE_VERSION"
|
||||
[[ -f "$version_file" ]] || { echo "$version_file manquant"; exit 1; }
|
||||
|
||||
# 2) Extract version
|
||||
project_version=$(tr -d '\r' < "$version_file" | head -n1 | sed 's/^v//')
|
||||
[[ -n "$project_version" ]] || { echo "Version vide dans $version_file"; exit 1; }
|
||||
echo "[release-guard] version=$project_version"
|
||||
|
||||
# 3) Changelog checks
|
||||
if ! grep -Eq "^## \\[$project_version\\]" CHANGELOG.md; then
|
||||
if [[ "$mode" == "wip" ]]; then
|
||||
grep -Eq "^## \\[Unreleased\\]" CHANGELOG.md || { echo "Section [Unreleased] absente du CHANGELOG"; exit 1; }
|
||||
else
|
||||
echo "Entrée CHANGELOG pour version $project_version manquante"; exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4) Tests (optional best-effort)
|
||||
if [[ -x tests/run_all_tests.sh ]]; then
|
||||
echo "[release-guard] exécution tests/run_all_tests.sh"
|
||||
./tests/run_all_tests.sh || { echo "Tests en échec"; exit 1; }
|
||||
else
|
||||
echo "[release-guard] tests absents (ok)"
|
||||
fi
|
||||
|
||||
# 5) Build/compile (optional based on project)
|
||||
if [[ -d sdk_relay ]] && command -v cargo >/dev/null 2>&1; then
|
||||
echo "[release-guard] cargo build (sdk_relay)"
|
||||
(cd sdk_relay && cargo build --quiet) || { echo "Compilation échouée"; exit 1; }
|
||||
else
|
||||
echo "[release-guard] build spécifique non applicable (ok)"
|
||||
fi
|
||||
|
||||
# 6) Release type handling
|
||||
case "$mode" in
|
||||
latest)
|
||||
;;
|
||||
wip)
|
||||
# En wip, autoriser versions suffixées; pas d’exigence d’entrée datée
|
||||
;;
|
||||
ci-verify)
|
||||
# En CI, on valide juste la présence de CHANGELOG et version
|
||||
;;
|
||||
*)
|
||||
echo "RELEASE_TYPE invalide: $mode (latest|wip|ci-verify)"; exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[release-guard] OK"
|
@ -1,166 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Script d'automatisation des push SSH (template Linux)
|
||||
# Utilise automatiquement la clé SSH pour pousser sur le remote courant via SSH.
|
||||
|
||||
GITEA_HOST="${GITEA_HOST:-git.4nkweb.com}"
|
||||
|
||||
echo "🔑 Configuration SSH pour push (template)..."
|
||||
|
||||
# Configuration SSH automatique
|
||||
echo "⚙️ Configuration Git pour utiliser SSH..."
|
||||
git config --global url."git@${GITEA_HOST}:".insteadOf "https://${GITEA_HOST}/"
|
||||
|
||||
# Vérifier la configuration SSH
|
||||
echo "🔍 Vérification de la configuration SSH..."
|
||||
if ! ssh -T git@"${GITEA_HOST}" 2>&1 | grep -qi "authenticated\|welcome"; then
|
||||
echo "❌ Échec de l'authentification SSH"
|
||||
echo "💡 Vérifiez que votre clé SSH est configurée :"
|
||||
echo " 1. ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_4nk"
|
||||
echo " 2. Ajouter la clé publique à votre compte Gitea"
|
||||
echo " 3. ssh-add ~/.ssh/id_ed25519_4nk"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Authentification SSH réussie"
|
||||
|
||||
# Fonction pour push automatique
|
||||
get_current_branch() {
|
||||
# Détecte la branche courante, compatible anciennes versions de git
|
||||
local br
|
||||
br="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
|
||||
if [ -z "$br" ] || [ "$br" = "HEAD" ]; then
|
||||
br="$(git symbolic-ref --short -q HEAD 2>/dev/null || true)"
|
||||
fi
|
||||
if [ -z "$br" ]; then
|
||||
# dernier recours: parser la sortie de "git branch"
|
||||
br="$(git branch 2>/dev/null | sed -n 's/^* //p' | head -n1)"
|
||||
fi
|
||||
echo "$br"
|
||||
}
|
||||
|
||||
auto_push() {
|
||||
local branch
|
||||
branch=${1:-$(get_current_branch)}
|
||||
local commit_message=${2:-"Auto-commit $(date '+%Y-%m-%d %H:%M:%S')"}
|
||||
|
||||
echo "🚀 Push automatique sur la branche: $branch"
|
||||
|
||||
# Ajouter tous les changements
|
||||
git add .
|
||||
|
||||
# Ne pas commiter si rien à commite
|
||||
if [[ -z "$(git diff --cached --name-only)" ]]; then
|
||||
echo "ℹ️ Aucun changement indexé. Skip commit/push."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Commiter avec le message fourni
|
||||
git commit -m "$commit_message" || true
|
||||
|
||||
# Push avec SSH automatique
|
||||
echo "📤 Push vers origin/$branch..."
|
||||
git push origin "$branch"
|
||||
|
||||
echo "✅ Push réussi !"
|
||||
}
|
||||
|
||||
# Fonction pour push avec message personnalisé
|
||||
push_with_message() {
|
||||
local message="$1"
|
||||
local branch=${2:-$(get_current_branch)}
|
||||
|
||||
echo "💬 Push avec message: $message"
|
||||
auto_push "$branch" "$message"
|
||||
}
|
||||
|
||||
# Fonction pour push rapide (sans message)
|
||||
quick_push() {
|
||||
local branch=${1:-$(get_current_branch)}
|
||||
auto_push "$branch"
|
||||
}
|
||||
|
||||
# Fonction pour push sur une branche spécifique
|
||||
push_branch() {
|
||||
local branch="$1"
|
||||
local message=${2:-"Update $branch $(date '+%Y-%m-%d %H:%M:%S')"}
|
||||
|
||||
echo "🌿 Push sur la branche: $branch"
|
||||
auto_push "$branch" "$message"
|
||||
}
|
||||
|
||||
# Fonction pour push et merge vers main
|
||||
push_and_merge() {
|
||||
local source_branch=${1:-$(get_current_branch)}
|
||||
local target_branch=${2:-main}
|
||||
|
||||
echo "🔄 Push et merge $source_branch -> $target_branch"
|
||||
|
||||
# Push de la branche source
|
||||
auto_push "$source_branch"
|
||||
|
||||
# Indication pour PR manuelle
|
||||
echo "🔗 Ouvrez une Pull Request sur votre forge pour $source_branch -> $target_branch"
|
||||
}
|
||||
|
||||
# Fonction pour status et push conditionnel
|
||||
status_and_push() {
|
||||
echo "📊 Statut du repository:"
|
||||
git status --short || true
|
||||
|
||||
if [[ -n $(git status --porcelain) ]]; then
|
||||
echo "📝 Changements détectés, push automatique..."
|
||||
auto_push
|
||||
else
|
||||
echo "✅ Aucun changement à pousser"
|
||||
fi
|
||||
}
|
||||
|
||||
# Menu interactif si aucun argument fourni
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "🤖 Script de push SSH automatique (template)"
|
||||
echo ""
|
||||
echo "Options disponibles:"
|
||||
echo " auto-ssh-push.sh quick - Push rapide"
|
||||
echo " auto-ssh-push.sh message \"Mon message\" - Push avec message"
|
||||
echo " auto-ssh-push.sh branch nom-branche - Push sur branche spécifique"
|
||||
echo " auto-ssh-push.sh merge [source] [target] - Push et préparation merge"
|
||||
echo " auto-ssh-push.sh status - Status et push conditionnel"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Traitement des arguments
|
||||
case "$1" in
|
||||
"quick")
|
||||
quick_push
|
||||
;;
|
||||
"message")
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
echo "❌ Message requis pour l'option 'message'"
|
||||
exit 1
|
||||
fi
|
||||
push_with_message "$2" "${3:-}"
|
||||
;;
|
||||
"branch")
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
echo "❌ Nom de branche requis pour l'option 'branch'"
|
||||
exit 1
|
||||
fi
|
||||
push_branch "$2" "${3:-}"
|
||||
;;
|
||||
"merge")
|
||||
push_and_merge "${2:-}" "${3:-}"
|
||||
;;
|
||||
"status")
|
||||
status_and_push
|
||||
;;
|
||||
*)
|
||||
echo "❌ Option inconnue: $1"
|
||||
echo "💡 Utilisez './scripts/auto-ssh-push.sh' pour voir les options"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "🎯 Push SSH automatique terminé !"
|
@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Script d'initialisation de l'environnement SSH (template Linux)
|
||||
# Configure automatiquement SSH pour les push via Gitea
|
||||
|
||||
GITEA_HOST="${GITEA_HOST:-git.4nkweb.com}"
|
||||
|
||||
echo "🚀 Initialisation de l'environnement SSH (template)..."
|
||||
|
||||
# Couleurs
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_status() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
print_status "Configuration SSH..."
|
||||
|
||||
# 1. Configuration Git pour SSH
|
||||
print_status "Configuration Git pour utiliser SSH (${GITEA_HOST})..."
|
||||
git config --global url."git@${GITEA_HOST}:".insteadOf "https://${GITEA_HOST}/"
|
||||
|
||||
# 2. Vérification des clés SSH
|
||||
print_status "Vérification des clés SSH existantes..."
|
||||
if [[ -f ~/.ssh/id_rsa || -f ~/.ssh/id_ed25519 ]]; then
|
||||
print_success "Clé SSH trouvée"
|
||||
else
|
||||
print_warning "Aucune clé SSH trouvée"
|
||||
fi
|
||||
|
||||
# 3. Test de la connexion SSH
|
||||
print_status "Test de la connexion SSH vers ${GITEA_HOST}..."
|
||||
if ssh -T git@"${GITEA_HOST}" 2>&1 | grep -qi "authenticated\|welcome"; then
|
||||
print_success "Authentification SSH réussie"
|
||||
else
|
||||
print_error "Échec de l'authentification SSH"
|
||||
fi
|
||||
|
||||
# 4. Alias Git
|
||||
print_status "Configuration des alias Git..."
|
||||
git config --global alias.ssh-push '!f() { git add . && git commit -m "${1:-Auto-commit $(date)}" && git push origin $(git branch --show-current); }; f'
|
||||
git config --global alias.quick-push '!f() { git add . && git commit -m "Update $(date)" && git push origin $(git branch --show-current); }; f'
|
||||
print_success "Alias Git configurés"
|
||||
|
||||
# 5. Rendu exécutable des scripts si chemin standard
|
||||
print_status "Configuration des permissions des scripts (si présents)..."
|
||||
chmod +x scripts/auto-ssh-push.sh 2>/dev/null || true
|
||||
chmod +x scripts/setup-ssh-ci.sh 2>/dev/null || true
|
||||
print_success "Scripts rendus exécutables (si présents)"
|
||||
|
||||
# 6. Résumé
|
||||
echo ""
|
||||
print_success "=== Configuration SSH terminée ==="
|
@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Script de configuration SSH pour CI/CD (template Linux)
|
||||
# Utilise automatiquement la clé SSH pour les opérations Git
|
||||
|
||||
GITEA_HOST="${GITEA_HOST:-git.4nkweb.com}"
|
||||
|
||||
echo "🔑 Configuration automatique de la clé SSH pour CI/CD..."
|
||||
|
||||
if [ -n "${CI:-}" ]; then
|
||||
echo "✅ Environnement CI détecté"
|
||||
|
||||
if [ -n "${SSH_PRIVATE_KEY:-}" ]; then
|
||||
echo "🔐 Configuration de la clé SSH privée..."
|
||||
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||
printf "%s" "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
if [ -n "${SSH_PUBLIC_KEY:-}" ]; then
|
||||
printf "%s" "$SSH_PUBLIC_KEY" > ~/.ssh/id_rsa.pub
|
||||
chmod 644 ~/.ssh/id_rsa.pub
|
||||
fi
|
||||
|
||||
cat > ~/.ssh/config << EOF
|
||||
Host ${GITEA_HOST}
|
||||
HostName ${GITEA_HOST}
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
EOF
|
||||
chmod 600 ~/.ssh/config
|
||||
|
||||
echo "🧪 Test SSH vers ${GITEA_HOST}..."
|
||||
ssh -T git@"${GITEA_HOST}" 2>&1 || true
|
||||
|
||||
git config --global url."git@${GITEA_HOST}:".insteadOf "https://${GITEA_HOST}/"
|
||||
echo "✅ Configuration SSH terminée"
|
||||
else
|
||||
echo "⚠️ SSH_PRIVATE_KEY non défini, bascule HTTPS"
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ Environnement local détecté"
|
||||
if [ -f ~/.ssh/id_rsa ] || [ -f ~/.ssh/id_ed25519 ]; then
|
||||
echo "🔑 Clé SSH locale trouvée"
|
||||
git config --global url."git@${GITEA_HOST}:".insteadOf "https://${GITEA_HOST}/"
|
||||
echo "✅ Configuration SSH locale terminée"
|
||||
else
|
||||
echo "⚠️ Aucune clé SSH trouvée; configuration manuelle requise"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "🎯 Configuration SSH CI/CD terminée"
|
@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "[security-audit] démarrage"
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
rc=0
|
||||
|
||||
# 1) Audit Rust (si Cargo.toml présent et cargo disponible)
|
||||
if command -v cargo >/dev/null 2>&1 && [ -f Cargo.toml ] || find . -maxdepth 2 -name Cargo.toml | grep -q . ; then
|
||||
echo "[security-audit] cargo audit"
|
||||
if ! cargo audit --deny warnings; then rc=1; fi || true
|
||||
else
|
||||
echo "[security-audit] pas de projet Rust (ok)"
|
||||
fi
|
||||
|
||||
# 2) Audit npm (si package.json présent)
|
||||
if [ -f package.json ]; then
|
||||
echo "[security-audit] npm audit --audit-level=moderate"
|
||||
if ! npm audit --audit-level=moderate; then rc=1; fi || true
|
||||
else
|
||||
echo "[security-audit] pas de package.json (ok)"
|
||||
fi
|
||||
|
||||
# 3) Recherche de secrets grossiers
|
||||
echo "[security-audit] scan secrets"
|
||||
if grep -RIE "(?i)(api[_-]?key|secret|password|private[_-]?key)" --exclude-dir .git --exclude-dir node_modules --exclude-dir target --exclude "*.md" . >/dev/null 2>&1; then
|
||||
echo "[security-audit] secrets potentiels détectés"; rc=1
|
||||
else
|
||||
echo "[security-audit] aucun secret évident"
|
||||
fi
|
||||
|
||||
echo "[security-audit] terminé rc=$rc"
|
||||
exit $rc
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
echo "[ihm_client] Préparation des dépendances wasm (pkg/sdk_client)"
|
||||
|
||||
PKG_DIR="$(pwd)/pkg"
|
||||
if [ -d "$PKG_DIR" ] && [ -f "$PKG_DIR/sdk_client.js" ]; then
|
||||
echo "[ihm_client] pkg déjà présent, rien à faire."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Sources possibles (priorité: URL tarball > tarball local > base RAW)
|
||||
SDK_URL="${SDK_CLIENT_PKG_URL:-}"
|
||||
SDK_TARBALL="${SDK_CLIENT_PKG_TARBALL:-}"
|
||||
# Par défaut, on pointe vers la branche docker-support du repo public
|
||||
SDK_BASE="${SDK_CLIENT_PKG_BASE:-https://git.4nkweb.com/4nk/ihm_client/raw/branch/docker-support/pkg}"
|
||||
|
||||
mkdir -p "$PKG_DIR"
|
||||
|
||||
if [ -n "$SDK_URL" ]; then
|
||||
echo "[ihm_client] Téléchargement depuis SDK_CLIENT_PKG_URL=$SDK_URL"
|
||||
TMP_TGZ="/tmp/sdk_client_pkg.tgz"
|
||||
curl -fsSL "$SDK_URL" -o "$TMP_TGZ"
|
||||
tar -xzf "$TMP_TGZ" -C "$PKG_DIR" --strip-components=1 || tar -xzf "$TMP_TGZ" -C "$PKG_DIR" || true
|
||||
rm -f "$TMP_TGZ"
|
||||
elif [ -n "$SDK_TARBALL" ] && [ -f "$SDK_TARBALL" ]; then
|
||||
echo "[ihm_client] Extraction du tarball local $SDK_TARBALL"
|
||||
tar -xzf "$SDK_TARBALL" -C "$PKG_DIR" --strip-components=1 || tar -xzf "$SDK_TARBALL" -C "$PKG_DIR" || true
|
||||
elif [ -n "$SDK_BASE" ]; then
|
||||
echo "[ihm_client] Téléchargement des fichiers depuis SDK_CLIENT_PKG_BASE=$SDK_BASE (branche docker-support)"
|
||||
# Liste des fichiers nécessaires issus de wasm-pack
|
||||
for f in \
|
||||
sdk_client.js \
|
||||
sdk_client_bg.wasm \
|
||||
sdk_client.d.ts \
|
||||
sdk_client_bg.js \
|
||||
sdk_client_bg.wasm.d.ts \
|
||||
package.json \
|
||||
README.md; do
|
||||
echo " - $f"
|
||||
curl -fsSL "$SDK_BASE/$f" -o "$PKG_DIR/$f"
|
||||
done
|
||||
else
|
||||
echo "[ERREUR] pkg/sdk_client absent et aucune source fournie."
|
||||
echo "Définissez SDK_CLIENT_PKG_URL (tar.gz), SDK_CLIENT_PKG_BASE (URL raw du dossier pkg) ou montez un tarball local via SDK_CLIENT_PKG_TARBALL."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
test -f "$PKG_DIR/sdk_client.js" || { echo "[ERREUR] pkg/sdk_client.js introuvable après extraction"; exit 3; }
|
||||
|
||||
echo "[ihm_client] Dépendance wasm prête."
|
@ -1,79 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de configuration SSH pour CI/CD ihm_client
|
||||
# Utilise automatiquement la clé SSH pour les opérations Git
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔑 Configuration automatique de la clé SSH pour ihm_client CI/CD..."
|
||||
|
||||
# Vérifier si on est dans un environnement CI
|
||||
if [ -n "$CI" ]; then
|
||||
echo "✅ Environnement CI détecté"
|
||||
|
||||
# Configuration SSH pour Gitea Actions
|
||||
if [ -n "$SSH_PRIVATE_KEY" ]; then
|
||||
echo "🔐 Configuration de la clé SSH privée..."
|
||||
|
||||
# Créer le répertoire SSH
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
|
||||
# Écrire la clé privée
|
||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
|
||||
# Ajouter la clé publique correspondante (si disponible)
|
||||
if [ -n "$SSH_PUBLIC_KEY" ]; then
|
||||
echo "$SSH_PUBLIC_KEY" > ~/.ssh/id_rsa.pub
|
||||
chmod 644 ~/.ssh/id_rsa.pub
|
||||
fi
|
||||
|
||||
# Configuration SSH pour git.4nkweb.com
|
||||
cat > ~/.ssh/config << EOF
|
||||
Host git.4nkweb.com
|
||||
HostName git.4nkweb.com
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile=/dev/null
|
||||
EOF
|
||||
|
||||
chmod 600 ~/.ssh/config
|
||||
|
||||
# Tester la connexion SSH
|
||||
echo "🧪 Test de connexion SSH vers git.4nkweb.com..."
|
||||
if ssh -T git@git.4nkweb.com 2>&1 | grep -q "Welcome"; then
|
||||
echo "✅ Connexion SSH réussie"
|
||||
else
|
||||
echo "⚠️ Connexion SSH établie (message de bienvenue non détecté)"
|
||||
fi
|
||||
|
||||
# Configurer Git pour utiliser SSH
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
|
||||
echo "✅ Configuration SSH terminée"
|
||||
else
|
||||
echo "⚠️ Variable SSH_PRIVATE_KEY non définie, utilisation de HTTPS"
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ Environnement local détecté"
|
||||
|
||||
# Vérifier si une clé SSH existe
|
||||
if [ -f ~/.ssh/id_rsa ]; then
|
||||
echo "🔑 Clé SSH locale trouvée"
|
||||
|
||||
# Configurer Git pour utiliser SSH localement
|
||||
git config --global url."git@git.4nkweb.com:".insteadOf "https://git.4nkweb.com/"
|
||||
|
||||
echo "✅ Configuration SSH locale terminée"
|
||||
else
|
||||
echo "⚠️ Aucune clé SSH trouvée, configuration manuelle requise"
|
||||
echo "💡 Pour configurer SSH manuellement :"
|
||||
echo " 1. Générer une clé SSH : ssh-keygen -t rsa -b 4096"
|
||||
echo " 2. Ajouter la clé publique à votre compte Gitea"
|
||||
echo " 3. Tester : ssh -T git@git.4nkweb.com"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "🎯 Configuration SSH terminée pour ihm_client"
|
@ -1,47 +0,0 @@
|
||||
Param(
|
||||
[string]$Root = "."
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$files = Get-ChildItem -Path $Root -Recurse -Filter *.md | Where-Object { $_.FullName -notmatch '\\archive\\' }
|
||||
$had = $false
|
||||
foreach ($f in $files) {
|
||||
try {
|
||||
$lines = Get-Content -LiteralPath $f.FullName -Encoding UTF8 -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning ("Impossible de lire: {0} — {1}" -f $f.FullName, $_.Exception.Message)
|
||||
continue
|
||||
}
|
||||
$map = @{}
|
||||
$firstMap = @{}
|
||||
$dups = @{}
|
||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||
$line = $lines[$i]
|
||||
if ($line -match '^\s{0,3}#{1,6}\s+(.*)$') {
|
||||
$t = $Matches[1].Trim()
|
||||
$norm = ([regex]::Replace($t, '\s+', ' ')).ToLowerInvariant()
|
||||
if ($map.ContainsKey($norm)) {
|
||||
if (-not $dups.ContainsKey($norm)) {
|
||||
$dups[$norm] = New-Object System.Collections.ArrayList
|
||||
$firstMap[$norm] = $map[$norm]
|
||||
}
|
||||
[void]$dups[$norm].Add($i + 1)
|
||||
} else {
|
||||
$map[$norm] = $i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($dups.Keys.Count -gt 0) {
|
||||
$had = $true
|
||||
Write-Output "=== $($f.FullName) ==="
|
||||
foreach ($k in $dups.Keys) {
|
||||
$first = $firstMap[$k]
|
||||
$others = ($dups[$k] -join ', ')
|
||||
Write-Output ("Heading: '{0}' first@{1} duplicates@[{2}]" -f $k, $first, $others)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-not $had) {
|
||||
Write-Output "No duplicate headings detected."
|
||||
}
|
@ -1,818 +0,0 @@
|
||||
:host {
|
||||
--primary-color: #3a506b;
|
||||
/* Bleu métallique */
|
||||
--secondary-color: #b0bec5;
|
||||
/* Gris acier */
|
||||
--accent-color: #d68c45;
|
||||
/* Cuivre */
|
||||
font-family: Arial, sans-serif;
|
||||
height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
background-image: url(../assets/bgd.webp);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-blend-mode: soft-light;
|
||||
height: 100vh;
|
||||
}
|
||||
.message {
|
||||
margin: 30px 0;
|
||||
font-size: 14px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.message strong {
|
||||
font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/** Modal Css */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 55%;
|
||||
height: 30%;
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
margin: 0;
|
||||
padding-bottom: 8px;
|
||||
width: 100%;
|
||||
font-size: 0.9rem;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.confirmation-box {
|
||||
/* margin-top: 20px; */
|
||||
align-content: center;
|
||||
width: 70%;
|
||||
height: 20%;
|
||||
/* padding: 20px; */
|
||||
font-size: 1.5em;
|
||||
color: #333333;
|
||||
top: 5%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: fixed;
|
||||
background: radial-gradient(circle, white, var(--primary-color));
|
||||
/* background-color: #CFD8DC; */
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
color: #37474f;
|
||||
height: 9vh;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-shadow:
|
||||
0px 8px 10px -5px rgba(0, 0, 0, 0.2),
|
||||
0px 16px 24px 2px rgba(0, 0, 0, 0.14),
|
||||
0px 6px 30px 5px rgba(0, 0, 0, 0.12);
|
||||
|
||||
.nav-right-icons {
|
||||
display: flex;
|
||||
.notification-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.notification-bell,
|
||||
.burger-menu {
|
||||
z-index: 3;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -0.7rem;
|
||||
left: -0.8rem;
|
||||
background-color: red;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 2.5px 6px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.notification-board {
|
||||
position: absolute;
|
||||
width: 20rem;
|
||||
min-height: 8rem;
|
||||
background-color: white;
|
||||
right: 0.5rem;
|
||||
display: none;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
|
||||
.notification-element {
|
||||
padding: 0.8rem 0;
|
||||
width: 100%;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
}
|
||||
.notification-element:not(:last-child) {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 100%;
|
||||
width: 100vw;
|
||||
align-content: center;
|
||||
position: relative;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
display: grid;
|
||||
height: 100vh;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 10px;
|
||||
grid-auto-rows: 10vh 15vh 1fr;
|
||||
}
|
||||
.title-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 2;
|
||||
}
|
||||
.page-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 3;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 20px 0;
|
||||
}
|
||||
@media only screen and (min-width: 600px) {
|
||||
.tab-container {
|
||||
display: none;
|
||||
}
|
||||
.page-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.process-container {
|
||||
grid-column: 3 / 6;
|
||||
grid-row: 3;
|
||||
|
||||
.card {
|
||||
min-width: 40vw;
|
||||
}
|
||||
}
|
||||
.separator {
|
||||
width: 2px;
|
||||
background-color: #78909c;
|
||||
height: 80%;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.tab-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.process-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 3;
|
||||
}
|
||||
.container {
|
||||
grid-auto-rows: 10vh 15vh 15vh 1fr;
|
||||
}
|
||||
.tab-container {
|
||||
grid-column: 1 / 8;
|
||||
grid-row: 3;
|
||||
}
|
||||
.page-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 4;
|
||||
}
|
||||
.separator {
|
||||
display: none;
|
||||
}
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #e0e4d6;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
color: #6200ea;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
}
|
||||
.tab.active {
|
||||
border-bottom: 2px solid #6200ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 80%;
|
||||
}
|
||||
.modal-content {
|
||||
width: 80%;
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.emoji-display {
|
||||
font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#emoji-display-2 {
|
||||
margin-top: 30px;
|
||||
font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#okButton {
|
||||
margin-bottom: 2em;
|
||||
cursor: pointer;
|
||||
background-color: #d0d0d7;
|
||||
color: white;
|
||||
border-style: none;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.pairing-request {
|
||||
font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
|
||||
font-size: 14px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.create-btn {
|
||||
margin-bottom: 2em;
|
||||
cursor: pointer;
|
||||
background-color: #d0d0d7;
|
||||
color: white;
|
||||
border-style: none;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.camera-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
/* height: 200px; */
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #3700b3;
|
||||
}
|
||||
|
||||
.card {
|
||||
min-width: 300px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
height: 60vh;
|
||||
justify-content: flex-start;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
font-size: 0.8em;
|
||||
position: relative;
|
||||
left: 2vw;
|
||||
width: 90%;
|
||||
.process-title {
|
||||
font-weight: bold;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.process-element {
|
||||
padding: 0.4rem 0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
&.selected {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-description {
|
||||
padding: 20px;
|
||||
font-size: 1rem;
|
||||
color: #333;
|
||||
width: 90%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.card-action {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 3.4rem;
|
||||
right: 1rem;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menu-content a {
|
||||
display: block;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-content a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.qr-code-scanner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* QR READER */
|
||||
#qr-reader div {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
#qr-reader div img {
|
||||
top: 15px;
|
||||
right: 25px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* INPUT CSS **/
|
||||
.input-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #eceff1;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 36vw;
|
||||
padding: 10px 0;
|
||||
font-size: 1rem;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
border-bottom: 2px solid #6200ea;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
position: absolute;
|
||||
margin-top: -0.5em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 10px 0;
|
||||
font-size: 1rem;
|
||||
color: #999;
|
||||
pointer-events: none;
|
||||
transition:
|
||||
transform 0.3s,
|
||||
color 0.3s,
|
||||
font-size 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus + .input-label,
|
||||
.input-field:not(:placeholder-shown) + .input-label {
|
||||
transform: translateY(-20px);
|
||||
font-size: 0.8em;
|
||||
color: #6200ea;
|
||||
}
|
||||
|
||||
.input-underline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background-color: #6200ea;
|
||||
transition:
|
||||
width 0.3s,
|
||||
left 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus ~ .input-underline {
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
position: absolute;
|
||||
flex-direction: column;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-content span {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.dropdown-content span:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
/** AUTOCOMPLETE **/
|
||||
|
||||
select[data-multi-select-plugin] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.multi-select-component {
|
||||
width: 36vw;
|
||||
padding: 5px 0;
|
||||
font-size: 1rem;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
-o-transition:
|
||||
border-color ease-in-out 0.15s,
|
||||
box-shadow ease-in-out 0.15s;
|
||||
transition:
|
||||
border-color ease-in-out 0.15s,
|
||||
box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
.multi-select-component:focus-within {
|
||||
box-shadow: inset 0px 0px 0px 2px #78abfe;
|
||||
}
|
||||
|
||||
.multi-select-component .btn-group {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.multiselect-native-select .multiselect-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.selected-processes {
|
||||
background-color: white;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.selected-wrapper {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
border: 1px solid #d9d9d9;
|
||||
background-color: #ededed;
|
||||
white-space: nowrap;
|
||||
margin: 1px 5px 5px 0;
|
||||
height: 22px;
|
||||
vertical-align: top;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.selected-wrapper .selected-label {
|
||||
max-width: 514px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.selected-wrapper .selected-close {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
line-height: 1.49rem;
|
||||
margin-left: 5px;
|
||||
padding-bottom: 10px;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
padding-right: 4px;
|
||||
opacity: 0.2;
|
||||
color: #000;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.search-container .selected-input {
|
||||
background: none;
|
||||
border: 0;
|
||||
height: 20px;
|
||||
width: 60px;
|
||||
padding: 0;
|
||||
margin-bottom: 6px;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.search-container .selected-input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dropdown-icon.active {
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
|
||||
.search-container .dropdown-icon {
|
||||
display: inline-block;
|
||||
padding: 10px 5px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 0 !important;
|
||||
/* needed */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
/* SVG background image */
|
||||
background-image: url('data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23818181%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C0%2C0%2C1.414%2C0l5-5a1%2C1%2C0%2C1%2C0-1.414-1.414Z%22%20fill%3D%22%23818181%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E');
|
||||
background-position: center;
|
||||
background-size: 10px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.search-container ul {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
z-index: 3;
|
||||
margin-top: 29px;
|
||||
width: 100%;
|
||||
right: 0px;
|
||||
background: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
}
|
||||
|
||||
.search-container ul :focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search-container ul li {
|
||||
display: block;
|
||||
text-align: left;
|
||||
padding: 8px 29px 2px 12px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-size: 14px;
|
||||
min-height: 31px;
|
||||
}
|
||||
|
||||
.search-container ul li:first-child {
|
||||
border-top: 1px solid #ccc;
|
||||
border-radius: 4px 0px 0 0;
|
||||
}
|
||||
|
||||
.search-container ul li:last-child {
|
||||
border-radius: 4px 0px 0 0;
|
||||
}
|
||||
|
||||
.search-container ul li:hover.not-cursor {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.search-container ul li:hover {
|
||||
color: #333;
|
||||
background-color: #f0f0f0;
|
||||
border-color: #adadad;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Adding scrool to select options */
|
||||
.autocomplete-list {
|
||||
max-height: 130px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/**************************************** Process page card ******************************************************/
|
||||
.process-card {
|
||||
min-width: 300px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
min-height: 40vh;
|
||||
max-height: 60vh;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.process-card-content {
|
||||
text-align: left;
|
||||
font-size: 0.8em;
|
||||
position: relative;
|
||||
left: 2vw;
|
||||
width: 90%;
|
||||
.process-title {
|
||||
font-weight: bold;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.process-element {
|
||||
padding: 0.4rem 0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
&.selected {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
}
|
||||
.selected-process-zone {
|
||||
background-color: rgba(26, 28, 24, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.process-card-description {
|
||||
padding: 20px;
|
||||
font-size: 1rem;
|
||||
color: #333;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.process-card-action {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/**************************************** Select Member Home Page ******************************************************/
|
||||
.custom-select {
|
||||
width: 100%;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.custom-select option {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-select option:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.custom-select::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.custom-select::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
.custom-select::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.custom-select::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<div class="nav-wrapper">
|
||||
<div id="profile-header-container"></div>
|
||||
<div class="brand-logo">4NK</div>
|
||||
<div class="nav-right-icons">
|
||||
<div class="notification-container">
|
||||
<div class="bell-icon">
|
||||
<svg class="notification-bell" onclick="openCloseNotifications()" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path
|
||||
d="M224 0c-17.7 0-32 14.3-32 32V51.2C119 66 64 130.6 64 208v25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416H424c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6C399.5 322.9 384 278.8 384 233.4V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32zm0 96c61.9 0 112 50.1 112 112v25.4c0 47.9 13.9 94.6 39.7 134.6H72.3C98.1 328 112 281.3 112 233.4V208c0-61.9 50.1-112 112-112zm64 352H224 160c0 17 6.7 33.3 18.7 45.3s28.3 18.7 45.3 18.7s33.3-6.7 45.3-18.7s18.7-28.3 18.7-45.3z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="notification-badge"></div>
|
||||
<div id="notification-board" class="notification-board">
|
||||
<div class="no-notification">No notifications available</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="burger-menu">
|
||||
<svg class="burger-menu" onclick="toggleMenu()" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||
<path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" />
|
||||
</svg>
|
||||
|
||||
<div class="menu-content" id="menu">
|
||||
<!-- <a onclick="unpair()">Revoke</a> -->
|
||||
<a onclick="importJSON()">Import</a>
|
||||
<a onclick="createBackUp()">Export</a>
|
||||
<a onclick="navigate('account')">Account</a>
|
||||
<a onclick="navigate('chat')">Chat</a>
|
||||
<a onclick="navigate('signature')">Signatures</a>
|
||||
<a onclick="navigate('process')">Process</a>
|
||||
<a onclick="disconnect()">Disconnect</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,219 +0,0 @@
|
||||
import ModalService from '~/services/modal.service';
|
||||
import { INotification } from '../../models/notification.model';
|
||||
import { currentRoute, navigate } from '../../router';
|
||||
import Services from '../../services/service';
|
||||
import { BackUp } from '~/models/backup.model';
|
||||
|
||||
let notifications = [];
|
||||
|
||||
export async function unpair() {
|
||||
const service = await Services.getInstance();
|
||||
await service.unpairDevice();
|
||||
await navigate('home');
|
||||
}
|
||||
|
||||
(window as any).unpair = unpair;
|
||||
|
||||
function toggleMenu() {
|
||||
const menu = document.getElementById('menu');
|
||||
if (menu) {
|
||||
if (menu.style.display === 'block') {
|
||||
menu.style.display = 'none';
|
||||
} else {
|
||||
menu.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
(window as any).toggleMenu = toggleMenu;
|
||||
|
||||
async function getNotifications() {
|
||||
const service = await Services.getInstance();
|
||||
notifications = service.getNotifications() || [];
|
||||
return notifications;
|
||||
}
|
||||
function openCloseNotifications() {
|
||||
const notifications = document.querySelector('.notification-board') as HTMLDivElement;
|
||||
notifications.style.display = notifications?.style.display === 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
(window as any).openCloseNotifications = openCloseNotifications;
|
||||
|
||||
export async function initHeader() {
|
||||
if (currentRoute === 'account') {
|
||||
// Charger le profile-header
|
||||
const profileContainer = document.getElementById('profile-header-container');
|
||||
if (profileContainer) {
|
||||
const profileHeaderHtml = await fetch('/src/components/profile-header/profile-header.html').then((res) => res.text());
|
||||
profileContainer.innerHTML = profileHeaderHtml;
|
||||
|
||||
// Initialiser les données du profil
|
||||
loadUserProfile();
|
||||
}
|
||||
}
|
||||
if (currentRoute === 'home') {
|
||||
hideSomeFunctionnalities();
|
||||
} else {
|
||||
fetchNotifications();
|
||||
setInterval(fetchNotifications, 2 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function hideSomeFunctionnalities() {
|
||||
const bell = document.querySelector('.bell-icon') as HTMLDivElement;
|
||||
if (bell) bell.style.display = 'none';
|
||||
const notifBadge = document.querySelector('.notification-badge') as HTMLDivElement;
|
||||
if (notifBadge) notifBadge.style.display = 'none';
|
||||
const actions = document.querySelectorAll('.menu-content a') as NodeListOf<HTMLAnchorElement>;
|
||||
const excludedActions = ['Import', 'Export'];
|
||||
for (const action of actions) {
|
||||
if (!excludedActions.includes(action.innerHTML)) {
|
||||
action.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setNotification(notifications: any[]): Promise<void> {
|
||||
const badge = document.querySelector('.notification-badge') as HTMLDivElement;
|
||||
const noNotifications = document.querySelector('.no-notification') as HTMLDivElement;
|
||||
if (notifications?.length) {
|
||||
badge.innerText = notifications.length.toString();
|
||||
const notificationBoard = document.querySelector('.notification-board') as HTMLDivElement;
|
||||
notificationBoard.querySelectorAll('.notification-element')?.forEach((elem) => elem.remove());
|
||||
noNotifications.style.display = 'none';
|
||||
for (const notif of notifications) {
|
||||
const notifElement = document.createElement('div');
|
||||
notifElement.className = 'notification-element';
|
||||
notifElement.setAttribute('notif-id', notif.processId);
|
||||
notifElement.innerHTML = `
|
||||
<div>Validation required : </div>
|
||||
<div style="text-overflow: ellipsis; content-visibility: auto;">${notif.processId}</div>
|
||||
`;
|
||||
// this.addSubscription(notifElement, 'click', 'goToProcessPage')
|
||||
notificationBoard.appendChild(notifElement);
|
||||
notifElement.addEventListener('click', async () => {
|
||||
const modalService = await ModalService.getInstance();
|
||||
modalService.injectValidationModal(notif);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
noNotifications.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchNotifications() {
|
||||
const service = await Services.getInstance();
|
||||
const data = service.getNotifications() || [];
|
||||
await setNotification(data);
|
||||
}
|
||||
|
||||
async function loadUserProfile() {
|
||||
// Charger les données du profil depuis le localStorage
|
||||
const userName = localStorage.getItem('userName');
|
||||
const userLastName = localStorage.getItem('userLastName');
|
||||
const userAvatar = localStorage.getItem('userAvatar') || 'https://via.placeholder.com/150';
|
||||
const userBanner = localStorage.getItem('userBanner') || 'https://via.placeholder.com/800x200';
|
||||
|
||||
// Mettre à jour les éléments du DOM
|
||||
const nameElement = document.querySelector('.user-name');
|
||||
const lastNameElement = document.querySelector('.user-lastname');
|
||||
const avatarElement = document.querySelector('.avatar');
|
||||
const bannerElement = document.querySelector('.banner-image');
|
||||
|
||||
if (nameElement) nameElement.textContent = userName;
|
||||
if (lastNameElement) lastNameElement.textContent = userLastName;
|
||||
if (avatarElement) (avatarElement as HTMLImageElement).src = userAvatar;
|
||||
if (bannerElement) (bannerElement as HTMLImageElement).src = userBanner;
|
||||
}
|
||||
|
||||
async function importJSON() {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = '.json';
|
||||
|
||||
input.onchange = async (e) => {
|
||||
const file = (e.target as HTMLInputElement).files?.[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
try {
|
||||
const content: BackUp = JSON.parse(e.target?.result as string);
|
||||
const service = await Services.getInstance();
|
||||
await service.importJSON(content);
|
||||
alert('Import réussi');
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
alert("Erreur lors de l'import: " + error);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
|
||||
input.click();
|
||||
}
|
||||
|
||||
(window as any).importJSON = importJSON;
|
||||
|
||||
async function createBackUp() {
|
||||
const service = await Services.getInstance();
|
||||
const backUp = await service.createBackUp();
|
||||
if (!backUp) {
|
||||
console.error('No device to backup');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const backUpJson = JSON.stringify(backUp, null, 2);
|
||||
const blob = new Blob([backUpJson], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = '4nk-backup.json';
|
||||
a.click();
|
||||
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
console.log('Backup successfully prepared for download');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
(window as any).createBackUp = createBackUp;
|
||||
|
||||
async function disconnect() {
|
||||
console.log('Disconnecting...');
|
||||
try {
|
||||
localStorage.clear();
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const request = indexedDB.deleteDatabase('4nk');
|
||||
request.onsuccess = () => {
|
||||
console.log('IndexedDB deleted successfully');
|
||||
resolve();
|
||||
};
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onblocked = () => {
|
||||
console.log('Database deletion was blocked');
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
|
||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||
await Promise.all(registrations.map((registration) => registration.unregister()));
|
||||
console.log('Service worker unregistered');
|
||||
|
||||
await navigate('home');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = window.location.origin;
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
console.error('Error during disconnect:', error);
|
||||
// force reload
|
||||
window.location.href = window.location.origin;
|
||||
}
|
||||
}
|
||||
|
||||
(window as any).disconnect = disconnect;
|
@ -1,14 +0,0 @@
|
||||
<div id="login-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title">Login</div>
|
||||
<div class="confirmation-box">
|
||||
<div class="message">
|
||||
Attempting to pair device with address
|
||||
<strong>{{device1}}</strong>
|
||||
with device with address
|
||||
<strong>{{device2}}</strong>
|
||||
</div>
|
||||
<div>Awaiting pairing validation...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,13 +0,0 @@
|
||||
import Routing from '/src/services/routing.service.ts';
|
||||
|
||||
const router = await Routing.getInstance();
|
||||
export async function confirmLogin() {
|
||||
router.confirmLogin();
|
||||
}
|
||||
|
||||
export async function closeLoginModal() {
|
||||
router.closeLoginModal();
|
||||
}
|
||||
|
||||
window.confirmLogin = confirmLogin;
|
||||
window.closeLoginModal = closeLoginModal;
|
@ -1,16 +0,0 @@
|
||||
<div id="modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title">Login</div>
|
||||
<div class="message">
|
||||
Do you want to pair device?<br />
|
||||
Attempting to pair device with address <br />
|
||||
<strong>{{device1}}</strong> <br />
|
||||
with device with address <br />
|
||||
<strong>{{device2}}</strong>
|
||||
</div>
|
||||
<div class="confirmation-box">
|
||||
<a class="btn confirmation-btn" onclick="confirm()">Confirm</a>
|
||||
<a class="btn refusal-btn" onclick="closeConfirmationModal()">Refuse</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,13 +0,0 @@
|
||||
import ModalService from '../../services/modal.service';
|
||||
|
||||
const modalService = await ModalService.getInstance();
|
||||
// export async function confirm() {
|
||||
// modalService.confirmPairing();
|
||||
// }
|
||||
|
||||
export async function closeConfirmationModal() {
|
||||
modalService.closeConfirmationModal();
|
||||
}
|
||||
|
||||
(window as any).confirm = confirm;
|
||||
(window as any).closeConfirmationModal = closeConfirmationModal;
|
@ -1,14 +0,0 @@
|
||||
<div id="creation-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title">Login</div>
|
||||
<div class="message">
|
||||
Do you want to create a 4NK member?<br />
|
||||
Attempting to create a member with address <br />
|
||||
<strong>{{device1}}</strong> <br />
|
||||
</div>
|
||||
<div class="confirmation-box">
|
||||
<a class="btn confirmation-btn" onclick="confirm()">Confirm</a>
|
||||
<a class="btn refusal-btn" onclick="closeConfirmationModal()">Refuse</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,6 +0,0 @@
|
||||
<div id="waiting-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title">Login</div>
|
||||
<div class="message">Waiting for Device 2...</div>
|
||||
</div>
|
||||
</div>
|
@ -1,73 +0,0 @@
|
||||
import QrScanner from 'qr-scanner';
|
||||
import Services from '../../services/service';
|
||||
import { prepareAndSendPairingTx } from '~/utils/sp-address.utils';
|
||||
|
||||
export default class QrScannerComponent extends HTMLElement {
|
||||
videoElement: any;
|
||||
wrapper: any;
|
||||
qrScanner: any;
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.style.position = 'relative';
|
||||
this.wrapper.style.width = '150px';
|
||||
this.wrapper.style.height = '150px';
|
||||
|
||||
this.videoElement = document.createElement('video');
|
||||
this.videoElement.style.width = '100%';
|
||||
document.body?.append(this.wrapper);
|
||||
this.wrapper.prepend(this.videoElement);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.initializeScanner();
|
||||
}
|
||||
|
||||
async initializeScanner() {
|
||||
if (!this.videoElement) {
|
||||
console.error('Video element not found!');
|
||||
return;
|
||||
}
|
||||
console.log('🚀 ~ QrScannerComponent ~ initializeScanner ~ this.videoElement:', this.videoElement);
|
||||
this.qrScanner = new QrScanner(this.videoElement, (result) => this.onQrCodeScanned(result), {
|
||||
highlightScanRegion: true,
|
||||
highlightCodeOutline: true,
|
||||
});
|
||||
|
||||
try {
|
||||
await QrScanner.hasCamera();
|
||||
this.qrScanner.start();
|
||||
this.videoElement.style = 'height: 200px; width: 200px';
|
||||
this.shadowRoot?.appendChild(this.wrapper);
|
||||
} catch (e) {
|
||||
console.error('No camera found or error starting the QR scanner', e);
|
||||
}
|
||||
}
|
||||
|
||||
async onQrCodeScanned(result: any) {
|
||||
console.log(`QR Code detected:`, result);
|
||||
const data = result.data;
|
||||
const scannedUrl = new URL(data);
|
||||
|
||||
// Extract the 'sp_address' parameter
|
||||
const spAddress = scannedUrl.searchParams.get('sp_address');
|
||||
if (spAddress) {
|
||||
// Call the sendPairingTx function with the extracted sp_address
|
||||
try {
|
||||
await prepareAndSendPairingTx();
|
||||
} catch (e) {
|
||||
console.error('Failed to pair:', e);
|
||||
}
|
||||
}
|
||||
this.qrScanner.stop(); // if you want to stop scanning after one code is detected
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
if (this.qrScanner) {
|
||||
this.qrScanner.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('qr-scanner', QrScannerComponent);
|
@ -1,70 +0,0 @@
|
||||
.validation-modal {
|
||||
display: block; /* Show the modal for demo purposes */
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgb(0, 0, 0);
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
padding-top: 60px;
|
||||
}
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 5% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
height: fit-content;
|
||||
}
|
||||
.modal-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.validation-box {
|
||||
margin-bottom: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
.expansion-panel-header {
|
||||
background-color: #e0e0e0;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.expansion-panel-body {
|
||||
display: none;
|
||||
background-color: #fafafa;
|
||||
padding: 10px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
.expansion-panel-body pre {
|
||||
background-color: #f6f8fa;
|
||||
padding: 10px;
|
||||
border-left: 4px solid #d1d5da;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.diff {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.diff-side {
|
||||
width: 48%;
|
||||
padding: 10px;
|
||||
}
|
||||
.diff-old {
|
||||
background-color: #fee;
|
||||
border: 1px solid #f00;
|
||||
}
|
||||
.diff-new {
|
||||
background-color: #e6ffe6;
|
||||
border: 1px solid #0f0;
|
||||
}
|
||||
.radio-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<div id="validation-modal" class="validation-modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title">Validate Process {{processId}}</div>
|
||||
<div class="validation-box"></div>
|
||||
<div class="modal-action">
|
||||
<button onclick="validate()">Validate</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,56 +0,0 @@
|
||||
import ModalService from '~/services/modal.service';
|
||||
|
||||
async function validate() {
|
||||
console.log('==> VALIDATE');
|
||||
const modalservice = await ModalService.getInstance();
|
||||
modalservice.closeValidationModal();
|
||||
}
|
||||
|
||||
export async function initValidationModal(processDiffs: any) {
|
||||
console.log('🚀 ~ initValidationModal ~ processDiffs:', processDiffs);
|
||||
for (const diff of processDiffs.diffs) {
|
||||
let diffs = '';
|
||||
for (const value of diff) {
|
||||
diffs += `
|
||||
<div class="radio-buttons">
|
||||
<label>
|
||||
<input type="radio" name="validation1" value="old" />
|
||||
Keep Old
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="validation1" value="new" />
|
||||
Keep New
|
||||
</label>
|
||||
</div>
|
||||
<div class="diff">
|
||||
<div class="diff-side diff-old">
|
||||
<pre>-${value.previous_value}</pre>
|
||||
</div>
|
||||
<div class="diff-side diff-new">
|
||||
<pre>+${value.new_value}</pre>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
const state = `
|
||||
<div class="expansion-panel">
|
||||
<div class="expansion-panel-header">State ${diff[0].new_state_merkle_root}</div>
|
||||
<div class="expansion-panel-body">
|
||||
${diffs}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const box = document.querySelector('.validation-box');
|
||||
if (box) box.innerHTML += state;
|
||||
}
|
||||
document.querySelectorAll('.expansion-panel-header').forEach((header) => {
|
||||
header.addEventListener('click', function (event) {
|
||||
const target = event.target as HTMLElement;
|
||||
const body = target.nextElementSibling as HTMLElement;
|
||||
if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(window as any).validate = validate;
|
@ -1,25 +0,0 @@
|
||||
<div id="validation-rule-modal" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: none; justify-content: center; align-items: center; z-index: 9999">
|
||||
<div style="background: white; padding: 2rem; border-radius: 0.5rem; width: 400px; max-width: 90%; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3)">
|
||||
<h2 style="font-size: 1.2rem; font-weight: bold; margin-bottom: 1rem">Add Validation Rule</h2>
|
||||
|
||||
<label style="display: block; margin-bottom: 0.5rem">
|
||||
Quorum:
|
||||
<input id="vr-quorum" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
|
||||
</label>
|
||||
|
||||
<label style="display: block; margin-bottom: 0.5rem">
|
||||
Min Sig Member:
|
||||
<input id="vr-minsig" type="number" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
|
||||
</label>
|
||||
|
||||
<label style="display: block; margin-bottom: 1rem">
|
||||
Fields (comma-separated):
|
||||
<input id="vr-fields" type="text" placeholder="e.g. field1, field2" style="width: 100%; padding: 0.5rem; margin-top: 0.25rem" />
|
||||
</label>
|
||||
|
||||
<div style="display: flex; justify-content: flex-end; gap: 1rem">
|
||||
<button id="vr-cancel" style="padding: 0.5rem 1rem">Cancel</button>
|
||||
<button id="vr-submit" style="padding: 0.5rem 1rem; background-color: #4f46e5; color: white; border: none; border-radius: 0.375rem">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,64 +0,0 @@
|
||||
export interface ValidationRule {
|
||||
quorum: number;
|
||||
fields: string[];
|
||||
min_sig_member: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and injects the modal HTML into the document if not already loaded.
|
||||
*/
|
||||
export async function loadValidationRuleModal(templatePath: string = '/src/components/validation-rule-modal/validation-rule-modal.html') {
|
||||
if (document.getElementById('validation-rule-modal')) return;
|
||||
|
||||
const res = await fetch(templatePath);
|
||||
const html = await res.text();
|
||||
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = html;
|
||||
|
||||
const modal = tempDiv.querySelector('#validation-rule-modal');
|
||||
if (!modal) {
|
||||
throw new Error('Modal HTML missing #validation-rule-modal');
|
||||
}
|
||||
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the modal and lets the user input a ValidationRule.
|
||||
* Calls the callback with the constructed rule on submit.
|
||||
*/
|
||||
export function showValidationRuleModal(onSubmit: (rule: ValidationRule) => void) {
|
||||
const modal = document.getElementById('validation-rule-modal')!;
|
||||
const quorumInput = document.getElementById('vr-quorum') as HTMLInputElement;
|
||||
const minsigInput = document.getElementById('vr-minsig') as HTMLInputElement;
|
||||
const fieldsInput = document.getElementById('vr-fields') as HTMLInputElement;
|
||||
|
||||
const cancelBtn = document.getElementById('vr-cancel')!;
|
||||
const submitBtn = document.getElementById('vr-submit')!;
|
||||
|
||||
// Reset values
|
||||
quorumInput.value = '';
|
||||
minsigInput.value = '';
|
||||
fieldsInput.value = '';
|
||||
|
||||
modal.style.display = 'flex';
|
||||
|
||||
cancelBtn.onclick = () => {
|
||||
modal.style.display = 'none';
|
||||
};
|
||||
|
||||
submitBtn.onclick = () => {
|
||||
const rule: ValidationRule = {
|
||||
quorum: parseInt(quorumInput.value),
|
||||
min_sig_member: parseInt(minsigInput.value),
|
||||
fields: fieldsInput.value
|
||||
.split(',')
|
||||
.map((f) => f.trim())
|
||||
.filter(Boolean),
|
||||
};
|
||||
|
||||
modal.style.display = 'none';
|
||||
onSubmit(rule);
|
||||
};
|
||||
}
|
10
modules/ihm_client/src/decs.d.ts
vendored
10
modules/ihm_client/src/decs.d.ts
vendored
@ -1,10 +0,0 @@
|
||||
declare class AccountComponent extends HTMLElement {
|
||||
_callback: any;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
fetchData(): Promise<void>;
|
||||
set callback(fn: any);
|
||||
get callback(): any;
|
||||
render(): void;
|
||||
}
|
||||
export { AccountComponent };
|
@ -1,3 +0,0 @@
|
||||
export { default as Services } from './services/service';
|
||||
export { default as Database } from './services/database.service';
|
||||
export { MessageType } from './models/process.model';
|
@ -1,22 +0,0 @@
|
||||
import { DocumentSignature } from '~/models/signature.models';
|
||||
|
||||
export interface Group {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
roles: Array<{
|
||||
name: string;
|
||||
members: Array<{ id: string | number; name: string }>;
|
||||
documents?: Array<any>;
|
||||
}>;
|
||||
commonDocuments: Array<{
|
||||
id: number;
|
||||
name: string;
|
||||
visibility: string;
|
||||
description: string;
|
||||
createdAt?: string | null;
|
||||
deadline?: string | null;
|
||||
signatures?: DocumentSignature[];
|
||||
status?: string;
|
||||
}>;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export interface Member {
|
||||
id: string | number;
|
||||
name: string;
|
||||
email?: string;
|
||||
avatar?: string;
|
||||
processRoles?: Array<{ processId: number | string; role: string }>;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*import { ChatComponent } from './pages/chat/chat-component';
|
||||
import { ChatElement } from './pages/chat/chat';*/
|
||||
import { AccountComponent } from './pages/account/account-component';
|
||||
import { AccountElement } from './pages/account/account';
|
||||
|
||||
export { AccountComponent, AccountElement };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
// Signatures supprimées
|
||||
/*'chat-component': ChatComponent;
|
||||
'chat-element': ChatElement;*/
|
||||
'account-component': AccountComponent;
|
||||
'account-element': AccountElement;
|
||||
}
|
||||
}
|
||||
|
||||
// Configuration pour le mode indépendant
|
||||
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) {
|
||||
// Initialiser les composants si nécessaire
|
||||
// Signatures supprimées
|
||||
/*customElements.define('chat-component', ChatComponent);
|
||||
customElements.define('chat-element', ChatElement);*/
|
||||
customElements.define('account-component', AccountComponent);
|
||||
customElements.define('account-element', AccountElement);
|
||||
}
|
@ -1,272 +0,0 @@
|
||||
export const ALLOWED_ROLES = ['User', 'Member', 'Peer', 'Payment', 'Deposit', 'Artefact', 'Resolve', 'Backup'];
|
||||
|
||||
export const STORAGE_KEYS = {
|
||||
pairing: 'pairingRows',
|
||||
wallet: 'walletRows',
|
||||
process: 'processRows',
|
||||
data: 'dataRows',
|
||||
};
|
||||
|
||||
// Initialiser le stockage des lignes par défaut dans le localStorage
|
||||
export const defaultRows = [
|
||||
{
|
||||
column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrz',
|
||||
column2: '🎊😑🎄😩',
|
||||
column3: 'Laptop',
|
||||
},
|
||||
{
|
||||
column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrx',
|
||||
column2: '🎏🎕😧🌥',
|
||||
column3: 'Phone',
|
||||
},
|
||||
];
|
||||
|
||||
export const mockNotifications: { [key: string]: Notification[] } = {};
|
||||
|
||||
export const notificationMessages = ['CPU usage high', 'Memory threshold reached', 'New update available', 'Backup completed', 'Security check required', 'Performance optimization needed', 'System alert', 'Network connectivity issue', 'Storage space low', 'Process checkpoint reached'];
|
||||
|
||||
export const mockDataRows = [
|
||||
{
|
||||
column1: 'User Project',
|
||||
column2: 'private',
|
||||
column3: 'User',
|
||||
column4: '6 months',
|
||||
column5: 'NDA signed',
|
||||
column6: 'Contract #123',
|
||||
processName: 'User Process',
|
||||
zone: 'A',
|
||||
},
|
||||
{
|
||||
column1: 'Process Project',
|
||||
column2: 'private',
|
||||
column3: 'Process',
|
||||
column4: '1 year',
|
||||
column5: 'Terms accepted',
|
||||
column6: 'Contract #456',
|
||||
processName: 'Process Management',
|
||||
zone: 'B',
|
||||
},
|
||||
{
|
||||
column1: 'Member Project',
|
||||
column2: 'private',
|
||||
column3: 'Member',
|
||||
column4: '3 months',
|
||||
column5: 'GDPR compliant',
|
||||
column6: 'Contract #789',
|
||||
processName: 'Member Process',
|
||||
zone: 'C',
|
||||
},
|
||||
{
|
||||
column1: 'Peer Project',
|
||||
column2: 'public',
|
||||
column3: 'Peer',
|
||||
column4: '2 years',
|
||||
column5: 'IP rights',
|
||||
column6: 'Contract #101',
|
||||
processName: 'Peer Process',
|
||||
zone: 'D',
|
||||
},
|
||||
{
|
||||
column1: 'Payment Project',
|
||||
column2: 'confidential',
|
||||
column3: 'Payment',
|
||||
column4: '1 year',
|
||||
column5: 'NDA signed',
|
||||
column6: 'Contract #102',
|
||||
processName: 'Payment Process',
|
||||
zone: 'E',
|
||||
},
|
||||
{
|
||||
column1: 'Deposit Project',
|
||||
column2: 'private',
|
||||
column3: 'Deposit',
|
||||
column4: '6 months',
|
||||
column5: 'Terms accepted',
|
||||
column6: 'Contract #103',
|
||||
processName: 'Deposit Process',
|
||||
zone: 'F',
|
||||
},
|
||||
{
|
||||
column1: 'Artefact Project',
|
||||
column2: 'public',
|
||||
column3: 'Artefact',
|
||||
column4: '1 year',
|
||||
column5: 'GDPR compliant',
|
||||
column6: 'Contract #104',
|
||||
processName: 'Artefact Process',
|
||||
zone: 'G',
|
||||
},
|
||||
{
|
||||
column1: 'Resolve Project',
|
||||
column2: 'private',
|
||||
column3: 'Resolve',
|
||||
column4: '2 years',
|
||||
column5: 'IP rights',
|
||||
column6: 'Contract #105',
|
||||
processName: 'Resolve Process',
|
||||
zone: 'H',
|
||||
},
|
||||
{
|
||||
column1: 'Backup Project',
|
||||
column2: 'public',
|
||||
column3: 'Backup',
|
||||
column4: '1 year',
|
||||
column5: 'NDA signed',
|
||||
column6: 'Contract #106',
|
||||
processName: 'Backup Process',
|
||||
zone: 'I',
|
||||
},
|
||||
];
|
||||
|
||||
export const mockProcessRows = [
|
||||
{
|
||||
process: 'User Project',
|
||||
role: 'User',
|
||||
notification: {
|
||||
messages: [
|
||||
{ id: 1, read: false, date: '2024-03-10', message: 'New user joined the project' },
|
||||
{ id: 2, read: false, date: '2024-03-09', message: 'Project milestone reached' },
|
||||
{ id: 3, read: false, date: '2024-03-08', message: 'Security update required' },
|
||||
{ id: 4, read: true, date: '2024-03-07', message: 'Weekly report available' },
|
||||
{ id: 5, read: true, date: '2024-03-06', message: 'Team meeting scheduled' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
process: 'Member Project',
|
||||
role: 'Member',
|
||||
notification: {
|
||||
messages: [
|
||||
{ id: 6, read: true, date: '2024-03-10', message: 'Member access granted' },
|
||||
{ id: 7, read: true, date: '2024-03-09', message: 'Documentation updated' },
|
||||
{ id: 8, read: true, date: '2024-03-08', message: 'Project status: on track' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
process: 'Peer Project',
|
||||
role: 'Peer',
|
||||
notification: {
|
||||
unread: 2,
|
||||
total: 4,
|
||||
messages: [
|
||||
{ id: 9, read: false, date: '2024-03-10', message: 'New peer project added' },
|
||||
{ id: 10, read: false, date: '2024-03-09', message: 'Project milestone reached' },
|
||||
{ id: 11, read: false, date: '2024-03-08', message: 'Security update required' },
|
||||
{ id: 12, read: true, date: '2024-03-07', message: 'Weekly report available' },
|
||||
{ id: 13, read: true, date: '2024-03-06', message: 'Team meeting scheduled' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
process: 'Deposit Project',
|
||||
role: 'Deposit',
|
||||
notification: {
|
||||
unread: 1,
|
||||
total: 10,
|
||||
messages: [
|
||||
{ id: 14, read: false, date: '2024-03-10', message: 'Deposit milestone reached' },
|
||||
{ id: 15, read: false, date: '2024-03-09', message: 'Security update required' },
|
||||
{ id: 16, read: false, date: '2024-03-08', message: 'Weekly report available' },
|
||||
{ id: 17, read: true, date: '2024-03-07', message: 'Team meeting scheduled' },
|
||||
{ id: 18, read: true, date: '2024-03-06', message: 'Project status: on track' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
process: 'Artefact Project',
|
||||
role: 'Artefact',
|
||||
notification: {
|
||||
unread: 0,
|
||||
total: 3,
|
||||
messages: [
|
||||
{ id: 19, read: false, date: '2024-03-10', message: 'New artefact added' },
|
||||
{ id: 20, read: false, date: '2024-03-09', message: 'Security update required' },
|
||||
{ id: 21, read: false, date: '2024-03-08', message: 'Weekly report available' },
|
||||
{ id: 22, read: true, date: '2024-03-07', message: 'Team meeting scheduled' },
|
||||
{ id: 23, read: true, date: '2024-03-06', message: 'Project status: on track' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
process: 'Resolve Project',
|
||||
role: 'Resolve',
|
||||
notification: {
|
||||
unread: 5,
|
||||
total: 12,
|
||||
messages: [
|
||||
{ id: 24, read: false, date: '2024-03-10', message: 'New issue reported' },
|
||||
{ id: 25, read: false, date: '2024-03-09', message: 'Security update required' },
|
||||
{ id: 26, read: false, date: '2024-03-08', message: 'Weekly report available' },
|
||||
{ id: 27, read: true, date: '2024-03-07', message: 'Team meeting scheduled' },
|
||||
{ id: 28, read: true, date: '2024-03-06', message: 'Project status: on track' },
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const mockContracts = {
|
||||
'Contract #123': {
|
||||
title: 'User Project Agreement',
|
||||
date: '2024-01-15',
|
||||
parties: ['Company XYZ', 'User Team'],
|
||||
terms: ['Data Protection', 'User Privacy', 'Access Rights', 'Service Level Agreement'],
|
||||
content: 'This agreement establishes the terms and conditions for user project management.',
|
||||
},
|
||||
'Contract #456': {
|
||||
title: 'Process Management Contract',
|
||||
date: '2024-02-01',
|
||||
parties: ['Company XYZ', 'Process Team'],
|
||||
terms: ['Process Workflow', 'Quality Standards', 'Performance Metrics', 'Monitoring Procedures'],
|
||||
content: 'This contract defines the process management standards and procedures.',
|
||||
},
|
||||
'Contract #789': {
|
||||
title: 'Member Access Agreement',
|
||||
date: '2024-03-15',
|
||||
parties: ['Company XYZ', 'Member Team'],
|
||||
terms: ['Member Rights', 'Access Levels', 'Security Protocol', 'Confidentiality Agreement'],
|
||||
content: 'This agreement outlines the terms for member access and privileges.',
|
||||
},
|
||||
'Contract #101': {
|
||||
title: 'Peer Collaboration Agreement',
|
||||
date: '2024-04-01',
|
||||
parties: ['Company XYZ', 'Peer Network'],
|
||||
terms: ['Collaboration Rules', 'Resource Sharing', 'Dispute Resolution', 'Network Protocol'],
|
||||
content: 'This contract establishes peer collaboration and networking guidelines.',
|
||||
},
|
||||
'Contract #102': {
|
||||
title: 'Payment Processing Agreement',
|
||||
date: '2024-05-01',
|
||||
parties: ['Company XYZ', 'Payment Team'],
|
||||
terms: ['Transaction Protocol', 'Security Measures', 'Fee Structure', 'Service Availability'],
|
||||
content: 'This agreement defines payment processing terms and conditions.',
|
||||
},
|
||||
'Contract #103': {
|
||||
title: 'Deposit Management Contract',
|
||||
date: '2024-06-01',
|
||||
parties: ['Company XYZ', 'Deposit Team'],
|
||||
terms: ['Deposit Rules', 'Storage Protocol', 'Access Control', 'Security Standards'],
|
||||
content: 'This contract outlines deposit management procedures and security measures.',
|
||||
},
|
||||
'Contract #104': {
|
||||
title: 'Artefact Handling Agreement',
|
||||
date: '2024-07-01',
|
||||
parties: ['Company XYZ', 'Artefact Team'],
|
||||
terms: ['Handling Procedures', 'Storage Guidelines', 'Access Protocol', 'Preservation Standards'],
|
||||
content: 'This agreement establishes artefact handling and preservation guidelines.',
|
||||
},
|
||||
'Contract #105': {
|
||||
title: 'Resolution Protocol Agreement',
|
||||
date: '2024-08-01',
|
||||
parties: ['Company XYZ', 'Resolution Team'],
|
||||
terms: ['Resolution Process', 'Time Constraints', 'Escalation Protocol', 'Documentation Requirements'],
|
||||
content: 'This contract defines the resolution process and protocol standards.',
|
||||
},
|
||||
'Contract #106': {
|
||||
title: 'Backup Service Agreement',
|
||||
date: '2024-09-01',
|
||||
parties: ['Company XYZ', 'Backup Team'],
|
||||
terms: ['Backup Schedule', 'Data Protection', 'Recovery Protocol', 'Service Reliability'],
|
||||
content: 'This agreement outlines backup service terms and recovery procedures.',
|
||||
},
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
export interface Row {
|
||||
column1: string;
|
||||
column2: string;
|
||||
column3: string;
|
||||
}
|
||||
|
||||
// Types supplémentaires nécessaires
|
||||
export interface Contract {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface WalletRow {
|
||||
column1: string; // Label
|
||||
column2: string; // Wallet
|
||||
column3: string; // Type
|
||||
}
|
||||
|
||||
export interface DataRow {
|
||||
column1: string; // Name
|
||||
column2: string; // Visibility
|
||||
column3: string; // Role
|
||||
column4: string; // Duration
|
||||
column5: string; // Legal
|
||||
column6: string; // Contract
|
||||
processName: string;
|
||||
zone: string;
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
message: string;
|
||||
timestamp: string;
|
||||
isRead: boolean;
|
||||
}
|
||||
|
||||
// Déplacer l'interface en dehors de la classe, au début du fichier
|
||||
export interface NotificationMessage {
|
||||
id: number;
|
||||
read: boolean;
|
||||
date: string;
|
||||
message: string;
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
export const groupsMock = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Group 🚀 ',
|
||||
roles: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Role 1',
|
||||
members: [
|
||||
{ id: 1, name: 'Member 1' },
|
||||
{ id: 2, name: 'Member 2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Role 2',
|
||||
members: [
|
||||
{ id: 3, name: 'Member 3' },
|
||||
{ id: 4, name: 'Member 4' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Group ₿',
|
||||
roles: [
|
||||
{
|
||||
id: 3,
|
||||
name: 'Role 1',
|
||||
members: [
|
||||
{ id: 5, name: 'Member 5' },
|
||||
{ id: 6, name: 'Member 6' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Group 🪙',
|
||||
roles: [
|
||||
{
|
||||
id: 4,
|
||||
name: 'Role 1',
|
||||
members: [
|
||||
{ id: 7, name: 'Member 7' },
|
||||
{ id: 8, name: 'Member 8' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
@ -1,64 +0,0 @@
|
||||
export const messagesMock = [
|
||||
{
|
||||
memberId: 1, // Conversations avec Mmber 1
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 1', text: 'Salut !', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Bonjour ! Comment ça va ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Tout va bien, merci !', time: '10:32 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 2, // Conversations avec Member 2
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 2', text: 'Salut, on se voit ce soir ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Oui, à quelle heure ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 3, // Conversations avec Member 3
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 3', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 4, // Conversations avec Member 4
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 4', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 5, // Conversations avec Member 5
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 5', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 6, // Conversations avec Member 6
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 6', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 7, // Conversations avec Member 7
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 7', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 8, // Conversations avec Member 8
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 8', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
];
|
@ -1,471 +0,0 @@
|
||||
// Définir les rôles autorisés
|
||||
const VALID_ROLES = ['User', 'Process', 'Member', 'Peer', 'Payment', 'Deposit', 'Artefact', 'Resolve', 'Backup'];
|
||||
|
||||
const VISIBILITY_LEVELS = {
|
||||
PUBLIC: 'public',
|
||||
CONFIDENTIAL: 'confidential',
|
||||
PRIVATE: 'private',
|
||||
};
|
||||
|
||||
const DOCUMENT_STATUS = {
|
||||
DRAFT: 'draft',
|
||||
PENDING: 'pending',
|
||||
IN_REVIEW: 'in_review',
|
||||
APPROVED: 'approved',
|
||||
REJECTED: 'rejected',
|
||||
EXPIRED: 'expired',
|
||||
};
|
||||
|
||||
// Fonction pour créer un rôle
|
||||
function createRole(name, members) {
|
||||
if (!VALID_ROLES.includes(name)) {
|
||||
throw new Error(`Role "${name}" is not valid.`);
|
||||
}
|
||||
return { name, members };
|
||||
}
|
||||
|
||||
export const groupsMock = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Processus 1',
|
||||
description: 'Description du processus 1',
|
||||
commonDocuments: [
|
||||
{
|
||||
id: 101,
|
||||
name: 'Règlement intérieur',
|
||||
description: 'Document vierge pour le règlement intérieur',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 102,
|
||||
name: 'Charte de confidentialité',
|
||||
description: 'Document vierge pour la charte de confidentialité',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 103,
|
||||
name: 'Procédures générales',
|
||||
description: 'Document vierge pour les procédures générales',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
name: 'Urgency A',
|
||||
description: "Document vierge pour le plan d'urgence A",
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 105,
|
||||
name: 'Urgency B',
|
||||
description: "Document vierge pour le plan d'urgence B",
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 106,
|
||||
name: 'Urgency C',
|
||||
description: "Document vierge pour le plan d'urgence C",
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 107,
|
||||
name: 'Document à signer',
|
||||
description: 'Document vierge pour le règlement intérieur',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
roles: [
|
||||
{
|
||||
name: 'User',
|
||||
members: [
|
||||
{ id: 1, name: 'Alice' },
|
||||
{ id: 2, name: 'Bob' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Document User A',
|
||||
description: 'Description du document User A.',
|
||||
visibility: 'public',
|
||||
createdAt: '2024-01-01',
|
||||
deadline: '2024-02-01',
|
||||
signatures: [
|
||||
{
|
||||
member: { id: 1, name: 'Alice' },
|
||||
signed: true,
|
||||
signedAt: '2024-01-15',
|
||||
},
|
||||
{
|
||||
member: { id: 2, name: 'Bob' },
|
||||
signed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Document User B',
|
||||
description: 'Document vierge pour le rôle User',
|
||||
visibility: 'confidential',
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Document User C',
|
||||
description: 'Document vierge pour validation utilisateur',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Document User D',
|
||||
description: 'Document vierge pour approbation utilisateur',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Process',
|
||||
members: [
|
||||
{ id: 3, name: 'Charlie' },
|
||||
{ id: 4, name: 'David' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 3,
|
||||
name: 'Document Process A',
|
||||
description: 'Description du document Process A.',
|
||||
visibility: 'confidential',
|
||||
createdAt: '2024-01-10',
|
||||
deadline: '2024-03-01',
|
||||
signatures: [
|
||||
{
|
||||
member: { id: 3, name: 'Charlie' },
|
||||
signed: true,
|
||||
signedAt: '2024-01-12',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'Document Process B',
|
||||
description: 'Document vierge pour processus interne',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'Document Process C',
|
||||
description: 'Document vierge pour validation processus',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Document Process D',
|
||||
description: 'Document vierge pour validation processus',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.PENDING,
|
||||
createdAt: '2024-01-15',
|
||||
deadline: '2024-02-01',
|
||||
signatures: [
|
||||
{
|
||||
member: { id: 3, name: 'Charlie' },
|
||||
signed: true,
|
||||
signedAt: '2024-01-15',
|
||||
},
|
||||
{
|
||||
member: { id: 4, name: 'David' },
|
||||
signed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: 'Document Process E',
|
||||
description: 'Document vierge pour validation processus',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.PENDING,
|
||||
createdAt: '2024-01-15',
|
||||
deadline: '2024-02-01',
|
||||
signatures: [
|
||||
{
|
||||
member: { id: 3, name: 'Charlie' },
|
||||
signed: true,
|
||||
signedAt: '2024-01-15',
|
||||
},
|
||||
{
|
||||
member: { id: 4, name: 'David' },
|
||||
signed: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Backup',
|
||||
members: [
|
||||
{ id: 15, name: 'Oscar' },
|
||||
{ id: 16, name: 'Patricia' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 11,
|
||||
name: 'Document Backup A',
|
||||
description: 'Document vierge pour sauvegarde',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Processus 2',
|
||||
description: 'Description du processus 2',
|
||||
commonDocuments: [
|
||||
{
|
||||
id: 201,
|
||||
name: 'Règlement intérieur',
|
||||
description: 'Document vierge pour le règlement intérieur',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 202,
|
||||
name: 'Charte de confidentialité',
|
||||
description: 'Document vierge pour la charte de confidentialité',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 203,
|
||||
name: 'Charte de confidentialité',
|
||||
description: 'Document vierge pour la charte de confidentialité',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 204,
|
||||
name: 'Charte de confidentialité',
|
||||
description: 'Document vierge pour la charte de confidentialité',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 205,
|
||||
name: 'Charte de confidentialité',
|
||||
description: 'Document vierge pour la charte de confidentialité',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
roles: [
|
||||
{
|
||||
name: 'Artefact',
|
||||
members: [
|
||||
{ id: 17, name: 'Quinn' },
|
||||
{ id: 18, name: 'Rachel' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 12,
|
||||
name: 'Document Artefact A',
|
||||
description: 'Document vierge pour artefact',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: 'Document Artefact B',
|
||||
description: 'Document vierge pour validation artefact',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Resolve',
|
||||
members: [
|
||||
{ id: 19, name: 'Sam' },
|
||||
{ id: 20, name: 'Tom' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 14,
|
||||
name: 'Document Resolve A',
|
||||
description: 'Document vierge pour résolution',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Processus 3',
|
||||
description: 'Description du processus 3',
|
||||
commonDocuments: [
|
||||
{
|
||||
id: 301,
|
||||
name: 'Règlement intérieur',
|
||||
description: 'Document vierge pour le règlement intérieur',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 302,
|
||||
name: 'Charte de confidentialité',
|
||||
description: 'Document vierge pour la charte de confidentialité',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 303,
|
||||
name: 'Procédures générales',
|
||||
description: 'Document vierge pour les procédures générales',
|
||||
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
roles: [
|
||||
{
|
||||
name: 'Deposit',
|
||||
members: [
|
||||
{ id: 21, name: 'Uma' },
|
||||
{ id: 22, name: 'Victor' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 15,
|
||||
name: 'Document Deposit A',
|
||||
description: 'Document vierge pour dépôt',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: 'Document Deposit B',
|
||||
description: 'Document vierge pour validation dépôt',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Payment',
|
||||
members: [
|
||||
{ id: 23, name: 'Walter' },
|
||||
{ id: 24, name: 'Xena' },
|
||||
],
|
||||
documents: [
|
||||
{
|
||||
id: 17,
|
||||
name: 'Document Payment B',
|
||||
description: 'Document vierge pour paiement',
|
||||
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
name: 'Document Payment C',
|
||||
description: 'Document vierge pour validation paiement',
|
||||
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||
status: DOCUMENT_STATUS.DRAFT,
|
||||
createdAt: null,
|
||||
deadline: null,
|
||||
signatures: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
@ -1,105 +0,0 @@
|
||||
export const membersMock = [
|
||||
// Processus 1
|
||||
{
|
||||
id: 1,
|
||||
name: 'Alice',
|
||||
avatar: 'A',
|
||||
email: 'alice@company.com',
|
||||
processRoles: [{ processId: 1, role: 'User' }],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Bob',
|
||||
avatar: 'B',
|
||||
email: 'bob@company.com',
|
||||
processRoles: [{ processId: 1, role: 'User' }],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Charlie',
|
||||
avatar: 'C',
|
||||
email: 'charlie@company.com',
|
||||
processRoles: [{ processId: 1, role: 'Process' }],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'David',
|
||||
avatar: 'D',
|
||||
email: 'david@company.com',
|
||||
processRoles: [{ processId: 1, role: 'Process' }],
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: 'Oscar',
|
||||
avatar: 'O',
|
||||
email: 'oscar@company.com',
|
||||
processRoles: [{ processId: 1, role: 'Backup' }],
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: 'Patricia',
|
||||
avatar: 'P',
|
||||
email: 'patricia@company.com',
|
||||
processRoles: [{ processId: 1, role: 'Backup' }],
|
||||
},
|
||||
|
||||
// Processus 2
|
||||
{
|
||||
id: 17,
|
||||
name: 'Quinn',
|
||||
avatar: 'Q',
|
||||
email: 'quinn@company.com',
|
||||
processRoles: [{ processId: 2, role: 'Artefact' }],
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
name: 'Rachel',
|
||||
avatar: 'R',
|
||||
email: 'rachel@company.com',
|
||||
processRoles: [{ processId: 2, role: 'Artefact' }],
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
name: 'Sam',
|
||||
avatar: 'S',
|
||||
email: 'sam@company.com',
|
||||
processRoles: [{ processId: 2, role: 'Resolve' }],
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: 'Tom',
|
||||
avatar: 'T',
|
||||
email: 'tom@company.com',
|
||||
processRoles: [{ processId: 2, role: 'Resolve' }],
|
||||
},
|
||||
|
||||
// Processus 3
|
||||
{
|
||||
id: 21,
|
||||
name: 'Uma',
|
||||
avatar: 'U',
|
||||
email: 'uma@company.com',
|
||||
processRoles: [{ processId: 3, role: 'Deposit' }],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
name: 'Victor',
|
||||
avatar: 'V',
|
||||
email: 'victor@company.com',
|
||||
processRoles: [{ processId: 3, role: 'Deposit' }],
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
name: 'Walter',
|
||||
avatar: 'W',
|
||||
email: 'walter@company.com',
|
||||
processRoles: [{ processId: 3, role: 'Payment' }],
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
name: 'Xena',
|
||||
avatar: 'X',
|
||||
email: 'xena@company.com',
|
||||
processRoles: [{ processId: 3, role: 'Payment' }],
|
||||
},
|
||||
];
|
@ -1,64 +0,0 @@
|
||||
export const messagesMock = [
|
||||
{
|
||||
memberId: 1, // Conversations avec Mmber 1
|
||||
messages: [
|
||||
{ id: 1, sender: 'Mmeber 1', text: 'Salut !', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Bonjour ! Comment ça va ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Tout va bien, merci !', time: '10:32 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 2, // Conversations avec Member 2
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 2', text: 'Salut, on se voit ce soir ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Oui, à quelle heure ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 3, // Conversations avec Member 3
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 3', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 4, // Conversations avec Member 4
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 4', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 5, // Conversations avec Member 5
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 5', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 6, // Conversations avec Member 6
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 6', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 7, // Conversations avec Member 7
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 7', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
{
|
||||
memberId: 8, // Conversations avec Member 8
|
||||
messages: [
|
||||
{ id: 1, sender: 'Member 8', text: 'Hey, ça va ?', time: '10:30 AM' },
|
||||
{ id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
{ id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
|
||||
],
|
||||
},
|
||||
];
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user