chore(template-sync): aligner avec 4NK_template (.cursor/.gitea/.gitea_template/scripts/ignores)
Some checks failed
CI - 4NK Node / Integration Tests (push) Failing after 9s
CI - 4NK Node / Docker Build & Test (push) Failing after 8s
CI - 4NK Node / Documentation Tests (push) Failing after 3s
CI - 4NK Node / Release Guard (push) Has been skipped
CI - 4NK Node / Performance Tests (push) Failing after 29s
CI - 4NK Node / Code Quality (push) Failing after 32s
CI - 4NK Node / Unit Tests (push) Failing after 30s
CI - 4NK Node / Security Tests (push) Failing after 28s
CI - 4NK Node / Notify (push) Failing after 1s
Some checks failed
CI - 4NK Node / Integration Tests (push) Failing after 9s
CI - 4NK Node / Docker Build & Test (push) Failing after 8s
CI - 4NK Node / Documentation Tests (push) Failing after 3s
CI - 4NK Node / Release Guard (push) Has been skipped
CI - 4NK Node / Performance Tests (push) Failing after 29s
CI - 4NK Node / Code Quality (push) Failing after 32s
CI - 4NK Node / Unit Tests (push) Failing after 30s
CI - 4NK Node / Security Tests (push) Failing after 28s
CI - 4NK Node / Notify (push) Failing after 1s
This commit is contained in:
commit
a189470d49
32
.cursor/rules/00-foundations.mdc
Normal file
32
.cursor/rules/00-foundations.mdc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Fondations de rédaction et de comportement
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
S’applique à tout le dépôt 4NK/4NK_node pour toute génération, refactorisation, édition inline ou discussion dans Cursor.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Garantir l’usage exclusif du français.
|
||||||
|
- Proscrire l’injection d’exemples de code applicatif dans la base de code.
|
||||||
|
- Assurer une cohérence stricte de terminologie et de ton.
|
||||||
|
- Exiger une introduction et/ou une conclusion dans toute proposition de texte.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Toujours répondre et documenter en français.
|
||||||
|
- Ne pas inclure d’exemples exécutables ou de quickstarts dans la base ; préférer des descriptions prescriptives.
|
||||||
|
- Tout contenu produit doit mentionner explicitement les artefacts à mettre à jour lorsqu’il impacte docs/ et tests/.
|
||||||
|
- Préserver la typographie française (capitaliser uniquement le premier mot d’un titre et les noms propres).
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Relecture linguistique et technique systématique.
|
||||||
|
- Refuser toute sortie avec exemples de code applicatif.
|
||||||
|
- Vérifier que l’issue traitée se conclut par un rappel des fichiers à mettre à jour.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- README.md, docs/**, tests/**, CHANGELOG.md, .gitea/**.
|
72
.cursor/rules/10-project-structure.mdc
Normal file
72
.cursor/rules/10-project-structure.mdc
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Structure projet 4NK_node
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Maintenance de l’arborescence canonique, création/mise à jour/suppression de fichiers et répertoires.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Garantir l’alignement strict avec l’arborescence 4NK_node.
|
||||||
|
- Prévenir toute dérive structurelle.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- S’assurer que l’arborescence suivante existe et reste conforme :
|
||||||
|
|
||||||
|
4NK/4NK_node
|
||||||
|
├── archive
|
||||||
|
├── CHANGELOG.md
|
||||||
|
├── CODE_OF_CONDUCT.md
|
||||||
|
├── CONTRIBUTING.md
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── docs
|
||||||
|
│ ├── API.md
|
||||||
|
│ ├── ARCHITECTURE.md
|
||||||
|
│ ├── COMMUNITY_GUIDE.md
|
||||||
|
│ ├── CONFIGURATION.md
|
||||||
|
│ ├── GITEA_SETUP.md
|
||||||
|
│ ├── INDEX.md
|
||||||
|
│ ├── INSTALLATION.md
|
||||||
|
│ ├── MIGRATION.md
|
||||||
|
│ ├── OPEN_SOURCE_CHECKLIST.md
|
||||||
|
│ ├── QUICK_REFERENCE.md
|
||||||
|
│ ├── RELEASE_PLAN.md
|
||||||
|
│ ├── ROADMAP.md
|
||||||
|
│ ├── SECURITY_AUDIT.md
|
||||||
|
│ ├── TESTING.md
|
||||||
|
│ └── USAGE.md
|
||||||
|
├── LICENSE
|
||||||
|
├── README.md
|
||||||
|
├── tests
|
||||||
|
│ ├── cleanup.sh
|
||||||
|
│ ├── connectivity
|
||||||
|
│ ├── external
|
||||||
|
│ ├── integration
|
||||||
|
│ ├── logs
|
||||||
|
│ ├── performance
|
||||||
|
│ ├── README.md
|
||||||
|
│ ├── reports
|
||||||
|
│ └── unit
|
||||||
|
└── .gitea
|
||||||
|
├── ISSUE_TEMPLATE
|
||||||
|
│ ├── bug_report.md
|
||||||
|
│ └── feature_request.md
|
||||||
|
├── PULL_REQUEST_TEMPLATE.md
|
||||||
|
└── workflows
|
||||||
|
└── ci.yml
|
||||||
|
|
||||||
|
- Tout document obsolète est déplacé vers archive/ avec métadonnées (date, raison).
|
||||||
|
- Interdire la suppression brute de fichiers sans archivage et note dans CHANGELOG.md.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Diff structurel comparé à cette référence.
|
||||||
|
- Erreur bloquante si un fichier « requis » manque.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- archive/**, docs/**, tests/**, .gitea/**, CHANGELOG.md.
|
||||||
|
|
33
.cursor/rules/20-documentation.mdc
Normal file
33
.cursor/rules/20-documentation.mdc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Documentation continue
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Mises à jour de docs/** corrélées à tout changement de code, configuration, dépendance, données ou CI.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
- Remplacer toute section générique « RESUME » par des mises à jour ciblées dans les fichiers appropriés.
|
||||||
|
- Tenir INDEX.md comme table des matières de référence.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
- À chaque changement, mettre à jour :
|
||||||
|
- API.md (spécifications, contrats, schémas, invariants).
|
||||||
|
- ARCHITECTURE.md (décisions, diagrammes, couplages, performances).
|
||||||
|
- CONFIGURATION.md (paramètres, formats, valeurs par défaut).
|
||||||
|
- INSTALLATION.md (pré-requis, étapes, vérifications).
|
||||||
|
- MIGRATION.md (chemins de migration, scripts, compatibilités).
|
||||||
|
- USAGE.md (parcours fonctionnels, contraintes).
|
||||||
|
- TESTING.md (pyramide, critères d’acceptation).
|
||||||
|
- SECURITY_AUDIT.md (menaces, contrôles, dettes résiduelles).
|
||||||
|
- RELEASE_PLAN.md, ROADMAP.md (planification), OPEN_SOURCE_CHECKLIST.md, COMMUNITY_GUIDE.md, GITEA_SETUP.md.
|
||||||
|
- Maintenir QUICK_REFERENCE.md pour les référentiels synthétiques utilisés par l’équipe.
|
||||||
|
- Ajouter un REX technique en cas d’hypothèses multiples avant résolution dans archive/.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
- Cohérence croisée entre README.md et INDEX.md.
|
||||||
|
- Refus si une modification de code n’a pas de trace dans docs/** correspondants.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
- docs/**, README.md, archive/**.
|
57
.cursor/rules/30-testing.mdc
Normal file
57
.cursor/rules/30-testing.mdc
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tests et qualité
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Stratégie de tests, exécution locale, stabilité, non-régression.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Exiger des tests verts avant tout commit.
|
||||||
|
- Couvrir les axes unit, integration, connectivity, performance, external.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Ajouter/mettre à jour des tests dans tests/unit, tests/integration, tests/connectivity, tests/performance, tests/external selon l’impact.
|
||||||
|
- Consigner les journaux dans tests/logs et les rapports dans tests/reports.
|
||||||
|
- Maintenir tests/README.md (stratégie, outillage, seuils).
|
||||||
|
- Fournir un nettoyage reproductible via tests/cleanup.sh.
|
||||||
|
- Bloquer l’édition si des tests échouent tant que la correction n’est pas appliquée.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refus d’un commit si tests en échec.
|
||||||
|
- Exiger justification et plan de test dans docs/TESTING.md pour toute refonte majeure.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- tests/**, docs/TESTING.md, CHANGELOG.md.
|
||||||
|
|
||||||
|
# Tests et qualité
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Stratégie de tests, exécution locale, stabilité, non-régression.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Exiger des tests verts avant tout commit.
|
||||||
|
- Couvrir les axes unit, integration, connectivity, performance, external.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Ajouter/mettre à jour des tests dans tests/unit, tests/integration, tests/connectivity, tests/performance, tests/external selon l’impact.
|
||||||
|
- Consigner les journaux dans tests/logs et les rapports dans tests/reports.
|
||||||
|
- Maintenir tests/README.md (stratégie, outillage, seuils).
|
||||||
|
- Fournir un nettoyage reproductible via tests/cleanup.sh.
|
||||||
|
- Bloquer l’édition si des tests échouent tant que la correction n’est pas appliquée.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refus d’un commit si tests en échec.
|
||||||
|
- Exiger justification et plan de test dans docs/TESTING.md pour toute refonte majeure.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- tests/**, docs/TESTING.md, CHANGELOG.md.
|
55
.cursor/rules/40-dependencies-and-build.mdc
Normal file
55
.cursor/rules/40-dependencies-and-build.mdc
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Dépendances, compilation et build
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Gestion des dépendances, compilation fréquente, politique de versions.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Ajouter automatiquement les dépendances manquantes si justifié.
|
||||||
|
- Rechercher systématiquement les dernières versions stables.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Lorsqu’une fonctionnalité nécessite une dépendance, l’ajouter et la documenter (nom, version, portée, impact) dans docs/ARCHITECTURE.md et docs/CONFIGURATION.md si nécessaire.
|
||||||
|
- Compiler très régulièrement et « quand nécessaire » (avant refactor, avant push, après mise à jour de dépendances).
|
||||||
|
- Corriger toute erreur de compilation/exécution avant de poursuivre.
|
||||||
|
- Documenter tout changement de dépendances (raison, risques, rollback).
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Interdire la progression si la compilation échoue.
|
||||||
|
- Vérifier la présence d’une note de changement dans CHANGELOG.md en cas de dépendance ajoutée/retirée.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- docs/ARCHITECTURE.md, docs/CONFIGURATION.md, CHANGELOG.md.
|
||||||
|
|
||||||
|
# Dépendances, compilation et build
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Gestion des dépendances, compilation fréquente, politique de versions.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Ajouter automatiquement les dépendances manquantes si justifié.
|
||||||
|
- Rechercher systématiquement les dernières versions stables.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Lorsqu’une fonctionnalité nécessite une dépendance, l’ajouter et la documenter (nom, version, portée, impact) dans docs/ARCHITECTURE.md et docs/CONFIGURATION.md si nécessaire.
|
||||||
|
- Compiler très régulièrement et « quand nécessaire » (avant refactor, avant push, après mise à jour de dépendances).
|
||||||
|
- Corriger toute erreur de compilation/exécution avant de poursuivre.
|
||||||
|
- Documenter tout changement de dépendances (raison, risques, rollback).
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Interdire la progression si la compilation échoue.
|
||||||
|
- Vérifier la présence d’une note de changement dans CHANGELOG.md en cas de dépendance ajoutée/retirée.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- docs/ARCHITECTURE.md, docs/CONFIGURATION.md, CHANGELOG.md.
|
65
.cursor/rules/41-ssh-automation.mdc
Normal file
65
.cursor/rules/41-ssh-automation.mdc
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Automatisation SSH et scripts
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Création, usage et vérification du dossier scripts/ et de ses trois scripts standards liés aux opérations SSH et CI.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Garantir la présence de scripts/ avec auto-ssh-push.sh, init-ssh-env.sh, setup-ssh-ci.sh.
|
||||||
|
- Encadrer l’usage de ces scripts (locaux et CI), la sécurité, l’idempotence et la traçabilité.
|
||||||
|
- Documenter toute mise à jour dans docs/SSH_UPDATE.md et CHANGELOG.md.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Créer et maintenir `scripts/auto-ssh-push.sh`, `scripts/init-ssh-env.sh`, `scripts/setup-ssh-ci.sh`.
|
||||||
|
- Exiger permissions d’exécution adaptées sur scripts/ (exécution locale et CI).
|
||||||
|
- Interdire le stockage de clés privées ou secrets en clair dans le dépôt.
|
||||||
|
- Utiliser des variables d’environnement et secrets CI pour toute donnée sensible.
|
||||||
|
- Rendre chaque script idempotent et verbosable ; produire un code de sortie non-zéro en cas d’échec.
|
||||||
|
- Tracer les opérations : consigner un résumé dans docs/SSH_UPDATE.md (objectif, variables requises, effets, points d’échec).
|
||||||
|
- Ajouter un contrôle automatique dans la CI pour vérifier l’existence et l’exécutabilité de ces scripts.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Échec bloquant si un des trois scripts manque ou n’est pas exécutable.
|
||||||
|
- Échec bloquant si docs/SSH_UPDATE.md n’est pas mis à jour lors d’une modification de scripts.
|
||||||
|
- Échec bloquant si un secret attendu n’est pas fourni en CI.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- scripts/**, docs/SSH_UPDATE.md, .gitea/workflows/ci.yml, CHANGELOG.md, docs/CONFIGURATION.md.
|
||||||
|
|
||||||
|
# Automatisation SSH et scripts
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Création, usage et vérification du dossier scripts/ et de ses trois scripts standards liés aux opérations SSH et CI.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Garantir la présence de scripts/ avec auto-ssh-push.sh, init-ssh-env.sh, setup-ssh-ci.sh.
|
||||||
|
- Encadrer l’usage de ces scripts (locaux et CI), la sécurité, l’idempotence et la traçabilité.
|
||||||
|
- Documenter toute mise à jour dans docs/SSH_UPDATE.md et CHANGELOG.md.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Créer et maintenir `scripts/auto-ssh-push.sh`, `scripts/init-ssh-env.sh`, `scripts/setup-ssh-ci.sh`.
|
||||||
|
- Exiger permissions d’exécution adaptées sur scripts/ (exécution locale et CI).
|
||||||
|
- Interdire le stockage de clés privées ou secrets en clair dans le dépôt.
|
||||||
|
- Utiliser des variables d’environnement et secrets CI pour toute donnée sensible.
|
||||||
|
- Rendre chaque script idempotent et verbosable ; produire un code de sortie non-zéro en cas d’échec.
|
||||||
|
- Tracer les opérations : consigner un résumé dans docs/SSH_UPDATE.md (objectif, variables requises, effets, points d’échec).
|
||||||
|
- Ajouter un contrôle automatique dans la CI pour vérifier l’existence et l’exécutabilité de ces scripts.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Échec bloquant si un des trois scripts manque ou n’est pas exécutable.
|
||||||
|
- Échec bloquant si docs/SSH_UPDATE.md n’est pas mis à jour lors d’une modification de scripts.
|
||||||
|
- Échec bloquant si un secret attendu n’est pas fourni en CI.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- scripts/**, docs/SSH_UPDATE.md, .gitea/workflows/ci.yml, CHANGELOG.md, docs/CONFIGURATION.md.
|
53
.cursor/rules/42-template-sync.mdc
Normal file
53
.cursor/rules/42-template-sync.mdc
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Synchronisation de template (4NK)
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Tous les projets issus de 4NK_project_template. Contrôle de l’alignement sur .cursor/, .gitea/, AGENTS.md, scripts/, docs/SSH_UPDATE.md.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Garantir l’absence de dérive sur les éléments normatifs.
|
||||||
|
- Exiger la mise à jour documentaire et du changelog à chaque synchronisation.
|
||||||
|
- Bloquer la progression en cas d’intégrité non conforme.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
- Lire la configuration de .4nk-sync.yml (source_repo, ref, paths, policy).
|
||||||
|
- Refuser toute modification locale dans le périmètre des paths sans PR de synchronisation.
|
||||||
|
- Après synchronisation : exiger mises à jour de CHANGELOG.md et docs/INDEX.md.
|
||||||
|
- Scripts : vérifier présence, permissions d’exécution et absence de secrets en clair.
|
||||||
|
- SSH : exiger mise à jour de docs/SSH_UPDATE.md si scripts/** modifié.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
- Erreur bloquante si manifest_checksum manquant ou invalide.
|
||||||
|
- Erreur bloquante si un path requis n’existe pas après sync.
|
||||||
|
- Erreur bloquante si tests/CI signalent des scripts non exécutables ou des fichiers sensibles.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
- .4nk-sync.yml, TEMPLATE_VERSION, .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md, CHANGELOG.md.
|
||||||
|
# Synchronisation de template (4NK)
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Tous les projets issus de 4NK_project_template. Contrôle de l’alignement sur .cursor/, .gitea/, AGENTS.md, scripts/, docs/SSH_UPDATE.md.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
- Garantir l’absence de dérive sur les éléments normatifs.
|
||||||
|
- Exiger la mise à jour documentaire et du changelog à chaque synchronisation.
|
||||||
|
- Bloquer la progression en cas d’intégrité non conforme.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
- Lire la configuration de .4nk-sync.yml (source_repo, ref, paths, policy).
|
||||||
|
- Refuser toute modification locale dans le périmètre des paths sans PR de synchronisation.
|
||||||
|
- Après synchronisation : exiger mises à jour de CHANGELOG.md et docs/INDEX.md.
|
||||||
|
- Scripts : vérifier présence, permissions d’exécution et absence de secrets en clair.
|
||||||
|
- SSH : exiger mise à jour de docs/SSH_UPDATE.md si scripts/** modifié.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
- Erreur bloquante si manifest_checksum manquant ou invalide.
|
||||||
|
- Erreur bloquante si un path requis n’existe pas après sync.
|
||||||
|
- Erreur bloquante si tests/CI signalent des scripts non exécutables ou des fichiers sensibles.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
- .4nk-sync.yml, TEMPLATE_VERSION, .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md, CHANGELOG.md.
|
156
.cursor/rules/4nkrules.mdc
Normal file
156
.cursor/rules/4nkrules.mdc
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
# cursor.mcd — règles d’or 4NK
|
||||||
|
language: fr
|
||||||
|
policies:
|
||||||
|
respond_in_french: true
|
||||||
|
no_examples_in_codebase: true
|
||||||
|
ask_before_push_or_tag: true
|
||||||
|
|
||||||
|
directories:
|
||||||
|
ensure:
|
||||||
|
- archive/
|
||||||
|
- docs/
|
||||||
|
- tests/
|
||||||
|
- .gitea/
|
||||||
|
docs:
|
||||||
|
required_files:
|
||||||
|
- API.md
|
||||||
|
- ARCHITECTURE.md
|
||||||
|
- COMMUNITY_GUIDE.md
|
||||||
|
- CONFIGURATION.md
|
||||||
|
- GITEA_SETUP.md
|
||||||
|
- INDEX.md
|
||||||
|
- INSTALLATION.md
|
||||||
|
- MIGRATION.md
|
||||||
|
- OPEN_SOURCE_CHECKLIST.md
|
||||||
|
- QUICK_REFERENCE.md
|
||||||
|
- RELEASE_PLAN.md
|
||||||
|
- ROADMAP.md
|
||||||
|
- SECURITY_AUDIT.md
|
||||||
|
- TESTING.md
|
||||||
|
- USAGE.md
|
||||||
|
tests:
|
||||||
|
required_files:
|
||||||
|
- cleanup.sh
|
||||||
|
- README.md
|
||||||
|
required_dirs:
|
||||||
|
- connectivity
|
||||||
|
- external
|
||||||
|
- integration
|
||||||
|
- logs
|
||||||
|
- performance
|
||||||
|
- reports
|
||||||
|
- unit
|
||||||
|
gitea:
|
||||||
|
required_files:
|
||||||
|
- PULL_REQUEST_TEMPLATE.md
|
||||||
|
required_dirs:
|
||||||
|
- ISSUE_TEMPLATE
|
||||||
|
- workflows
|
||||||
|
ISSUE_TEMPLATE:
|
||||||
|
required_files:
|
||||||
|
- bug_report.md
|
||||||
|
- feature_request.md
|
||||||
|
workflows:
|
||||||
|
required_files:
|
||||||
|
- ci.yml
|
||||||
|
|
||||||
|
files:
|
||||||
|
required_root_files:
|
||||||
|
- CHANGELOG.md
|
||||||
|
- CODE_OF_CONDUCT.md
|
||||||
|
- CONTRIBUTING.md
|
||||||
|
- docker-compose.yml
|
||||||
|
- LICENSE
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
documentation:
|
||||||
|
update_on:
|
||||||
|
- feature_added
|
||||||
|
- feature_modified
|
||||||
|
- feature_removed
|
||||||
|
- feature_discovered
|
||||||
|
replace_sections_named: ["RESUME"]
|
||||||
|
rex_required_on_multiple_hypotheses: true
|
||||||
|
archive_obsolete_docs: true
|
||||||
|
|
||||||
|
compilation:
|
||||||
|
compile_often: true
|
||||||
|
compile_when_needed: true
|
||||||
|
fail_on_errors: true
|
||||||
|
|
||||||
|
problem_solving:
|
||||||
|
auto_run_steps:
|
||||||
|
- minimal_repro
|
||||||
|
- inspect_logs
|
||||||
|
- bisect_changes
|
||||||
|
- form_hypotheses
|
||||||
|
- targeted_tests
|
||||||
|
- implement_fix
|
||||||
|
- non_regression
|
||||||
|
|
||||||
|
office_docs:
|
||||||
|
docx_reader: docx2txt
|
||||||
|
fallback:
|
||||||
|
- pandoc_convert
|
||||||
|
- request_alternate_source
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
auto_add_missing: true
|
||||||
|
always_check_latest_stable: true
|
||||||
|
document_changes_in_docs: true
|
||||||
|
|
||||||
|
csv_models:
|
||||||
|
treat_as_source_of_truth: true
|
||||||
|
multirow_headers_supported: true
|
||||||
|
confirm_in_docs: true
|
||||||
|
require_column_definitions: true
|
||||||
|
|
||||||
|
file_processing:
|
||||||
|
study_each_file: true
|
||||||
|
ask_questions_if_needed: true
|
||||||
|
adapt_code_if_needed: true
|
||||||
|
propose_solution_if_unreadable: true
|
||||||
|
|
||||||
|
types_and_properties:
|
||||||
|
auto_correct_incoherences: true
|
||||||
|
document_transformations: true
|
||||||
|
|
||||||
|
functional_consistency:
|
||||||
|
always_ask_clarifying_questions: true
|
||||||
|
|
||||||
|
frontend_architecture:
|
||||||
|
react_code_splitting: true
|
||||||
|
state_management: ["redux", "context_api"]
|
||||||
|
data_service_abstraction: true
|
||||||
|
|
||||||
|
execution_discipline:
|
||||||
|
finish_started_work: true
|
||||||
|
|
||||||
|
open_source_and_gitea:
|
||||||
|
prepare_every_project: true
|
||||||
|
gitea_remote: "git.4nkweb.com"
|
||||||
|
required_files:
|
||||||
|
- LICENSE
|
||||||
|
- CONTRIBUTING.md
|
||||||
|
- CHANGELOG.md
|
||||||
|
- CODE_OF_CONDUCT.md
|
||||||
|
align_with_4NK_node_on_creation: true
|
||||||
|
keep_alignment_updated: true
|
||||||
|
|
||||||
|
tests_and_docs:
|
||||||
|
update_docs_and_tests_with_code: true
|
||||||
|
require_green_tests_before_commit: true
|
||||||
|
|
||||||
|
versioning:
|
||||||
|
manage_with_changelog: true
|
||||||
|
confirm_before_push: true
|
||||||
|
confirm_before_tag: true
|
||||||
|
propose_semver_bump: true
|
||||||
|
|
||||||
|
pre_commit:
|
||||||
|
run_all_tests: true
|
||||||
|
block_on_errors: true
|
||||||
|
|
||||||
|
---
|
54
.cursor/rules/50-data-csv-models.mdc
Normal file
54
.cursor/rules/50-data-csv-models.mdc
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
|
# Modélisation des données à partir de CSV
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Utilisation des CSV comme base des modèles de données, y compris en-têtes multi-lignes.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Confirmer la structure inférée pour chaque CSV.
|
||||||
|
- Demander une définition formelle de toutes les colonnes.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Gérer explicitement les en-têtes multi-lignes (titre principal + sous-colonnes).
|
||||||
|
- Confirmer par écrit dans docs/API.md ou docs/ARCHITECTURE.md : nombre de lignes d’en-tête, mapping colonnes→types, unités, domaines de valeurs, nullabilité, contraintes.
|
||||||
|
- Poser des questions si ambiguïtés ; proposer une normalisation temporaire documentée.
|
||||||
|
- Corriger automatiquement les incohérences de types si une règle de mapping est établie ailleurs et documenter la transformation.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Aucune ingestion sans spécification de colonnes validée.
|
||||||
|
- Traçabilité des corrections de types (avant/après) dans docs/ARCHITECTURE.md.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- docs/API.md, docs/ARCHITECTURE.md, docs/USAGE.md.
|
||||||
|
|
||||||
|
# Modélisation des données à partir de CSV
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Utilisation des CSV comme base des modèles de données, y compris en-têtes multi-lignes.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Confirmer la structure inférée pour chaque CSV.
|
||||||
|
- Demander une définition formelle de toutes les colonnes.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Gérer explicitement les en-têtes multi-lignes (titre principal + sous-colonnes).
|
||||||
|
- Confirmer par écrit dans docs/API.md ou docs/ARCHITECTURE.md : nombre de lignes d’en-tête, mapping colonnes→types, unités, domaines de valeurs, nullabilité, contraintes.
|
||||||
|
- Poser des questions si ambiguïtés ; proposer une normalisation temporaire documentée.
|
||||||
|
- Corriger automatiquement les incohérences de types si une règle de mapping est établie ailleurs et documenter la transformation.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Aucune ingestion sans spécification de colonnes validée.
|
||||||
|
- Traçabilité des corrections de types (avant/après) dans docs/ARCHITECTURE.md.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- docs/API.md, docs/ARCHITECTURE.md, docs/USAGE.md.
|
41
.cursor/rules/60-office-docs.mdc
Normal file
41
.cursor/rules/60-office-docs.mdc
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
|
# Lecture des documents bureautiques
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Lecture des fichiers .docx et alternatives.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
- Utiliser docx2txt par défaut.
|
||||||
|
- Proposer des solutions de repli si lecture impossible.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
- Lire les .docx avec docx2txt.
|
||||||
|
- En cas d’échec, proposer : conversion via pandoc, demande d’une source alternative, ou extraction textuelle.
|
||||||
|
- Documenter dans docs/INDEX.md la provenance et le statut des documents importés.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
- Vérification que les contenus extraits sont intégrés aux fichiers docs/ concernés.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
- docs/**, archive/**.
|
||||||
|
# Lecture des documents bureautiques
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Lecture des fichiers .docx et alternatives.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
- Utiliser docx2txt par défaut.
|
||||||
|
- Proposer des solutions de repli si lecture impossible.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
- Lire les .docx avec docx2txt.
|
||||||
|
- En cas d’échec, proposer : conversion via pandoc, demande d’une source alternative, ou extraction textuelle.
|
||||||
|
- Documenter dans docs/INDEX.md la provenance et le statut des documents importés.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
- Vérification que les contenus extraits sont intégrés aux fichiers docs/ concernés.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
- docs/**, archive/**.
|
56
.cursor/rules/70-frontend-architecture.mdc
Normal file
56
.cursor/rules/70-frontend-architecture.mdc
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# Architecture frontend
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Qualité du bundle, découpage, état global et couche de services.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Réduire la taille du bundle initial via code splitting.
|
||||||
|
- Éviter le prop drilling via Redux ou Context API.
|
||||||
|
- Abstraire les services de données pour testabilité et maintenance.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Mettre en place React.lazy et Suspense pour le chargement différé des vues/segments.
|
||||||
|
- Centraliser l’état global via Redux ou Context API.
|
||||||
|
- Isoler les appels « data » derrière une couche d’abstraction à interface stable.
|
||||||
|
- Interdire l’ajout d’exemples front dans la base de code.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Vérifier que les points d’entrée sont minimes et que les segments non critiques sont chargés à la demande.
|
||||||
|
- S’assurer que docs/ARCHITECTURE.md décrit les décisions et les points d’extension.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- docs/ARCHITECTURE.md, docs/TESTING.md.
|
||||||
|
# Architecture frontend
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Qualité du bundle, découpage, état global et couche de services.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Réduire la taille du bundle initial via code splitting.
|
||||||
|
- Éviter le prop drilling via Redux ou Context API.
|
||||||
|
- Abstraire les services de données pour testabilité et maintenance.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Mettre en place React.lazy et Suspense pour le chargement différé des vues/segments.
|
||||||
|
- Centraliser l’état global via Redux ou Context API.
|
||||||
|
- Isoler les appels « data » derrière une couche d’abstraction à interface stable.
|
||||||
|
- Interdire l’ajout d’exemples front dans la base de code.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Vérifier que les points d’entrée sont minimes et que les segments non critiques sont chargés à la demande.
|
||||||
|
- S’assurer que docs/ARCHITECTURE.md décrit les décisions et les points d’extension.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- docs/ARCHITECTURE.md, docs/TESTING.md.
|
53
.cursor/rules/80-versioning-and-release.mdc
Normal file
53
.cursor/rules/80-versioning-and-release.mdc
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# Versionnage et publication
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Gestion sémantique des versions, CHANGELOG, confirmation push/tag.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Tenir CHANGELOG.md comme source unique de vérité.
|
||||||
|
- Demander confirmation avant push et tag.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- À chaque changement significatif, mettre à jour CHANGELOG.md (ajouts, changements, corrections, ruptures).
|
||||||
|
- Proposer un bump semver (major/minor/patch) motivé par l’impact.
|
||||||
|
- Avant tout push ou tag, demander confirmation explicite.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refus si modification sans entrée correspondante dans CHANGELOG.md.
|
||||||
|
- Cohérence entre CHANGELOG.md, docs/RELEASE_PLAN.md et docs/ROADMAP.md.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- CHANGELOG.md, docs/RELEASE_PLAN.md, docs/ROADMAP.md.
|
||||||
|
|
||||||
|
# Versionnage et publication
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Gestion sémantique des versions, CHANGELOG, confirmation push/tag.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Tenir CHANGELOG.md comme source unique de vérité.
|
||||||
|
- Demander confirmation avant push et tag.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- À chaque changement significatif, mettre à jour CHANGELOG.md (ajouts, changements, corrections, ruptures).
|
||||||
|
- Proposer un bump semver (major/minor/patch) motivé par l’impact.
|
||||||
|
- Avant tout push ou tag, demander confirmation explicite.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refus si modification sans entrée correspondante dans CHANGELOG.md.
|
||||||
|
- Cohérence entre CHANGELOG.md, docs/RELEASE_PLAN.md et docs/ROADMAP.md.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- CHANGELOG.md, docs/RELEASE_PLAN.md, docs/ROADMAP.md.
|
37
.cursor/rules/85-release-guard.mdc
Normal file
37
.cursor/rules/85-release-guard.mdc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Garde de release: tests, documentation, compilation, version, changelog, tag
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Contrôler systématiquement avant push/tag: tests verts, docs mises à jour, build OK, alignement numéro de version ↔ changelog ↔ tag git, mise à jour de déploiement, confirmation utilisateur (latest vs wip).
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Empêcher toute publication sans vérifications minimales.
|
||||||
|
- Exiger la cohérence sémantique (VERSION/TEMPLATE_VERSION ↔ CHANGELOG ↔ tag git).
|
||||||
|
- Demander explicitement « latest » ou « wip » et appliquer la bonne stratégie.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Avant push/tag, exécuter: tests, compilation, lints (si configurés).
|
||||||
|
- Mettre à jour la documentation et le changelog en conséquence.
|
||||||
|
- Aligner le fichier de version (VERSION ou TEMPLATE_VERSION), l’entrée CHANGELOG et le tag.
|
||||||
|
- Demander confirmation utilisateur: `latest` (release stable) ou `wip` (travail en cours).
|
||||||
|
- latest: entrée datée dans CHANGELOG, version stable, tag `vX.Y.Z`.
|
||||||
|
- wip: suffixe `-wip` recommandé dans version/tag (ex: `vX.Y.Z-wip.N`).
|
||||||
|
- Mettre à jour le déploiement après publication (si pipeline défini), sinon documenter l’étape.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refuser push/tag si:
|
||||||
|
- tests/compilation échouent,
|
||||||
|
- CHANGELOG non mis à jour,
|
||||||
|
- VERSION/TEMPLATE_VERSION absent ou incohérent,
|
||||||
|
- release type non fourni (ni latest, ni wip).
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- CHANGELOG.md, VERSION ou TEMPLATE_VERSION, docs/**, .gitea/workflows/**, scripts/**.
|
||||||
|
|
59
.cursor/rules/90-gitea-and-oss.mdc
Normal file
59
.cursor/rules/90-gitea-and-oss.mdc
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Open source et Gitea
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Conformité open source, templates Gitea, CI.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Préparer chaque projet pour un dépôt Gitea (git.4nkweb.com).
|
||||||
|
- Maintenir les fichiers de gouvernance et la CI.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Vérifier la présence et l’actualité de : LICENSE, CONTRIBUTING.md, CODE_OF_CONDUCT.md, OPEN_SOURCE_CHECKLIST.md.
|
||||||
|
- Maintenir .gitea/ :
|
||||||
|
- ISSUE_TEMPLATE/bug_report.md, feature_request.md
|
||||||
|
- PULL_REQUEST_TEMPLATE.md
|
||||||
|
- workflows/ci.yml
|
||||||
|
- Documenter dans docs/GITEA_SETUP.md la configuration distante et les permissions.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refus si un des fichiers « gouvernance/CI » manque.
|
||||||
|
- Cohérence entre docs/OPEN_SOURCE_CHECKLIST.md et l’état du repo.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- .gitea/**, docs/GITEA_SETUP.md, docs/OPEN_SOURCE_CHECKLIST.md.
|
||||||
|
|
||||||
|
# Open source et Gitea
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Conformité open source, templates Gitea, CI.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Préparer chaque projet pour un dépôt Gitea (git.4nkweb.com).
|
||||||
|
- Maintenir les fichiers de gouvernance et la CI.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Vérifier la présence et l’actualité de : LICENSE, CONTRIBUTING.md, CODE_OF_CONDUCT.md, OPEN_SOURCE_CHECKLIST.md.
|
||||||
|
- Maintenir .gitea/ :
|
||||||
|
- ISSUE_TEMPLATE/bug_report.md, feature_request.md
|
||||||
|
- PULL_REQUEST_TEMPLATE.md
|
||||||
|
- workflows/ci.yml
|
||||||
|
- Documenter dans docs/GITEA_SETUP.md la configuration distante et les permissions.
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Refus si un des fichiers « gouvernance/CI » manque.
|
||||||
|
- Cohérence entre docs/OPEN_SOURCE_CHECKLIST.md et l’état du repo.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- .gitea/**, docs/GITEA_SETUP.md, docs/OPEN_SOURCE_CHECKLIST.md.
|
53
.cursor/rules/95-triage-and-problem-solving.mdc
Normal file
53
.cursor/rules/95-triage-and-problem-solving.mdc
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tri, diagnostic et résolution de problèmes
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Boucle de triage : reproduction, diagnostic, correctif, non-régression.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Exécuter automatiquement les étapes de résolution.
|
||||||
|
- Bloquer l’avancement tant que les erreurs ne sont pas corrigées.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Étapes obligatoires : reproduction minimale, inspection des logs, bissection des changements, formulation d’hypothèses, tests ciblés, correctif, test de non-régression.
|
||||||
|
- Lorsque plusieurs hypothèses ont été testées, produire un REX dans archive/ avec liens vers les commits.
|
||||||
|
- Poser des questions de cohérence fonctionnelle si des ambiguïtés subsistent (contrats d’API, invariants, SLA).
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Interdiction de clore une tâche si un test échoue ou si une alerte critique subsiste.
|
||||||
|
- Traçabilité du REX si investigations multiples.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- tests/**, archive/**, docs/TESTING.md, docs/ARCHITECTURE.md.
|
||||||
|
|
||||||
|
# Tri, diagnostic et résolution de problèmes
|
||||||
|
|
||||||
|
[portée]
|
||||||
|
Boucle de triage : reproduction, diagnostic, correctif, non-régression.
|
||||||
|
|
||||||
|
[objectifs]
|
||||||
|
|
||||||
|
- Exécuter automatiquement les étapes de résolution.
|
||||||
|
- Bloquer l’avancement tant que les erreurs ne sont pas corrigées.
|
||||||
|
|
||||||
|
[directives]
|
||||||
|
|
||||||
|
- Étapes obligatoires : reproduction minimale, inspection des logs, bissection des changements, formulation d’hypothèses, tests ciblés, correctif, test de non-régression.
|
||||||
|
- Lorsque plusieurs hypothèses ont été testées, produire un REX dans archive/ avec liens vers les commits.
|
||||||
|
- Poser des questions de cohérence fonctionnelle si des ambiguïtés subsistent (contrats d’API, invariants, SLA).
|
||||||
|
|
||||||
|
[validations]
|
||||||
|
|
||||||
|
- Interdiction de clore une tâche si un test échoue ou si une alerte critique subsiste.
|
||||||
|
- Traçabilité du REX si investigations multiples.
|
||||||
|
|
||||||
|
[artefacts concernés]
|
||||||
|
|
||||||
|
- tests/**, archive/**, docs/TESTING.md, docs/ARCHITECTURE.md.
|
16
.cursor/rules/ruleset-index.md
Normal file
16
.cursor/rules/ruleset-index.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Index des règles .cursor/rules
|
||||||
|
|
||||||
|
- 00-foundations.mdc : règles linguistiques et éditoriales (français, pas d’exemples en base, introduction/conclusion).
|
||||||
|
- 10-project-structure.mdc : arborescence canonique 4NK_node et garde-fous.
|
||||||
|
- 20-documentation.mdc : documentation continue, remplacement de « RESUME », INDEX.md.
|
||||||
|
- 30-testing.mdc : tests (unit, integration, connectivity, performance, external), logs/reports.
|
||||||
|
- 40-dependencies-and-build.mdc : dépendances, compilation, corrections bloquantes.
|
||||||
|
- 50-data-csv-models.mdc : CSV avec en-têtes multi-lignes, définition des colonnes.
|
||||||
|
- 60-office-docs.mdc : lecture .docx via docx2txt + repli.
|
||||||
|
- 70-frontend-architecture.mdc : React.lazy/Suspense, état global, couche de services.
|
||||||
|
- 80-versioning-and-release.mdc : CHANGELOG, semver, confirmation push/tag.
|
||||||
|
- 85-release-guard.mdc : garde de release (tests/doc/build/version/changelog/tag; latest vs wip).
|
||||||
|
- 90-gitea-and-oss.mdc : fichiers open source, .gitea, CI, Gitea remote.
|
||||||
|
- 95-triage-and-problem-solving.mdc : boucle de diagnostic, REX, non-régression.
|
||||||
|
|
||||||
|
Ces règles sont conçues pour être ajoutées au contexte de Cursor depuis l’interface (@Cursor Rules) et s’appuient sur le mécanisme de règles projet stockées dans `.cursor/rules/`. :contentReference[oaicite:3]{index=3}
|
24
.cursorignore
Normal file
24
.cursorignore
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
coverage/
|
||||||
|
.cache/
|
||||||
|
.turbo/
|
||||||
|
.parcel-cache/
|
||||||
|
assets/ihm/
|
||||||
|
web/ihm/
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
**/*.map
|
||||||
|
**/*.min.*
|
||||||
|
**/*.wasm
|
||||||
|
**/*.png
|
||||||
|
**/*.jpg
|
||||||
|
**/*.jpeg
|
||||||
|
**/*.svg
|
||||||
|
**/*.ico
|
||||||
|
**/*.pdf
|
||||||
|
|
||||||
|
!.cursor/
|
||||||
|
|
||||||
|
!AGENTS.md
|
97
.gitea/ISSUE_TEMPLATE/bug_report.md
Normal file
97
.gitea/ISSUE_TEMPLATE/bug_report.md
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Signaler un bug pour nous aider à améliorer 4NK Node
|
||||||
|
title: '[BUG] '
|
||||||
|
labels: ['bug', 'needs-triage']
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Description du Bug
|
||||||
|
|
||||||
|
Description claire et concise du problème.
|
||||||
|
|
||||||
|
## 🔄 Étapes pour Reproduire
|
||||||
|
|
||||||
|
1. Aller à '...'
|
||||||
|
2. Cliquer sur '...'
|
||||||
|
3. Faire défiler jusqu'à '...'
|
||||||
|
4. Voir l'erreur
|
||||||
|
|
||||||
|
## ✅ Comportement Attendu
|
||||||
|
|
||||||
|
Description de ce qui devrait se passer.
|
||||||
|
|
||||||
|
## ❌ Comportement Actuel
|
||||||
|
|
||||||
|
Description de ce qui se passe actuellement.
|
||||||
|
|
||||||
|
## 📸 Capture d'Écran
|
||||||
|
|
||||||
|
Si applicable, ajoutez une capture d'écran pour expliquer votre problème.
|
||||||
|
|
||||||
|
## 💻 Informations Système
|
||||||
|
|
||||||
|
- **OS** : [ex: Ubuntu 20.04, macOS 12.0, Windows 11]
|
||||||
|
- **Docker** : [ex: 20.10.0]
|
||||||
|
- **Docker Compose** : [ex: 2.0.0]
|
||||||
|
- **Version 4NK Node** : [ex: v1.0.0]
|
||||||
|
- **Architecture** : [ex: x86_64, ARM64]
|
||||||
|
|
||||||
|
## 📋 Configuration
|
||||||
|
|
||||||
|
### Services Actifs
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables d'Environnement
|
||||||
|
```bash
|
||||||
|
# Bitcoin Core
|
||||||
|
BITCOIN_NETWORK=signet
|
||||||
|
BITCOIN_RPC_PORT=18443
|
||||||
|
|
||||||
|
# Blindbit
|
||||||
|
BLINDBIT_PORT=8000
|
||||||
|
|
||||||
|
# SDK Relay
|
||||||
|
SDK_RELAY_PORTS=8090-8095
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Logs
|
||||||
|
|
||||||
|
### Logs Pertinents
|
||||||
|
```
|
||||||
|
Logs pertinents ici
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs d'Erreur
|
||||||
|
```
|
||||||
|
Logs d'erreur ici
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs de Debug
|
||||||
|
```
|
||||||
|
Logs de debug ici (si RUST_LOG=debug)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Tentatives de Résolution
|
||||||
|
|
||||||
|
- [ ] Redémarrage des services
|
||||||
|
- [ ] Nettoyage des volumes Docker
|
||||||
|
- [ ] Vérification de la connectivité réseau
|
||||||
|
- [ ] Mise à jour des dépendances
|
||||||
|
- [ ] Vérification de la configuration
|
||||||
|
|
||||||
|
## 📚 Contexte Supplémentaire
|
||||||
|
|
||||||
|
Toute autre information pertinente sur le problème.
|
||||||
|
|
||||||
|
## 🔗 Liens Utiles
|
||||||
|
|
||||||
|
- [Documentation](docs/)
|
||||||
|
- [Guide de Dépannage](docs/TROUBLESHOOTING.md)
|
||||||
|
- [Issues Similaires](https://git.4nkweb.com/4nk/4NK_node/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Merci de votre contribution !** 🙏
|
156
.gitea/ISSUE_TEMPLATE/feature_request.md
Normal file
156
.gitea/ISSUE_TEMPLATE/feature_request.md
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
about: Proposer une nouvelle fonctionnalité pour 4NK Node
|
||||||
|
title: '[FEATURE] '
|
||||||
|
labels: ['enhancement', 'needs-triage']
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Résumé
|
||||||
|
|
||||||
|
Description claire et concise de la fonctionnalité souhaitée.
|
||||||
|
|
||||||
|
## 💡 Motivation
|
||||||
|
|
||||||
|
Pourquoi cette fonctionnalité est-elle nécessaire ? Quels problèmes résout-elle ?
|
||||||
|
|
||||||
|
### Problèmes Actuels
|
||||||
|
- Problème 1
|
||||||
|
- Problème 2
|
||||||
|
- Problème 3
|
||||||
|
|
||||||
|
### Avantages de la Solution
|
||||||
|
- Avantage 1
|
||||||
|
- Avantage 2
|
||||||
|
- Avantage 3
|
||||||
|
|
||||||
|
## 🎯 Proposition
|
||||||
|
|
||||||
|
Description détaillée de la fonctionnalité proposée.
|
||||||
|
|
||||||
|
### Fonctionnalités Principales
|
||||||
|
- [ ] Fonctionnalité 1
|
||||||
|
- [ ] Fonctionnalité 2
|
||||||
|
- [ ] Fonctionnalité 3
|
||||||
|
|
||||||
|
### Interface Utilisateur
|
||||||
|
Description de l'interface utilisateur si applicable.
|
||||||
|
|
||||||
|
### API Changes
|
||||||
|
Description des changements d'API si applicable.
|
||||||
|
|
||||||
|
## 🔄 Alternatives Considérées
|
||||||
|
|
||||||
|
Autres solutions envisagées et pourquoi elles n'ont pas été choisies.
|
||||||
|
|
||||||
|
### Alternative 1
|
||||||
|
- **Description** : ...
|
||||||
|
- **Pourquoi rejetée** : ...
|
||||||
|
|
||||||
|
### Alternative 2
|
||||||
|
- **Description** : ...
|
||||||
|
- **Pourquoi rejetée** : ...
|
||||||
|
|
||||||
|
## 📊 Impact
|
||||||
|
|
||||||
|
### Impact sur les Utilisateurs
|
||||||
|
- Impact positif 1
|
||||||
|
- Impact positif 2
|
||||||
|
- Impact négatif potentiel (si applicable)
|
||||||
|
|
||||||
|
### Impact sur l'Architecture
|
||||||
|
- Changements nécessaires
|
||||||
|
- Compatibilité avec l'existant
|
||||||
|
- Performance
|
||||||
|
|
||||||
|
### Impact sur la Maintenance
|
||||||
|
- Complexité ajoutée
|
||||||
|
- Tests nécessaires
|
||||||
|
- Documentation requise
|
||||||
|
|
||||||
|
## 💻 Exemples d'Utilisation
|
||||||
|
|
||||||
|
### Cas d'Usage 1
|
||||||
|
```bash
|
||||||
|
# Exemple de commande ou configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cas d'Usage 2
|
||||||
|
```python
|
||||||
|
# Exemple de code Python
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cas d'Usage 3
|
||||||
|
```javascript
|
||||||
|
// Exemple de code JavaScript
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Tests
|
||||||
|
|
||||||
|
### Tests Nécessaires
|
||||||
|
- [ ] Tests unitaires
|
||||||
|
- [ ] Tests d'intégration
|
||||||
|
- [ ] Tests de performance
|
||||||
|
- [ ] Tests de sécurité
|
||||||
|
- [ ] Tests de compatibilité
|
||||||
|
|
||||||
|
### Scénarios de Test
|
||||||
|
- Scénario 1
|
||||||
|
- Scénario 2
|
||||||
|
- Scénario 3
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
### Documentation Requise
|
||||||
|
- [ ] Guide d'utilisation
|
||||||
|
- [ ] Documentation API
|
||||||
|
- [ ] Exemples de code
|
||||||
|
- [ ] Guide de migration
|
||||||
|
- [ ] FAQ
|
||||||
|
|
||||||
|
## 🔧 Implémentation
|
||||||
|
|
||||||
|
### Étapes Proposées
|
||||||
|
1. **Phase 1** : [Description]
|
||||||
|
2. **Phase 2** : [Description]
|
||||||
|
3. **Phase 3** : [Description]
|
||||||
|
|
||||||
|
### Estimation de Temps
|
||||||
|
- **Développement** : X jours/semaines
|
||||||
|
- **Tests** : X jours/semaines
|
||||||
|
- **Documentation** : X jours/semaines
|
||||||
|
- **Total** : X jours/semaines
|
||||||
|
|
||||||
|
### Ressources Nécessaires
|
||||||
|
- Développeur(s)
|
||||||
|
- Testeur(s)
|
||||||
|
- Documentateur(s)
|
||||||
|
- Infrastructure
|
||||||
|
|
||||||
|
## 🎯 Critères de Succès
|
||||||
|
|
||||||
|
Comment mesurer le succès de cette fonctionnalité ?
|
||||||
|
|
||||||
|
- [ ] Critère 1
|
||||||
|
- [ ] Critère 2
|
||||||
|
- [ ] Critère 3
|
||||||
|
|
||||||
|
## 🔗 Liens Utiles
|
||||||
|
|
||||||
|
- [Documentation existante](docs/)
|
||||||
|
- [Issues similaires](https://git.4nkweb.com/4nk/4NK_node/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
|
||||||
|
- [Roadmap](https://git.4nkweb.com/4nk/4NK_node/projects)
|
||||||
|
- [Discussions](https://git.4nkweb.com/4nk/4NK_node/issues)
|
||||||
|
|
||||||
|
## 📋 Checklist
|
||||||
|
|
||||||
|
- [ ] J'ai vérifié que cette fonctionnalité n'existe pas déjà
|
||||||
|
- [ ] J'ai lu la documentation existante
|
||||||
|
- [ ] J'ai vérifié les issues similaires
|
||||||
|
- [ ] J'ai fourni des exemples d'utilisation
|
||||||
|
- [ ] J'ai considéré l'impact sur l'existant
|
||||||
|
- [ ] J'ai proposé des tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Merci de votre contribution à l'amélioration de 4NK Node !** 🌟
|
180
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
180
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# Pull Request - 4NK Node
|
||||||
|
|
||||||
|
## 📋 Description
|
||||||
|
|
||||||
|
Description claire et concise des changements apportés.
|
||||||
|
|
||||||
|
### Type de Changement
|
||||||
|
- [ ] 🐛 Bug fix
|
||||||
|
- [ ] ✨ Nouvelle fonctionnalité
|
||||||
|
- [ ] 📚 Documentation
|
||||||
|
- [ ] 🧪 Tests
|
||||||
|
- [ ] 🔧 Refactoring
|
||||||
|
- [ ] 🚀 Performance
|
||||||
|
- [ ] 🔒 Sécurité
|
||||||
|
- [ ] 🎨 Style/UI
|
||||||
|
- [ ] 🏗️ Architecture
|
||||||
|
- [ ] 📦 Build/CI
|
||||||
|
|
||||||
|
### Composants Affectés
|
||||||
|
- [ ] Bitcoin Core
|
||||||
|
- [ ] Blindbit
|
||||||
|
- [ ] SDK Relay
|
||||||
|
- [ ] Tor
|
||||||
|
- [ ] Docker/Infrastructure
|
||||||
|
- [ ] Tests
|
||||||
|
- [ ] Documentation
|
||||||
|
- [ ] Scripts
|
||||||
|
|
||||||
|
## 🔗 Issue(s) Liée(s)
|
||||||
|
|
||||||
|
Fixes #(issue)
|
||||||
|
Relates to #(issue)
|
||||||
|
|
||||||
|
## 🧪 Tests
|
||||||
|
|
||||||
|
### Tests Exécutés
|
||||||
|
- [ ] Tests unitaires
|
||||||
|
- [ ] Tests d'intégration
|
||||||
|
- [ ] Tests de connectivité
|
||||||
|
- [ ] Tests externes
|
||||||
|
- [ ] Tests de performance
|
||||||
|
|
||||||
|
### Commandes de Test
|
||||||
|
```bash
|
||||||
|
# Tests complets
|
||||||
|
./tests/run_all_tests.sh
|
||||||
|
|
||||||
|
# Tests spécifiques
|
||||||
|
./tests/run_unit_tests.sh
|
||||||
|
./tests/run_integration_tests.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Résultats des Tests
|
||||||
|
```
|
||||||
|
Résultats des tests ici
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📸 Captures d'Écran
|
||||||
|
|
||||||
|
Si applicable, ajoutez des captures d'écran pour les changements visuels.
|
||||||
|
|
||||||
|
## 🔧 Changements Techniques
|
||||||
|
|
||||||
|
### Fichiers Modifiés
|
||||||
|
- `fichier1.rs` - Description des changements
|
||||||
|
- `fichier2.py` - Description des changements
|
||||||
|
- `docker-compose.yml` - Description des changements
|
||||||
|
|
||||||
|
### Nouveaux Fichiers
|
||||||
|
- `nouveau_fichier.rs` - Description
|
||||||
|
- `nouveau_script.sh` - Description
|
||||||
|
|
||||||
|
### Fichiers Supprimés
|
||||||
|
- `ancien_fichier.rs` - Raison de la suppression
|
||||||
|
|
||||||
|
### Changements de Configuration
|
||||||
|
```yaml
|
||||||
|
# Exemple de changement de configuration
|
||||||
|
service:
|
||||||
|
new_option: value
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
### Documentation Mise à Jour
|
||||||
|
- [ ] README.md
|
||||||
|
- [ ] docs/INSTALLATION.md
|
||||||
|
- [ ] docs/USAGE.md
|
||||||
|
- [ ] docs/API.md
|
||||||
|
- [ ] docs/ARCHITECTURE.md
|
||||||
|
|
||||||
|
### Nouvelle Documentation
|
||||||
|
- [ ] Nouveau guide créé
|
||||||
|
- [ ] Exemples ajoutés
|
||||||
|
- [ ] API documentée
|
||||||
|
|
||||||
|
## 🔍 Code Review Checklist
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
- [ ] Le code suit les standards du projet
|
||||||
|
- [ ] Les noms de variables/fonctions sont clairs
|
||||||
|
- [ ] Les commentaires sont appropriés
|
||||||
|
- [ ] Pas de code mort ou commenté
|
||||||
|
- [ ] Gestion d'erreurs appropriée
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- [ ] Pas de régression de performance
|
||||||
|
- [ ] Optimisations appliquées si nécessaire
|
||||||
|
- [ ] Tests de performance ajoutés
|
||||||
|
|
||||||
|
### Sécurité
|
||||||
|
- [ ] Pas de vulnérabilités introduites
|
||||||
|
- [ ] Validation des entrées utilisateur
|
||||||
|
- [ ] Gestion sécurisée des secrets
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
- [ ] Couverture de tests suffisante
|
||||||
|
- [ ] Tests pour les cas d'erreur
|
||||||
|
- [ ] Tests d'intégration si nécessaire
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- [ ] Code auto-documenté
|
||||||
|
- [ ] Documentation mise à jour
|
||||||
|
- [ ] Exemples fournis
|
||||||
|
|
||||||
|
## 🚀 Déploiement
|
||||||
|
|
||||||
|
### Impact sur le Déploiement
|
||||||
|
- [ ] Aucun impact
|
||||||
|
- [ ] Migration de données requise
|
||||||
|
- [ ] Changement de configuration
|
||||||
|
- [ ] Redémarrage des services
|
||||||
|
|
||||||
|
### Étapes de Déploiement
|
||||||
|
```bash
|
||||||
|
# Étapes pour déployer les changements
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Métriques
|
||||||
|
|
||||||
|
### Impact sur les Performances
|
||||||
|
- Temps de réponse : +/- X%
|
||||||
|
- Utilisation mémoire : +/- X%
|
||||||
|
- Utilisation CPU : +/- X%
|
||||||
|
|
||||||
|
### Impact sur la Stabilité
|
||||||
|
- Taux d'erreur : +/- X%
|
||||||
|
- Disponibilité : +/- X%
|
||||||
|
|
||||||
|
## 🔄 Compatibilité
|
||||||
|
|
||||||
|
### Compatibilité Ascendante
|
||||||
|
- [ ] Compatible avec les versions précédentes
|
||||||
|
- [ ] Migration automatique
|
||||||
|
- [ ] Migration manuelle requise
|
||||||
|
|
||||||
|
### Compatibilité Descendante
|
||||||
|
- [ ] Compatible avec les futures versions
|
||||||
|
- [ ] API stable
|
||||||
|
- [ ] Configuration stable
|
||||||
|
|
||||||
|
## 🎯 Critères de Succès
|
||||||
|
|
||||||
|
- [ ] Critère 1
|
||||||
|
- [ ] Critère 2
|
||||||
|
- [ ] Critère 3
|
||||||
|
|
||||||
|
## 📝 Notes Supplémentaires
|
||||||
|
|
||||||
|
Informations supplémentaires importantes pour les reviewers.
|
||||||
|
|
||||||
|
## 🔗 Liens Utiles
|
||||||
|
|
||||||
|
- [Documentation](docs/)
|
||||||
|
- [Tests](tests/)
|
||||||
|
- [Issues liées](https://git.4nkweb.com/4nk/4NK_node/issues)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Merci pour votre contribution !** 🙏
|
14
.gitea/workflows/LOCAL_OVERRIDES.yml
Normal file
14
.gitea/workflows/LOCAL_OVERRIDES.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# LOCAL_OVERRIDES.yml — dérogations locales contrôlées
|
||||||
|
overrides:
|
||||||
|
- path: ".gitea/workflows/ci.yml"
|
||||||
|
reason: "spécificité d’environnement"
|
||||||
|
owner: "@maintainer_handle"
|
||||||
|
expires: "2025-12-31"
|
||||||
|
- path: "scripts/auto-ssh-push.sh"
|
||||||
|
reason: "flux particulier temporaire"
|
||||||
|
owner: "@maintainer_handle"
|
||||||
|
expires: "2025-10-01"
|
||||||
|
policy:
|
||||||
|
allow_only_listed_paths: true
|
||||||
|
require_expiry: true
|
||||||
|
audit_in_ci: true
|
345
.gitea/workflows/ci.yml
Normal file
345
.gitea/workflows/ci.yml
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
name: CI - 4NK Node
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUST_VERSION: '1.70'
|
||||||
|
DOCKER_COMPOSE_VERSION: '2.20.0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Job de vérification du code
|
||||||
|
code-quality:
|
||||||
|
name: Code Quality
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Cache Rust dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
- name: Run clippy
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo clippy --all-targets --all-features -- -D warnings
|
||||||
|
|
||||||
|
- name: Run rustfmt
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
|
||||||
|
- name: Check documentation
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo doc --no-deps
|
||||||
|
|
||||||
|
- name: Check for TODO/FIXME
|
||||||
|
run: |
|
||||||
|
if grep -r "TODO\|FIXME" . --exclude-dir=.git --exclude-dir=target; then
|
||||||
|
echo "Found TODO/FIXME comments. Please address them."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Job de tests unitaires
|
||||||
|
unit-tests:
|
||||||
|
name: Unit Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Cache Rust dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo test --lib --bins
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo test --tests
|
||||||
|
|
||||||
|
# Job de tests d'intégration
|
||||||
|
integration-tests:
|
||||||
|
name: Integration Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
docker:
|
||||||
|
image: docker:24.0.5
|
||||||
|
options: >-
|
||||||
|
--health-cmd "docker info"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 2375:2375
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build Docker images
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-bitcoin ./bitcoin
|
||||||
|
docker build -t 4nk-node-blindbit ./blindbit
|
||||||
|
docker build -t 4nk-node-sdk-relay -f ./sdk_relay/Dockerfile ..
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
# Tests de connectivité de base
|
||||||
|
./tests/run_connectivity_tests.sh || true
|
||||||
|
|
||||||
|
# Tests d'intégration
|
||||||
|
./tests/run_integration_tests.sh || true
|
||||||
|
|
||||||
|
- name: Upload test results
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: test-results
|
||||||
|
path: |
|
||||||
|
tests/logs/
|
||||||
|
tests/reports/
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
# Job de tests de sécurité
|
||||||
|
security-tests:
|
||||||
|
name: Security Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Run cargo audit
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo audit --deny warnings
|
||||||
|
|
||||||
|
- name: Check for secrets
|
||||||
|
run: |
|
||||||
|
# Vérifier les secrets potentiels
|
||||||
|
if grep -r "password\|secret\|key\|token" . --exclude-dir=.git --exclude-dir=target --exclude=*.md; then
|
||||||
|
echo "Potential secrets found. Please review."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check file permissions
|
||||||
|
run: |
|
||||||
|
# Vérifier les permissions sensibles
|
||||||
|
find . -type f -perm /0111 -name "*.conf" -o -name "*.key" -o -name "*.pem" | while read file; do
|
||||||
|
if [[ $(stat -c %a "$file") != "600" ]]; then
|
||||||
|
echo "Warning: $file has insecure permissions"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Job de build et test Docker
|
||||||
|
docker-build:
|
||||||
|
name: Docker Build & Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
docker:
|
||||||
|
image: docker:24.0.5
|
||||||
|
options: >-
|
||||||
|
--health-cmd "docker info"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 2375:2375
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build and test Bitcoin Core
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-bitcoin:test ./bitcoin
|
||||||
|
docker run --rm 4nk-node-bitcoin:test bitcoin-cli --version
|
||||||
|
|
||||||
|
- name: Build and test Blindbit
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-blindbit:test ./blindbit
|
||||||
|
docker run --rm 4nk-node-blindbit:test --version || true
|
||||||
|
|
||||||
|
- name: Build and test SDK Relay
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-sdk-relay:test -f ./sdk_relay/Dockerfile ..
|
||||||
|
docker run --rm 4nk-node-sdk-relay:test --version || true
|
||||||
|
|
||||||
|
- name: Test Docker Compose
|
||||||
|
run: |
|
||||||
|
docker-compose config
|
||||||
|
docker-compose build --no-cache
|
||||||
|
|
||||||
|
# Job de tests de documentation
|
||||||
|
documentation-tests:
|
||||||
|
name: Documentation Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Check markdown links
|
||||||
|
run: |
|
||||||
|
# Vérification basique des liens markdown
|
||||||
|
find . -name "*.md" -exec grep -l "\[.*\](" {} \; | while read file; do
|
||||||
|
echo "Checking links in $file"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Check documentation structure
|
||||||
|
run: |
|
||||||
|
# Vérifier la présence des fichiers de documentation essentiels
|
||||||
|
required_files=(
|
||||||
|
"README.md"
|
||||||
|
"LICENSE"
|
||||||
|
"CONTRIBUTING.md"
|
||||||
|
"CHANGELOG.md"
|
||||||
|
"CODE_OF_CONDUCT.md"
|
||||||
|
"SECURITY.md"
|
||||||
|
"docs/INDEX.md"
|
||||||
|
"docs/INSTALLATION.md"
|
||||||
|
"docs/USAGE.md"
|
||||||
|
)
|
||||||
|
|
||||||
|
for file in "${required_files[@]}"; do
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
echo "Missing required documentation file: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Validate documentation
|
||||||
|
run: |
|
||||||
|
# Vérifier la cohérence de la documentation
|
||||||
|
if ! grep -q "4NK Node" README.md; then
|
||||||
|
echo "README.md should mention '4NK Node'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Job de release guard (cohérence release)
|
||||||
|
release-guard:
|
||||||
|
name: Release Guard
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [code-quality, unit-tests, documentation-tests]
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Ensure guard scripts are executable
|
||||||
|
run: |
|
||||||
|
chmod +x scripts/release/guard.sh || true
|
||||||
|
chmod +x scripts/checks/version_alignment.sh || true
|
||||||
|
|
||||||
|
- name: Version alignment check
|
||||||
|
run: |
|
||||||
|
if [ -f scripts/checks/version_alignment.sh ]; then
|
||||||
|
./scripts/checks/version_alignment.sh
|
||||||
|
else
|
||||||
|
echo "No version alignment script (ok)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Release guard (CI verify)
|
||||||
|
env:
|
||||||
|
RELEASE_TYPE: ci-verify
|
||||||
|
run: |
|
||||||
|
if [ -f scripts/release/guard.sh ]; then
|
||||||
|
./scripts/release/guard.sh
|
||||||
|
else
|
||||||
|
echo "No guard script (ok)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Job de tests de performance
|
||||||
|
performance-tests:
|
||||||
|
name: Performance Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Run performance tests
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo test --release --test performance_tests || true
|
||||||
|
|
||||||
|
- name: Check memory usage
|
||||||
|
run: |
|
||||||
|
# Tests de base de consommation mémoire
|
||||||
|
echo "Performance tests completed"
|
||||||
|
|
||||||
|
# Job de notification
|
||||||
|
notify:
|
||||||
|
name: Notify
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [code-quality, unit-tests, integration-tests, security-tests, docker-build, documentation-tests]
|
||||||
|
if: always()
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Notify success
|
||||||
|
if: needs.code-quality.result == 'success' && needs.unit-tests.result == 'success' && needs.integration-tests.result == 'success' && needs.security-tests.result == 'success' && needs.docker-build.result == 'success' && needs.documentation-tests.result == 'success'
|
||||||
|
run: |
|
||||||
|
echo "✅ All tests passed successfully!"
|
||||||
|
|
||||||
|
- name: Notify failure
|
||||||
|
if: needs.code-quality.result == 'failure' || needs.unit-tests.result == 'failure' || needs.integration-tests.result == 'failure' || needs.security-tests.result == 'failure' || needs.docker-build.result == 'failure' || needs.documentation-tests.result == 'failure'
|
||||||
|
run: |
|
||||||
|
echo "❌ Some tests failed!"
|
||||||
|
exit 1
|
39
.gitea/workflows/template-sync.yml
Normal file
39
.gitea/workflows/template-sync.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# .gitea/workflows/template-sync.yml — synchronisation et contrôles d’intégrité
|
||||||
|
name: 4NK Template Sync
|
||||||
|
on:
|
||||||
|
schedule: # planification régulière
|
||||||
|
- cron: "0 4 * * 1" # exécution hebdomadaire (UTC)
|
||||||
|
workflow_dispatch: {} # déclenchement manuel
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-and-sync:
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- name: Lire TEMPLATE_VERSION et .4nk-sync.yml
|
||||||
|
# Doit charger ref courant, source_repo et périmètre paths
|
||||||
|
|
||||||
|
- name: Récupérer la version publiée du template/4NK_rules
|
||||||
|
# Doit comparer TEMPLATE_VERSION avec ref amont
|
||||||
|
|
||||||
|
- name: Créer branche de synchronisation si divergence
|
||||||
|
# Doit créer chore/template-sync-<date> et préparer un commit
|
||||||
|
|
||||||
|
- name: Synchroniser les chemins autoritatifs
|
||||||
|
# Doit mettre à jour .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md
|
||||||
|
|
||||||
|
- name: Contrôles post-sync (bloquants)
|
||||||
|
# 1) Vérifier présence et exécutable des scripts/*.sh
|
||||||
|
# 2) Vérifier mise à jour CHANGELOG.md et docs/INDEX.md
|
||||||
|
# 3) Vérifier docs/SSH_UPDATE.md si scripts/** a changé
|
||||||
|
# 4) Vérifier absence de secrets en clair dans scripts/**
|
||||||
|
# 5) Vérifier manifest_checksum si publié
|
||||||
|
|
||||||
|
- name: Tests, lint, sécurité statique
|
||||||
|
# Doit exiger un état vert
|
||||||
|
|
||||||
|
- name: Ouvrir PR de synchronisation
|
||||||
|
# Titre: "[template-sync] chore: aligner .cursor/.gitea/AGENTS.md/scripts"
|
||||||
|
# Doit inclure résumé des fichiers modifiés et la version appliquée
|
||||||
|
|
||||||
|
- name: Mettre à jour TEMPLATE_VERSION (dans PR)
|
||||||
|
# Doit remplacer la valeur par la ref appliquée
|
99
.gitea_template/ISSUE_TEMPLATE/bug_report.md
Normal file
99
.gitea_template/ISSUE_TEMPLATE/bug_report.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Signaler un bug pour nous aider à améliorer 4NK Node
|
||||||
|
title: '[BUG] '
|
||||||
|
labels: ['bug', 'needs-triage']
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
> Ce fichier est un modèle (template). Adaptez les champs à votre projet dérivé.
|
||||||
|
|
||||||
|
## 🐛 Description du Bug
|
||||||
|
|
||||||
|
Description claire et concise du problème.
|
||||||
|
|
||||||
|
## 🔄 Étapes pour Reproduire
|
||||||
|
|
||||||
|
1. Aller à '...'
|
||||||
|
2. Cliquer sur '...'
|
||||||
|
3. Faire défiler jusqu'à '...'
|
||||||
|
4. Voir l'erreur
|
||||||
|
|
||||||
|
## ✅ Comportement Attendu
|
||||||
|
|
||||||
|
Description de ce qui devrait se passer.
|
||||||
|
|
||||||
|
## ❌ Comportement Actuel
|
||||||
|
|
||||||
|
Description de ce qui se passe actuellement.
|
||||||
|
|
||||||
|
## 📸 Capture d'Écran
|
||||||
|
|
||||||
|
Si applicable, ajoutez une capture d'écran pour expliquer votre problème.
|
||||||
|
|
||||||
|
## 💻 Informations Système
|
||||||
|
|
||||||
|
- **OS** : [ex: Ubuntu 20.04, macOS 12.0, Windows 11]
|
||||||
|
- **Docker** : [ex: 20.10.0]
|
||||||
|
- **Docker Compose** : [ex: 2.0.0]
|
||||||
|
- **Version 4NK Node** : [ex: v1.0.0]
|
||||||
|
- **Architecture** : [ex: x86_64, ARM64]
|
||||||
|
|
||||||
|
## 📋 Configuration
|
||||||
|
|
||||||
|
### Services Actifs
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables d'Environnement
|
||||||
|
```bash
|
||||||
|
# Bitcoin Core
|
||||||
|
BITCOIN_NETWORK=signet
|
||||||
|
BITCOIN_RPC_PORT=18443
|
||||||
|
|
||||||
|
# Blindbit
|
||||||
|
BLINDBIT_PORT=8000
|
||||||
|
|
||||||
|
# SDK Relay
|
||||||
|
SDK_RELAY_PORTS=8090-8095
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Logs
|
||||||
|
|
||||||
|
### Logs Pertinents
|
||||||
|
```
|
||||||
|
Logs pertinents ici
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs d'Erreur
|
||||||
|
```
|
||||||
|
Logs d'erreur ici
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs de Debug
|
||||||
|
```
|
||||||
|
Logs de debug ici (si RUST_LOG=debug)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Tentatives de Résolution
|
||||||
|
|
||||||
|
- [ ] Redémarrage des services
|
||||||
|
- [ ] Nettoyage des volumes Docker
|
||||||
|
- [ ] Vérification de la connectivité réseau
|
||||||
|
- [ ] Mise à jour des dépendances
|
||||||
|
- [ ] Vérification de la configuration
|
||||||
|
|
||||||
|
## 📚 Contexte Supplémentaire
|
||||||
|
|
||||||
|
Toute autre information pertinente sur le problème.
|
||||||
|
|
||||||
|
## 🔗 Liens Utiles
|
||||||
|
|
||||||
|
- [Documentation](docs/)
|
||||||
|
- [Guide de Dépannage](docs/TROUBLESHOOTING.md)
|
||||||
|
- [Issues Similaires](https://git.4nkweb.com/4nk/4NK_node/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Merci de votre contribution !** 🙏
|
158
.gitea_template/ISSUE_TEMPLATE/feature_request.md
Normal file
158
.gitea_template/ISSUE_TEMPLATE/feature_request.md
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
about: Proposer une nouvelle fonctionnalité pour 4NK Node
|
||||||
|
title: '[FEATURE] '
|
||||||
|
labels: ['enhancement', 'needs-triage']
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
> Ce fichier est un modèle (template). Adaptez les champs à votre projet dérivé.
|
||||||
|
|
||||||
|
## 🚀 Résumé
|
||||||
|
|
||||||
|
Description claire et concise de la fonctionnalité souhaitée.
|
||||||
|
|
||||||
|
## 💡 Motivation
|
||||||
|
|
||||||
|
Pourquoi cette fonctionnalité est-elle nécessaire ? Quels problèmes résout-elle ?
|
||||||
|
|
||||||
|
### Problèmes Actuels
|
||||||
|
- Problème 1
|
||||||
|
- Problème 2
|
||||||
|
- Problème 3
|
||||||
|
|
||||||
|
### Avantages de la Solution
|
||||||
|
- Avantage 1
|
||||||
|
- Avantage 2
|
||||||
|
- Avantage 3
|
||||||
|
|
||||||
|
## 🎯 Proposition
|
||||||
|
|
||||||
|
Description détaillée de la fonctionnalité proposée.
|
||||||
|
|
||||||
|
### Fonctionnalités Principales
|
||||||
|
- [ ] Fonctionnalité 1
|
||||||
|
- [ ] Fonctionnalité 2
|
||||||
|
- [ ] Fonctionnalité 3
|
||||||
|
|
||||||
|
### Interface Utilisateur
|
||||||
|
Description de l'interface utilisateur si applicable.
|
||||||
|
|
||||||
|
### API Changes
|
||||||
|
Description des changements d'API si applicable.
|
||||||
|
|
||||||
|
## 🔄 Alternatives Considérées
|
||||||
|
|
||||||
|
Autres solutions envisagées et pourquoi elles n'ont pas été choisies.
|
||||||
|
|
||||||
|
### Alternative 1
|
||||||
|
- **Description** : ...
|
||||||
|
- **Pourquoi rejetée** : ...
|
||||||
|
|
||||||
|
### Alternative 2
|
||||||
|
- **Description** : ...
|
||||||
|
- **Pourquoi rejetée** : ...
|
||||||
|
|
||||||
|
## 📊 Impact
|
||||||
|
|
||||||
|
### Impact sur les Utilisateurs
|
||||||
|
- Impact positif 1
|
||||||
|
- Impact positif 2
|
||||||
|
- Impact négatif potentiel (si applicable)
|
||||||
|
|
||||||
|
### Impact sur l'Architecture
|
||||||
|
- Changements nécessaires
|
||||||
|
- Compatibilité avec l'existant
|
||||||
|
- Performance
|
||||||
|
|
||||||
|
### Impact sur la Maintenance
|
||||||
|
- Complexité ajoutée
|
||||||
|
- Tests nécessaires
|
||||||
|
- Documentation requise
|
||||||
|
|
||||||
|
## 💻 Exemples d'Utilisation
|
||||||
|
|
||||||
|
### Cas d'Usage 1
|
||||||
|
```bash
|
||||||
|
# Exemple de commande ou configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cas d'Usage 2
|
||||||
|
```python
|
||||||
|
# Exemple de code Python
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cas d'Usage 3
|
||||||
|
```javascript
|
||||||
|
// Exemple de code JavaScript
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Tests
|
||||||
|
|
||||||
|
### Tests Nécessaires
|
||||||
|
- [ ] Tests unitaires
|
||||||
|
- [ ] Tests d'intégration
|
||||||
|
- [ ] Tests de performance
|
||||||
|
- [ ] Tests de sécurité
|
||||||
|
- [ ] Tests de compatibilité
|
||||||
|
|
||||||
|
### Scénarios de Test
|
||||||
|
- Scénario 1
|
||||||
|
- Scénario 2
|
||||||
|
- Scénario 3
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
### Documentation Requise
|
||||||
|
- [ ] Guide d'utilisation
|
||||||
|
- [ ] Documentation API
|
||||||
|
- [ ] Exemples de code
|
||||||
|
- [ ] Guide de migration
|
||||||
|
- [ ] FAQ
|
||||||
|
|
||||||
|
## 🔧 Implémentation
|
||||||
|
|
||||||
|
### Étapes Proposées
|
||||||
|
1. **Phase 1** : [Description]
|
||||||
|
2. **Phase 2** : [Description]
|
||||||
|
3. **Phase 3** : [Description]
|
||||||
|
|
||||||
|
### Estimation de Temps
|
||||||
|
- **Développement** : X jours/semaines
|
||||||
|
- **Tests** : X jours/semaines
|
||||||
|
- **Documentation** : X jours/semaines
|
||||||
|
- **Total** : X jours/semaines
|
||||||
|
|
||||||
|
### Ressources Nécessaires
|
||||||
|
- Développeur(s)
|
||||||
|
- Testeur(s)
|
||||||
|
- Documentateur(s)
|
||||||
|
- Infrastructure
|
||||||
|
|
||||||
|
## 🎯 Critères de Succès
|
||||||
|
|
||||||
|
Comment mesurer le succès de cette fonctionnalité ?
|
||||||
|
|
||||||
|
- [ ] Critère 1
|
||||||
|
- [ ] Critère 2
|
||||||
|
- [ ] Critère 3
|
||||||
|
|
||||||
|
## 🔗 Liens Utiles
|
||||||
|
|
||||||
|
- [Documentation existante](docs/)
|
||||||
|
- [Issues similaires](https://git.4nkweb.com/4nk/4NK_node/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
|
||||||
|
- [Roadmap](https://git.4nkweb.com/4nk/4NK_node/projects)
|
||||||
|
- [Discussions](https://git.4nkweb.com/4nk/4NK_node/issues)
|
||||||
|
|
||||||
|
## 📋 Checklist
|
||||||
|
|
||||||
|
- [ ] J'ai vérifié que cette fonctionnalité n'existe pas déjà
|
||||||
|
- [ ] J'ai lu la documentation existante
|
||||||
|
- [ ] J'ai vérifié les issues similaires
|
||||||
|
- [ ] J'ai fourni des exemples d'utilisation
|
||||||
|
- [ ] J'ai considéré l'impact sur l'existant
|
||||||
|
- [ ] J'ai proposé des tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Merci de votre contribution à l'amélioration de 4NK Node !** 🌟
|
183
.gitea_template/PULL_REQUEST_TEMPLATE.md
Normal file
183
.gitea_template/PULL_REQUEST_TEMPLATE.md
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
# Pull Request - 4NK Node
|
||||||
|
|
||||||
|
> Ce fichier est un modèle PR. Adaptez les sections à votre projet dérivé.
|
||||||
|
|
||||||
|
## 📋 Description
|
||||||
|
|
||||||
|
Description claire et concise des changements apportés.
|
||||||
|
|
||||||
|
### Type de Changement
|
||||||
|
- [ ] 🐛 Bug fix
|
||||||
|
- [ ] ✨ Nouvelle fonctionnalité
|
||||||
|
- [ ] 📚 Documentation
|
||||||
|
- [ ] 🧪 Tests
|
||||||
|
- [ ] 🔧 Refactoring
|
||||||
|
- [ ] 🚀 Performance
|
||||||
|
- [ ] 🔒 Sécurité
|
||||||
|
- [ ] 🎨 Style/UI
|
||||||
|
- [ ] 🏗️ Architecture
|
||||||
|
- [ ] 📦 Build/CI
|
||||||
|
|
||||||
|
### Composants Affectés
|
||||||
|
- [ ] Bitcoin Core
|
||||||
|
- [ ] Blindbit
|
||||||
|
- [ ] SDK Relay
|
||||||
|
- [ ] Tor
|
||||||
|
- [ ] Docker/Infrastructure
|
||||||
|
- [ ] Tests
|
||||||
|
- [ ] Documentation
|
||||||
|
- [ ] Scripts
|
||||||
|
|
||||||
|
## 🔗 Issue(s) Liée(s)
|
||||||
|
|
||||||
|
Fixes #(issue)
|
||||||
|
Relates to #(issue)
|
||||||
|
|
||||||
|
## 🧪 Tests
|
||||||
|
|
||||||
|
### Tests Exécutés
|
||||||
|
- [ ] Tests unitaires
|
||||||
|
- [ ] Tests d'intégration
|
||||||
|
- [ ] Tests de connectivité
|
||||||
|
- [ ] Tests externes
|
||||||
|
- [ ] Tests de performance
|
||||||
|
- [ ] Release Guard local (`RELEASE_TYPE=ci-verify scripts/release/guard.sh`)
|
||||||
|
|
||||||
|
### Commandes de Test
|
||||||
|
```bash
|
||||||
|
# Tests complets
|
||||||
|
./tests/run_all_tests.sh
|
||||||
|
|
||||||
|
# Tests spécifiques
|
||||||
|
./tests/run_unit_tests.sh
|
||||||
|
./tests/run_integration_tests.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Résultats des Tests
|
||||||
|
```
|
||||||
|
Résultats des tests ici
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📸 Captures d'Écran
|
||||||
|
|
||||||
|
Si applicable, ajoutez des captures d'écran pour les changements visuels.
|
||||||
|
|
||||||
|
## 🔧 Changements Techniques
|
||||||
|
|
||||||
|
### Fichiers Modifiés
|
||||||
|
- `fichier1.rs` - Description des changements
|
||||||
|
- `fichier2.py` - Description des changements
|
||||||
|
- `docker-compose.yml` - Description des changements
|
||||||
|
|
||||||
|
### Nouveaux Fichiers
|
||||||
|
- `nouveau_fichier.rs` - Description
|
||||||
|
- `nouveau_script.sh` - Description
|
||||||
|
|
||||||
|
### Fichiers Supprimés
|
||||||
|
- `ancien_fichier.rs` - Raison de la suppression
|
||||||
|
|
||||||
|
### Changements de Configuration
|
||||||
|
```yaml
|
||||||
|
# Exemple de changement de configuration
|
||||||
|
service:
|
||||||
|
new_option: value
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
### Documentation Mise à Jour
|
||||||
|
- [ ] README.md
|
||||||
|
- [ ] docs/INSTALLATION.md
|
||||||
|
- [ ] docs/USAGE.md
|
||||||
|
- [ ] docs/API.md
|
||||||
|
- [ ] docs/ARCHITECTURE.md
|
||||||
|
|
||||||
|
### Nouvelle Documentation
|
||||||
|
- [ ] Nouveau guide créé
|
||||||
|
- [ ] Exemples ajoutés
|
||||||
|
- [ ] API documentée
|
||||||
|
|
||||||
|
## 🔍 Code Review Checklist
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
- [ ] Le code suit les standards du projet
|
||||||
|
- [ ] Les noms de variables/fonctions sont clairs
|
||||||
|
- [ ] Les commentaires sont appropriés
|
||||||
|
- [ ] Pas de code mort ou commenté
|
||||||
|
- [ ] Gestion d'erreurs appropriée
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- [ ] Pas de régression de performance
|
||||||
|
- [ ] Optimisations appliquées si nécessaire
|
||||||
|
- [ ] Tests de performance ajoutés
|
||||||
|
|
||||||
|
### Sécurité
|
||||||
|
- [ ] Pas de vulnérabilités introduites
|
||||||
|
- [ ] Validation des entrées utilisateur
|
||||||
|
- [ ] Gestion sécurisée des secrets
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
- [ ] Couverture de tests suffisante
|
||||||
|
- [ ] Tests pour les cas d'erreur
|
||||||
|
- [ ] Tests d'intégration si nécessaire
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- [ ] Code auto-documenté
|
||||||
|
- [ ] Documentation mise à jour
|
||||||
|
- [ ] Exemples fournis
|
||||||
|
|
||||||
|
## 🚀 Déploiement
|
||||||
|
|
||||||
|
### Impact sur le Déploiement
|
||||||
|
- [ ] Aucun impact
|
||||||
|
- [ ] Migration de données requise
|
||||||
|
- [ ] Changement de configuration
|
||||||
|
- [ ] Redémarrage des services
|
||||||
|
|
||||||
|
### Étapes de Déploiement
|
||||||
|
```bash
|
||||||
|
# Étapes pour déployer les changements
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Métriques
|
||||||
|
|
||||||
|
### Impact sur les Performances
|
||||||
|
- Temps de réponse : +/- X%
|
||||||
|
- Utilisation mémoire : +/- X%
|
||||||
|
- Utilisation CPU : +/- X%
|
||||||
|
|
||||||
|
### Impact sur la Stabilité
|
||||||
|
- Taux d'erreur : +/- X%
|
||||||
|
- Disponibilité : +/- X%
|
||||||
|
|
||||||
|
## 🔄 Compatibilité
|
||||||
|
|
||||||
|
### Compatibilité Ascendante
|
||||||
|
- [ ] Compatible avec les versions précédentes
|
||||||
|
- [ ] Migration automatique
|
||||||
|
- [ ] Migration manuelle requise
|
||||||
|
|
||||||
|
### Compatibilité Descendante
|
||||||
|
- [ ] Compatible avec les futures versions
|
||||||
|
- [ ] API stable
|
||||||
|
- [ ] Configuration stable
|
||||||
|
|
||||||
|
## 🎯 Critères de Succès
|
||||||
|
|
||||||
|
- [ ] Critère 1
|
||||||
|
- [ ] Critère 2
|
||||||
|
- [ ] Critère 3
|
||||||
|
|
||||||
|
## 📝 Notes Supplémentaires
|
||||||
|
|
||||||
|
Informations supplémentaires importantes pour les reviewers.
|
||||||
|
|
||||||
|
## 🔗 Liens Utiles
|
||||||
|
|
||||||
|
- [Documentation](docs/)
|
||||||
|
- [Tests](tests/)
|
||||||
|
- [Issues liées](https://git.4nkweb.com/4nk/4NK_node/issues)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Merci pour votre contribution !** 🙏
|
14
.gitea_template/workflows/LOCAL_OVERRIDES.yml
Normal file
14
.gitea_template/workflows/LOCAL_OVERRIDES.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# LOCAL_OVERRIDES.yml — dérogations locales contrôlées (fichier modèle)
|
||||||
|
overrides:
|
||||||
|
- path: ".gitea/workflows/ci.yml"
|
||||||
|
reason: "spécificité d’environnement"
|
||||||
|
owner: "@maintainer_handle"
|
||||||
|
expires: "2025-12-31"
|
||||||
|
- path: "scripts/scripts/auto-ssh-push.sh"
|
||||||
|
reason: "flux particulier temporaire"
|
||||||
|
owner: "@maintainer_handle"
|
||||||
|
expires: "2025-10-01"
|
||||||
|
policy:
|
||||||
|
allow_only_listed_paths: true
|
||||||
|
require_expiry: true
|
||||||
|
audit_in_ci: true
|
346
.gitea_template/workflows/ci.yml
Normal file
346
.gitea_template/workflows/ci.yml
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
# Template CI - 4NK Node (ce fichier est un modèle, adaptez selon votre projet)
|
||||||
|
name: CI - 4NK Node
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUST_VERSION: '1.70'
|
||||||
|
DOCKER_COMPOSE_VERSION: '2.20.0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Job de vérification du code
|
||||||
|
code-quality:
|
||||||
|
name: Code Quality
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Cache Rust dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
- name: Run clippy
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo clippy --all-targets --all-features -- -D warnings
|
||||||
|
|
||||||
|
- name: Run rustfmt
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
|
||||||
|
- name: Check documentation
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo doc --no-deps
|
||||||
|
|
||||||
|
- name: Check for TODO/FIXME
|
||||||
|
run: |
|
||||||
|
if grep -r "TODO\|FIXME" . --exclude-dir=.git --exclude-dir=target; then
|
||||||
|
echo "Found TODO/FIXME comments. Please address them."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Job de tests unitaires
|
||||||
|
unit-tests:
|
||||||
|
name: Unit Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Cache Rust dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo test --lib --bins
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo test --tests
|
||||||
|
|
||||||
|
# Job de tests d'intégration
|
||||||
|
integration-tests:
|
||||||
|
name: Integration Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
docker:
|
||||||
|
image: docker:24.0.5
|
||||||
|
options: >-
|
||||||
|
--health-cmd "docker info"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 2375:2375
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build Docker images
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-bitcoin ./bitcoin
|
||||||
|
docker build -t 4nk-node-blindbit ./blindbit
|
||||||
|
docker build -t 4nk-node-sdk-relay -f ./sdk_relay/Dockerfile ..
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
# Tests de connectivité de base
|
||||||
|
./tests/run_connectivity_tests.sh || true
|
||||||
|
|
||||||
|
# Tests d'intégration
|
||||||
|
./tests/run_integration_tests.sh || true
|
||||||
|
|
||||||
|
- name: Upload test results
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: test-results
|
||||||
|
path: |
|
||||||
|
tests/logs/
|
||||||
|
tests/reports/
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
# Job de tests de sécurité
|
||||||
|
security-tests:
|
||||||
|
name: Security Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Run cargo audit
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo audit --deny warnings
|
||||||
|
|
||||||
|
- name: Check for secrets
|
||||||
|
run: |
|
||||||
|
# Vérifier les secrets potentiels
|
||||||
|
if grep -r "password\|secret\|key\|token" . --exclude-dir=.git --exclude-dir=target --exclude=*.md; then
|
||||||
|
echo "Potential secrets found. Please review."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check file permissions
|
||||||
|
run: |
|
||||||
|
# Vérifier les permissions sensibles
|
||||||
|
find . -type f -perm /0111 -name "*.conf" -o -name "*.key" -o -name "*.pem" | while read file; do
|
||||||
|
if [[ $(stat -c %a "$file") != "600" ]]; then
|
||||||
|
echo "Warning: $file has insecure permissions"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Job de build et test Docker
|
||||||
|
docker-build:
|
||||||
|
name: Docker Build & Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
docker:
|
||||||
|
image: docker:24.0.5
|
||||||
|
options: >-
|
||||||
|
--health-cmd "docker info"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 2375:2375
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build and test Bitcoin Core
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-bitcoin:test ./bitcoin
|
||||||
|
docker run --rm 4nk-node-bitcoin:test bitcoin-cli --version
|
||||||
|
|
||||||
|
- name: Build and test Blindbit
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-blindbit:test ./blindbit
|
||||||
|
docker run --rm 4nk-node-blindbit:test --version || true
|
||||||
|
|
||||||
|
- name: Build and test SDK Relay
|
||||||
|
run: |
|
||||||
|
docker build -t 4nk-node-sdk-relay:test -f ./sdk_relay/Dockerfile ..
|
||||||
|
docker run --rm 4nk-node-sdk-relay:test --version || true
|
||||||
|
|
||||||
|
- name: Test Docker Compose
|
||||||
|
run: |
|
||||||
|
docker-compose config
|
||||||
|
docker-compose build --no-cache
|
||||||
|
|
||||||
|
# Job de tests de documentation
|
||||||
|
documentation-tests:
|
||||||
|
name: Documentation Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Check markdown links
|
||||||
|
run: |
|
||||||
|
# Vérification basique des liens markdown
|
||||||
|
find . -name "*.md" -exec grep -l "\[.*\](" {} \; | while read file; do
|
||||||
|
echo "Checking links in $file"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Check documentation structure
|
||||||
|
run: |
|
||||||
|
# Vérifier la présence des fichiers de documentation essentiels
|
||||||
|
required_files=(
|
||||||
|
"README.md"
|
||||||
|
"LICENSE"
|
||||||
|
"CONTRIBUTING.md"
|
||||||
|
"CHANGELOG.md"
|
||||||
|
"CODE_OF_CONDUCT.md"
|
||||||
|
"SECURITY.md"
|
||||||
|
"docs/INDEX.md"
|
||||||
|
"docs/INSTALLATION.md"
|
||||||
|
"docs/USAGE.md"
|
||||||
|
)
|
||||||
|
|
||||||
|
for file in "${required_files[@]}"; do
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
echo "Missing required documentation file: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Validate documentation
|
||||||
|
run: |
|
||||||
|
# Vérifier la cohérence de la documentation
|
||||||
|
if ! grep -q "4NK Node" README.md; then
|
||||||
|
echo "README.md should mention '4NK Node'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Job de release guard (cohérence release)
|
||||||
|
release-guard:
|
||||||
|
name: Release Guard
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [code-quality, unit-tests, documentation-tests]
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Ensure guard scripts are executable
|
||||||
|
run: |
|
||||||
|
chmod +x scripts/release/guard.sh || true
|
||||||
|
chmod +x scripts/checks/version_alignment.sh || true
|
||||||
|
|
||||||
|
- name: Version alignment check
|
||||||
|
run: |
|
||||||
|
if [ -f scripts/checks/version_alignment.sh ]; then
|
||||||
|
./scripts/checks/version_alignment.sh
|
||||||
|
else
|
||||||
|
echo "No version alignment script (ok)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Release guard (CI verify)
|
||||||
|
env:
|
||||||
|
RELEASE_TYPE: ci-verify
|
||||||
|
run: |
|
||||||
|
if [ -f scripts/release/guard.sh ]; then
|
||||||
|
./scripts/release/guard.sh
|
||||||
|
else
|
||||||
|
echo "No guard script (ok)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Job de tests de performance
|
||||||
|
performance-tests:
|
||||||
|
name: Performance Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Run performance tests
|
||||||
|
run: |
|
||||||
|
cd sdk_relay
|
||||||
|
cargo test --release --test performance_tests || true
|
||||||
|
|
||||||
|
- name: Check memory usage
|
||||||
|
run: |
|
||||||
|
# Tests de base de consommation mémoire
|
||||||
|
echo "Performance tests completed"
|
||||||
|
|
||||||
|
# Job de notification
|
||||||
|
notify:
|
||||||
|
name: Notify
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [code-quality, unit-tests, integration-tests, security-tests, docker-build, documentation-tests]
|
||||||
|
if: always()
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Notify success
|
||||||
|
if: needs.code-quality.result == 'success' && needs.unit-tests.result == 'success' && needs.integration-tests.result == 'success' && needs.security-tests.result == 'success' && needs.docker-build.result == 'success' && needs.documentation-tests.result == 'success'
|
||||||
|
run: |
|
||||||
|
echo "✅ All tests passed successfully!"
|
||||||
|
|
||||||
|
- name: Notify failure
|
||||||
|
if: needs.code-quality.result == 'failure' || needs.unit-tests.result == 'failure' || needs.integration-tests.result == 'failure' || needs.security-tests.result == 'failure' || needs.docker-build.result == 'failure' || needs.documentation-tests.result == 'failure'
|
||||||
|
run: |
|
||||||
|
echo "❌ Some tests failed!"
|
||||||
|
exit 1
|
39
.gitea_template/workflows/template-sync.yml
Normal file
39
.gitea_template/workflows/template-sync.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# .gitea/workflows/template-sync.yml — synchronisation et contrôles d’intégrité (fichier modèle)
|
||||||
|
name: 4NK Template Sync
|
||||||
|
on:
|
||||||
|
schedule: # planification régulière
|
||||||
|
- cron: "0 4 * * 1" # exécution hebdomadaire (UTC)
|
||||||
|
workflow_dispatch: {} # déclenchement manuel
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-and-sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Lire TEMPLATE_VERSION et .4nk-sync.yml
|
||||||
|
# Doit charger ref courant, source_repo et périmètre paths
|
||||||
|
|
||||||
|
- name: Récupérer la version publiée du template/4NK_rules
|
||||||
|
# Doit comparer TEMPLATE_VERSION avec ref amont
|
||||||
|
|
||||||
|
- name: Créer branche de synchronisation si divergence
|
||||||
|
# Doit créer chore/template-sync-<date> et préparer un commit
|
||||||
|
|
||||||
|
- name: Synchroniser les chemins autoritatifs
|
||||||
|
# Doit mettre à jour .cursor/**, .gitea/**, AGENTS.md, scripts/**, docs/SSH_UPDATE.md
|
||||||
|
|
||||||
|
- name: Contrôles post-sync (bloquants)
|
||||||
|
# 1) Vérifier présence et exécutable des scripts/*.sh
|
||||||
|
# 2) Vérifier mise à jour CHANGELOG.md et docs/INDEX.md
|
||||||
|
# 3) Vérifier docs/SSH_UPDATE.md si scripts/** a changé
|
||||||
|
# 4) Vérifier absence de secrets en clair dans scripts/**
|
||||||
|
# 5) Vérifier manifest_checksum si publié
|
||||||
|
|
||||||
|
- name: Tests, lint, sécurité statique
|
||||||
|
# Doit exiger un état vert
|
||||||
|
|
||||||
|
- name: Ouvrir PR de synchronisation
|
||||||
|
# Titre: "[template-sync] chore: aligner .cursor/.gitea/AGENTS.md/scripts"
|
||||||
|
# Doit inclure résumé des fichiers modifiés et la version appliquée
|
||||||
|
|
||||||
|
- name: Mettre à jour TEMPLATE_VERSION (dans PR)
|
||||||
|
# Doit remplacer la valeur par la ref appliquée
|
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Dépendances
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Builds / artefacts
|
||||||
|
/dist/
|
||||||
|
/build/
|
||||||
|
/coverage/
|
||||||
|
/.cache/
|
||||||
|
/.turbo/
|
||||||
|
/.parcel-cache/
|
||||||
|
/tmp/
|
||||||
|
|
||||||
|
# Sorties synchronisées depuis ihm_client
|
||||||
|
/assets/ihm/
|
||||||
|
/web/ihm/
|
||||||
|
|
||||||
|
# Journaux
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Environnements
|
||||||
|
.env
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Éditeurs / OS
|
||||||
|
.DS_Store
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Jest
|
||||||
|
.jest-cache/
|
||||||
|
.jest/
|
||||||
|
|
||||||
|
!.cursor/
|
||||||
|
|
||||||
|
!AGENTS.md
|
263
AGENTS.md
Normal file
263
AGENTS.md
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Table des matières
|
||||||
|
- [Introduction](#introduction)
|
||||||
|
- [Principes communs](#principes-communs)
|
||||||
|
- [Agents fondamentaux](#agents-fondamentaux)
|
||||||
|
- [Agents spécialisés documentation](#agents-spécialisés-documentation)
|
||||||
|
- [Agents spécialisés tests](#agents-spécialisés-tests)
|
||||||
|
- [Agents techniques](#agents-techniques)
|
||||||
|
- [Agents frontend](#agents-frontend)
|
||||||
|
- [Agents open source et CI](#agents-open-source-et-ci)
|
||||||
|
- [Agents de synchronisation et dérogations](#agents-de-synchronisation-et-d%C3%A9rogations)
|
||||||
|
- [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 `4NK/4NK_node` et, par extension, tout dépôt dérivé de `4NK_project_template`.
|
||||||
|
Il impose une coordination stricte entre code, documentation, tests, dépendances, CI/CD, synchronisation de template et gouvernance open source.
|
||||||
|
Les règles opérationnelles détaillées sont précisées dans `.cursor/rules/` (notamment `41-ssh-automation.mdc` et `42-template-sync.mdc`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principes communs
|
||||||
|
- Langue exclusive : français.
|
||||||
|
- Pas d’exemples de code applicatif injectés dans la base.
|
||||||
|
- Toute contribution doit contenir une introduction et/ou une conclusion.
|
||||||
|
- Interdiction de secrets en clair dans le dépôt.
|
||||||
|
- Confirmation nécessaire avant `push` et `tag`.
|
||||||
|
- Toute modification impactant des éléments normatifs doit mettre à jour la documentation et le changelog.
|
||||||
|
- Le flux de publication applique un garde de release (tests/doc/build/alignement version/changelog/tag, latest vs wip).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents fondamentaux
|
||||||
|
|
||||||
|
### Agent Fondation (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Garantir la conformité éditoriale : français, pas d’exemples applicatifs, introduction/conclusion.
|
||||||
|
- Vérifier la cohérence terminologique.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- Tous fichiers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Structure (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Maintenir l’arborescence canonique (incluant `.cursor/`, `.gitea/`, `scripts/`, `docs/SSH_UPDATE.md`).
|
||||||
|
- Archiver le contenu obsolète dans `archive/` avec métadonnées.
|
||||||
|
- Interdire toute suppression non tracée.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `archive/`, `docs/**`, `tests/**`, `.cursor/**`, `.gitea/**`, `scripts/**`, `CHANGELOG.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents spécialisés documentation
|
||||||
|
|
||||||
|
### Agent Documentation (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Mettre à jour `docs/**` selon l’impact des changements.
|
||||||
|
- Tenir `docs/INDEX.md` comme table des matières centrale.
|
||||||
|
- Produire des REX techniques dans `archive/` en cas d’investigations multiples.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `docs/**`, `README.md`, `archive/**`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Données CSV (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Traiter les CSV comme source des modèles de données (en-têtes multi-lignes inclus).
|
||||||
|
- Exiger une définition complète de toutes les colonnes.
|
||||||
|
- Corriger et documenter les incohérences de types.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `docs/API.md`, `docs/ARCHITECTURE.md`, `docs/USAGE.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Documents bureautiques (Consulté)
|
||||||
|
**Missions**
|
||||||
|
- Lire `.docx` via `docx2txt`; proposer des alternatives en cas d’échec.
|
||||||
|
- Documenter les imports dans `docs/INDEX.md`.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `docs/**`, `archive/**`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents spécialisés tests
|
||||||
|
|
||||||
|
### Agent Tests (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Couvrir `unit`, `integration`, `connectivity`, `performance`, `external`.
|
||||||
|
- Gérer `tests/logs` et `tests/reports`.
|
||||||
|
- Exiger des tests verts avant commit.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `tests/**`, `docs/TESTING.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Performance (Consulté)
|
||||||
|
**Missions**
|
||||||
|
- Réaliser des benchmarks reproductibles.
|
||||||
|
- Valider l’impact performance avant fusion.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `tests/performance/`, `tests/reports/`, `docs/TESTING.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents techniques
|
||||||
|
|
||||||
|
### Agent Dépendances (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Ajouter les dépendances manquantes lorsque justifié.
|
||||||
|
- Vérifier les dernières versions stables.
|
||||||
|
- Documenter les impacts dans `ARCHITECTURE.md`, `CONFIGURATION.md`, `CHANGELOG.md`.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `docs/ARCHITECTURE.md`, `docs/CONFIGURATION.md`, `CHANGELOG.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Compilation (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Compiler très régulièrement et aux étapes critiques.
|
||||||
|
- Bloquer toute progression en cas d’erreurs de build/runtime.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- Artefacts de build, scripts d’outillage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Résolution (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Conduire la boucle de diagnostic complète : reproduction minimale, logs, bissection, hypothèses, tests ciblés, correctif, non-régression.
|
||||||
|
- Produire un REX quand plusieurs hypothèses ont été testées.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `tests/**`, `archive/**`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent SSH & scripts (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Garantir la présence et l’usage correct de `scripts/auto-ssh-push.sh`, `scripts/init-ssh-env.sh`, `scripts/setup-ssh-ci.sh`.
|
||||||
|
- Assurer permissions d’exécution, idempotence, journalisation non sensible, gestion d’erreurs robuste.
|
||||||
|
- Interdire secrets en clair, gérer via secrets CI et variables d’environnement.
|
||||||
|
- Exiger la mise à jour de `docs/SSH_UPDATE.md` à toute évolution des scripts ou des flux SSH.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `scripts/**`, `.gitea/workflows/ci.yml`, `docs/SSH_UPDATE.md`, `docs/CONFIGURATION.md`, `CHANGELOG.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents frontend
|
||||||
|
|
||||||
|
### Agent Frontend (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Mettre en place `React.lazy`/`Suspense` (code splitting).
|
||||||
|
- Centraliser l’état (Redux ou Context API).
|
||||||
|
- Abstraire les services de données.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `docs/ARCHITECTURE.md`, `docs/TESTING.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents open source et CI
|
||||||
|
|
||||||
|
### Agent Open Source (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Maintenir : `LICENSE`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `docs/OPEN_SOURCE_CHECKLIST.md`.
|
||||||
|
- Vérifier l’alignement continu avec `4NK_node`.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- Fichiers de gouvernance cités ci-dessus.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Gitea (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Garantir `.gitea/ISSUE_TEMPLATE/*`, `PULL_REQUEST_TEMPLATE.md`, `.gitea/workflows/ci.yml`.
|
||||||
|
- Documenter la configuration distante dans `docs/GITEA_SETUP.md`.
|
||||||
|
- Déclencher les étapes CI pertinentes (tests, lint, sécurité, vérifs `scripts/`).
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `.gitea/**`, `docs/GITEA_SETUP.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Versionnage (Responsable)
|
||||||
|
**Missions**
|
||||||
|
- Tenir `CHANGELOG.md` comme source unique de vérité.
|
||||||
|
- Proposer un bump sémantique justifié.
|
||||||
|
- Demander confirmation avant push et tag.
|
||||||
|
- Orchestrer le `release-guard` (CI + scripts) et consigner latest vs wip.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `CHANGELOG.md`, `docs/RELEASE_PLAN.md`, `docs/ROADMAP.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agents de synchronisation et dérogations
|
||||||
|
|
||||||
|
### Agent Synchronisation de template (Accountable)
|
||||||
|
**Références**
|
||||||
|
- `.4nk-sync.yml` (manifeste), `TEMPLATE_VERSION` (pointeur), `.gitea/workflows/template-sync.yml` (CI dédiée).
|
||||||
|
- Règles Cursor : `.cursor/rules/42-template-sync.mdc` et `.cursor/rules/10-project-structure.mdc`.
|
||||||
|
|
||||||
|
**Missions**
|
||||||
|
- Assurer l’alignement automatique sur le template pour : `.cursor/**`, `.gitea/**`, `AGENTS.md`, `scripts/**`, `docs/SSH_UPDATE.md`.
|
||||||
|
- Déclencher/valider la PR `[template-sync]` créée par la CI.
|
||||||
|
- Exiger la mise à jour de `CHANGELOG.md` et `docs/INDEX.md` après synchronisation.
|
||||||
|
- Vérifier l’intégrité (`manifest_checksum`, checksums de fichiers si publiés), les permissions, l’absence de secrets.
|
||||||
|
- Mettre à jour `TEMPLATE_VERSION` dans la PR.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `.4nk-sync.yml`, `TEMPLATE_VERSION`, `.cursor/**`, `.gitea/**`, `AGENTS.md`, `scripts/**`, `docs/SSH_UPDATE.md`, `CHANGELOG.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Agent Dérogations locales (Responsable)
|
||||||
|
**Références**
|
||||||
|
- `LOCAL_OVERRIDES.yml` (facultatif, mais recommandé).
|
||||||
|
|
||||||
|
**Missions**
|
||||||
|
- Enregistrer toute divergence locale dans le périmètre synchronisé (path, raison, propriétaire, échéance).
|
||||||
|
- Faire respecter : seules les dérogations listées et non expirées sont tolérées par la CI.
|
||||||
|
- Auditer périodiquement et résorber les dérogations.
|
||||||
|
|
||||||
|
**Artefacts**
|
||||||
|
- `LOCAL_OVERRIDES.yml`, `CHANGELOG.md` (mentionner les dérogations significatives).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matrice de coordination
|
||||||
|
|
||||||
|
| Type de changement | Agents impliqués | Artefacts principaux | Validation obligatoire |
|
||||||
|
|----------------------------------|----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------|
|
||||||
|
| Ajout de fonctionnalité | Documentation, Tests, Dépendances, Frontend | `docs/API.md`, `docs/USAGE.md`, `docs/ARCHITECTURE.md`, `tests/unit`, `tests/integration`, `CHANGELOG.md` (*Added*) | Oui |
|
||||||
|
| Correction de bug | Résolution, Tests, Documentation | `tests/unit`, `docs/TESTING.md`, `archive/` (REX si nécessaire), `CHANGELOG.md` (*Fixed*) | Oui |
|
||||||
|
| Refactorisation / amélioration | Structure, Documentation, Compilation | `docs/ARCHITECTURE.md`, `archive/`, `CHANGELOG.md` (*Changed*) | Oui |
|
||||||
|
| Dépendance ajoutée/mise à jour | Dépendances, Compilation, Documentation | `docs/ARCHITECTURE.md`, `docs/CONFIGURATION.md`, `CHANGELOG.md` (*Dependencies*) | Oui |
|
||||||
|
| Données CSV modifiées | Données CSV, Documentation, Tests | `docs/API.md`, `docs/ARCHITECTURE.md`, `docs/USAGE.md`, `tests/unit`, `CHANGELOG.md` (*Data model update*) | Oui |
|
||||||
|
| Migration / breaking change | Documentation, Tests, Résolution, Versionnage | `docs/MIGRATION.md`, `docs/INSTALLATION.md`, `docs/RELEASE_PLAN.md`, `docs/ROADMAP.md`, `tests/integration`, `CHANGELOG.md` (*Breaking*) | Oui |
|
||||||
|
| Sécurité / audit | Documentation, Tests, Open Source, Sécurité proactive | `docs/SECURITY_AUDIT.md`, `tests/external`, `tests/connectivity`, `CHANGELOG.md` (*Security*) | Oui |
|
||||||
|
| Préparation open source / CI | Open Source, Gitea, Versionnage, Documentation communautaire, Contributeurs externes | `.gitea/**`, `docs/GITEA_SETUP.md`, `docs/OPEN_SOURCE_CHECKLIST.md`, `CHANGELOG.md` (*CI/CD* / *Governance*) | Oui |
|
||||||
|
| Optimisation performance | Performance, Tests, Documentation | `tests/performance`, `tests/reports`, `docs/ARCHITECTURE.md`, `CHANGELOG.md` (*Performance*) | Oui |
|
||||||
|
| Évolution frontend | Frontend, Documentation, Tests | `docs/ARCHITECTURE.md`, `docs/USAGE.md`, `tests/integration`, `CHANGELOG.md` (*Frontend*) | Oui |
|
||||||
|
| Évolution CI/CD ou scripts SSH | SSH & scripts, Gitea, Versionnage, Documentation | `scripts/**`, `.gitea/workflows/ci.yml`, `docs/SSH_UPDATE.md`, `docs/CONFIGURATION.md`, `CHANGELOG.md` (*CI/CD*) | Oui |
|
||||||
|
| **Synchronisation de template** | **Synchronisation de template**, Gitea, Versionnage, Structure, Documentation, SSH & scripts | `.4nk-sync.yml`, `TEMPLATE_VERSION`, `.cursor/**`, `.gitea/**`, `AGENTS.md`, `scripts/**`, `docs/SSH_UPDATE.md`, `CHANGELOG.md` | **Oui** |
|
||||||
|
| Dérogation locale contrôlée | Dérogations locales, Gitea, Synchronisation de template, Versionnage | `LOCAL_OVERRIDES.yml`, `CHANGELOG.md` (mention), CI tolérante uniquement sur chemins listés et non expirés | Oui |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
Ce `AGENTS.md` mis à jour introduit l’**Agent Synchronisation de template** et l’**Agent Dérogations locales**, renforce l’**Agent SSH & scripts**, et rattache l’ensemble aux règles Cursor et à la CI Gitea. La matrice de coordination formalise les validations obligatoires pour chaque type de changement, garantissant cohérence structurelle, qualité documentaire, sécurité, traçabilité et stabilité à long terme sur tous les projets issus de `4NK_project_template`.
|
14
CHANGELOG.md
Normal file
14
CHANGELOG.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Changelog - sdk_wallet
|
||||||
|
|
||||||
|
Ce projet suit le format Keep a Changelog et le Semantic Versioning.
|
||||||
|
|
||||||
|
## [0.1.0] - 2025-08-27
|
||||||
|
### Added
|
||||||
|
- Squelette React Native (Redux, React.lazy/Suspense)
|
||||||
|
- Pont WebView ↔ ihm_client via postMessage
|
||||||
|
- Scripts PowerShell: build-ihm, copy-ihm, sync:ihm
|
||||||
|
- TypeScript, Jest (jsdom), config TS/Jest
|
||||||
|
- Écran `WalletScreen` et composant `WebWallet`
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
- Chargement local des assets d’`ihm_client` prévu via `assets/ihm/`
|
10
CODE_OF_CONDUCT.md
Normal file
10
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Code de Conduite
|
||||||
|
|
||||||
|
Nous nous engageons à fournir un environnement ouvert et accueillant. Soyez respectueux, constructif et professionnel. Tout comportement abusif, discriminatoire ou harcelant n’est pas toléré.
|
||||||
|
|
||||||
|
- Agissez de bonne foi, assumez des intentions positives
|
||||||
|
- Pas de harcèlement, d’intimidation ou de propos discriminatoires
|
||||||
|
- Respectez la confidentialité et la sécurité
|
||||||
|
- Utilisez des canaux appropriés pour signaler des incidents
|
||||||
|
|
||||||
|
Contact: contact@4nkweb.com
|
23
CONTRIBUTING.md
Normal file
23
CONTRIBUTING.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Contribuer à sdk_wallet
|
||||||
|
|
||||||
|
Merci de votre intérêt !
|
||||||
|
|
||||||
|
## Démarrage
|
||||||
|
- Node 18+ / 20+, pnpm ou npm
|
||||||
|
- `npm install`
|
||||||
|
- `npm run typecheck && npm test`
|
||||||
|
|
||||||
|
## Branches et commits
|
||||||
|
- Feature branches: `feat/<scope>`
|
||||||
|
- Fixes: `fix/<scope>`
|
||||||
|
- Commits conventionnels (conventional commits)
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
- Ajoutez des tests dans `tests/`
|
||||||
|
- Isolez l’état et les ressources, pas d’effets globaux
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Mettez à jour `docs/` et `CHANGELOG.md` pour chaque changement utilisateur
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
- MIT
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 4NK
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
27
docs/ARCHITECTURE.md
Normal file
27
docs/ARCHITECTURE.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Architecture - sdk_wallet
|
||||||
|
|
||||||
|
## Vue d’ensemble
|
||||||
|
- Application mobile React Native
|
||||||
|
- État centralisé avec Redux Toolkit
|
||||||
|
- UI Web intégrée via `react-native-webview` qui charge `ihm_client` (build Vite)
|
||||||
|
- Pont de messages `window.postMessage` redirigé vers `ReactNativeWebView.postMessage`
|
||||||
|
|
||||||
|
## Flux
|
||||||
|
1. L’app charge `assets/ihm/index.html` (build de `ihm_client`)
|
||||||
|
2. Le script injecté remappe `window.postMessage` et expose `window.__RN_RECEIVE__`
|
||||||
|
3. `ihm_client` émet `LISTENING`, `LINK_ACCEPTED`, etc. → captés côté RN
|
||||||
|
4. RN met à jour Redux (tokens, état), puis peut envoyer des messages: `REQUEST_LINK`, `VALIDATE_TOKEN`, etc.
|
||||||
|
|
||||||
|
## Découpage
|
||||||
|
- `src/bridge/` : sérialisation et gestion des messages
|
||||||
|
- `src/components/` : `WebWallet` (WebView)
|
||||||
|
- `src/screens/` : `WalletScreen`
|
||||||
|
- `src/store/` : état (tokens, dernier message)
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
- Respect de l’origine dans `ihm_client` (réponses vers `event.origin`)
|
||||||
|
- Les tokens ne sortent pas du store sans action explicite
|
||||||
|
|
||||||
|
## Performances
|
||||||
|
- Code splitting avec `React.lazy`/`Suspense`
|
||||||
|
- Build `ihm_client` optimisé via Vite
|
6
docs/INDEX.md
Normal file
6
docs/INDEX.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Documentation - sdk_wallet
|
||||||
|
|
||||||
|
- Architecture: `ARCHITECTURE.md`
|
||||||
|
- Intégration iframe/WebView: `INTEGRATION.md`
|
||||||
|
- Tests: `TESTING.md`
|
||||||
|
- Notes de version: `../CHANGELOG.md`
|
20
docs/INTEGRATION.md
Normal file
20
docs/INTEGRATION.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Intégration WebView ↔ ihm_client
|
||||||
|
|
||||||
|
## Principes
|
||||||
|
- `ihm_client` parle via `window.postMessage` (cf. `ihm_client/docs/INTEGRATION_IFRAME.md`)
|
||||||
|
- En mobile, on charge `ihm_client` dans une WebView
|
||||||
|
- On redirige `window.postMessage` vers `ReactNativeWebView.postMessage`
|
||||||
|
- Canal entrant: RN appelle `window.__RN_RECEIVE__(jsonString)` pour simuler un `MessageEvent`
|
||||||
|
|
||||||
|
## Messages pris en charge (extraits)
|
||||||
|
- REQUEST_LINK → LINK_ACCEPTED|ERROR
|
||||||
|
- VALIDATE_TOKEN → VALIDATE_TOKEN
|
||||||
|
- RENEW_TOKEN → RENEW_TOKEN
|
||||||
|
|
||||||
|
## Mapping côté RN
|
||||||
|
- Sortant: RN → `__RN_RECEIVE__(jsonString)` (déclenche un `message` côté page)
|
||||||
|
- Entrant: page → `postMessage(any)` redirigé vers RN `onMessage`
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
- `ihm_client` valide l’origine et les tokens
|
||||||
|
- RN ne manipule pas directement les tokens côté page
|
12
docs/TESTING.md
Normal file
12
docs/TESTING.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Tests - sdk_wallet
|
||||||
|
|
||||||
|
## Portée
|
||||||
|
- Bridge: sérialisation, réception des messages, mise à jour Redux
|
||||||
|
- Store: reducers `setTokens`, `setLastMessageType`
|
||||||
|
|
||||||
|
## Commandes
|
||||||
|
- `npm test` (Jest + ts-jest, jsdom)
|
||||||
|
|
||||||
|
## Isolation
|
||||||
|
- Pas d’accès réseau
|
||||||
|
- Pas d’exemples exécutables; tests en mémoire
|
6758
ihm/account-component-DbdHSqFJ.mjs
Normal file
6758
ihm/account-component-DbdHSqFJ.mjs
Normal file
File diff suppressed because one or more lines are too long
BIN
ihm/assets/4nk_image.png
Normal file
BIN
ihm/assets/4nk_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
BIN
ihm/assets/4nk_revoke.jpg
Normal file
BIN
ihm/assets/4nk_revoke.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
BIN
ihm/assets/bgd.webp
Normal file
BIN
ihm/assets/bgd.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 509 KiB |
BIN
ihm/assets/camera.jpg
Normal file
BIN
ihm/assets/camera.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
34
ihm/assets/home.js
Normal file
34
ihm/assets/home.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
BIN
ihm/assets/qr_code.png
Normal file
BIN
ihm/assets/qr_code.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
BIN
ihm/bgd-I4_In7H5.webp
Normal file
BIN
ihm/bgd-I4_In7H5.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 509 KiB |
877
ihm/index--72nVAQK.css
Normal file
877
ihm/index--72nVAQK.css
Normal file
@ -0,0 +1,877 @@
|
|||||||
|
: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(/bgd-I4_In7H5.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%;
|
||||||
|
}
|
11827
ihm/index-CZvdFchg.mjs
Normal file
11827
ihm/index-CZvdFchg.mjs
Normal file
File diff suppressed because one or more lines are too long
1
ihm/index.html
Normal file
1
ihm/index.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<!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"><link rel="stylesheet" href="/style/4nk.css"><script src="https://unpkg.com/html5-qrcode"></script><title>4NK Application</title><script type="module" crossorigin src="/index-CZvdFchg.mjs"></script><link rel="stylesheet" crossorigin href="/index--72nVAQK.css"></head><body><div id="header-container"></div><div id="containerId" class="container"></div></body></html>
|
100
ihm/qr-scanner-worker.min-Dy0qkKA4.mjs
Normal file
100
ihm/qr-scanner-worker.min-Dy0qkKA4.mjs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
const createWorker=()=>new Worker(URL.createObjectURL(new Blob([`class x{constructor(a,b){this.width=b;this.height=a.length/b;this.data=a}static createEmpty(a,b){return new x(new Uint8ClampedArray(a*b),a)}get(a,b){return 0>a||a>=this.width||0>b||b>=this.height?!1:!!this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c?1:0}setRegion(a,b,c,d,e){for(let f=b;f<b+d;f++)for(let g=a;g<a+c;g++)this.set(g,f,!!e)}}
|
||||||
|
class A{constructor(a,b,c){this.width=a;a*=b;if(c&&c.length!==a)throw Error("Wrong buffer size");this.data=c||new Uint8ClampedArray(a)}get(a,b){return this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c}}
|
||||||
|
class ba{constructor(a){this.bitOffset=this.byteOffset=0;this.bytes=a}readBits(a){if(1>a||32<a||a>this.available())throw Error("Cannot read "+a.toString()+" bits");var b=0;if(0<this.bitOffset){b=8-this.bitOffset;var c=a<b?a:b;b-=c;b=(this.bytes[this.byteOffset]&255>>8-c<<b)>>b;a-=c;this.bitOffset+=c;8===this.bitOffset&&(this.bitOffset=0,this.byteOffset++)}if(0<a){for(;8<=a;)b=b<<8|this.bytes[this.byteOffset]&255,this.byteOffset++,a-=8;0<a&&(c=8-a,b=b<<a|(this.bytes[this.byteOffset]&255>>c<<c)>>c,
|
||||||
|
this.bitOffset+=a)}return b}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var B,C=B||(B={});C.Numeric="numeric";C.Alphanumeric="alphanumeric";C.Byte="byte";C.Kanji="kanji";C.ECI="eci";C.StructuredAppend="structuredappend";var D,E=D||(D={});E[E.Terminator=0]="Terminator";E[E.Numeric=1]="Numeric";E[E.Alphanumeric=2]="Alphanumeric";E[E.Byte=4]="Byte";E[E.Kanji=8]="Kanji";E[E.ECI=7]="ECI";E[E.StructuredAppend=3]="StructuredAppend";let F="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split("");
|
||||||
|
function ca(a,b){let c=[],d="";b=a.readBits([8,16,16][b]);for(let e=0;e<b;e++){let f=a.readBits(8);c.push(f)}try{d+=decodeURIComponent(c.map(e=>\`%\${("0"+e.toString(16)).substr(-2)}\`).join(""))}catch(e){}return{bytes:c,text:d}}
|
||||||
|
function da(a,b){a=new ba(a);let c=9>=b?0:26>=b?1:2;for(b={text:"",bytes:[],chunks:[],version:b};4<=a.available();){var d=a.readBits(4);if(d===D.Terminator)return b;if(d===D.ECI)0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(7)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(14)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(21)}):b.chunks.push({type:B.ECI,assignmentNumber:-1});else if(d===D.Numeric){var e=a,f=[];d="";for(var g=
|
||||||
|
e.readBits([10,12,14][c]);3<=g;){var h=e.readBits(10);if(1E3<=h)throw Error("Invalid numeric value above 999");var k=Math.floor(h/100),m=Math.floor(h/10)%10;h%=10;f.push(48+k,48+m,48+h);d+=k.toString()+m.toString()+h.toString();g-=3}if(2===g){g=e.readBits(7);if(100<=g)throw Error("Invalid numeric value above 99");e=Math.floor(g/10);g%=10;f.push(48+e,48+g);d+=e.toString()+g.toString()}else if(1===g){e=e.readBits(4);if(10<=e)throw Error("Invalid numeric value above 9");f.push(48+e);d+=e.toString()}b.text+=
|
||||||
|
d;b.bytes.push(...f);b.chunks.push({type:B.Numeric,text:d})}else if(d===D.Alphanumeric){e=a;f=[];d="";for(g=e.readBits([9,11,13][c]);2<=g;)m=e.readBits(11),k=Math.floor(m/45),m%=45,f.push(F[k].charCodeAt(0),F[m].charCodeAt(0)),d+=F[k]+F[m],g-=2;1===g&&(e=e.readBits(6),f.push(F[e].charCodeAt(0)),d+=F[e]);b.text+=d;b.bytes.push(...f);b.chunks.push({type:B.Alphanumeric,text:d})}else if(d===D.Byte)d=ca(a,c),b.text+=d.text,b.bytes.push(...d.bytes),b.chunks.push({type:B.Byte,bytes:d.bytes,text:d.text});
|
||||||
|
else if(d===D.Kanji){f=a;d=[];e=f.readBits([8,10,12][c]);for(g=0;g<e;g++)k=f.readBits(13),k=Math.floor(k/192)<<8|k%192,k=7936>k?k+33088:k+49472,d.push(k>>8,k&255);f=(new TextDecoder("shift-jis")).decode(Uint8Array.from(d));b.text+=f;b.bytes.push(...d);b.chunks.push({type:B.Kanji,bytes:d,text:f})}else d===D.StructuredAppend&&b.chunks.push({type:B.StructuredAppend,currentSequence:a.readBits(4),totalSequence:a.readBits(4),parity:a.readBits(8)})}if(0===a.available()||0===a.readBits(a.available()))return b}
|
||||||
|
class G{constructor(a,b){if(0===b.length)throw Error("No coefficients.");this.field=a;let c=b.length;if(1<c&&0===b[0]){let d=1;for(;d<c&&0===b[d];)d++;if(d===c)this.coefficients=a.zero.coefficients;else for(this.coefficients=new Uint8ClampedArray(c-d),a=0;a<this.coefficients.length;a++)this.coefficients[a]=b[d+a]}else this.coefficients=b}degree(){return this.coefficients.length-1}isZero(){return 0===this.coefficients[0]}getCoefficient(a){return this.coefficients[this.coefficients.length-1-a]}addOrSubtract(a){if(this.isZero())return a;
|
||||||
|
if(a.isZero())return this;let b=this.coefficients;a=a.coefficients;b.length>a.length&&([b,a]=[a,b]);let c=new Uint8ClampedArray(a.length),d=a.length-b.length;for(var e=0;e<d;e++)c[e]=a[e];for(e=d;e<a.length;e++)c[e]=b[e-d]^a[e];return new G(this.field,c)}multiply(a){if(0===a)return this.field.zero;if(1===a)return this;let b=this.coefficients.length,c=new Uint8ClampedArray(b);for(let d=0;d<b;d++)c[d]=this.field.multiply(this.coefficients[d],a);return new G(this.field,c)}multiplyPoly(a){if(this.isZero()||
|
||||||
|
a.isZero())return this.field.zero;let b=this.coefficients,c=b.length;a=a.coefficients;let d=a.length,e=new Uint8ClampedArray(c+d-1);for(let f=0;f<c;f++){let g=b[f];for(let h=0;h<d;h++)e[f+h]=H(e[f+h],this.field.multiply(g,a[h]))}return new G(this.field,e)}multiplyByMonomial(a,b){if(0>a)throw Error("Invalid degree less than 0");if(0===b)return this.field.zero;let c=this.coefficients.length;a=new Uint8ClampedArray(c+a);for(let d=0;d<c;d++)a[d]=this.field.multiply(this.coefficients[d],b);return new G(this.field,
|
||||||
|
a)}evaluateAt(a){let b=0;if(0===a)return this.getCoefficient(0);let c=this.coefficients.length;if(1===a)return this.coefficients.forEach(d=>{b^=d}),b;b=this.coefficients[0];for(let d=1;d<c;d++)b=H(this.field.multiply(a,b),this.coefficients[d]);return b}}function H(a,b){return a^b}
|
||||||
|
class ea{constructor(a,b,c){this.primitive=a;this.size=b;this.generatorBase=c;this.expTable=Array(this.size);this.logTable=Array(this.size);a=1;for(b=0;b<this.size;b++)this.expTable[b]=a,a*=2,a>=this.size&&(a=(a^this.primitive)&this.size-1);for(a=0;a<this.size-1;a++)this.logTable[this.expTable[a]]=a;this.zero=new G(this,Uint8ClampedArray.from([0]));this.one=new G(this,Uint8ClampedArray.from([1]))}multiply(a,b){return 0===a||0===b?0:this.expTable[(this.logTable[a]+this.logTable[b])%(this.size-1)]}inverse(a){if(0===
|
||||||
|
a)throw Error("Can't invert 0");return this.expTable[this.size-this.logTable[a]-1]}buildMonomial(a,b){if(0>a)throw Error("Invalid monomial degree less than 0");if(0===b)return this.zero;a=new Uint8ClampedArray(a+1);a[0]=b;return new G(this,a)}log(a){if(0===a)throw Error("Can't take log(0)");return this.logTable[a]}exp(a){return this.expTable[a]}}
|
||||||
|
function fa(a,b,c,d){b.degree()<c.degree()&&([b,c]=[c,b]);let e=a.zero;for(var f=a.one;c.degree()>=d/2;){var g=b;let h=e;b=c;e=f;if(b.isZero())return null;c=g;f=a.zero;g=b.getCoefficient(b.degree());for(g=a.inverse(g);c.degree()>=b.degree()&&!c.isZero();){let k=c.degree()-b.degree(),m=a.multiply(c.getCoefficient(c.degree()),g);f=f.addOrSubtract(a.buildMonomial(k,m));c=c.addOrSubtract(b.multiplyByMonomial(k,m))}f=f.multiplyPoly(e).addOrSubtract(h);if(c.degree()>=b.degree())return null}d=f.getCoefficient(0);
|
||||||
|
if(0===d)return null;a=a.inverse(d);return[f.multiply(a),c.multiply(a)]}
|
||||||
|
function ha(a,b){let c=new Uint8ClampedArray(a.length);c.set(a);a=new ea(285,256,0);var d=new G(a,c),e=new Uint8ClampedArray(b),f=!1;for(var g=0;g<b;g++){var h=d.evaluateAt(a.exp(g+a.generatorBase));e[e.length-1-g]=h;0!==h&&(f=!0)}if(!f)return c;d=new G(a,e);d=fa(a,a.buildMonomial(b,1),d,b);if(null===d)return null;b=d[0];g=b.degree();if(1===g)b=[b.getCoefficient(1)];else{e=Array(g);f=0;for(h=1;h<a.size&&f<g;h++)0===b.evaluateAt(h)&&(e[f]=a.inverse(h),f++);b=f!==g?null:e}if(null==b)return null;e=d[1];
|
||||||
|
f=b.length;d=Array(f);for(g=0;g<f;g++){h=a.inverse(b[g]);let k=1;for(let m=0;m<f;m++)g!==m&&(k=a.multiply(k,H(1,a.multiply(b[m],h))));d[g]=a.multiply(e.evaluateAt(h),a.inverse(k));0!==a.generatorBase&&(d[g]=a.multiply(d[g],h))}for(e=0;e<b.length;e++){f=c.length-1-a.log(b[e]);if(0>f)return null;c[f]^=d[e]}return c}
|
||||||
|
let I=[{infoBits:null,versionNumber:1,alignmentPatternCenters:[],errorCorrectionLevels:[{ecCodewordsPerBlock:7,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:13,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:13}]},{ecCodewordsPerBlock:17,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:9}]}]},{infoBits:null,versionNumber:2,alignmentPatternCenters:[6,18],errorCorrectionLevels:[{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1,
|
||||||
|
dataCodewordsPerBlock:34}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:28}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]}]},{infoBits:null,versionNumber:3,alignmentPatternCenters:[6,22],errorCorrectionLevels:[{ecCodewordsPerBlock:15,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:55}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:18,
|
||||||
|
ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:13}]}]},{infoBits:null,versionNumber:4,alignmentPatternCenters:[6,26],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:80}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:32}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:9}]}]},
|
||||||
|
{infoBits:null,versionNumber:5,alignmentPatternCenters:[6,30],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:43}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:11},{numBlocks:2,dataCodewordsPerBlock:12}]}]},{infoBits:null,versionNumber:6,alignmentPatternCenters:[6,
|
||||||
|
34],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:27}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:31892,versionNumber:7,alignmentPatternCenters:[6,22,38],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:78}]},{ecCodewordsPerBlock:18,
|
||||||
|
ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:31}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:13},{numBlocks:1,dataCodewordsPerBlock:14}]}]},{infoBits:34236,versionNumber:8,alignmentPatternCenters:[6,24,42],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:97}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:38},
|
||||||
|
{numBlocks:2,dataCodewordsPerBlock:39}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:18},{numBlocks:2,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:14},{numBlocks:2,dataCodewordsPerBlock:15}]}]},{infoBits:39577,versionNumber:9,alignmentPatternCenters:[6,26,46],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:36},
|
||||||
|
{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:12},{numBlocks:4,dataCodewordsPerBlock:13}]}]},{infoBits:42195,versionNumber:10,alignmentPatternCenters:[6,28,50],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68},{numBlocks:2,dataCodewordsPerBlock:69}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,
|
||||||
|
dataCodewordsPerBlock:43},{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]}]},{infoBits:48118,versionNumber:11,alignmentPatternCenters:[6,30,54],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:81}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1,
|
||||||
|
dataCodewordsPerBlock:50},{numBlocks:4,dataCodewordsPerBlock:51}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:22},{numBlocks:4,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:12},{numBlocks:8,dataCodewordsPerBlock:13}]}]},{infoBits:51042,versionNumber:12,alignmentPatternCenters:[6,32,58],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:92},{numBlocks:2,dataCodewordsPerBlock:93}]},
|
||||||
|
{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:36},{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:20},{numBlocks:6,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:55367,versionNumber:13,alignmentPatternCenters:[6,34,62],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:107}]},
|
||||||
|
{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:37},{numBlocks:1,dataCodewordsPerBlock:38}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:20},{numBlocks:4,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:11},{numBlocks:4,dataCodewordsPerBlock:12}]}]},{infoBits:58893,versionNumber:14,alignmentPatternCenters:[6,26,46,66],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:115},
|
||||||
|
{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:40},{numBlocks:5,dataCodewordsPerBlock:41}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:16},{numBlocks:5,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:5,dataCodewordsPerBlock:13}]}]},{infoBits:63784,versionNumber:15,alignmentPatternCenters:[6,26,48,70],errorCorrectionLevels:[{ecCodewordsPerBlock:22,
|
||||||
|
ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:87},{numBlocks:1,dataCodewordsPerBlock:88}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:41},{numBlocks:5,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:7,dataCodewordsPerBlock:13}]}]},{infoBits:68472,versionNumber:16,alignmentPatternCenters:[6,26,50,
|
||||||
|
74],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:98},{numBlocks:1,dataCodewordsPerBlock:99}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:70749,
|
||||||
|
versionNumber:17,alignmentPatternCenters:[6,30,54,78],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:1,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22},{numBlocks:15,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:17,
|
||||||
|
dataCodewordsPerBlock:15}]}]},{infoBits:76311,versionNumber:18,alignmentPatternCenters:[6,30,56,82],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:120},{numBlocks:1,dataCodewordsPerBlock:121}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:43},{numBlocks:4,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22},{numBlocks:1,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,
|
||||||
|
dataCodewordsPerBlock:14},{numBlocks:19,dataCodewordsPerBlock:15}]}]},{infoBits:79154,versionNumber:19,alignmentPatternCenters:[6,30,58,86],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:113},{numBlocks:4,dataCodewordsPerBlock:114}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:44},{numBlocks:11,dataCodewordsPerBlock:45}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:21},{numBlocks:4,dataCodewordsPerBlock:22}]},
|
||||||
|
{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:13},{numBlocks:16,dataCodewordsPerBlock:14}]}]},{infoBits:84390,versionNumber:20,alignmentPatternCenters:[6,34,62,90],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:41},{numBlocks:13,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24},
|
||||||
|
{numBlocks:5,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:15},{numBlocks:10,dataCodewordsPerBlock:16}]}]},{infoBits:87683,versionNumber:21,alignmentPatternCenters:[6,28,50,72,94],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:116},{numBlocks:4,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22},
|
||||||
|
{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:16},{numBlocks:6,dataCodewordsPerBlock:17}]}]},{infoBits:92361,versionNumber:22,alignmentPatternCenters:[6,26,50,74,98],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:111},{numBlocks:7,dataCodewordsPerBlock:112}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24},
|
||||||
|
{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:13}]}]},{infoBits:96236,versionNumber:23,alignmentPatternCenters:[6,30,54,74,102],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:121},{numBlocks:5,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:47},{numBlocks:14,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24},
|
||||||
|
{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:16,dataCodewordsPerBlock:15},{numBlocks:14,dataCodewordsPerBlock:16}]}]},{infoBits:102084,versionNumber:24,alignmentPatternCenters:[6,28,54,80,106],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:45},{numBlocks:14,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,
|
||||||
|
ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24},{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:30,dataCodewordsPerBlock:16},{numBlocks:2,dataCodewordsPerBlock:17}]}]},{infoBits:102881,versionNumber:25,alignmentPatternCenters:[6,32,58,84,110],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:106},{numBlocks:4,dataCodewordsPerBlock:107}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:47},{numBlocks:13,
|
||||||
|
dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:110507,versionNumber:26,alignmentPatternCenters:[6,30,58,86,114],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:114},{numBlocks:2,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19,
|
||||||
|
dataCodewordsPerBlock:46},{numBlocks:4,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:28,dataCodewordsPerBlock:22},{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:33,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]}]},{infoBits:110734,versionNumber:27,alignmentPatternCenters:[6,34,62,90,118],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]},
|
||||||
|
{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:23},{numBlocks:26,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:15},{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:117786,versionNumber:28,alignmentPatternCenters:[6,26,50,74,98,122],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:117},
|
||||||
|
{numBlocks:10,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:45},{numBlocks:23,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:24},{numBlocks:31,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:31,dataCodewordsPerBlock:16}]}]},{infoBits:119615,versionNumber:29,alignmentPatternCenters:[6,30,54,78,102,126],errorCorrectionLevels:[{ecCodewordsPerBlock:30,
|
||||||
|
ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:116},{numBlocks:7,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:21,dataCodewordsPerBlock:45},{numBlocks:7,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:23},{numBlocks:37,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:15},{numBlocks:26,dataCodewordsPerBlock:16}]}]},{infoBits:126325,versionNumber:30,alignmentPatternCenters:[6,
|
||||||
|
26,52,78,104,130],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:115},{numBlocks:10,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:47},{numBlocks:10,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24},{numBlocks:25,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15},{numBlocks:25,dataCodewordsPerBlock:16}]}]},
|
||||||
|
{infoBits:127568,versionNumber:31,alignmentPatternCenters:[6,30,56,82,108,134],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:3,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:46},{numBlocks:29,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:24},{numBlocks:1,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15},
|
||||||
|
{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:133589,versionNumber:32,alignmentPatternCenters:[6,34,60,86,112,138],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:24},{numBlocks:35,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,
|
||||||
|
dataCodewordsPerBlock:15},{numBlocks:35,dataCodewordsPerBlock:16}]}]},{infoBits:136944,versionNumber:33,alignmentPatternCenters:[6,30,58,86,114,142],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115},{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:21,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:24},{numBlocks:19,dataCodewordsPerBlock:25}]},
|
||||||
|
{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:141498,versionNumber:34,alignmentPatternCenters:[6,34,62,90,118,146],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:6,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:44,
|
||||||
|
dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:59,dataCodewordsPerBlock:16},{numBlocks:1,dataCodewordsPerBlock:17}]}]},{infoBits:145311,versionNumber:35,alignmentPatternCenters:[6,30,54,78,102,126,150],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:121},{numBlocks:7,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:47},{numBlocks:26,dataCodewordsPerBlock:48}]},
|
||||||
|
{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:39,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:41,dataCodewordsPerBlock:16}]}]},{infoBits:150283,versionNumber:36,alignmentPatternCenters:[6,24,50,76,102,128,154],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:121},{numBlocks:14,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,
|
||||||
|
dataCodewordsPerBlock:47},{numBlocks:34,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:46,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:64,dataCodewordsPerBlock:16}]}]},{infoBits:152622,versionNumber:37,alignmentPatternCenters:[6,28,54,80,106,132,158],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]},
|
||||||
|
{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:46},{numBlocks:14,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:49,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:24,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:158308,versionNumber:38,alignmentPatternCenters:[6,32,58,84,110,136,162],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,
|
||||||
|
dataCodewordsPerBlock:122},{numBlocks:18,dataCodewordsPerBlock:123}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:46},{numBlocks:32,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:48,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:15},{numBlocks:32,dataCodewordsPerBlock:16}]}]},{infoBits:161089,versionNumber:39,alignmentPatternCenters:[6,26,54,82,110,138,166],
|
||||||
|
errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:40,dataCodewordsPerBlock:47},{numBlocks:7,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:43,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:15},{numBlocks:67,dataCodewordsPerBlock:16}]}]},{infoBits:167017,
|
||||||
|
versionNumber:40,alignmentPatternCenters:[6,30,58,86,114,142,170],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:118},{numBlocks:6,dataCodewordsPerBlock:119}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:18,dataCodewordsPerBlock:47},{numBlocks:31,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:24},{numBlocks:34,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:15},
|
||||||
|
{numBlocks:61,dataCodewordsPerBlock:16}]}]}];function J(a,b){a^=b;for(b=0;a;)b++,a&=a-1;return b}function K(a,b){return b<<1|a}
|
||||||
|
let ia=[{bits:21522,formatInfo:{errorCorrectionLevel:1,dataMask:0}},{bits:20773,formatInfo:{errorCorrectionLevel:1,dataMask:1}},{bits:24188,formatInfo:{errorCorrectionLevel:1,dataMask:2}},{bits:23371,formatInfo:{errorCorrectionLevel:1,dataMask:3}},{bits:17913,formatInfo:{errorCorrectionLevel:1,dataMask:4}},{bits:16590,formatInfo:{errorCorrectionLevel:1,dataMask:5}},{bits:20375,formatInfo:{errorCorrectionLevel:1,dataMask:6}},{bits:19104,formatInfo:{errorCorrectionLevel:1,dataMask:7}},{bits:30660,formatInfo:{errorCorrectionLevel:0,
|
||||||
|
dataMask:0}},{bits:29427,formatInfo:{errorCorrectionLevel:0,dataMask:1}},{bits:32170,formatInfo:{errorCorrectionLevel:0,dataMask:2}},{bits:30877,formatInfo:{errorCorrectionLevel:0,dataMask:3}},{bits:26159,formatInfo:{errorCorrectionLevel:0,dataMask:4}},{bits:25368,formatInfo:{errorCorrectionLevel:0,dataMask:5}},{bits:27713,formatInfo:{errorCorrectionLevel:0,dataMask:6}},{bits:26998,formatInfo:{errorCorrectionLevel:0,dataMask:7}},{bits:5769,formatInfo:{errorCorrectionLevel:3,dataMask:0}},{bits:5054,
|
||||||
|
formatInfo:{errorCorrectionLevel:3,dataMask:1}},{bits:7399,formatInfo:{errorCorrectionLevel:3,dataMask:2}},{bits:6608,formatInfo:{errorCorrectionLevel:3,dataMask:3}},{bits:1890,formatInfo:{errorCorrectionLevel:3,dataMask:4}},{bits:597,formatInfo:{errorCorrectionLevel:3,dataMask:5}},{bits:3340,formatInfo:{errorCorrectionLevel:3,dataMask:6}},{bits:2107,formatInfo:{errorCorrectionLevel:3,dataMask:7}},{bits:13663,formatInfo:{errorCorrectionLevel:2,dataMask:0}},{bits:12392,formatInfo:{errorCorrectionLevel:2,
|
||||||
|
dataMask:1}},{bits:16177,formatInfo:{errorCorrectionLevel:2,dataMask:2}},{bits:14854,formatInfo:{errorCorrectionLevel:2,dataMask:3}},{bits:9396,formatInfo:{errorCorrectionLevel:2,dataMask:4}},{bits:8579,formatInfo:{errorCorrectionLevel:2,dataMask:5}},{bits:11994,formatInfo:{errorCorrectionLevel:2,dataMask:6}},{bits:11245,formatInfo:{errorCorrectionLevel:2,dataMask:7}}],ja=[a=>0===(a.y+a.x)%2,a=>0===a.y%2,a=>0===a.x%3,a=>0===(a.y+a.x)%3,a=>0===(Math.floor(a.y/2)+Math.floor(a.x/3))%2,a=>0===a.x*a.y%
|
||||||
|
2+a.x*a.y%3,a=>0===(a.y*a.x%2+a.y*a.x%3)%2,a=>0===((a.y+a.x)%2+a.y*a.x%3)%2];
|
||||||
|
function ka(a,b,c){c=ja[c.dataMask];let d=a.height;var e=17+4*b.versionNumber;let f=x.createEmpty(e,e);f.setRegion(0,0,9,9,!0);f.setRegion(e-8,0,8,9,!0);f.setRegion(0,e-8,9,8,!0);for(var g of b.alignmentPatternCenters)for(var h of b.alignmentPatternCenters)6===g&&6===h||6===g&&h===e-7||g===e-7&&6===h||f.setRegion(g-2,h-2,5,5,!0);f.setRegion(6,9,1,e-17,!0);f.setRegion(9,6,e-17,1,!0);6<b.versionNumber&&(f.setRegion(e-11,0,3,6,!0),f.setRegion(0,e-11,6,3,!0));b=[];h=g=0;e=!0;for(let k=d-1;0<k;k-=2){6===
|
||||||
|
k&&k--;for(let m=0;m<d;m++){let l=e?d-1-m:m;for(let n=0;2>n;n++){let q=k-n;if(!f.get(q,l)){h++;let r=a.get(q,l);c({y:l,x:q})&&(r=!r);g=g<<1|r;8===h&&(b.push(g),g=h=0)}}}e=!e}return b}
|
||||||
|
function la(a){var b=a.height,c=Math.floor((b-17)/4);if(6>=c)return I[c-1];c=0;for(var d=5;0<=d;d--)for(var e=b-9;e>=b-11;e--)c=K(a.get(e,d),c);d=0;for(e=5;0<=e;e--)for(let g=b-9;g>=b-11;g--)d=K(a.get(e,g),d);a=Infinity;let f;for(let g of I){if(g.infoBits===c||g.infoBits===d)return g;b=J(c,g.infoBits);b<a&&(f=g,a=b);b=J(d,g.infoBits);b<a&&(f=g,a=b)}if(3>=a)return f}
|
||||||
|
function ma(a){let b=0;for(var c=0;8>=c;c++)6!==c&&(b=K(a.get(c,8),b));for(c=7;0<=c;c--)6!==c&&(b=K(a.get(8,c),b));var d=a.height;c=0;for(var e=d-1;e>=d-7;e--)c=K(a.get(8,e),c);for(e=d-8;e<d;e++)c=K(a.get(e,8),c);a=Infinity;d=null;for(let {bits:f,formatInfo:g}of ia){if(f===b||f===c)return g;e=J(b,f);e<a&&(d=g,a=e);b!==c&&(e=J(c,f),e<a&&(d=g,a=e))}return 3>=a?d:null}
|
||||||
|
function na(a,b,c){let d=b.errorCorrectionLevels[c],e=[],f=0;d.ecBlocks.forEach(h=>{for(let k=0;k<h.numBlocks;k++)e.push({numDataCodewords:h.dataCodewordsPerBlock,codewords:[]}),f+=h.dataCodewordsPerBlock+d.ecCodewordsPerBlock});if(a.length<f)return null;a=a.slice(0,f);b=d.ecBlocks[0].dataCodewordsPerBlock;for(c=0;c<b;c++)for(var g of e)g.codewords.push(a.shift());if(1<d.ecBlocks.length)for(g=d.ecBlocks[0].numBlocks,b=d.ecBlocks[1].numBlocks,c=0;c<b;c++)e[g+c].codewords.push(a.shift());for(;0<a.length;)for(let h of e)h.codewords.push(a.shift());
|
||||||
|
return e}function L(a){let b=la(a);if(!b)return null;var c=ma(a);if(!c)return null;a=ka(a,b,c);var d=na(a,b,c.errorCorrectionLevel);if(!d)return null;c=d.reduce((e,f)=>e+f.numDataCodewords,0);c=new Uint8ClampedArray(c);a=0;for(let e of d){d=ha(e.codewords,e.codewords.length-e.numDataCodewords);if(!d)return null;for(let f=0;f<e.numDataCodewords;f++)c[a++]=d[f]}try{return da(c,b.versionNumber)}catch(e){return null}}
|
||||||
|
function M(a,b,c,d){var e=a.x-b.x+c.x-d.x;let f=a.y-b.y+c.y-d.y;if(0===e&&0===f)return{a11:b.x-a.x,a12:b.y-a.y,a13:0,a21:c.x-b.x,a22:c.y-b.y,a23:0,a31:a.x,a32:a.y,a33:1};let g=b.x-c.x;var h=d.x-c.x;let k=b.y-c.y,m=d.y-c.y;c=g*m-h*k;h=(e*m-h*f)/c;e=(g*f-e*k)/c;return{a11:b.x-a.x+h*b.x,a12:b.y-a.y+h*b.y,a13:h,a21:d.x-a.x+e*d.x,a22:d.y-a.y+e*d.y,a23:e,a31:a.x,a32:a.y,a33:1}}
|
||||||
|
function oa(a,b,c,d){a=M(a,b,c,d);return{a11:a.a22*a.a33-a.a23*a.a32,a12:a.a13*a.a32-a.a12*a.a33,a13:a.a12*a.a23-a.a13*a.a22,a21:a.a23*a.a31-a.a21*a.a33,a22:a.a11*a.a33-a.a13*a.a31,a23:a.a13*a.a21-a.a11*a.a23,a31:a.a21*a.a32-a.a22*a.a31,a32:a.a12*a.a31-a.a11*a.a32,a33:a.a11*a.a22-a.a12*a.a21}}
|
||||||
|
function pa(a,b){var c=oa({x:3.5,y:3.5},{x:b.dimension-3.5,y:3.5},{x:b.dimension-6.5,y:b.dimension-6.5},{x:3.5,y:b.dimension-3.5}),d=M(b.topLeft,b.topRight,b.alignmentPattern,b.bottomLeft),e=d.a11*c.a11+d.a21*c.a12+d.a31*c.a13,f=d.a12*c.a11+d.a22*c.a12+d.a32*c.a13,g=d.a13*c.a11+d.a23*c.a12+d.a33*c.a13,h=d.a11*c.a21+d.a21*c.a22+d.a31*c.a23,k=d.a12*c.a21+d.a22*c.a22+d.a32*c.a23,m=d.a13*c.a21+d.a23*c.a22+d.a33*c.a23,l=d.a11*c.a31+d.a21*c.a32+d.a31*c.a33,n=d.a12*c.a31+d.a22*c.a32+d.a32*c.a33,q=d.a13*
|
||||||
|
c.a31+d.a23*c.a32+d.a33*c.a33;c=x.createEmpty(b.dimension,b.dimension);d=(r,u)=>{const p=g*r+m*u+q;return{x:(e*r+h*u+l)/p,y:(f*r+k*u+n)/p}};for(let r=0;r<b.dimension;r++)for(let u=0;u<b.dimension;u++){let p=d(u+.5,r+.5);c.set(u,r,a.get(Math.floor(p.x),Math.floor(p.y)))}return{matrix:c,mappingFunction:d}}let N=(a,b)=>Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));function O(a){return a.reduce((b,c)=>b+c)}
|
||||||
|
function qa(a,b,c){let d=N(a,b),e=N(b,c),f=N(a,c),g,h,k;e>=d&&e>=f?[g,h,k]=[b,a,c]:f>=e&&f>=d?[g,h,k]=[a,b,c]:[g,h,k]=[a,c,b];0>(k.x-h.x)*(g.y-h.y)-(k.y-h.y)*(g.x-h.x)&&([g,k]=[k,g]);return{bottomLeft:g,topLeft:h,topRight:k}}
|
||||||
|
function ra(a,b,c,d){d=(O(P(a,c,d,5))/7+O(P(a,b,d,5))/7+O(P(c,a,d,5))/7+O(P(b,a,d,5))/7)/4;if(1>d)throw Error("Invalid module size");b=Math.round(N(a,b)/d);a=Math.round(N(a,c)/d);a=Math.floor((b+a)/2)+7;switch(a%4){case 0:a++;break;case 2:a--}return{dimension:a,moduleSize:d}}
|
||||||
|
function Q(a,b,c,d){let e=[{x:Math.floor(a.x),y:Math.floor(a.y)}];var f=Math.abs(b.y-a.y)>Math.abs(b.x-a.x);if(f){var g=Math.floor(a.y);var h=Math.floor(a.x);a=Math.floor(b.y);b=Math.floor(b.x)}else g=Math.floor(a.x),h=Math.floor(a.y),a=Math.floor(b.x),b=Math.floor(b.y);let k=Math.abs(a-g),m=Math.abs(b-h),l=Math.floor(-k/2),n=g<a?1:-1,q=h<b?1:-1,r=!0;for(let u=g,p=h;u!==a+n;u+=n){g=f?p:u;h=f?u:p;if(c.get(g,h)!==r&&(r=!r,e.push({x:g,y:h}),e.length===d+1))break;l+=m;if(0<l){if(p===b)break;p+=q;l-=k}}c=
|
||||||
|
[];for(f=0;f<d;f++)e[f]&&e[f+1]?c.push(N(e[f],e[f+1])):c.push(0);return c}function P(a,b,c,d){let e=b.y-a.y,f=b.x-a.x;b=Q(a,b,c,Math.ceil(d/2));a=Q(a,{x:a.x-f,y:a.y-e},c,Math.ceil(d/2));c=b.shift()+a.shift()-1;return a.concat(c).concat(...b)}function R(a,b){let c=O(a)/O(b),d=0;b.forEach((e,f)=>{d+=Math.pow(a[f]-e*c,2)});return{averageSize:c,error:d}}
|
||||||
|
function S(a,b,c){try{let d=P(a,{x:-1,y:a.y},c,b.length),e=P(a,{x:a.x,y:-1},c,b.length),f=P(a,{x:Math.max(0,a.x-a.y)-1,y:Math.max(0,a.y-a.x)-1},c,b.length),g=P(a,{x:Math.min(c.width,a.x+a.y)+1,y:Math.min(c.height,a.y+a.x)+1},c,b.length),h=R(d,b),k=R(e,b),m=R(f,b),l=R(g,b),n=(h.averageSize+k.averageSize+m.averageSize+l.averageSize)/4;return Math.sqrt(h.error*h.error+k.error*k.error+m.error*m.error+l.error*l.error)+(Math.pow(h.averageSize-n,2)+Math.pow(k.averageSize-n,2)+Math.pow(m.averageSize-n,2)+
|
||||||
|
Math.pow(l.averageSize-n,2))/n}catch(d){return Infinity}}function T(a,b){for(var c=Math.round(b.x);a.get(c,Math.round(b.y));)c--;for(var d=Math.round(b.x);a.get(d,Math.round(b.y));)d++;c=(c+d)/2;for(d=Math.round(b.y);a.get(Math.round(c),d);)d--;for(b=Math.round(b.y);a.get(Math.round(c),b);)b++;return{x:c,y:(d+b)/2}}
|
||||||
|
function sa(a){var b=[],c=[];let d=[];var e=[];for(let p=0;p<=a.height;p++){var f=0,g=!1;let t=[0,0,0,0,0];for(let v=-1;v<=a.width;v++){var h=a.get(v,p);if(h===g)f++;else{t=[t[1],t[2],t[3],t[4],f];f=1;g=h;var k=O(t)/7;k=Math.abs(t[0]-k)<k&&Math.abs(t[1]-k)<k&&Math.abs(t[2]-3*k)<3*k&&Math.abs(t[3]-k)<k&&Math.abs(t[4]-k)<k&&!h;var m=O(t.slice(-3))/3;h=Math.abs(t[2]-m)<m&&Math.abs(t[3]-m)<m&&Math.abs(t[4]-m)<m&&h;if(k){let z=v-t[3]-t[4],y=z-t[2];k={startX:y,endX:z,y:p};m=c.filter(w=>y>=w.bottom.startX&&
|
||||||
|
y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5<t[2]/(w.bottom.endX-w.bottom.startX));0<m.length?m[0].bottom=k:c.push({top:k,bottom:k})}if(h){let z=v-t[4],y=z-t[3];h={startX:y,y:p,endX:z};k=e.filter(w=>y>=w.bottom.startX&&y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5<t[2]/(w.bottom.endX-w.bottom.startX));0<k.length?
|
||||||
|
k[0].bottom=h:e.push({top:h,bottom:h})}}}b.push(...c.filter(v=>v.bottom.y!==p&&2<=v.bottom.y-v.top.y));c=c.filter(v=>v.bottom.y===p);d.push(...e.filter(v=>v.bottom.y!==p));e=e.filter(v=>v.bottom.y===p)}b.push(...c.filter(p=>2<=p.bottom.y-p.top.y));d.push(...e);c=[];for(var l of b)2>l.bottom.y-l.top.y||(b=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4,e=(l.top.y+l.bottom.y+1)/2,a.get(Math.round(b),Math.round(e))&&(f=[l.top.endX-l.top.startX,l.bottom.endX-l.bottom.startX,l.bottom.y-l.top.y+
|
||||||
|
1],f=O(f)/f.length,g=S({x:Math.round(b),y:Math.round(e)},[1,1,3,1,1],a),c.push({score:g,x:b,y:e,size:f})));if(3>c.length)return null;c.sort((p,t)=>p.score-t.score);l=[];for(b=0;b<Math.min(c.length,5);++b){e=c[b];f=[];for(var n of c)n!==e&&f.push(Object.assign(Object.assign({},n),{score:n.score+Math.pow(n.size-e.size,2)/e.size}));f.sort((p,t)=>p.score-t.score);l.push({points:[e,f[0],f[1]],score:e.score+f[0].score+f[1].score})}l.sort((p,t)=>p.score-t.score);let {topRight:q,topLeft:r,bottomLeft:u}=qa(...l[0].points);
|
||||||
|
l=U(a,d,q,r,u);n=[];l&&n.push({alignmentPattern:{x:l.alignmentPattern.x,y:l.alignmentPattern.y},bottomLeft:{x:u.x,y:u.y},dimension:l.dimension,topLeft:{x:r.x,y:r.y},topRight:{x:q.x,y:q.y}});l=T(a,q);b=T(a,r);c=T(a,u);(a=U(a,d,l,b,c))&&n.push({alignmentPattern:{x:a.alignmentPattern.x,y:a.alignmentPattern.y},bottomLeft:{x:c.x,y:c.y},topLeft:{x:b.x,y:b.y},topRight:{x:l.x,y:l.y},dimension:a.dimension});return 0===n.length?null:n}
|
||||||
|
function U(a,b,c,d,e){let f,g;try{({dimension:f,moduleSize:g}=ra(d,c,e,a))}catch(l){return null}var h=c.x-d.x+e.x,k=c.y-d.y+e.y;c=(N(d,e)+N(d,c))/2/g;e=1-3/c;let m={x:d.x+e*(h-d.x),y:d.y+e*(k-d.y)};b=b.map(l=>{const n=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4;l=(l.top.y+l.bottom.y+1)/2;if(a.get(Math.floor(n),Math.floor(l))){var q=S({x:Math.floor(n),y:Math.floor(l)},[1,1,1],a)+N({x:n,y:l},m);return{x:n,y:l,score:q}}}).filter(l=>!!l).sort((l,n)=>l.score-n.score);return{alignmentPattern:15<=
|
||||||
|
c&&b.length?b[0]:m,dimension:f}}
|
||||||
|
function V(a){var b=sa(a);if(!b)return null;for(let e of b){b=pa(a,e);var c=b.matrix;if(null==c)c=null;else{var d=L(c);if(d)c=d;else{for(d=0;d<c.width;d++)for(let f=d+1;f<c.height;f++)c.get(d,f)!==c.get(f,d)&&(c.set(d,f,!c.get(d,f)),c.set(f,d,!c.get(f,d)));c=L(c)}}if(c)return{binaryData:c.bytes,data:c.text,chunks:c.chunks,version:c.version,location:{topRightCorner:b.mappingFunction(e.dimension,0),topLeftCorner:b.mappingFunction(0,0),bottomRightCorner:b.mappingFunction(e.dimension,e.dimension),bottomLeftCorner:b.mappingFunction(0,
|
||||||
|
e.dimension),topRightFinderPattern:e.topRight,topLeftFinderPattern:e.topLeft,bottomLeftFinderPattern:e.bottomLeft,bottomRightAlignmentPattern:e.alignmentPattern},matrix:b.matrix}}return null}let ta={inversionAttempts:"attemptBoth",greyScaleWeights:{red:.2126,green:.7152,blue:.0722,useIntegerApproximation:!1},canOverwriteImage:!0};function W(a,b){Object.keys(b).forEach(c=>{a[c]=b[c]})}
|
||||||
|
function X(a,b,c,d={}){let e=Object.create(null);W(e,ta);W(e,d);d="onlyInvert"===e.inversionAttempts||"invertFirst"===e.inversionAttempts;var f="attemptBoth"===e.inversionAttempts||d;var g=e.greyScaleWeights,h=e.canOverwriteImage,k=b*c;if(a.length!==4*k)throw Error("Malformed data passed to binarizer.");var m=0;if(h){var l=new Uint8ClampedArray(a.buffer,m,k);m+=k}l=new A(b,c,l);if(g.useIntegerApproximation)for(var n=0;n<c;n++)for(var q=0;q<b;q++){var r=4*(n*b+q);l.set(q,n,g.red*a[r]+g.green*a[r+1]+
|
||||||
|
g.blue*a[r+2]+128>>8)}else for(n=0;n<c;n++)for(q=0;q<b;q++)r=4*(n*b+q),l.set(q,n,g.red*a[r]+g.green*a[r+1]+g.blue*a[r+2]);g=Math.ceil(b/8);n=Math.ceil(c/8);q=g*n;if(h){var u=new Uint8ClampedArray(a.buffer,m,q);m+=q}u=new A(g,n,u);for(q=0;q<n;q++)for(r=0;r<g;r++){var p=Infinity,t=0;for(var v=0;8>v;v++)for(let w=0;8>w;w++){let aa=l.get(8*r+w,8*q+v);p=Math.min(p,aa);t=Math.max(t,aa)}v=(p+t)/2;v=Math.min(255,1.11*v);24>=t-p&&(v=p/2,0<q&&0<r&&(t=(u.get(r,q-1)+2*u.get(r-1,q)+u.get(r-1,q-1))/4,p<t&&(v=t)));
|
||||||
|
u.set(r,q,v)}h?(q=new Uint8ClampedArray(a.buffer,m,k),m+=k,q=new x(q,b)):q=x.createEmpty(b,c);r=null;f&&(h?(a=new Uint8ClampedArray(a.buffer,m,k),r=new x(a,b)):r=x.createEmpty(b,c));for(b=0;b<n;b++)for(a=0;a<g;a++){c=g-3;c=2>a?2:a>c?c:a;h=n-3;h=2>b?2:b>h?h:b;k=0;for(m=-2;2>=m;m++)for(p=-2;2>=p;p++)k+=u.get(c+m,h+p);c=k/25;for(h=0;8>h;h++)for(k=0;8>k;k++)m=8*a+h,p=8*b+k,t=l.get(m,p),q.set(m,p,t<=c),f&&r.set(m,p,!(t<=c))}f=f?{binarized:q,inverted:r}:{binarized:q};let {binarized:z,inverted:y}=f;(f=V(d?
|
||||||
|
y:z))||"attemptBoth"!==e.inversionAttempts&&"invertFirst"!==e.inversionAttempts||(f=V(d?z:y));return f}X.default=X;let Y="dontInvert",Z={red:77,green:150,blue:29,useIntegerApproximation:!0};
|
||||||
|
self.onmessage=a=>{let b=a.data.id,c=a.data.data;switch(a.data.type){case "decode":(a=X(c.data,c.width,c.height,{inversionAttempts:Y,greyScaleWeights:Z}))?self.postMessage({id:b,type:"qrResult",data:a.data,cornerPoints:[a.location.topLeftCorner,a.location.topRightCorner,a.location.bottomRightCorner,a.location.bottomLeftCorner]}):self.postMessage({id:b,type:"qrResult",data:null});break;case "grayscaleWeights":Z.red=c.red;Z.green=c.green;Z.blue=c.blue;Z.useIntegerApproximation=c.useIntegerApproximation;
|
||||||
|
break;case "inversionMode":switch(c){case "original":Y="dontInvert";break;case "invert":Y="onlyInvert";break;case "both":Y="attemptBoth";break;default:throw Error("Invalid inversion mode");}break;case "close":self.close()}}
|
||||||
|
`]),{type:"application/javascript"}));
|
||||||
|
|
||||||
|
export { createWorker };
|
1454
ihm/sdk_client-CuF7MH2z.mjs
Normal file
1454
ihm/sdk_client-CuF7MH2z.mjs
Normal file
File diff suppressed because it is too large
Load Diff
BIN
ihm/sdk_client_bg-B6ah1IVY.wasm
Normal file
BIN
ihm/sdk_client_bg-B6ah1IVY.wasm
Normal file
Binary file not shown.
877
ihm/style/4nk.css
Normal file
877
ihm/style/4nk.css
Normal file
@ -0,0 +1,877 @@
|
|||||||
|
: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%;
|
||||||
|
}
|
1507
ihm/style/account.css
Normal file
1507
ihm/style/account.css
Normal file
File diff suppressed because it is too large
Load Diff
597
ihm/style/chat.css
Normal file
597
ihm/style/chat.css
Normal file
@ -0,0 +1,597 @@
|
|||||||
|
/* 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);
|
||||||
|
}
|
1664
ihm/style/signature.css
Normal file
1664
ihm/style/signature.css
Normal file
File diff suppressed because it is too large
Load Diff
2
ihm/types/components/header/header.d.ts
vendored
Normal file
2
ihm/types/components/header/header.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export declare function unpair(): Promise<void>;
|
||||||
|
export declare function initHeader(): Promise<void>;
|
1
ihm/types/components/modal/confirmation-modal.d.ts
vendored
Normal file
1
ihm/types/components/modal/confirmation-modal.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function closeConfirmationModal(): Promise<void>;
|
10
ihm/types/components/qrcode-scanner/qrcode-scanner-component.d.ts
vendored
Normal file
10
ihm/types/components/qrcode-scanner/qrcode-scanner-component.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export default class QrScannerComponent extends HTMLElement {
|
||||||
|
videoElement: any;
|
||||||
|
wrapper: any;
|
||||||
|
qrScanner: any;
|
||||||
|
constructor();
|
||||||
|
connectedCallback(): void;
|
||||||
|
initializeScanner(): Promise<void>;
|
||||||
|
onQrCodeScanned(result: any): Promise<void>;
|
||||||
|
disconnectedCallback(): void;
|
||||||
|
}
|
1
ihm/types/components/validation-modal/validation-modal.d.ts
vendored
Normal file
1
ihm/types/components/validation-modal/validation-modal.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function initValidationModal(processDiffs: any): Promise<void>;
|
14
ihm/types/components/validation-rule-modal/validation-rule-modal.d.ts
vendored
Normal file
14
ihm/types/components/validation-rule-modal/validation-rule-modal.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
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 declare function loadValidationRuleModal(templatePath?: string): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Opens the modal and lets the user input a ValidationRule.
|
||||||
|
* Calls the callback with the constructed rule on submit.
|
||||||
|
*/
|
||||||
|
export declare function showValidationRuleModal(onSubmit: (rule: ValidationRule) => void): void;
|
3
ihm/types/index.d.ts
vendored
Normal file
3
ihm/types/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { default as Services } from './services/service';
|
||||||
|
export { default as Database } from './services/database.service';
|
||||||
|
export { MessageType } from './models/process.model';
|
24
ihm/types/interface/groupInterface.d.ts
vendored
Normal file
24
ihm/types/interface/groupInterface.d.ts
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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;
|
||||||
|
}>;
|
||||||
|
}
|
10
ihm/types/interface/memberInterface.d.ts
vendored
Normal file
10
ihm/types/interface/memberInterface.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface Member {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
email?: string;
|
||||||
|
avatar?: string;
|
||||||
|
processRoles?: Array<{
|
||||||
|
processId: number | string;
|
||||||
|
role: string;
|
||||||
|
}>;
|
||||||
|
}
|
9
ihm/types/main.d.ts
vendored
Normal file
9
ihm/types/main.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { AccountComponent } from './pages/account/account-component';
|
||||||
|
import { AccountElement } from './pages/account/account';
|
||||||
|
export { AccountComponent, AccountElement };
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'account-component': AccountComponent;
|
||||||
|
'account-element': AccountElement;
|
||||||
|
}
|
||||||
|
}
|
118
ihm/types/mocks/mock-account/constAccountMock.d.ts
vendored
Normal file
118
ihm/types/mocks/mock-account/constAccountMock.d.ts
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
export declare const ALLOWED_ROLES: string[];
|
||||||
|
export declare const STORAGE_KEYS: {
|
||||||
|
pairing: string;
|
||||||
|
wallet: string;
|
||||||
|
process: string;
|
||||||
|
data: string;
|
||||||
|
};
|
||||||
|
export declare const defaultRows: {
|
||||||
|
column1: string;
|
||||||
|
column2: string;
|
||||||
|
column3: string;
|
||||||
|
}[];
|
||||||
|
export declare const mockNotifications: {
|
||||||
|
[key: string]: Notification[];
|
||||||
|
};
|
||||||
|
export declare const notificationMessages: string[];
|
||||||
|
export declare const mockDataRows: {
|
||||||
|
column1: string;
|
||||||
|
column2: string;
|
||||||
|
column3: string;
|
||||||
|
column4: string;
|
||||||
|
column5: string;
|
||||||
|
column6: string;
|
||||||
|
processName: string;
|
||||||
|
zone: string;
|
||||||
|
}[];
|
||||||
|
export declare const mockProcessRows: ({
|
||||||
|
process: string;
|
||||||
|
role: string;
|
||||||
|
notification: {
|
||||||
|
messages: {
|
||||||
|
id: number;
|
||||||
|
read: boolean;
|
||||||
|
date: string;
|
||||||
|
message: string;
|
||||||
|
}[];
|
||||||
|
unread?: undefined;
|
||||||
|
total?: undefined;
|
||||||
|
};
|
||||||
|
} | {
|
||||||
|
process: string;
|
||||||
|
role: string;
|
||||||
|
notification: {
|
||||||
|
unread: number;
|
||||||
|
total: number;
|
||||||
|
messages: {
|
||||||
|
id: number;
|
||||||
|
read: boolean;
|
||||||
|
date: string;
|
||||||
|
message: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
})[];
|
||||||
|
export declare const mockContracts: {
|
||||||
|
'Contract #123': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #456': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #789': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #101': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #102': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #103': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #104': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #105': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
'Contract #106': {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
};
|
38
ihm/types/mocks/mock-account/interfacesAccountMock.d.ts
vendored
Normal file
38
ihm/types/mocks/mock-account/interfacesAccountMock.d.ts
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
export interface Row {
|
||||||
|
column1: string;
|
||||||
|
column2: string;
|
||||||
|
column3: string;
|
||||||
|
}
|
||||||
|
export interface Contract {
|
||||||
|
title: string;
|
||||||
|
date: string;
|
||||||
|
parties: string[];
|
||||||
|
terms: string[];
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
export interface WalletRow {
|
||||||
|
column1: string;
|
||||||
|
column2: string;
|
||||||
|
column3: string;
|
||||||
|
}
|
||||||
|
export interface DataRow {
|
||||||
|
column1: string;
|
||||||
|
column2: string;
|
||||||
|
column3: string;
|
||||||
|
column4: string;
|
||||||
|
column5: string;
|
||||||
|
column6: string;
|
||||||
|
processName: string;
|
||||||
|
zone: string;
|
||||||
|
}
|
||||||
|
export interface Notification {
|
||||||
|
message: string;
|
||||||
|
timestamp: string;
|
||||||
|
isRead: boolean;
|
||||||
|
}
|
||||||
|
export interface NotificationMessage {
|
||||||
|
id: number;
|
||||||
|
read: boolean;
|
||||||
|
date: string;
|
||||||
|
message: string;
|
||||||
|
}
|
9
ihm/types/mocks/mock-signature/messagesMock.d.ts
vendored
Normal file
9
ihm/types/mocks/mock-signature/messagesMock.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export declare const messagesMock: {
|
||||||
|
memberId: number;
|
||||||
|
messages: {
|
||||||
|
id: number;
|
||||||
|
sender: string;
|
||||||
|
text: string;
|
||||||
|
time: string;
|
||||||
|
}[];
|
||||||
|
}[];
|
6
ihm/types/models/backup.model.d.ts
vendored
Normal file
6
ihm/types/models/backup.model.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { Device, Process, SecretsStore } from 'pkg/sdk_client';
|
||||||
|
export interface BackUp {
|
||||||
|
device: Device;
|
||||||
|
secrets: SecretsStore;
|
||||||
|
processes: Record<string, Process>;
|
||||||
|
}
|
24
ihm/types/models/notification.model.d.ts
vendored
Normal file
24
ihm/types/models/notification.model.d.ts
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
export interface INotification {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
sendToNotificationPage?: boolean;
|
||||||
|
path?: string;
|
||||||
|
}
|
||||||
|
export interface IUser {
|
||||||
|
id: string;
|
||||||
|
information?: any;
|
||||||
|
}
|
||||||
|
export interface IMessage {
|
||||||
|
id: string;
|
||||||
|
message: any;
|
||||||
|
}
|
||||||
|
export interface UserDiff {
|
||||||
|
new_state_merkle_root: string;
|
||||||
|
field: string;
|
||||||
|
previous_value: string;
|
||||||
|
new_value: string;
|
||||||
|
notify_user: boolean;
|
||||||
|
need_validation: boolean;
|
||||||
|
proof: any;
|
||||||
|
}
|
56
ihm/types/models/process.model.d.ts
vendored
Normal file
56
ihm/types/models/process.model.d.ts
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
export interface IProcess {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
icon?: string;
|
||||||
|
zoneList: IZone[];
|
||||||
|
}
|
||||||
|
export interface IZone {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
export interface INotification {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
sendToNotificationPage?: boolean;
|
||||||
|
path?: string;
|
||||||
|
}
|
||||||
|
export declare enum MessageType {
|
||||||
|
LISTENING = "LISTENING",
|
||||||
|
REQUEST_LINK = "REQUEST_LINK",
|
||||||
|
LINK_ACCEPTED = "LINK_ACCEPTED",
|
||||||
|
CREATE_PAIRING = "CREATE_PAIRING",
|
||||||
|
PAIRING_CREATED = "PAIRING_CREATED",
|
||||||
|
ERROR = "ERROR",
|
||||||
|
VALIDATE_TOKEN = "VALIDATE_TOKEN",
|
||||||
|
RENEW_TOKEN = "RENEW_TOKEN",
|
||||||
|
GET_PAIRING_ID = "GET_PAIRING_ID",
|
||||||
|
GET_PROCESSES = "GET_PROCESSES",
|
||||||
|
GET_MY_PROCESSES = "GET_MY_PROCESSES",
|
||||||
|
PROCESSES_RETRIEVED = "PROCESSES_RETRIEVED",
|
||||||
|
RETRIEVE_DATA = "RETRIEVE_DATA",
|
||||||
|
DATA_RETRIEVED = "DATA_RETRIEVED",
|
||||||
|
DECODE_PUBLIC_DATA = "DECODE_PUBLIC_DATA",
|
||||||
|
PUBLIC_DATA_DECODED = "PUBLIC_DATA_DECODED",
|
||||||
|
GET_MEMBER_ADDRESSES = "GET_MEMBER_ADDRESSES",
|
||||||
|
MEMBER_ADDRESSES_RETRIEVED = "MEMBER_ADDRESSES_RETRIEVED",
|
||||||
|
CREATE_PROCESS = "CREATE_PROCESS",
|
||||||
|
PROCESS_CREATED = "PROCESS_CREATED",
|
||||||
|
UPDATE_PROCESS = "UPDATE_PROCESS",
|
||||||
|
PROCESS_UPDATED = "PROCESS_UPDATED",
|
||||||
|
NOTIFY_UPDATE = "NOTIFY_UPDATE",
|
||||||
|
UPDATE_NOTIFIED = "UPDATE_NOTIFIED",
|
||||||
|
VALIDATE_STATE = "VALIDATE_STATE",
|
||||||
|
STATE_VALIDATED = "STATE_VALIDATED",
|
||||||
|
HASH_VALUE = "HASH_VALUE",
|
||||||
|
VALUE_HASHED = "VALUE_HASHED",
|
||||||
|
GET_MERKLE_PROOF = "GET_MERKLE_PROOF",
|
||||||
|
MERKLE_PROOF_RETRIEVED = "MERKLE_PROOF_RETRIEVED",
|
||||||
|
VALIDATE_MERKLE_PROOF = "VALIDATE_MERKLE_PROOF",
|
||||||
|
MERKLE_PROOF_VALIDATED = "MERKLE_PROOF_VALIDATED",
|
||||||
|
ADD_DEVICE = "ADD_DEVICE",
|
||||||
|
DEVICE_ADDED = "DEVICE_ADDED"
|
||||||
|
}
|
60
ihm/types/models/signature.models.d.ts
vendored
Normal file
60
ihm/types/models/signature.models.d.ts
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
export interface Group {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
roles: {
|
||||||
|
id?: number;
|
||||||
|
name: string;
|
||||||
|
members: {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
documents?: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
visibility: string;
|
||||||
|
createdAt: string | null;
|
||||||
|
deadline: string | null;
|
||||||
|
signatures: DocumentSignature[];
|
||||||
|
status?: string;
|
||||||
|
files?: Array<{
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
}>;
|
||||||
|
}[];
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
export interface Message {
|
||||||
|
id: number;
|
||||||
|
sender: string;
|
||||||
|
text?: string;
|
||||||
|
time: string;
|
||||||
|
type: 'text' | 'file';
|
||||||
|
fileName?: string;
|
||||||
|
fileData?: string;
|
||||||
|
}
|
||||||
|
export interface MemberMessages {
|
||||||
|
memberId: string;
|
||||||
|
messages: Message[];
|
||||||
|
}
|
||||||
|
export interface DocumentSignature {
|
||||||
|
signed: boolean;
|
||||||
|
member: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
signedAt?: string;
|
||||||
|
}
|
||||||
|
export interface RequestParams {
|
||||||
|
processId: number;
|
||||||
|
processName: string;
|
||||||
|
roleId: number;
|
||||||
|
roleName: string;
|
||||||
|
documentId: number;
|
||||||
|
documentName: string;
|
||||||
|
}
|
||||||
|
export interface Notification {
|
||||||
|
memberId: string;
|
||||||
|
text: string;
|
||||||
|
time: string;
|
||||||
|
}
|
12
ihm/types/pages/account/account-component.d.ts
vendored
Normal file
12
ihm/types/pages/account/account-component.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { AccountElement } from './account';
|
||||||
|
declare class AccountComponent extends HTMLElement {
|
||||||
|
_callback: any;
|
||||||
|
accountElement: AccountElement | null;
|
||||||
|
constructor();
|
||||||
|
connectedCallback(): void;
|
||||||
|
fetchData(): Promise<void>;
|
||||||
|
set callback(fn: any);
|
||||||
|
get callback(): any;
|
||||||
|
render(): void;
|
||||||
|
}
|
||||||
|
export { AccountComponent };
|
98
ihm/types/pages/account/account.d.ts
vendored
Normal file
98
ihm/types/pages/account/account.d.ts
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
initAccount: () => void;
|
||||||
|
showContractPopup: (contractId: string) => void;
|
||||||
|
showPairing: () => Promise<void>;
|
||||||
|
showWallet: () => void;
|
||||||
|
showData: () => void;
|
||||||
|
addWalletRow: () => void;
|
||||||
|
confirmWalletRow: () => void;
|
||||||
|
cancelWalletRow: () => void;
|
||||||
|
openAvatarPopup: () => void;
|
||||||
|
closeAvatarPopup: () => void;
|
||||||
|
editDeviceName: (cell: HTMLTableCellElement) => void;
|
||||||
|
showNotifications: (processName: string) => void;
|
||||||
|
closeNotificationPopup: (event: Event) => void;
|
||||||
|
markAsRead: (processName: string, messageId: number, element: HTMLElement) => void;
|
||||||
|
exportRecovery: () => void;
|
||||||
|
confirmDeleteAccount: () => void;
|
||||||
|
deleteAccount: () => void;
|
||||||
|
updateNavbarBanner: (bannerUrl: string) => void;
|
||||||
|
saveBannerToLocalStorage: (bannerUrl: string) => void;
|
||||||
|
loadSavedBanner: () => void;
|
||||||
|
cancelAddRowPairing: () => void;
|
||||||
|
saveName: (cell: HTMLElement, input: HTMLInputElement) => void;
|
||||||
|
showProcessNotifications: (processName: string) => void;
|
||||||
|
handleLogout: () => void;
|
||||||
|
initializeEventListeners: () => void;
|
||||||
|
showProcess: () => void;
|
||||||
|
showProcessCreation: () => void;
|
||||||
|
showDocumentValidation: () => void;
|
||||||
|
updateNavbarName: (name: string) => void;
|
||||||
|
updateNavbarLastName: (lastName: string) => void;
|
||||||
|
showAlert: (title: string, text?: string, icon?: string) => void;
|
||||||
|
addRowPairing: () => void;
|
||||||
|
confirmRowPairing: () => void;
|
||||||
|
cancelRowPairing: () => void;
|
||||||
|
deleteRowPairing: (button: HTMLButtonElement) => void;
|
||||||
|
generateRecoveryWords: () => string[];
|
||||||
|
exportUserData: () => void;
|
||||||
|
updateActionButtons: () => void;
|
||||||
|
showQRCodeModal: (pairingId: string) => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare class AccountElement extends HTMLElement {
|
||||||
|
private dom;
|
||||||
|
constructor();
|
||||||
|
connectedCallback(): void;
|
||||||
|
private showAlert;
|
||||||
|
private confirmDeleteAccount;
|
||||||
|
private deleteAccount;
|
||||||
|
private updateNavbarBanner;
|
||||||
|
private saveBannerToLocalStorage;
|
||||||
|
private loadSavedBanner;
|
||||||
|
private closeNotificationPopup;
|
||||||
|
private markAsRead;
|
||||||
|
private calculateNotifications;
|
||||||
|
private exportRecovery;
|
||||||
|
private generateRecoveryWords;
|
||||||
|
private exportUserData;
|
||||||
|
private updateActionButtons;
|
||||||
|
private getConfirmFunction;
|
||||||
|
private getCancelFunction;
|
||||||
|
private addRowPairing;
|
||||||
|
private updateTableContent;
|
||||||
|
private confirmRowPairing;
|
||||||
|
private cancelRowPairing;
|
||||||
|
private resetButtonContainer;
|
||||||
|
private deleteRowPairing;
|
||||||
|
private editDeviceName;
|
||||||
|
private finishEditing;
|
||||||
|
private handleAvatarUpload;
|
||||||
|
private showProcessCreation;
|
||||||
|
private showDocumentValidation;
|
||||||
|
private showProcess;
|
||||||
|
private showProcessNotifications;
|
||||||
|
private handleLogout;
|
||||||
|
private showContractPopup;
|
||||||
|
private hideAllContent;
|
||||||
|
private showPairing;
|
||||||
|
private showWallet;
|
||||||
|
private updateWalletTableContent;
|
||||||
|
private showData;
|
||||||
|
private addWalletRow;
|
||||||
|
private confirmWalletRow;
|
||||||
|
private cancelWalletRow;
|
||||||
|
private updateDataTableContent;
|
||||||
|
private openAvatarPopup;
|
||||||
|
private setupEventListeners;
|
||||||
|
private closeAvatarPopup;
|
||||||
|
private loadAvatar;
|
||||||
|
private loadUserInfo;
|
||||||
|
private updateNavbarName;
|
||||||
|
private updateNavbarLastName;
|
||||||
|
private updateProfilePreview;
|
||||||
|
private initializeEventListeners;
|
||||||
|
private showQRCodeModal;
|
||||||
|
}
|
||||||
|
export { AccountElement };
|
33
ihm/types/pages/account/document-validation.d.ts
vendored
Normal file
33
ihm/types/pages/account/document-validation.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export interface Vin {
|
||||||
|
txid: string;
|
||||||
|
vout: number;
|
||||||
|
prevout: {
|
||||||
|
scriptpubkey: string;
|
||||||
|
scriptpubkey_asm: string;
|
||||||
|
scriptpubkey_type: string;
|
||||||
|
scriptpubkey_address: string;
|
||||||
|
value: number;
|
||||||
|
};
|
||||||
|
scriptsig: string;
|
||||||
|
scriptsig_asm: string;
|
||||||
|
witness: string[];
|
||||||
|
is_coinbase: boolean;
|
||||||
|
sequence: number;
|
||||||
|
}
|
||||||
|
export interface TransactionInfo {
|
||||||
|
txid: string;
|
||||||
|
version: number;
|
||||||
|
locktime: number;
|
||||||
|
vin: Vin[];
|
||||||
|
vout: any[];
|
||||||
|
size: number;
|
||||||
|
weight: number;
|
||||||
|
fee: number;
|
||||||
|
status: {
|
||||||
|
confirmed: boolean;
|
||||||
|
block_height: number;
|
||||||
|
block_hash: string;
|
||||||
|
block_time: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export declare function getDocumentValidation(container: HTMLElement): void;
|
8
ihm/types/pages/account/key-value-section.d.ts
vendored
Normal file
8
ihm/types/pages/account/key-value-section.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import type { RoleDefinition } from '../../../pkg/sdk_client';
|
||||||
|
export declare function createKeyValueSection(title: string, id: string, isRoleSection?: boolean): {
|
||||||
|
element: HTMLDivElement;
|
||||||
|
getData: () => Record<string, RoleDefinition> | Record<string, string | {
|
||||||
|
type: string;
|
||||||
|
data: Uint8Array;
|
||||||
|
}>;
|
||||||
|
};
|
1
ihm/types/pages/account/process-creation.d.ts
vendored
Normal file
1
ihm/types/pages/account/process-creation.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function getProcessCreation(container: HTMLElement): Promise<void>;
|
4
ihm/types/pages/account/process.d.ts
vendored
Normal file
4
ihm/types/pages/account/process.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export declare function createProcessTab(container: HTMLElement, processes: {
|
||||||
|
name: string;
|
||||||
|
publicData: Record<string, any>;
|
||||||
|
}[]): HTMLElement;
|
8
ihm/types/pages/home/home-component.d.ts
vendored
Normal file
8
ihm/types/pages/home/home-component.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export declare class LoginComponent extends HTMLElement {
|
||||||
|
_callback: any;
|
||||||
|
constructor();
|
||||||
|
connectedCallback(): void;
|
||||||
|
set callback(fn: any);
|
||||||
|
get callback(): any;
|
||||||
|
render(): void;
|
||||||
|
}
|
4
ihm/types/pages/home/home.d.ts
vendored
Normal file
4
ihm/types/pages/home/home.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
|
||||||
|
export { QrScannerComponent };
|
||||||
|
export declare function initHomePage(): Promise<void>;
|
||||||
|
export declare function openModal(myAddress: string, receiverAddress: string): Promise<void>;
|
5
ihm/types/router.d.ts
vendored
Normal file
5
ihm/types/router.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import '../public/style/4nk.css';
|
||||||
|
export declare let currentRoute: string;
|
||||||
|
export declare function navigate(path: string): Promise<void>;
|
||||||
|
export declare function init(): Promise<void>;
|
||||||
|
export declare function registerAllListeners(): Promise<void>;
|
43
ihm/types/services/database.service.d.ts
vendored
Normal file
43
ihm/types/services/database.service.d.ts
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
export declare class Database {
|
||||||
|
private static instance;
|
||||||
|
private db;
|
||||||
|
private dbName;
|
||||||
|
private dbVersion;
|
||||||
|
private serviceWorkerRegistration;
|
||||||
|
private messageChannel;
|
||||||
|
private messageChannelForGet;
|
||||||
|
private serviceWorkerCheckIntervalId;
|
||||||
|
private storeDefinitions;
|
||||||
|
private constructor();
|
||||||
|
static getInstance(): Promise<Database>;
|
||||||
|
private init;
|
||||||
|
getDb(): Promise<IDBDatabase>;
|
||||||
|
getStoreList(): {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
registerServiceWorker(path: string): Promise<void>;
|
||||||
|
private waitForServiceWorkerActivation;
|
||||||
|
private checkForUpdates;
|
||||||
|
private handleServiceWorkerMessage;
|
||||||
|
private handleDownloadList;
|
||||||
|
private handleAddObjectResponse;
|
||||||
|
private handleGetObjectResponse;
|
||||||
|
addObject(payload: {
|
||||||
|
storeName: string;
|
||||||
|
object: any;
|
||||||
|
key: any;
|
||||||
|
}): Promise<void>;
|
||||||
|
batchWriting(payload: {
|
||||||
|
storeName: string;
|
||||||
|
objects: {
|
||||||
|
key: any;
|
||||||
|
object: any;
|
||||||
|
}[];
|
||||||
|
}): Promise<void>;
|
||||||
|
getObject(storeName: string, key: string): Promise<any | null>;
|
||||||
|
dumpStore(storeName: string): Promise<Record<string, any>>;
|
||||||
|
deleteObject(storeName: string, key: string): Promise<void>;
|
||||||
|
clearStore(storeName: string): Promise<void>;
|
||||||
|
requestStoreByIndex(storeName: string, indexName: string, request: string): Promise<any[]>;
|
||||||
|
}
|
||||||
|
export default Database;
|
28
ihm/types/services/modal.service.d.ts
vendored
Normal file
28
ihm/types/services/modal.service.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import type { RoleDefinition } from 'pkg/sdk_client';
|
||||||
|
interface ConfirmationModalOptions {
|
||||||
|
title: string;
|
||||||
|
content: string;
|
||||||
|
confirmText?: string;
|
||||||
|
cancelText?: string;
|
||||||
|
}
|
||||||
|
export default class ModalService {
|
||||||
|
private static instance;
|
||||||
|
private stateId;
|
||||||
|
private processId;
|
||||||
|
private constructor();
|
||||||
|
private paired_addresses;
|
||||||
|
private modal;
|
||||||
|
static getInstance(): Promise<ModalService>;
|
||||||
|
openLoginModal(myAddress: string, receiverAddress: string): void;
|
||||||
|
injectModal(members: any[]): Promise<void>;
|
||||||
|
injectCreationModal(members: any[]): Promise<void>;
|
||||||
|
injectWaitingModal(): Promise<void>;
|
||||||
|
injectValidationModal(processDiff: any): Promise<void>;
|
||||||
|
closeValidationModal(): Promise<void>;
|
||||||
|
openPairingConfirmationModal(roleDefinition: Record<string, RoleDefinition>, processId: string, stateId: string): Promise<void>;
|
||||||
|
confirmLogin(): void;
|
||||||
|
closeLoginModal(): Promise<void>;
|
||||||
|
showConfirmationModal(options: ConfirmationModalOptions, fullscreen?: boolean): Promise<boolean>;
|
||||||
|
closeConfirmationModal(): Promise<void>;
|
||||||
|
}
|
||||||
|
export {};
|
167
ihm/types/services/service.d.ts
vendored
Normal file
167
ihm/types/services/service.d.ts
vendored
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import type { ApiReturn, Device, Member, MerkleProofResult, Process, ProcessState, RoleDefinition, SecretsStore, UserDiff } from '../../pkg/sdk_client';
|
||||||
|
import { BackUp } from '~/models/backup.model';
|
||||||
|
export declare const U32_MAX = 4294967295;
|
||||||
|
export default class Services {
|
||||||
|
private static initializing;
|
||||||
|
private static instance;
|
||||||
|
private processId;
|
||||||
|
private stateId;
|
||||||
|
private sdkClient;
|
||||||
|
private processesCache;
|
||||||
|
private myProcesses;
|
||||||
|
private notifications;
|
||||||
|
private subscriptions;
|
||||||
|
private database;
|
||||||
|
private routingInstance;
|
||||||
|
private relayAddresses;
|
||||||
|
private membersList;
|
||||||
|
private currentBlockHeight;
|
||||||
|
private constructor();
|
||||||
|
static getInstance(): Promise<Services>;
|
||||||
|
init(): Promise<void>;
|
||||||
|
setProcessId(processId: string | null): void;
|
||||||
|
setStateId(stateId: string | null): void;
|
||||||
|
getProcessId(): string | null;
|
||||||
|
getStateId(): string | null;
|
||||||
|
/**
|
||||||
|
* Calls `this.addWebsocketConnection` for each `wsurl` in relayAddresses.
|
||||||
|
* Waits for at least one handshake message before returning.
|
||||||
|
*/
|
||||||
|
connectAllRelays(): Promise<void>;
|
||||||
|
addWebsocketConnection(url: string): Promise<void>;
|
||||||
|
/**
|
||||||
|
* Add or update a key/value pair in relayAddresses.
|
||||||
|
* @param wsurl - The WebSocket URL (key).
|
||||||
|
* @param spAddress - The SP Address (value).
|
||||||
|
*/
|
||||||
|
updateRelay(wsurl: string, spAddress: string): void;
|
||||||
|
/**
|
||||||
|
* Retrieve the spAddress for a given wsurl.
|
||||||
|
* @param wsurl - The WebSocket URL to look up.
|
||||||
|
* @returns The SP Address if found, or undefined if not.
|
||||||
|
*/
|
||||||
|
getSpAddress(wsurl: string): string | undefined;
|
||||||
|
/**
|
||||||
|
* Get all key/value pairs from relayAddresses.
|
||||||
|
* @returns An array of objects containing wsurl and spAddress.
|
||||||
|
*/
|
||||||
|
getAllRelays(): {
|
||||||
|
wsurl: string;
|
||||||
|
spAddress: string;
|
||||||
|
}[];
|
||||||
|
/**
|
||||||
|
* Print all key/value pairs for debugging.
|
||||||
|
*/
|
||||||
|
printAllRelays(): void;
|
||||||
|
isPaired(): boolean;
|
||||||
|
unpairDevice(): Promise<void>;
|
||||||
|
getSecretForAddress(address: string): Promise<string | null>;
|
||||||
|
getAllSecrets(): Promise<SecretsStore>;
|
||||||
|
getAllDiffs(): Promise<Record<string, UserDiff>>;
|
||||||
|
getDiffByValue(value: string): Promise<UserDiff | null>;
|
||||||
|
private getTokensFromFaucet;
|
||||||
|
checkConnections(members: Member[]): Promise<void>;
|
||||||
|
connectAddresses(addresses: string[]): Promise<ApiReturn>;
|
||||||
|
private ensureSufficientAmount;
|
||||||
|
private waitForAmount;
|
||||||
|
createPairingProcess(userName: string, pairWith: string[]): Promise<ApiReturn>;
|
||||||
|
private isFileBlob;
|
||||||
|
private splitData;
|
||||||
|
createProcess(privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition>): Promise<ApiReturn>;
|
||||||
|
updateProcess(process: Process, privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition> | null): Promise<ApiReturn>;
|
||||||
|
createPrdUpdate(processId: string, stateId: string): Promise<ApiReturn>;
|
||||||
|
createPrdResponse(processId: string, stateId: string): Promise<ApiReturn>;
|
||||||
|
approveChange(processId: string, stateId: string): Promise<ApiReturn>;
|
||||||
|
rejectChange(processId: string, stateId: string): Promise<ApiReturn>;
|
||||||
|
resetDevice(): Promise<void>;
|
||||||
|
sendNewTxMessage(message: string): void;
|
||||||
|
sendCommitMessage(message: string): void;
|
||||||
|
sendCipherMessages(ciphers: string[]): void;
|
||||||
|
sendFaucetMessage(message: string): void;
|
||||||
|
parseCipher(message: string): Promise<void>;
|
||||||
|
parseNewTx(newTxMsg: string): Promise<void>;
|
||||||
|
handleApiReturn(apiReturn: ApiReturn): Promise<void>;
|
||||||
|
openPairingConfirmationModal(processId: string): Promise<void>;
|
||||||
|
confirmPairing(): Promise<void>;
|
||||||
|
updateDevice(): Promise<void>;
|
||||||
|
pairDevice(): Promise<void>;
|
||||||
|
getAmount(): BigInt;
|
||||||
|
getDeviceAddress(): string;
|
||||||
|
dumpDeviceFromMemory(): Device;
|
||||||
|
dumpNeuteredDevice(): Device | null;
|
||||||
|
getPairingProcessId(): string;
|
||||||
|
saveDeviceInDatabase(device: Device): Promise<void>;
|
||||||
|
getDeviceFromDatabase(): Promise<Device | null>;
|
||||||
|
getMemberFromDevice(): Promise<string[] | null>;
|
||||||
|
isChildRole(parent: any, child: any): boolean;
|
||||||
|
rolesContainsUs(roles: Record<string, RoleDefinition>): boolean;
|
||||||
|
rolesContainsMember(roles: Record<string, RoleDefinition>, pairingProcessId: string): boolean;
|
||||||
|
dumpWallet(): Promise<any>;
|
||||||
|
createFaucetMessage(): any;
|
||||||
|
createNewDevice(): Promise<string>;
|
||||||
|
restoreDevice(device: Device): void;
|
||||||
|
updateDeviceBlockHeight(): Promise<void>;
|
||||||
|
private removeProcess;
|
||||||
|
batchSaveProcessesToDb(processes: Record<string, Process>): Promise<void>;
|
||||||
|
saveProcessToDb(processId: string, process: Process): Promise<void>;
|
||||||
|
saveBlobToDb(hash: string, data: Blob): Promise<void>;
|
||||||
|
getBlobFromDb(hash: string): Promise<Blob | null>;
|
||||||
|
saveDataToStorage(hash: string, data: Blob, ttl: number | null): Promise<void>;
|
||||||
|
fetchValueFromStorage(hash: string): Promise<any | null>;
|
||||||
|
testDataInStorage(hash: string): Promise<Record<string, boolean | null> | null>;
|
||||||
|
saveDiffsToDb(diffs: UserDiff[]): Promise<void>;
|
||||||
|
getProcess(processId: string): Promise<Process | null>;
|
||||||
|
getProcesses(): Promise<Record<string, Process>>;
|
||||||
|
restoreProcessesFromBackUp(processes: Record<string, Process>): Promise<void>;
|
||||||
|
restoreProcessesFromDB(): Promise<void>;
|
||||||
|
clearSecretsFromDB(): Promise<void>;
|
||||||
|
restoreSecretsFromBackUp(secretsStore: SecretsStore): Promise<void>;
|
||||||
|
restoreSecretsFromDB(): Promise<void>;
|
||||||
|
decodeValue(value: number[]): any | null;
|
||||||
|
decryptAttribute(processId: string, state: ProcessState, attribute: string): Promise<any | null>;
|
||||||
|
getNotifications(): any[] | null;
|
||||||
|
setNotifications(notifications: any[]): void;
|
||||||
|
importJSON(backup: BackUp): Promise<void>;
|
||||||
|
createBackUp(): Promise<BackUp | null>;
|
||||||
|
device1: boolean;
|
||||||
|
device2Ready: boolean;
|
||||||
|
resetState(): void;
|
||||||
|
handleHandshakeMsg(url: string, parsedMsg: any): Promise<void>;
|
||||||
|
private lookForStateId;
|
||||||
|
/**
|
||||||
|
* Waits for at least one handshake message to be received from any connected relay.
|
||||||
|
* This ensures that the relay addresses are fully populated and the member list is updated.
|
||||||
|
* @returns A promise that resolves when at least one handshake message is received.
|
||||||
|
*/
|
||||||
|
private waitForHandshakeMessage;
|
||||||
|
/**
|
||||||
|
* Retourne la liste de tous les membres ordonnés par leur process id
|
||||||
|
* @returns Un tableau contenant tous les membres
|
||||||
|
*/
|
||||||
|
getAllMembersSorted(): Record<string, Member>;
|
||||||
|
getAllMembers(): Record<string, Member>;
|
||||||
|
getAddressesForMemberId(memberId: string): string[] | null;
|
||||||
|
compareMembers(memberA: string[], memberB: string[]): boolean;
|
||||||
|
handleCommitError(response: string): Promise<void>;
|
||||||
|
getRoles(process: Process): Record<string, RoleDefinition> | null;
|
||||||
|
getPublicData(process: Process): Record<string, any> | null;
|
||||||
|
getProcessName(process: Process): string | null;
|
||||||
|
getMyProcesses(): Promise<string[] | null>;
|
||||||
|
requestDataFromPeers(processId: string, stateIds: string[], roles: Record<string, RoleDefinition>[]): Promise<void>;
|
||||||
|
hexToBlob(hexString: string): Blob;
|
||||||
|
hexToUInt8Array(hexString: string): Uint8Array;
|
||||||
|
blobToHex(blob: Blob): Promise<string>;
|
||||||
|
getHashForFile(commitedIn: string, label: string, fileBlob: {
|
||||||
|
type: string;
|
||||||
|
data: Uint8Array;
|
||||||
|
}): string;
|
||||||
|
getMerkleProofForFile(processState: ProcessState, attributeName: string): MerkleProofResult;
|
||||||
|
validateMerkleProof(proof: MerkleProofResult, hash: string): boolean;
|
||||||
|
getLastCommitedState(process: Process): ProcessState | null;
|
||||||
|
getLastCommitedStateIndex(process: Process): number | null;
|
||||||
|
getUncommitedStates(process: Process): ProcessState[];
|
||||||
|
getStateFromId(process: Process, stateId: string): ProcessState | null;
|
||||||
|
getNextStateAfterId(process: Process, stateId: string): ProcessState | null;
|
||||||
|
isPairingProcess(roles: Record<string, RoleDefinition>): boolean;
|
||||||
|
updateMemberPublicName(process: Process, newName: string): Promise<ApiReturn>;
|
||||||
|
}
|
4
ihm/types/services/storage.service.d.ts
vendored
Normal file
4
ihm/types/services/storage.service.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { AxiosResponse } from 'axios';
|
||||||
|
export declare function storeData(servers: string[], key: string, value: Blob, ttl: number | null): Promise<AxiosResponse | null>;
|
||||||
|
export declare function retrieveData(servers: string[], key: string): Promise<ArrayBuffer | null>;
|
||||||
|
export declare function testData(servers: string[], key: string): Promise<Record<string, boolean | null> | null>;
|
17
ihm/types/services/token.d.ts
vendored
Normal file
17
ihm/types/services/token.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
interface TokenPair {
|
||||||
|
accessToken: string;
|
||||||
|
refreshToken: string;
|
||||||
|
}
|
||||||
|
export default class TokenService {
|
||||||
|
private static instance;
|
||||||
|
private readonly SECRET_KEY;
|
||||||
|
private readonly ACCESS_TOKEN_EXPIRATION;
|
||||||
|
private readonly REFRESH_TOKEN_EXPIRATION;
|
||||||
|
private readonly encoder;
|
||||||
|
private constructor();
|
||||||
|
static getInstance(): Promise<TokenService>;
|
||||||
|
generateSessionToken(origin: string): Promise<TokenPair>;
|
||||||
|
validateToken(token: string, origin: string): Promise<boolean>;
|
||||||
|
refreshAccessToken(refreshToken: string, origin: string): Promise<string | null>;
|
||||||
|
}
|
||||||
|
export {};
|
1
ihm/types/utils/document.utils.d.ts
vendored
Normal file
1
ihm/types/utils/document.utils.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function getCorrectDOM(componentTag: string): Node;
|
4
ihm/types/utils/html.utils.d.ts
vendored
Normal file
4
ihm/types/utils/html.utils.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export declare function interpolate(template: string, data: {
|
||||||
|
[key: string]: string;
|
||||||
|
}): string;
|
||||||
|
export declare function getCorrectDOM(componentTag: string): Node;
|
12
ihm/types/utils/messageMock.d.ts
vendored
Normal file
12
ihm/types/utils/messageMock.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
declare class MessageStore {
|
||||||
|
private readonly STORAGE_KEY;
|
||||||
|
private messages;
|
||||||
|
constructor();
|
||||||
|
private loadFromLocalStorage;
|
||||||
|
getMessages(): any[];
|
||||||
|
setMessages(messages: any[]): void;
|
||||||
|
private saveToLocalStorage;
|
||||||
|
addMessage(memberId: string | number, message: any): void;
|
||||||
|
}
|
||||||
|
export declare const messageStore: MessageStore;
|
||||||
|
export {};
|
23
ihm/types/utils/notification.store.d.ts
vendored
Normal file
23
ihm/types/utils/notification.store.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
interface INotification {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
time?: string;
|
||||||
|
memberId?: string;
|
||||||
|
}
|
||||||
|
declare class NotificationStore {
|
||||||
|
private static instance;
|
||||||
|
private notifications;
|
||||||
|
private constructor();
|
||||||
|
static getInstance(): NotificationStore;
|
||||||
|
addNotification(notification: INotification): void;
|
||||||
|
removeNotification(index: number): void;
|
||||||
|
getNotifications(): INotification[];
|
||||||
|
private saveToLocalStorage;
|
||||||
|
private loadFromLocalStorage;
|
||||||
|
private updateUI;
|
||||||
|
private renderNotificationBoard;
|
||||||
|
refreshNotifications(): void;
|
||||||
|
}
|
||||||
|
export declare const notificationStore: NotificationStore;
|
||||||
|
export {};
|
5
ihm/types/utils/service.utils.d.ts
vendored
Normal file
5
ihm/types/utils/service.utils.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export declare function splitPrivateData(data: Record<string, any>, privateFields: string[]): {
|
||||||
|
privateData: Record<string, any>;
|
||||||
|
publicData: Record<string, any>;
|
||||||
|
};
|
||||||
|
export declare function isValid32ByteHex(value: string): boolean;
|
8
ihm/types/utils/sp-address.utils.d.ts
vendored
Normal file
8
ihm/types/utils/sp-address.utils.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export declare function copyToClipboard(fullAddress: string): Promise<void>;
|
||||||
|
export declare function generateEmojiList(): string[];
|
||||||
|
export declare function addressToEmoji(text: string): Promise<string>;
|
||||||
|
export declare function displayEmojis(text: string): Promise<void>;
|
||||||
|
export declare function initAddressInput(): void;
|
||||||
|
export declare function prepareAndSendPairingTx(): Promise<void>;
|
||||||
|
export declare function generateQRCode(spAddress: string): Promise<void>;
|
||||||
|
export declare function generateCreateBtn(): Promise<void>;
|
2
ihm/types/utils/subscription.utils.d.ts
vendored
Normal file
2
ihm/types/utils/subscription.utils.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export declare function cleanSubscriptions(): void;
|
||||||
|
export declare function addSubscription(element: Element | Document, event: any, eventHandler: EventListenerOrEventListenerObject): void;
|
5
ihm/types/websockets.d.ts
vendored
Normal file
5
ihm/types/websockets.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type { AnkFlag } from 'pkg/sdk_client';
|
||||||
|
export declare function initWebsocket(url: string): Promise<void>;
|
||||||
|
export declare function sendMessage(flag: AnkFlag, message: string): void;
|
||||||
|
export declare function getUrl(): string;
|
||||||
|
export declare function close(): void;
|
15
jest.config.js
Normal file
15
jest.config.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/** @type {import('jest').Config} */
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
roots: ['<rootDir>/tests'],
|
||||||
|
moduleNameMapper: {
|
||||||
|
'^@/components/(.*)$': '<rootDir>/src/components/$1',
|
||||||
|
'^@/screens/(.*)$': '<rootDir>/src/screens/$1',
|
||||||
|
'^@/store/(.*)$': '<rootDir>/src/store/$1',
|
||||||
|
'^@/store$': '<rootDir>/src/store/index.ts',
|
||||||
|
'^@/services/(.*)$': '<rootDir>/src/services/$1',
|
||||||
|
'^@/bridge/(.*)$': '<rootDir>/src/bridge/$1'
|
||||||
|
},
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts']
|
||||||
|
};
|
10746
package-lock.json
generated
Normal file
10746
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
package.json
Normal file
40
package.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "sdk_wallet",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "Wallet Bitcoin mobile 4NK: conteneur React Native + WebView (ihm_client) + intégration sdk_client.",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "npm run prepare",
|
||||||
|
"prepare": "node -e \"console.log('prepare sdk_wallet')\"",
|
||||||
|
"build:ihm": "pwsh -File ./scripts/build-ihm.ps1",
|
||||||
|
"copy:ihm": "pwsh -File ./scripts/copy-ihm-dist.ps1",
|
||||||
|
"sync:ihm": "npm run build:ihm && npm run copy:ihm",
|
||||||
|
"typecheck": "tsc -p .",
|
||||||
|
"test": "jest --runInBand",
|
||||||
|
"lint": "echo 'lint placeholder'",
|
||||||
|
"build": "npm run typecheck",
|
||||||
|
"dev": "node -e \"console.log('Utilisez le dossier web/ pour l'hôte navigateur: npm run serve:web')\"",
|
||||||
|
"serve:web": "http-server ./web -p 5174 -c-1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@reduxjs/toolkit": "^2.2.5",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-native": "^0.74.7",
|
||||||
|
"react-native-safe-area-context": "^4.10.5",
|
||||||
|
"react-native-webview": "^13.8.6",
|
||||||
|
"react-redux": "^9.1.2",
|
||||||
|
"uuid": "^9.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^29.5.14",
|
||||||
|
"@types/react": "^18.3.3",
|
||||||
|
"@types/react-native": "^0.73.0",
|
||||||
|
"@types/uuid": "^9.0.8",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"jest-environment-jsdom": "^30.1.0",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
|
"ts-jest": "^29.2.5",
|
||||||
|
"typescript": "^5.5.4"
|
||||||
|
}
|
||||||
|
}
|
14
scripts/build-ihm.ps1
Normal file
14
scripts/build-ihm.ps1
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
param()
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
Push-Location "$PSScriptRoot/../..\ihm_client"
|
||||||
|
try {
|
||||||
|
if (Test-Path package-lock.json) {
|
||||||
|
npm ci --silent
|
||||||
|
} else {
|
||||||
|
npm install --silent
|
||||||
|
}
|
||||||
|
npm run build
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
20
scripts/checks/version_alignment.sh
Normal file
20
scripts/checks/version_alignment.sh
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/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"
|
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