From 7610ebcb696932e97d89cafebfeab8a0c5ecae03 Mon Sep 17 00:00:00 2001 From: Nicolas Cantu Date: Mon, 25 Aug 2025 18:46:06 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20int=C3=A9gration=20compl=C3=A8te=20de?= =?UTF-8?q?=20ihm=5Fclient=20dans=20l'infrastructure=204NK=5Fnode=20-=20Aj?= =?UTF-8?q?out=20du=20service=20ihm=5Fclient=20au=20docker-compose.yml=20-?= =?UTF-8?q?=20Configuration=20des=20variables=20d'environnement=20pour=20l?= =?UTF-8?q?a=20communication=20avec=20les=20SDK=20relays=20-=20Ajout=20du?= =?UTF-8?q?=20volume=20ihm=5Fclient=5Flogs=20-=20Cr=C3=A9ation=20des=20scr?= =?UTF-8?q?ipts=20de=20d=C3=A9marrage=20start-ihm-client.sh=20et=20start-4?= =?UTF-8?q?nk-node-with-ui.sh=20-=20Interface=20utilisateur=20accessible?= =?UTF-8?q?=20sur=20http://localhost:8080?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 30 + ihm_client/Dockerfile | 53 + ihm_client/index.html | 26 + ihm_client/nginx.conf | 96 + ihm_client/package.json | 51 + ihm_client/public/assets/4nk_image.png | Bin 0 -> 62845 bytes ihm_client/public/assets/4nk_revoke.jpg | Bin 0 -> 68608 bytes ihm_client/public/assets/bgd.webp | Bin 0 -> 520872 bytes ihm_client/public/assets/camera.jpg | Bin 0 -> 74603 bytes ihm_client/public/assets/home.js | 34 + ihm_client/public/assets/qr_code.png | Bin 0 -> 9072 bytes ihm_client/public/style/4nk.css | 877 ++++++++ ihm_client/public/style/account.css | 1507 ++++++++++++++ ihm_client/public/style/chat.css | 597 ++++++ ihm_client/public/style/signature.css | 1664 ++++++++++++++++ ihm_client/src/4nk.css | 818 ++++++++ ihm_client/src/components/header/header.html | 36 + ihm_client/src/components/header/header.ts | 220 +++ .../components/login-modal/login-modal.html | 14 + .../src/components/login-modal/login-modal.js | 13 + .../components/modal/confirmation-modal.html | 16 + .../components/modal/confirmation-modal.ts | 13 + .../src/components/modal/creation-modal.html | 14 + .../src/components/modal/waiting-modal.html | 8 + .../qrcode-scanner-component.ts | 73 + .../validation-modal/validation-modal.css | 70 + .../validation-modal/validation-modal.html | 11 + .../validation-modal/validation-modal.ts | 56 + .../validation-rule-modal.html | 42 + .../validation-rule-modal.ts | 61 + ihm_client/src/decs.d.ts | 10 + ihm_client/src/index.ts | 3 + ihm_client/src/interface/groupInterface.ts | 22 + ihm_client/src/interface/memberInterface.ts | 7 + .../interface/signatureResponseInterface.ts | 0 ihm_client/src/main.ts | 30 + .../mocks/mock-account/constAccountMock.ts | 272 +++ .../mock-account/interfacesAccountMock.ts | 45 + ihm_client/src/mocks/mock-chat/groupsMock.js | 52 + .../src/mocks/mock-chat/messagesMock.js | 64 + .../src/mocks/mock-signature/groupsMock.js | 471 +++++ .../src/mocks/mock-signature/membersMocks.js | 105 + .../src/mocks/mock-signature/messagesMock.ts | 64 + ihm_client/src/models/backup.model.ts | 7 + ihm_client/src/models/notification.model.ts | 30 + ihm_client/src/models/process.model.ts | 65 + ihm_client/src/models/signature.models.ts | 59 + .../src/pages/account/account-component.ts | 62 + ihm_client/src/pages/account/account.html | 10 + ihm_client/src/pages/account/account.ts | 1589 +++++++++++++++ .../src/pages/account/document-validation.ts | 321 +++ .../src/pages/account/key-value-section.ts | 196 ++ .../src/pages/account/process-creation.ts | 93 + ihm_client/src/pages/account/process.ts | 66 + ihm_client/src/pages/chat/chat-component.ts | 49 + ihm_client/src/pages/chat/chat.html | 14 + ihm_client/src/pages/chat/chat.ts | 1738 ++++++++++++++++ ihm_client/src/pages/home/home-component.ts | 49 + ihm_client/src/pages/home/home.html | 42 + ihm_client/src/pages/home/home.ts | 96 + .../process-element/process-component.ts | 51 + .../process-element/process-element.html | 5 + .../pages/process-element/process-element.ts | 50 + .../pages/process/process-list-component.ts | 49 + ihm_client/src/pages/process/process.html | 19 + ihm_client/src/pages/process/process.ts | 520 +++++ .../pages/signature/signature-component.ts | 58 + ihm_client/src/pages/signature/signature.html | 12 + ihm_client/src/pages/signature/signature.ts | 1758 +++++++++++++++++ ihm_client/src/router.ts | 945 +++++++++ ihm_client/src/scanner.js | 13 + .../src/service-workers/cache.worker.js | 8 + .../src/service-workers/database.worker.js | 281 +++ ihm_client/src/services/database.service.ts | 454 +++++ ihm_client/src/services/modal.service.ts | 240 +++ ihm_client/src/services/service.ts | 1752 ++++++++++++++++ ihm_client/src/services/storage.service.ts | 81 + ihm_client/src/services/token.ts | 87 + ihm_client/src/types/raw-imports.d.ts | 35 + ihm_client/src/types/sdk_client.d.ts | 258 +++ ihm_client/src/utils/document.utils.ts | 4 + ihm_client/src/utils/html.utils.ts | 8 + ihm_client/src/utils/messageMock.ts | 53 + ihm_client/src/utils/notification.store.ts | 96 + ihm_client/src/utils/service.utils.ts | 24 + ihm_client/src/utils/sp-address.utils.ts | 216 ++ ihm_client/src/utils/subscription.utils.ts | 19 + ihm_client/src/websockets.ts | 89 + ihm_client/start.sh | 124 ++ ihm_client/tsconfig.json | 29 + ihm_client/vite.config.ts | 81 + start-4nk-node-with-ui.sh | 77 + start-ihm-client.sh | 30 + 93 files changed, 19557 insertions(+) create mode 100644 ihm_client/Dockerfile create mode 100755 ihm_client/index.html create mode 100644 ihm_client/nginx.conf create mode 100755 ihm_client/package.json create mode 100755 ihm_client/public/assets/4nk_image.png create mode 100755 ihm_client/public/assets/4nk_revoke.jpg create mode 100755 ihm_client/public/assets/bgd.webp create mode 100755 ihm_client/public/assets/camera.jpg create mode 100755 ihm_client/public/assets/home.js create mode 100755 ihm_client/public/assets/qr_code.png create mode 100755 ihm_client/public/style/4nk.css create mode 100755 ihm_client/public/style/account.css create mode 100755 ihm_client/public/style/chat.css create mode 100755 ihm_client/public/style/signature.css create mode 100644 ihm_client/src/4nk.css create mode 100755 ihm_client/src/components/header/header.html create mode 100755 ihm_client/src/components/header/header.ts create mode 100755 ihm_client/src/components/login-modal/login-modal.html create mode 100755 ihm_client/src/components/login-modal/login-modal.js create mode 100755 ihm_client/src/components/modal/confirmation-modal.html create mode 100755 ihm_client/src/components/modal/confirmation-modal.ts create mode 100644 ihm_client/src/components/modal/creation-modal.html create mode 100644 ihm_client/src/components/modal/waiting-modal.html create mode 100644 ihm_client/src/components/qrcode-scanner/qrcode-scanner-component.ts create mode 100644 ihm_client/src/components/validation-modal/validation-modal.css create mode 100755 ihm_client/src/components/validation-modal/validation-modal.html create mode 100755 ihm_client/src/components/validation-modal/validation-modal.ts create mode 100644 ihm_client/src/components/validation-rule-modal/validation-rule-modal.html create mode 100644 ihm_client/src/components/validation-rule-modal/validation-rule-modal.ts create mode 100644 ihm_client/src/decs.d.ts create mode 100755 ihm_client/src/index.ts create mode 100644 ihm_client/src/interface/groupInterface.ts create mode 100644 ihm_client/src/interface/memberInterface.ts create mode 100644 ihm_client/src/interface/signatureResponseInterface.ts create mode 100644 ihm_client/src/main.ts create mode 100644 ihm_client/src/mocks/mock-account/constAccountMock.ts create mode 100644 ihm_client/src/mocks/mock-account/interfacesAccountMock.ts create mode 100755 ihm_client/src/mocks/mock-chat/groupsMock.js create mode 100755 ihm_client/src/mocks/mock-chat/messagesMock.js create mode 100755 ihm_client/src/mocks/mock-signature/groupsMock.js create mode 100755 ihm_client/src/mocks/mock-signature/membersMocks.js create mode 100755 ihm_client/src/mocks/mock-signature/messagesMock.ts create mode 100644 ihm_client/src/models/backup.model.ts create mode 100755 ihm_client/src/models/notification.model.ts create mode 100755 ihm_client/src/models/process.model.ts create mode 100755 ihm_client/src/models/signature.models.ts create mode 100644 ihm_client/src/pages/account/account-component.ts create mode 100755 ihm_client/src/pages/account/account.html create mode 100755 ihm_client/src/pages/account/account.ts create mode 100644 ihm_client/src/pages/account/document-validation.ts create mode 100644 ihm_client/src/pages/account/key-value-section.ts create mode 100644 ihm_client/src/pages/account/process-creation.ts create mode 100644 ihm_client/src/pages/account/process.ts create mode 100644 ihm_client/src/pages/chat/chat-component.ts create mode 100755 ihm_client/src/pages/chat/chat.html create mode 100755 ihm_client/src/pages/chat/chat.ts create mode 100644 ihm_client/src/pages/home/home-component.ts create mode 100755 ihm_client/src/pages/home/home.html create mode 100755 ihm_client/src/pages/home/home.ts create mode 100644 ihm_client/src/pages/process-element/process-component.ts create mode 100755 ihm_client/src/pages/process-element/process-element.html create mode 100755 ihm_client/src/pages/process-element/process-element.ts create mode 100644 ihm_client/src/pages/process/process-list-component.ts create mode 100755 ihm_client/src/pages/process/process.html create mode 100755 ihm_client/src/pages/process/process.ts create mode 100644 ihm_client/src/pages/signature/signature-component.ts create mode 100755 ihm_client/src/pages/signature/signature.html create mode 100755 ihm_client/src/pages/signature/signature.ts create mode 100755 ihm_client/src/router.ts create mode 100755 ihm_client/src/scanner.js create mode 100644 ihm_client/src/service-workers/cache.worker.js create mode 100755 ihm_client/src/service-workers/database.worker.js create mode 100755 ihm_client/src/services/database.service.ts create mode 100755 ihm_client/src/services/modal.service.ts create mode 100755 ihm_client/src/services/service.ts create mode 100644 ihm_client/src/services/storage.service.ts create mode 100644 ihm_client/src/services/token.ts create mode 100644 ihm_client/src/types/raw-imports.d.ts create mode 100644 ihm_client/src/types/sdk_client.d.ts create mode 100644 ihm_client/src/utils/document.utils.ts create mode 100755 ihm_client/src/utils/html.utils.ts create mode 100755 ihm_client/src/utils/messageMock.ts create mode 100755 ihm_client/src/utils/notification.store.ts create mode 100644 ihm_client/src/utils/service.utils.ts create mode 100755 ihm_client/src/utils/sp-address.utils.ts create mode 100755 ihm_client/src/utils/subscription.utils.ts create mode 100755 ihm_client/src/websockets.ts create mode 100644 ihm_client/start.sh create mode 100755 ihm_client/tsconfig.json create mode 100755 ihm_client/vite.config.ts create mode 100755 start-4nk-node-with-ui.sh create mode 100755 start-ihm-client.sh diff --git a/docker-compose.yml b/docker-compose.yml index e177cbca..73d22d9a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -218,6 +218,34 @@ services: retries: 3 start_period: 60s + ihm_client: + build: + context: ./ihm_client + dockerfile: Dockerfile + container_name: 4nk-ihm-client + ports: + - "8080:80" + environment: + - SDK_RELAY_WS_URL=ws://sdk_relay_1:8090 + - SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091 + - BITCOIN_RPC_URL=http://bitcoin:18443 + - BLINDBIT_URL=http://blindbit:8000 + volumes: + - ihm_client_logs:/var/log/nginx + networks: + - btcnet + depends_on: + - sdk_relay_1 + - sdk_relay_2 + - sdk_relay_3 + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--timeout=5", "--spider", "http://localhost"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + volumes: bitcoin_data: name: 4nk_node_bitcoin_data @@ -229,6 +257,8 @@ volumes: name: 4nk_node_sdk_relay_2_data sdk_relay_3_data: name: 4nk_node_sdk_relay_3_data + ihm_client_logs: + driver: local networks: btcnet: diff --git a/ihm_client/Dockerfile b/ihm_client/Dockerfile new file mode 100644 index 00000000..e3e37402 --- /dev/null +++ b/ihm_client/Dockerfile @@ -0,0 +1,53 @@ +# Dockerfile optimisé pour l'intégration dans 4NK_node +FROM node:20-alpine AS builder + +WORKDIR /app + +# Installation des dépendances système +RUN apk update && apk add --no-cache \ + git \ + build-base \ + python3 \ + make \ + g++ + +# Copie des fichiers de dépendances +COPY package*.json ./ + +# Installation des dépendances +RUN npm ci --only=production + +# Copie du code source +COPY . . + +# Build de l'application +RUN npm run build + +# Image de production +FROM nginx:alpine + +# Installation de Node.js pour les scripts de démarrage +RUN apk update && apk add --no-cache nodejs npm + +# Copie des fichiers buildés +COPY --from=builder /app/dist /usr/share/nginx/html +COPY --from=builder /app/package*.json /app/ + +# Copie de la configuration nginx optimisée pour 4NK_node +COPY nginx.4nk-node.conf /etc/nginx/conf.d/default.conf + +# Script de démarrage +COPY start-4nk-node.sh /start-4nk-node.sh +RUN chmod +x /start-4nk-node.sh + +# Exposition des ports +EXPOSE 80 3003 + +# Variables d'environnement pour 4NK_node +ENV SDK_RELAY_WS_URL=ws://sdk_relay_1:8090 +ENV SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091 +ENV BITCOIN_RPC_URL=http://bitcoin:18443 +ENV BLINDBIT_URL=http://blindbit:8000 + +# Point d'entrée +CMD ["/start-4nk-node.sh"] diff --git a/ihm_client/index.html b/ihm_client/index.html new file mode 100755 index 00000000..f7f60fb4 --- /dev/null +++ b/ihm_client/index.html @@ -0,0 +1,26 @@ + + + + + + + + + + + 4NK Application + + +
+
+ +
+ + + + \ No newline at end of file diff --git a/ihm_client/nginx.conf b/ihm_client/nginx.conf new file mode 100644 index 00000000..318b3e4a --- /dev/null +++ b/ihm_client/nginx.conf @@ -0,0 +1,96 @@ +server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # Gestion des fichiers statiques + location / { + try_files $uri $uri/ /index.html; + + # Headers de sécurité + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + } + + # Proxy vers sdk_relay WebSocket + location /ws/ { + proxy_pass http://sdk_relay_1:8090; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 86400; + proxy_send_timeout 86400; + } + + # Proxy vers sdk_relay HTTP API + location /api/ { + proxy_pass http://sdk_relay_1:8091/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # CORS headers + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE" always; + add_header Access-Control-Allow-Headers "Authorization,Content-Type,Accept,X-Requested-With" always; + + # Gestion des requêtes OPTIONS + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin "*"; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE"; + add_header Access-Control-Allow-Headers "Authorization,Content-Type,Accept,X-Requested-With"; + add_header Content-Length 0; + add_header Content-Type text/plain; + return 204; + } + } + + # Proxy vers Bitcoin Core RPC (si nécessaire) + location /bitcoin/ { + proxy_pass http://bitcoin:18443/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Authentification basique pour Bitcoin RPC + auth_basic "Bitcoin RPC"; + auth_basic_user_file /etc/nginx/.htpasswd; + } + + # Proxy vers Blindbit (si nécessaire) + location /blindbit/ { + proxy_pass http://blindbit:8000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Cache pour les assets statiques + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + try_files $uri =404; + } + + # Gestion des erreurs + error_page 404 /index.html; + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + root /usr/share/nginx/html; + } + + # Logs + access_log /var/log/nginx/ihm_client_access.log; + error_log /var/log/nginx/ihm_client_error.log; +} diff --git a/ihm_client/package.json b/ihm_client/package.json new file mode 100755 index 00000000..77528b6b --- /dev/null +++ b/ihm_client/package.json @@ -0,0 +1,51 @@ +{ + "name": "sdk_client", + "version": "1.0.0", + "description": "", + "main": "dist/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build_wasm": "./scripts/setup-remote-deps.sh", + "cleanup_deps": "./scripts/cleanup-deps.sh", + "start": "vite --host 0.0.0.0", + "build": "tsc && vite build", + "deploy": "sudo cp -r dist/* /var/www/html/", + "prettify": "prettier --config ./.prettierrc --write \"src/**/*{.ts,.html,.css,.js}\"", + "build:dist": "tsc -p tsconfig.build.json" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@rollup/plugin-typescript": "^12.1.1", + "copy-webpack-plugin": "^12.0.2", + "html-webpack-plugin": "^5.6.0", + "prettier": "^3.3.3", + "rimraf": "^6.0.1", + "ts-loader": "^9.5.1", + "typescript": "^5.3.3", + "vite": "^5.4.11", + "vite-plugin-static-copy": "^1.0.6", + "webpack": "^5.90.3", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.2" + }, + "dependencies": { + "@angular/elements": "^19.0.1", + "@types/jsonwebtoken": "^9.0.9", + "@types/qrcode": "^1.5.5", + "@vitejs/plugin-react": "^4.3.1", + "@vitejs/plugin-vue": "^5.0.5", + "axios": "^1.11.0", + "html5-qrcode": "^2.3.8", + "jose": "^6.0.13", + "jsonwebtoken": "^9.0.2", + "pdf-lib": "^1.17.1", + "qr-scanner": "^1.4.2", + "qrcode": "^1.5.4", + "sweetalert2": "^11.22.4", + "vite-plugin-copy": "^0.1.6", + "vite-plugin-html": "^3.2.2", + "vite-plugin-wasm": "^3.3.0" + } +} diff --git a/ihm_client/public/assets/4nk_image.png b/ihm_client/public/assets/4nk_image.png new file mode 100755 index 0000000000000000000000000000000000000000..d58693f1a03d4e31009b72cd8a21769440200b07 GIT binary patch literal 62845 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 U;dRa>rjT_Gmj3|bujfDi+2{c=761SM literal 0 HcmV?d00001 diff --git a/ihm_client/public/assets/bgd.webp b/ihm_client/public/assets/bgd.webp new file mode 100755 index 0000000000000000000000000000000000000000..aa457afa1e489818367225ab86a19ac786cbded1 GIT binary patch literal 520872 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

k<3Q^vxDP*08^ctv(g$8v5wAfC0!~y*x%Z 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≶w1#1xk3LJog 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 z%0D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

=)RC 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

wO*v-|?p7VJC7YRnBqE10ZT)a`l#) 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 T%Syq??H3uB9myUj2NC%{Hqm{N literal 0 HcmV?d00001 diff --git a/ihm_client/public/assets/camera.jpg b/ihm_client/public/assets/camera.jpg new file mode 100755 index 0000000000000000000000000000000000000000..adde7dd827ae726da58baea29086611903516300 GIT binary patch literal 74603 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

|-hC{$S3`O@W-5!EFD-kMaM#t}f0he!YHK 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 literal 0 HcmV?d00001 diff --git a/ihm_client/public/assets/home.js b/ihm_client/public/assets/home.js new file mode 100755 index 00000000..2a54d5d5 --- /dev/null +++ b/ihm_client/public/assets/home.js @@ -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(); + } + } \ No newline at end of file diff --git a/ihm_client/public/assets/qr_code.png b/ihm_client/public/assets/qr_code.png new file mode 100755 index 0000000000000000000000000000000000000000..defa41075ed357d834f6c574d0002e5f16ae6d84 GIT binary patch literal 9072 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 literal 0 HcmV?d00001 diff --git a/ihm_client/public/style/4nk.css b/ihm_client/public/style/4nk.css new file mode 100755 index 00000000..02b45334 --- /dev/null +++ b/ihm_client/public/style/4nk.css @@ -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%; +} \ No newline at end of file diff --git a/ihm_client/public/style/account.css b/ihm_client/public/style/account.css new file mode 100755 index 00000000..09fe0c6a --- /dev/null +++ b/ihm_client/public/style/account.css @@ -0,0 +1,1507 @@ +/* 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; + display: flex; + height: 100vh; + background-color: #e9edf1; + flex-direction: column; +} + +/*-------------------------------------- Avatar--------------------------------------*/ + +.avatar-section { + position: relative; + height: 60px; + width: 260px; + margin-left: 10px; + overflow: hidden; + border-radius: 10px; +} + +.user-info { + display: flex; + flex-direction: column; + color: white; +} + +.user-name, .user-lastname { + font-size: 0.9rem; + font-weight: 700; +} + + +.user-name:hover, .user-lastname:hover { + color: var(--accent-color); + cursor: pointer; +} + +.avatar-container { + width: 45px; + height: 45px; + flex-shrink: 0; +} + +.avatar-container { + width: 80px; /* Taille réduite */ + height: 80px; + margin: 0 auto; +} + +.avatar { + height: 100%; + border-radius: 50%; + object-fit: cover; + border: 2px solid white; +} + +.avatar img { + width: 100%; + height: 100%; + border-radius: 50%; +} + + +/*-------------------------------------- BANNER--------------------------------------*/ + +/* Styles pour la bannière avec image */ +.banner-image-container { + position: relative; + width: 100%; + height: 200px; + overflow: hidden; + border-radius: 10px; + margin-bottom: 15px; +} + +.banner-image { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: 1; +} + +.banner-content { + position: relative; + z-index: 2; + display: flex; + align-items: center; + gap: 15px; + height: 100%; + padding: 0 15px; + background: rgba(0, 0, 0, 0.3); + overflow: visible; +} + +.banner-content .avatar-container { + width: 45px; + height: 45px; + overflow: hidden; + border-radius: 50%; + border: 2px solid white; + transition: transform 0.3s ease; +} + +.banner-content .avatar { + width: 100%; + height: 100%; + object-fit: cover; + border: none; +} + +.banner-content .avatar-container:hover { + transform: scale(1.15); + cursor: pointer; +} + +/* Style pour le bouton de changement de bannière */ +.banner-upload-label { + display: block; + width: auto; + padding: 12px 20px; + background-color: var(--accent-color); + color: white; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s; + text-align: center; + font-size: 16px; + margin: 20px auto; + max-width: 250px; +} + +.banner-upload-label:hover { + background-color: #b06935; +} + +.banner-controls { + margin-top: 15px; + display: flex; + justify-content: center; + width: 100%; +} + +.banner-preview { + margin: 10px 0; +} + +.banner-preview h3 { + margin: 0 0 10px 0; + font-size: 18px; +} + +.banner-image-container { + height: 150px; + margin-bottom: 10px; +} + + +.nav-wrapper { + position: fixed; + background: white; + display: flex; + justify-content: space-between; + align-items: center; + height: 9vh; + width: 100vw; + left: 0; + top: 0; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + z-index: 1000; +} +/* Mise à jour des styles de la navbar pour inclure l'image de bannière */ +.nav-wrapper .avatar-section { + position: relative; + background: none; +} + +.nav-wrapper .banner-image { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: -1; + filter: brightness(0.7); +} + + + +/*-------------------------------------- Popup--------------------------------------*/ +/* Styles pour la popup */ +.popup { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1000; +} + +.popup-content { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: white; + padding: 20px; + border-radius: var(--border-radius); + box-shadow: var(--box-shadow); + width: 400px; + max-height: 80vh; + overflow-y: auto; +} +.popup-content h2 { + margin: 0 0 15px 0; + font-size: 24px; +} + +.close-popup { + position: absolute; + right: 15px; + top: 10px; + font-size: 24px; + cursor: pointer; + color: #666; +} + +.close-popup:hover { + color: #000; +} + +.popup-avatar { + text-align: center; + margin: 20px 0; + position: relative; +} + +.avatar-upload-label { + position: relative; + display: inline-block; + cursor: pointer; + width: 0%; + margin-left: -20%; +} + +.avatar-overlay { + position: absolute; + top: 0; + left: 50px; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.3s; +} + +.avatar-overlay span { + color: white; + font-size: 14px; + text-align: center; +} + +.avatar-upload-label:hover .avatar-overlay { + opacity: 1; +} + +.popup-avatar img { + width: 100px; + height: 100px; + border-radius: 50%; + border: 3px solid var(--accent-color); + object-fit: cover; +} + +.popup-info { + margin: 15px 0; +} + +.info-row { + margin: 8px 0; + display: flex; + align-items: center; + gap: 10px; +} + +.popup-info strong { + min-width: 100px; /* Largeur fixe pour l'alignement */ +} + +/* Editable Name and Lastname */ +.editable { + cursor: pointer; + display: inline-block; + min-width: 100px; + padding: 2px 5px; + transition: background-color 0.3s; +} + +.editable:hover { + background-color: #f0f0f0; +} + +.editable.editing { + background-color: white; + border: 1px solid var(--accent-color); + outline: none; +} + +.edit-input { + border: 1px solid var(--accent-color); + border-radius: 3px; + padding: 2px 5px; + font-size: inherit; + font-family: inherit; + outline: none; + width: 100%; + min-width: 100px; + margin: 0; + box-sizing: border-box; +} + +/* Boutons */ + + +.popup-button-container { + display: flex +; + flex-direction: column; + margin-top: 20px; + gap: 15px; +} + +.action-buttons-row { + display: flex +; + justify-content: space-between; + gap: 15px; +} +.banner-upload-label, +.export-btn, +.delete-account-btn { + padding: 8px 15px; + margin: 10px 0; + font-size: 14px; +} + +.delete-account-btn { + background-color: #dc3545; +} + + +.export-btn, +.delete-account-btn { + flex: 1; /* Pour qu'ils prennent la même largeur */ + padding: 12px 20px; + border: none; + border-radius: 8px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s; + color: white; + text-align: center; +} + + + +/* Séparateurs */ +.popup-info, +.export-section, +.delete-account-section { + padding-top: 10px; + margin-top: 10px; + border-top: 1px solid #eee; +} + +.logout-btn { + background-color: rgb(108, 117, 125); + font-size: 16px; + cursor: pointer; + color: white; + text-align: center; + flex: 1 1 0%; + padding: 12px 20px; + border-width: initial; + border-style: none; + border-color: initial; + border-image: initial; + border-radius: 8px; + transition: background-color 0.3s; +} + +/*-------------------------------------- Delete Account--------------------------------------*/ +.delete-account-section { + margin-top: 30px; + padding-top: 20px; + border-top: 1px solid #ddd; + text-align: center; +} + +.delete-account-btn { + background-color: #dc3545; +} + +.delete-account-btn:hover { + background-color: #c82333; +} + +/* Style pour la modal de confirmation */ +.confirm-delete-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.confirm-delete-content { + background-color: white; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + max-width: 400px; + width: 90%; + text-align: center; +} + +.confirm-delete-content h3 { + margin-top: 0; + color: #333; +} + +.confirm-delete-content p { + margin: 15px 0; + color: #666; +} + +.confirm-delete-buttons { + display: flex; + justify-content: center; + gap: 10px; + margin-top: 20px; +} + +.confirm-delete-buttons button { + padding: 8px 20px; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.3s; +} + +.confirm-delete-buttons .confirm-btn { + background-color: #dc3545; + color: white; +} + +.confirm-delete-buttons .confirm-btn:hover { + background-color: #c82333; +} + +.confirm-delete-buttons .cancel-btn { + background-color: #6c757d; + color: white; +} + +.confirm-delete-buttons .cancel-btn:hover { + background-color: #5a6268; +} + +/*-------------------------------------- Export--------------------------------------*/ +.export-section { + margin: 20px 0; + text-align: center; + padding: 15px 0; + border-top: 1px solid #ddd; +} + +.export-btn { + background-color: var(--accent-color); +} + +.export-btn:hover { + background-color: #b06935; +} + +.export-section, +.delete-account-section { + width: 100%; + display: flex; + justify-content: center; + margin: 15px 0; +} + +.export-btn, +.delete-account-btn { + width: 80%; + padding: 12px 20px; + border: none; + border-radius: 8px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s; + color: white; + text-align: center; +} + +/*-------------------------------------- NAVBAR--------------------------------------*/ + +.brand-logo { + font-size: 1.5rem; + 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 { + margin-right: 20px; +} + +.burger-menu { + height: 20px; + width: 20px; + margin-right: 1rem; + cursor: pointer; +} + +/* Par défaut, le menu est masqué */ +#menu { + display: none; + /* Menu caché par défaut */ + transition: display 0.3s ease-in-out; +} + + +.burger-menu { + width: 24px; + height: 24px; + cursor: pointer; +} + +.burger-menu-icon { + width: 100%; + height: 100%; +} +/* 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 information sur l'account */ + +.parameter-list { + width: 24.5%; + 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; +} + +.parameter-list ul { + padding: 15px; + margin-left: 10px; + border-radius: 8px; + background-color: #273646; + cursor: pointer; + transition: background-color 0.3s, box-shadow 0.3s; +} + + +.parameter-list ul:hover { + background-color: #34495e; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} + + +/* Zone des info des parametre */ + +.parameter-area { + display: flex; + flex-direction: column; + flex: 1; + min-width: 0; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + margin: 0px; + margin-top: 20px; + margin-left: 1%; + margin-bottom: -7px; +} + +/* En-tête du parametre */ +.parameter-header { + background-color: #34495e; + color: white; + padding: 15px; + font-size: 20px; + font-weight: bold; + border-radius: 10px 10px 0 0; + text-align: center; +} + +/* Style du tableau dans parameter-area */ +.parameter-table { + width: 100%; + border-collapse: collapse; + margin: 15px 0; + table-layout: fixed; +} + +.parameter-table th, .parameter-table td { + border: 1px solid #ddd; + padding: 8px; + white-space: nowrap; + overflow: hidden; + text-align: center; +} + +.parameter-table th { + background-color: var(--secondary-color); + color: white; + font-weight: bold; +} + +.parameter-table tr:nth-child(even) { + background-color: #f2f2f2; +} + + + +.parameter-table tr:hover { + background-color: #ddd; +} + +/* Conteneur pour les boutons */ +.button-container { + display: flex; + justify-content: center; + gap: 15px; + margin: 15px 0; +} + +/* Boutons "Ajouter une ligne" et "Confirmer" */ +.add-row-button, .confirm-all-button, .delete-row-button { + background-color: var(--accent-color); + color: white; + border: none; + padding: 8px 15px; + cursor: pointer; + border-radius: 5px; + font-size: 0.9em; + margin-right: 5px; +} + +.add-row-button:hover, .confirm-all-button:hover, .delete-row-button:hover { + background-color: #b06935; +} + + +.button-style { + background-color: var(--accent-color); + color: white; + border: none; + border-radius: 5px; + padding: 10px 20px; + cursor: pointer; + transition: background-color 0.3s; +} + +.button-style:hover { + background-color: darkorange; +} + +.content-container { + width: 100%; +} + +#pairing-content, +#wallet-content { + width: 100%; +} + +.editable-cell { + cursor: pointer; +} + +.editable-cell:hover { + background-color: #f5f5f5; +} + +.edit-input { + width: 100%; + padding: 5px; + box-sizing: border-box; + border: 1px solid #ddd; + border-radius: 4px; +} + +/*-------------------------------------- Notification--------------------------------------*/ +.notification-cell { + position: relative; +} + +.notification-bell { + position: relative; + display: inline-block; +} + +.notification-badge { + position: absolute; + top: -8px; + right: -8px; + background-color: red; + color: white; + border-radius: 50%; + padding: 2px 6px; + font-size: 12px; + min-width: 15px; + text-align: center; +} + +.fa-bell { + color: #666; + font-size: 20px; +} + + +/* Media Queries pour Mobile */ +@media screen and (max-width: 768px) { + /* Navbar */ + .nav-wrapper { + height: 9vh; + padding: 0; + display: flex; + justify-content: space-between; + align-items: center; + } + + /* Section avatar (gauche) */ + .avatar-section { + width: 200px; /* Largeur réduite */ + margin-left: 10px; + order: 0; /* Garde à gauche */ + } + + .avatar-container { + width: 35px; + height: 35px; + } + + .user-info span { + font-size: 0.8rem; + } + + /* Logo (centre) */ + .brand-logo { + order: 0; + flex: 0 0 auto; + padding: 0; + font-size: 1.2rem; + } + + /* Menu burger (droite) */ + .nav-right-icons { + order: 0; + width: auto; + padding-right: 15px; + } + + .burger-menu { + width: 24px; + height: 24px; + } + + /* Ajustements pour la bannière */ + .banner-image-container { + height: 100%; + } + + .banner-content { + padding: 0 10px; + } + + /* Style des boutons dans la popup */ + .button-container { + display: flex; + gap: 10px; + margin: 15px 0; + width: 100%; + } + + .export-btn, + .delete-account-btn { + flex: 1; + padding: 12px 15px; + border: none; + border-radius: 8px; + font-size: 14px; + cursor: pointer; + transition: background-color 0.3s; + color: white; + } + + .export-btn { + background-color: var(--accent-color); + } + + .delete-account-btn { + background-color: var(--danger-color); + } +} + +/* Media Queries pour très petits écrans */ +@media screen and (max-width: 380px) { + .avatar-section { + width: 150px; + } + + .user-info span { + font-size: 0.7rem; + } +} + +/* Style des boutons */ +.button-container { + display: flex; + gap: 15px; + margin: 15px 0; + width: 100%; +} + +.export-btn, +.delete-account-btn { + flex: 1; + padding: 12px 20px; + border: none; + border-radius: 8px; + color: white; + cursor: pointer; + transition: background-color 0.3s; + font-size: 14px; + display: block; +} + +.export-btn { + background-color: var(--accent-color); +} + +.delete-account-btn { + background-color: rgb(219, 17, 17); + display: block; + visibility: visible; +} + +.export-btn:hover { + background-color: #b06935; +} + +.delete-account-btn:hover { + background-color: #b60718; +} + +@media screen and (max-width: 768px) { + .button-container { + gap: 10px; + } + + .export-btn, + .delete-account-btn { + padding: 12px 15px; + font-size: 14px; + } +} + +/* Style pour les boutons de la popup */ +.popup-buttons { + display: flex; + gap: 15px; + margin: 15px 0; + width: 100%; +} + +/* Style pour les boutons d'action des tableaux */ +.button-container { + display: flex; + gap: 15px; + margin: 15px 0; + width: 100%; +} + +/* Style pour le header mobile */ +.mobile-nav { + display: none; + width: 100%; + padding: 10px; + background-color: #34495e; + overflow-x: auto; + white-space: nowrap; +} + +.mobile-nav ul { + display: flex; + gap: 10px; + margin: 0; + padding: 0; + list-style: none; +} + +/* Media Query pour mobile */ +@media screen and (max-width: 768px) { + .parameter-list { + display: flex; + width: 100%; + min-width: 100%; + height: auto; + overflow-x: auto; + background-color: rgb(31, 44, 61); + padding: 10px; + border-right: none; + border-bottom: 2px solid rgb(44, 62, 80); + } + + .mobile-nav { + display: flex; /* Affiche la navigation mobile */ + } + + .parameter-header { + display: flex; + flex-direction: column; + } + + .parameter-list-ul { + text-align: center; + flex: 1 1 0%; + margin: 0px 5px; + padding: 10px; + white-space: nowrap; + margin-bottom: none; + } + + .parameter-list-ul:hover { + background-color: #34495e; + } + + .container { + flex-direction: column; + } + + .parameter-area { + margin: -5px; + } +} + +/* Style pour le header et la navigation mobile */ +.parameter-header { + background-color: #34495e; + padding: 20px 0; + margin: 0; + width: 100%; +} + +.mobile-nav { + display: none; /* Par défaut caché */ + width: 100%; + padding: 10px; + background-color: #34495e; + overflow-x: auto; +} + +.mobile-nav ul { + display: flex; + gap: 10px; + margin: 0; + padding: 10px; + list-style: none; +} + +.mobile-nav li { + flex: 0 0 auto; + white-space: nowrap; +} + +/* Ajoutez ces styles pour la bannière dans la popup */ +.banner-container { + width: 100%; + margin-bottom: 20px; +} + +.banner-wrapper { + width: 100%; + height: 120px; + overflow: hidden; + position: relative; + border-radius: 10px; +} + +.banner-wrapper img { + width: 100%; + height: 100%; + object-fit: cover; + position: absolute; + top: 0; + left: 0; +} + +/* Mise à jour des styles existants */ +.popup-content { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: white; + padding: 20px; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + width: 90%; + max-width: 500px; + max-height: 80vh; + overflow-y: auto; +} + +/* Style pour le conteneur de la bannière */ +.banner-upload-label { + display: block; + width: auto; + padding: 12px 20px; + background-color: var(--accent-color); + color: white; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s; + text-align: center; + font-size: 16px; + margin: 10px auto; + max-width: 200px; +} + +/* ---------------------Style pour la popup de contrat--------------------- */ + +.contract-popup-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; + z-index: 1000; +} + +.contract-popup-content { + background: white; + padding: 30px; + border-radius: 8px; + max-width: 600px; + width: 90%; + max-height: 80vh; + overflow-y: auto; + position: relative; +} + +.close-contract-popup { + position: absolute; + top: 15px; + right: 15px; + background: none; + border: none; + font-size: 24px; + cursor: pointer; + color: #666; +} + +/* Style pour la popup d'alerte */ +.alert-popup { + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); + background-color: #f44336; + color: white; + padding: 15px 25px; + border-radius: 4px; + box-shadow: 0 2px 5px rgba(0,0,0,0.2); + z-index: 1000; + display: none; + animation: slideDown 0.3s ease-out; +} + +/* ---------------------Style pour la popup notification--------------------- */ + + +.notifications-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; +} + +.notifications-content { + position: relative; + background: white; + border-radius: 8px; + padding: 24px; + width: 90%; + max-width: 500px; +} + +.close-button { + position: absolute; + top: 15px; + right: 20px; + font-size: 24px; + color: #666; + cursor: pointer; + transition: color 0.2s; +} + +.close-button:hover { + color: #000; +} + +.notifications-title { + padding-right: 30px; /* Pour éviter que le titre ne chevauche le bouton de fermeture */ +} + +.notifications-title { + font-size: 24px; + color: #445B6E; + margin-bottom: 20px; + font-weight: 500; +} + +.notifications-list { + display: flex; + flex-direction: column; + gap: 16px; +} + +.notification-item { + display: flex; + align-items: flex-start; + padding: 12px 0; + border-bottom: 1px solid #eee; + cursor: pointer; +} + +.notification-status { + margin-right: 16px; + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; +} + +.dot-icon, .check-icon { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; +} + +.notification-content { + flex: 1; +} + +.notification-message { + font-size: 16px; + color: #333; + margin-bottom: 4px; +} + +.notification-date { + font-size: 14px; + color: #666; +} + +.notification-item:hover { + background-color: #f8f9fa; +} + +.notification-item.read { + opacity: 0.7; +} + +.notification-item.unread { + background-color: #fff; +} + +.close-notifications { + position: absolute; + top: 15px; + right: 15px; + border: none; + background: none; + font-size: 24px; + color: #666; + cursor: pointer; +} + +/*-------------------------------------- STYLE ACTION BUTTON ---------------------*/ + +.action-buttons-wrapper { + display: flex; + flex-direction: row; + gap: 10px; + justify-content: center; + margin: 20px 0; +} + +.action-button { + display: flex; + align-items: center; + justify-content: center; + padding: 0; + border-radius: 8px; + border: none; + font-size: 16px; + cursor: pointer; + transition: all 0.3s ease; + color: white; + height: 40px; + width: 40px; +} + +.confirm-button { + background-color: #4CAF50; +} + +.confirm-button:hover { + background-color: #3d8b40; + transform: translateY(-2px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); +} + +.cancel-button { + background-color: rgb(244, 67, 54); +} + +.cancel-button:hover { + background-color: #d32f2f; + transform: translateY(-2px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); +} + +.banner-image.clickable { + cursor: pointer; + transition: opacity 0.3s ease; +} + +.banner-image.clickable:hover { + opacity: 0.8; +} + +.parameter-list-ul.profile { + position: relative; + overflow: hidden; + max-height: 200px; + margin-bottom: 20px; +} + + +.profile-preview { + position: relative; + width: 100%; + height: 100%; +} + +.preview-banner { + position: relative; + width: 100%; + height: 120px; + overflow: hidden; +} + +.preview-banner-img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.preview-info { + position: relative; + display: flex; + align-items: center; + padding: 10px; + gap: 10px; + background: rgba(0, 0, 0, 0.3); +} + +.preview-avatar { + width: 45px; + height: 45px; + border-radius: 50%; + border: 2px solid white; +} + +/* ---------------------Style pour le QR code--------------------- */ + +.qr-code { + width: 50px; + height: 50px; + cursor: pointer; + transition: transform 0.2s ease; +} + +.qr-code:hover { + transform: scale(1.5); +} + +.qr-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.qr-modal-content { + background-color: white; + padding: 20px; + border-radius: 8px; + position: relative; + text-align: center; +} + +.close-qr-modal { + position: absolute; + right: 10px; + top: 5px; + font-size: 24px; + cursor: pointer; + color: #666; +} + +.close-qr-modal:hover { + color: #000; +} + +.qr-code-large { + max-width: 300px; + margin: 10px 0; +} + +.qr-address { + margin-top: 10px; + word-break: break-all; + font-size: 12px; + color: #666; +} + +.pairing-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.pairing-modal-content { + background-color: white; + padding: 2rem; + border-radius: 8px; + width: 90%; + max-width: 500px; +} + +.pairing-form { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.form-group label { + font-weight: bold; +} + +.button-group { + display: flex; + gap: 1rem; + justify-content: flex-end; + margin-top: 1rem; +} + +.button-group button { + padding: 0.5rem 1rem; + border-radius: 4px; + cursor: pointer; +} + +.confirm-button { + background-color: var(--accent-color); + color: white; + border: none; +} + +.cancel-button { + background-color: #ccc; + border: none; +} diff --git a/ihm_client/public/style/chat.css b/ihm_client/public/style/chat.css new file mode 100755 index 00000000..ad2f97f5 --- /dev/null +++ b/ihm_client/public/style/chat.css @@ -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); +} \ No newline at end of file diff --git a/ihm_client/public/style/signature.css b/ihm_client/public/style/signature.css new file mode 100755 index 00000000..2c8cf285 --- /dev/null +++ b/ihm_client/public/style/signature.css @@ -0,0 +1,1664 @@ +/* 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; + display: flex; + height: 100vh; + background-color: #e9edf1; + flex-direction: column; +} + + + +/* 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: 209vh; +} + + +/* 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: 10px; + 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); +} + + +/* Zone de chat */ + +.chat-area { + display: flex; + flex-direction: column; + flex: 1; + min-width: 0; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + margin: 0px; + margin-top: 20px; + margin-left: 1%; + margin-bottom: -7px; +} + +/* 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 { + max-width: 100%; + border-radius: 5px; + overflow-wrap: break-word; + word-wrap: break-word; + background-color: #f1f1f1; + display: flex; + flex-direction: column; +} + +.message-container .message { + align-self: flex-start; +} + +.message-container .message.user { + align-self: flex-end; + margin-left: auto; + color: white; +} + +.message { + padding: 12px 18px; + background-color: #e1e1e1; + border-radius: 15px; + max-width: 70%; + font-size: 16px; + line-height: 1.4; + margin-bottom: 0%; + white-space: pre-wrap; + word-wrap: break-word; + position: relative; + display: inline-block; +} + +/* Messages de l'utilisateur */ +.message.user { + background-color: #3498db; + color: white; + align-self: flex-end; + text-align: right; +} + +/* 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; + /* 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; +} + +#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; + } +} + +#process-details { + flex: 1; + background: white; + border-radius: 8px; + margin: 10px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + display: none; + overflow: hidden; +} + +.process-details-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px; + background: #f8f9fa; + border-bottom: 1px solid #eee; + border-radius: 8px 8px 0 0; +} + +.process-details-header h2 { + margin: 0; + color: #333; +} + +.close-btn { + background: none; + border: none; + font-size: 24px; + cursor: pointer; + color: #666; +} + +.close-btn:hover { + color: #333; +} + +.process-details-content { + padding: 20px; + overflow-y: auto; + height: calc(100% - 70px); +} + +.details-section { + margin-bottom: 30px; +} + +.details-section h3 { + color: #444; + margin-bottom: 15px; + padding-bottom: 8px; + border-bottom: 2px solid #f0f0f0; +} + +.documents-list { + list-style: none; + padding: 0; +} + +.documents-list li { + padding: 8px 0; + border-bottom: 1px solid #eee; +} + +.roles-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: 20px; +} + +.role-block { + background: #f8f9fa; + border-radius: 8px; + padding: 15px; + border: 1px solid #eee; +} + +.role-block h4 { + color: #555; + margin: 0 0 10px 0; + padding-bottom: 8px; + border-bottom: 1px solid #eee; +} + +.members-list { + list-style: none; + padding: 0; +} + +.members-list li { + padding: 8px 12px; + margin: 4px 0; + cursor: pointer; + border-radius: 4px; + transition: background-color 0.2s; +} + +.members-list li:hover { + background-color: #e9ecef; +} + +.group-list-item { + padding: 8px 16px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.group-item-container { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} + +.process-name { + flex-grow: 1; + cursor: pointer; +} + +.settings-icon { + cursor: pointer; + padding: 5px 8px; + margin-left: 10px; + border-radius: 4px; +} + +.settings-icon:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.process-details { + position: fixed; + top: 9vh; + right: 0; + bottom: 0; + left: 23.5%; + background-color: white; + box-sizing: border-box; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + border-radius: 8px; + margin: 10px; + z-index: 990; +} + +.process-details-content { + height: calc(100% - 60px); /* Ajusté pour tenir compte du header */ + overflow-y: auto; + padding: 20px; +} + +.documents-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 20px; + margin-top: 15px; +} + +.document-card { + background: white; + border-radius: 8px; + padding: 15px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + border: 1px solid #eee; +} + +.document-card.public { + border-left: 4px solid #4CAF50; +} + +.document-card.private { + border-left: 4px solid #FFC107; +} + +.document-card.confidential { + border-left: 4px solid #F44336; +} + +.document-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +.document-header h4 { + margin: 0; + color: #333; +} + +.document-visibility { + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + font-weight: bold; +} + +.public .document-visibility { + background-color: #E8F5E9; + color: #2E7D32; +} + +.private .document-visibility { + background-color: #FFF3E0; + color: #F57C00; +} + +.confidential .document-visibility { + background-color: #FFEBEE; + color: #C62828; +} + +.document-info { + margin: 10px 0; + font-size: 14px; + color: #666; +} + +.document-info p { + margin: 5px 0; +} + +.signatures-list { + margin-top: 10px; +} + +.signature-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px; + border-radius: 4px; + margin: 5px 0; + background-color: #f8f9fa; +} + +.signature-item.signed { + background-color: #E8F5E9; +} + +.signature-item.pending { + background-color: #FFF3E0; +} + +.signer-name { + font-weight: 500; +} + +.signature-status { + font-size: 12px; +} + +.signed .signature-status { + color: #2E7D32; +} + +.pending .signature-status { + color: #F57C00; +} + +.user-selector { + position: relative; + margin-right: 20px; +} + +#userSwitchBtn { + background: none; + border: none; + cursor: pointer; + padding: 8px 12px; + border-radius: 4px; + display: flex; + align-items: center; + color: var(--primary-color); +} + +#userSwitchBtn:hover { + background-color: rgba(0, 0, 0, 0.05); +} + +.current-user-info { + display: flex; + align-items: center; + gap: 8px; +} + +.user-avatar { + background-color: var(--primary-color); + color: white; + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; +} + +.user-list { + position: absolute; + top: 100%; + right: 0; + background: white; + border-radius: 4px; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); + display: none; + z-index: 1000; + max-height: 400px; + overflow-y: auto; + width: 250px; +} + +.user-list.show { + display: block; +} + +.user-list-item { + padding: 8px 16px; + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; +} + +.user-list-item:hover { + background-color: rgba(0, 0, 0, 0.05); +} + +.user-list-item .user-avatar { + width: 24px; + height: 24px; + font-size: 12px; +} + +.user-list-item .user-email { + font-size: 12px; + color: #666; + display: block; +} + +.document-card { + margin-bottom: 20px; + padding: 10px; + border: 1px solid #ccc; + border-radius: 5px; +} + +.progress-bar { + background-color: #f3f3f3; + border-radius: 5px; + height: 10px; + width: 100%; + margin-top: 5px; +} + +.progress { + background-color: #4caf50; /* Couleur de la barre de progression */ + height: 100%; + border-radius: 5px; +} + +.new-request-btn { + background-color: #4caf50; + color: white; + border: none; + border-radius: 5px; + padding: 10px 15px; + cursor: pointer; + margin-left: 10px; +} + +.new-request-btn:hover { + background-color: #45a049; +} + +.header-buttons { + display: flex; + align-items: center; + gap: 10px; +} + +.close-btn { + background: none; + border: none; + font-size: 24px; + cursor: pointer; + color: #666; +} + +.close-btn:hover { + color: #333; +} + +.new-request-view { + padding: 20px; + background-color: white; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + margin: 20px; +} + +.upload-area { + border: 2px dashed #ccc; + padding: 20px; + text-align: center; + margin: 20px 0; +} + +.upload-icon { + font-size: 50px; + margin: 10px 0; +} + +/* New Request View */ +.new-request-view { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: white; + z-index: 1000; + padding: 20px; + box-sizing: border-box; + overflow-y: auto; +} + +.upload-area { + border: 2px dashed #ccc; + padding: 40px; + text-align: center; + margin: 20px auto; + max-width: 600px; + background-color: #f9f9f9; + border-radius: 8px; + cursor: pointer; +} + +.upload-icon { + font-size: 50px; + margin: 20px 0; +} + +.new-request-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 60px; + padding: 0 20px; +} + +.upload-area { + border: 2px dashed #ccc; + padding: 40px; + text-align: center; + margin: 20px auto; + max-width: 600px; + background-color: #f9f9f9; + border-radius: 8px; + cursor: pointer; +} + +.details-header { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #f8f9fa; + padding: 5px 20px; + border-radius:20px; +} + +.header-buttons { + display: flex; + align-items: center; + gap: 10px; + flex-direction: row; +} + +.close-btn { + background: none; + border: none; + font-size: 24px; + cursor: pointer; + color: #666; + padding: 5px; +} + +.close-btn:hover { + color: #333; +} + +.new-request-btn { + background-color: #4caf50; + color: white; + border: none; + border-radius: 5px; + padding: 8px 16px; + cursor: pointer; + /* margin-left: 10px; <- Supprimez cette ligne si elle existe */ +} + +.new-request-btn:hover { + background-color: #45a049; +} + +/* Ajoutez ces styles à votre fichier CSS existant */ +.document-card.vierge { + background-color: #fff3cd; + border: 2px solid #ffeeba; +} + +.document-card.vierge .document-header { + background-color: #fff3cd; +} + +.document-card.vierge h4 { + color: #856404; +} + +.document-card.vierge .document-info { + color: #856404; +} + +/* Style pour l'emoji d'avertissement */ +.document-card.vierge h4::before { + margin-right: 8px; +} + +.vierge-documents-container { + padding: 20px; + overflow-y: auto; + max-height: calc(100vh - 150px); +} + +.document-form { + padding: 15px; + background-color: #fff; + border-radius: 0 0 5px 5px; + display: flex; + gap: 20px; +} + +.form-left { + flex: 1; + display: flex; + flex-direction: column; + gap: 15px; +} + +.form-right { + display: flex; + flex-direction: column; + align-items: flex-end; /* Aligner le bouton à droite */ +} + +.form-group { + flex: 2; + display: flex; + flex-direction: column; + margin-bottom: 15px; +} + +.form-group-members { + flex: 2; + display: flex; + flex-direction: column; + margin-bottom: 15px; + font-weight: bold; +} + +.submit-btn { + background-color: #4caf50; + color: white; + border: none; + border-radius: 5px; + padding: 10px 15px; + cursor: pointer; + margin-left: 47%; + margin-top: 20px; +} + +.submit-btn:hover { + background-color: #45a049; +} + +.upload-format { + font-size: 12px; + color: #666; + margin: 5px 0; +} + +.browse-btn { + background-color: #4caf50; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + margin-top: 10px; +} + +.browse-btn:hover { + background-color: #45a049; +} + +.document-selector { + padding: 20px; + margin-bottom: 20px; +} + +.document-selector label { + display: block; + margin-bottom: 10px; + font-weight: bold; + color: #666; +} + +.document-selector select { + width: 100%; + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 16px; + background-color: white; +} + +#selected-document-form { + padding: 0 20px; + overflow: auto; + height: 65%; +} + +/* Style pour l'option avec l'emoji */ +.document-selector select option { + padding: 10px; + font-size: 14px; +} + +.members-selection { + max-height: 200px; + overflow-y: auto; + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px; + background-color: white; +} + +.member-checkbox { + display: flex; + align-items: center; + margin-bottom: 8px; + padding: 5px; +} + +.member-checkbox:hover { + background-color: #f5f5f5; +} + +.member-checkbox input[type="checkbox"] { + margin-right: 10px; +} + +.member-checkbox label { + cursor: pointer; + flex: 1; +} + +/* Style pour le conteneur des membres */ +.members-selection-container { + display: flex; + flex-direction: column; + align-items: center; /* Centrer la liste des membres */ + width: 100%; +} + +#members-list { + width: 60%; + height: 100%; + margin-bottom: -40px; + margin-top: 10px; +} + +/* Style pour le label des membres */ +.members-selection-container label { + font-weight: bold; /* Mettre le texte en gras */ + margin-bottom: 10px; /* Espacement en bas */ + display: block; /* Affichage en bloc */ +} + +/* Style pour les cases à cocher des membres */ +.member-checkbox { + display: flex; + align-items: center; + margin-bottom: 8px; + padding: 5px; + border-radius: 4px; /* Coins arrondis */ + transition: background-color 0.2s; /* Transition pour l'effet de survol */ +} + +.member-checkbox:hover { + background-color: #e9ecef; /* Couleur de fond au survol */ +} + +/* Style pour les labels */ +.form-group label { + font-weight: bold; + margin-bottom: 5px; +} + +/* Style pour les champs de saisie */ +.form-group input, +.form-group select { + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 16px; + width: 80%; +} + +.add-members-btn { + background-color: #4caf50; + color: white; + border: none; + border-radius: 5px; + padding: 10px 15px; + cursor: pointer; + margin-top: 10px; /* Espacement au-dessus du bouton */ +} + +.add-members-btn:hover { + background-color: #45a049; +} + +/* Styles pour l'overlay et la modale */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 999; +} + +.modal { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: white; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + z-index: 1000; + width: 25%; + max-width: 500px; +} + +.modal-content { + max-height: 70vh; + overflow-y: auto; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 10px; + margin-top: 20px; + padding-top: 10px; + border-top: 1px solid #eee; +} + +.confirm-btn { + background-color: #4caf50; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; +} + +.confirm-btn:hover { + background-color: #45a049; +} + +.selected-member { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #f5f5f5; + padding: 8px 12px; + margin: 4px 0; + border-radius: 4px; +} + +.cancel-btn { + background-color: #df2020; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; +} + +.cancel-btn:hover { + background-color: #c62828; / +} + +.remove-member-btn { + background-color: #dc3545; + color: white; + border: none; + border-radius: 50%; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 16px; + padding: 0; + margin-left: 8px; +} + +.remove-member-btn:hover { + background-color: #c82333; +} + +#description { + height: 100px; + width: 100%; + border-radius: 20px; + padding: 10px 0; + padding-left: 10px; + resize: none; + +} + +.role-item-container { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + padding: 5px 0; +} + +.role-item-container span:last-child { + margin-left: 10px; +} + +.document-card .new-request-btn { + margin-top: 60%; + margin-left: 65%; + padding: 6px 12px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 0.9em; +} + +.document-card .new-request-btn:hover { + background-color: #45a049; +} + +/* Styles pour la modale de nouveau document */ +.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-document { + background: white; + padding: 20px; + border-radius: 8px; + width: 97%; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +.modal-header h2 { + margin: 0; + color: #333; +} + +.modal-body { + margin-bottom: 20px; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 10px; + padding-top: 20px; + border-top: 1px solid #eee; +} + +.modal-document { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} +.form-group { + margin-bottom: 15px; +} + +.form-group label { + display: block; + margin-bottom: 5px; + font-weight: bold; + color: #555; +} + +.form-control { + width: 100%; + padding: 8px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 14px; +} + +.form-row { + display: flex; + gap: 15px; + margin-bottom: 15px; +} + +.form-group.half { + flex: 1; + margin-bottom: 0; /* Annule la marge du form-group standard */ +} + +.selected-signatories { + margin: 10px 0; + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + min-height: 50px; +} + +.signatory-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 5px; + margin: 5px 0; + background: #f5f5f5; + border-radius: 4px; +} + +.remove-btn { + background: none; + border: none; + color: #dc3545; + cursor: pointer; + font-size: 18px; + padding: 0 5px; +} + +.remove-btn:hover { + color: #bd2130; +} + +.btn-primary { + background: #4CAF50; + color: white; + padding: 10px 20px; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.btn-primary:hover { + background: #45a049; +} + +.btn-secondary { + background: #6c757d; + color: white; + padding: 8px 15px; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.btn-secondary:hover { + background: #5a6268; +} + +.signatories-list { + max-height: 300px; + overflow-y: auto; +} + +.signatory-option { + display: flex; + align-items: center; + gap: 10px; + padding: 8px; + border-bottom: 1px solid #eee; +} + +.role-select { + padding: 4px; + border: 1px solid #ddd; + border-radius: 4px; + margin-left: auto; +} + +.role-section { + margin-bottom: 20px; + padding: 10px; + background: #f8f9fa; + border-radius: 4px; +} + +.role-section h4 { + margin: 0 0 10px 0; + color: #495057; +} + +.members-selection { + max-height: 300px; + overflow-y: auto; + padding: 10px; + border: 1px solid #dee2e6; + border-radius: 4px; +} + +input[type="file"] { + padding: 10px; + border: 1px dashed #ccc; + border-radius: 4px; + width: 100%; + margin-top: 5px; +} + +.file-upload-container { + border: 2px dashed #ccc; + padding: 20px; + text-align: center; + margin: 10px 0; + border-radius: 5px; + cursor: pointer; +} + +.file-upload-container:hover { + background-color: #f5f5f5; + border-color: #666; +} + +.file-upload-container.dragover { + background-color: #f0f0f0; + border-color: #4CAF50; +} + +.file-list { + margin-top: 10px; +} + +.file-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px; + margin: 5px 0; + background: #f5f5f5; + border-radius: 4px; +} + +.file-info { + display: flex; + gap: 10px; + align-items: center; +} + +.remove-file { + background: none; + border: none; + color: #ff4444; + cursor: pointer; + font-size: 18px; +} + +#fileInput { + display: none; +} + +.required-signatories { + margin: 10px 0; +} + +.signatory-item { + display: flex; + align-items: center; + gap: 10px; + padding: 8px; + margin: 5px 0; + background: #f5f5f5; + border-radius: 4px; +} + +.signatory-item.locked { + background: #e8e8e8; + cursor: not-allowed; +} + +.member-name { + font-weight: 500; +} + +.role-info { + color: #666; + font-size: 0.9em; +} + +.lock-icon { + margin-left: auto; + opacity: 0.6; +} + +/* Style pour la popup d'alerte */ +.alert-popup { + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); + background-color: #f44336; + color: white; + padding: 15px 25px; + border-radius: 4px; + box-shadow: 0 2px 5px rgba(0,0,0,0.2); + z-index: 1000; + display: none; + animation: slideDown 0.3s ease-out; +} + +.sign-button { + background-color: #4CAF50; + color: white; + padding: 8px 16px; + border: none; + border-radius: 4px; + cursor: pointer; + margin-top: 10px; +} + +.sign-button:hover { + background-color: #45a049; +} + +.sign-button:disabled { + background-color: #cccccc; + cursor: not-allowed; +} + +.modal-document { + background: white; + border-radius: 8px; + max-width: 800px; + width: 90%; + max-height: 95vh; + overflow-y: auto; + position: relative; +} + +.document-details { + padding: 20px; +} + +.info-section { + margin: 20px 0; + background: #f8f9fa; + padding: 15px; + border-radius: 6px; +} + +.info-row { + display: flex; + justify-content: space-between; + margin-bottom: 10px; +} + +.label { + font-weight: bold; + color: #666; +} + +.description-section { + margin: 20px 0; +} + +.signatures-section { + margin: 20px 0; +} + +.signature-item { + display: flex; + justify-content: space-between; + padding: 8px; + border-bottom: 1px solid #eee; +} + +.signature-item.signed { + background-color: #e8f5e9; +} + +.signature-item.pending { + background-color: #fff3e0; +} + +.files-section { + margin: 20px 0; +} + +.file-item { + display: flex; + align-items: center; + padding: 8px; + background: #f8f9fa; + margin-bottom: 5px; + border-radius: 4px; +} + +.file-icon { + margin-right: 10px; +} + +.download-link { + margin-left: auto; +} + +.confirmation-section { + margin-top: 30px; + text-align: center; +} + +.warning-text { + color: #f44336; + margin-bottom: 15px; +} + +.sign-confirm-btn { + background-color: #4CAF50; + color: white; + padding: 10px 20px; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.sign-confirm-btn:hover { + background-color: #45a049; +} + +.signature-slider-container { + margin: 20px 20%; + padding: 10px; +} + +.slider-track { + position: relative; + background: #e0e0e0; + height: 40px; + border-radius: 20px; + display: flex; + align-items: center; + overflow: hidden; +} + +.slider-handle { + position: absolute; + left: 0; + width: 40px; + height: 40px; + background: #4CAF50; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + touch-action: none; + z-index: 1; +} + +.slider-arrow { + color: white; + font-size: 20px; +} + +.slider-text { + width: 100%; + text-align: center; + color: #666; + user-select: none; +} \ No newline at end of file diff --git a/ihm_client/src/4nk.css b/ihm_client/src/4nk.css new file mode 100644 index 00000000..180690f6 --- /dev/null +++ b/ihm_client/src/4nk.css @@ -0,0 +1,818 @@ +:host { + --primary-color: #3a506b; + /* Bleu métallique */ + --secondary-color: #b0bec5; + /* Gris acier */ + --accent-color: #d68c45; + /* Cuivre */ + font-family: Arial, sans-serif; + height: 100vh; + font-size: 16px; +} +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; + background-color: #f4f4f4; + background-image: url(../assets/bgd.webp); + background-repeat: no-repeat; + background-size: cover; + background-blend-mode: soft-light; + height: 100vh; +} +.message { + margin: 30px 0; + font-size: 14px; + overflow-wrap: anywhere; +} + +.message strong { + font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif; + font-size: 20px; +} + +/** Modal Css */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + justify-content: center; + align-items: center; + z-index: 3; +} + +.modal-content { + width: 55%; + height: 30%; + background-color: white; + border-radius: 4px; + padding: 20px; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; +} + +.modal-title { + margin: 0; + padding-bottom: 8px; + width: 100%; + font-size: 0.9rem; + border-bottom: 1px solid #ccc; +} + +.confirmation-box { + /* margin-top: 20px; */ + align-content: center; + width: 70%; + height: 20%; + /* padding: 20px; */ + font-size: 1.5em; + color: #333333; + top: 5%; + position: relative; +} + +.nav-wrapper { + position: fixed; + background: radial-gradient(circle, white, var(--primary-color)); + /* background-color: #CFD8DC; */ + display: flex; + justify-content: flex-end; + align-items: center; + color: #37474f; + height: 9vh; + width: 100vw; + left: 0; + top: 0; + box-shadow: + 0px 8px 10px -5px rgba(0, 0, 0, 0.2), + 0px 16px 24px 2px rgba(0, 0, 0, 0.14), + 0px 6px 30px 5px rgba(0, 0, 0, 0.12); + + .nav-right-icons { + display: flex; + .notification-container { + position: relative; + display: inline-block; + } + .notification-bell, + .burger-menu { + z-index: 3; + height: 20px; + width: 20px; + margin-right: 1rem; + } + .notification-badge { + position: absolute; + top: -0.7rem; + left: -0.8rem; + background-color: red; + color: white; + border-radius: 50%; + padding: 2.5px 6px; + font-size: 0.8rem; + font-weight: bold; + } + } + .notification-board { + position: absolute; + width: 20rem; + min-height: 8rem; + background-color: white; + right: 0.5rem; + display: none; + border-radius: 4px; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + display: none; + + .notification-element { + padding: 0.8rem 0; + width: 100%; + &:hover { + background-color: rgba(26, 28, 24, 0.08); + } + } + .notification-element:not(:last-child) { + border-bottom: 1px solid; + } + } +} + +.brand-logo { + height: 100%; + width: 100vw; + align-content: center; + position: relative; + display: flex; + position: absolute; + align-items: center; + justify-content: center; + text-align: center; + font-size: 1.5em; + font-weight: bold; +} + +.container { + text-align: center; + display: grid; + height: 100vh; + grid-template-columns: repeat(7, 1fr); + gap: 10px; + grid-auto-rows: 10vh 15vh 1fr; +} +.title-container { + grid-column: 2 / 7; + grid-row: 2; +} +.page-container { + grid-column: 2 / 7; + grid-row: 3; + justify-content: center; + display: flex; + padding: 1rem; + box-sizing: border-box; + max-height: 60vh; +} + +h1 { + font-size: 2em; + margin: 20px 0; +} +@media only screen and (min-width: 600px) { + .tab-container { + display: none; + } + .page-container { + display: flex; + align-items: center; + } + .process-container { + grid-column: 3 / 6; + grid-row: 3; + + .card { + min-width: 40vw; + } + } + .separator { + width: 2px; + background-color: #78909c; + height: 80%; + margin: 0 0.5em; + } + .tab-content { + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: center; + height: 80%; + } +} + +@media only screen and (max-width: 600px) { + .process-container { + grid-column: 2 / 7; + grid-row: 3; + } + .container { + grid-auto-rows: 10vh 15vh 15vh 1fr; + } + .tab-container { + grid-column: 1 / 8; + grid-row: 3; + } + .page-container { + grid-column: 2 / 7; + grid-row: 4; + } + .separator { + display: none; + } + .tabs { + display: flex; + flex-grow: 1; + overflow: hidden; + z-index: 1; + border-bottom-style: solid; + border-bottom-width: 1px; + border-bottom-color: #e0e4d6; + } + + .tab { + flex: 1; + text-align: center; + padding: 10px 0; + cursor: pointer; + font-size: 1rem; + color: #6200ea; + &:hover { + background-color: rgba(26, 28, 24, 0.08); + } + } + .tab.active { + border-bottom: 2px solid #6200ea; + font-weight: bold; + } + + .card.tab-content { + display: none; + } + + .tab-content.active { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 80%; + } + .modal-content { + width: 80%; + height: 20%; + } +} + +.qr-code { + display: flex; + justify-content: center; + align-items: center; + height: 200px; +} + +.emoji-display { + font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif; + font-size: 20px; +} + +#emoji-display-2 { + margin-top: 30px; + font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif; + font-size: 20px; +} + +#okButton { + margin-bottom: 2em; + cursor: pointer; + background-color: #d0d0d7; + color: white; + border-style: none; + border-radius: 5px; + color: #000; + padding: 2px; + margin-top: 10px; +} + +.pairing-request { + font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif; + font-size: 14px; + margin-top: 0px; +} + +.create-btn { + margin-bottom: 2em; + cursor: pointer; + background-color: #d0d0d7; + color: white; + border-style: none; + border-radius: 5px; + color: #000; + padding: 2px; +} + +.camera-card { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + /* height: 200px; */ +} + +.btn { + display: inline-block; + padding: 10px 20px; + background-color: var(--primary-color); + color: white; + text-align: center; + border-radius: 5px; + cursor: pointer; + text-decoration: none; +} + +.btn:hover { + background-color: #3700b3; +} + +.card { + min-width: 300px; + border: 1px solid #e0e0e0; + border-radius: 8px; + background-color: white; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + box-sizing: border-box; + overflow: hidden; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + height: 60vh; + justify-content: flex-start; + padding: 1rem; + overflow-y: auto; +} + +.card-content { + flex-grow: 1; + flex-direction: column; + display: flex; + justify-content: flex-start; + align-items: center; + text-align: left; + font-size: 0.8em; + position: relative; + left: 2vw; + width: 90%; + .process-title { + font-weight: bold; + padding: 1rem 0; + } + .process-element { + padding: 0.4rem 0; + &:hover { + background-color: rgba(26, 28, 24, 0.08); + } + &.selected { + background-color: rgba(26, 28, 24, 0.08); + } + } +} + +.card-description { + padding: 20px; + font-size: 1rem; + color: #333; + width: 90%; + height: 50px; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 0px; +} + +.card-action { + width: 100%; +} + +.menu-content { + display: none; + position: absolute; + top: 3.4rem; + right: 1rem; + background-color: white; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + border-radius: 5px; + overflow: hidden; +} + +.menu-content a { + display: block; + padding: 10px 20px; + text-decoration: none; + color: #333; + border-bottom: 1px solid #e0e0e0; + &:hover { + background-color: rgba(26, 28, 24, 0.08); + } +} + +.menu-content a:last-child { + border-bottom: none; +} + +.qr-code-scanner { + display: none; +} + +/* QR READER */ +#qr-reader div { + position: inherit; +} + +#qr-reader div img { + top: 15px; + right: 25px; + margin-top: 5px; +} + +/* INPUT CSS **/ +.input-container { + position: relative; + width: 100%; + background-color: #eceff1; +} + +.input-field { + width: 36vw; + padding: 10px 0; + font-size: 1rem; + border: none; + border-bottom: 1px solid #ccc; + outline: none; + background: transparent; + transition: border-color 0.3s; +} + +.input-field:focus { + border-bottom: 2px solid #6200ea; +} + +.input-label { + position: absolute; + margin-top: -0.5em; + top: 0; + left: 0; + padding: 10px 0; + font-size: 1rem; + color: #999; + pointer-events: none; + transition: + transform 0.3s, + color 0.3s, + font-size 0.3s; +} + +.input-field:focus + .input-label, +.input-field:not(:placeholder-shown) + .input-label { + transform: translateY(-20px); + font-size: 0.8em; + color: #6200ea; +} + +.input-underline { + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 2px; + background-color: #6200ea; + transition: + width 0.3s, + left 0.3s; +} + +.input-field:focus ~ .input-underline { + width: 100%; + left: 0; +} + +.dropdown-content { + position: absolute; + flex-direction: column; + top: 100%; + left: 0; + width: 100%; + max-height: 150px; + overflow-y: auto; + border: 1px solid #ccc; + border-radius: 4px; + background-color: white; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + display: none; + z-index: 1; +} + +.dropdown-content span { + padding: 10px; + cursor: pointer; + list-style: none; +} + +.dropdown-content span:hover { + background-color: #f0f0f0; +} + +/** AUTOCOMPLETE **/ + +select[data-multi-select-plugin] { + display: none !important; +} + +.multi-select-component { + width: 36vw; + padding: 5px 0; + font-size: 1rem; + border: none; + border-bottom: 1px solid #ccc; + outline: none; + background: transparent; + display: flex; + flex-direction: row; + height: auto; + width: 100%; + -o-transition: + border-color ease-in-out 0.15s, + box-shadow ease-in-out 0.15s; + transition: + border-color ease-in-out 0.15s, + box-shadow ease-in-out 0.15s; +} + +.autocomplete-list { + border-radius: 4px 0px 0px 4px; +} + +.multi-select-component:focus-within { + box-shadow: inset 0px 0px 0px 2px #78abfe; +} + +.multi-select-component .btn-group { + display: none !important; +} + +.multiselect-native-select .multiselect-container { + width: 100%; +} + +.selected-processes { + background-color: white; + padding: 0.4em; +} + +.selected-wrapper { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + display: inline-block; + border: 1px solid #d9d9d9; + background-color: #ededed; + white-space: nowrap; + margin: 1px 5px 5px 0; + height: 22px; + vertical-align: top; + cursor: default; +} + +.selected-wrapper .selected-label { + max-width: 514px; + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 4px; + vertical-align: top; +} + +.selected-wrapper .selected-close { + display: inline-block; + text-decoration: none; + font-size: 14px; + line-height: 1.49rem; + margin-left: 5px; + padding-bottom: 10px; + height: 100%; + vertical-align: top; + padding-right: 4px; + opacity: 0.2; + color: #000; + text-shadow: 0 1px 0 #fff; + font-weight: 700; +} + +.search-container { + display: flex; + flex-direction: row; +} + +.search-container .selected-input { + background: none; + border: 0; + height: 20px; + width: 60px; + padding: 0; + margin-bottom: 6px; + -webkit-box-shadow: none; + box-shadow: none; +} + +.search-container .selected-input:focus { + outline: none; +} + +.dropdown-icon.active { + transform: rotateX(180deg); +} + +.search-container .dropdown-icon { + display: inline-block; + padding: 10px 5px; + position: absolute; + top: 5px; + right: 5px; + width: 10px; + height: 10px; + border: 0 !important; + /* needed */ + -webkit-appearance: none; + -moz-appearance: none; + /* SVG background image */ + background-image: url('data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23818181%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C0%2C0%2C1.414%2C0l5-5a1%2C1%2C0%2C1%2C0-1.414-1.414Z%22%20fill%3D%22%23818181%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E'); + background-position: center; + background-size: 10px; + background-repeat: no-repeat; +} + +.search-container ul { + position: absolute; + list-style: none; + padding: 0; + z-index: 3; + margin-top: 29px; + width: 100%; + right: 0px; + background: #fff; + border: 1px solid #ccc; + border-top: none; + border-bottom: none; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); +} + +.search-container ul :focus { + outline: none; +} + +.search-container ul li { + display: block; + text-align: left; + padding: 8px 29px 2px 12px; + border-bottom: 1px solid #ccc; + font-size: 14px; + min-height: 31px; +} + +.search-container ul li:first-child { + border-top: 1px solid #ccc; + border-radius: 4px 0px 0 0; +} + +.search-container ul li:last-child { + border-radius: 4px 0px 0 0; +} + +.search-container ul li:hover.not-cursor { + cursor: default; +} + +.search-container ul li:hover { + color: #333; + background-color: #f0f0f0; + border-color: #adadad; + cursor: pointer; +} + +/* Adding scrool to select options */ +.autocomplete-list { + max-height: 130px; + overflow-y: auto; +} + +/**************************************** Process page card ******************************************************/ +.process-card { + min-width: 300px; + border: 1px solid #e0e0e0; + border-radius: 8px; + background-color: white; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + overflow: hidden; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + min-height: 40vh; + max-height: 60vh; + justify-content: space-between; + padding: 1rem; + overflow-y: auto; +} + +.process-card-content { + text-align: left; + font-size: 0.8em; + position: relative; + left: 2vw; + width: 90%; + .process-title { + font-weight: bold; + padding: 1rem 0; + } + .process-element { + padding: 0.4rem 0; + &:hover { + background-color: rgba(26, 28, 24, 0.08); + } + &.selected { + background-color: rgba(26, 28, 24, 0.08); + } + } + .selected-process-zone { + background-color: rgba(26, 28, 24, 0.08); + } +} + +.process-card-description { + padding: 20px; + font-size: 1rem; + color: #333; + width: 90%; +} + +.process-card-action { + width: 100%; +} + +/**************************************** Select Member Home Page ******************************************************/ +.custom-select { + width: 100%; + max-height: 150px; + overflow-y: auto; + direction: ltr; + background-color: white; + border: 1px solid #ccc; + border-radius: 4px; + margin: 10px 0; +} + +.custom-select option { + padding: 8px 12px; + cursor: pointer; +} + +.custom-select option:hover { + background-color: #f0f0f0; +} + +.custom-select::-webkit-scrollbar { + width: 8px; +} + +.custom-select::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.custom-select::-webkit-scrollbar-thumb { + background: #888; + border-radius: 4px; +} + +.custom-select::-webkit-scrollbar-thumb:hover { + background: #555; +} \ No newline at end of file diff --git a/ihm_client/src/components/header/header.html b/ihm_client/src/components/header/header.html new file mode 100755 index 00000000..9d2ae652 --- /dev/null +++ b/ihm_client/src/components/header/header.html @@ -0,0 +1,36 @@ + diff --git a/ihm_client/src/components/header/header.ts b/ihm_client/src/components/header/header.ts new file mode 100755 index 00000000..9e3ae9cc --- /dev/null +++ b/ihm_client/src/components/header/header.ts @@ -0,0 +1,220 @@ +import ModalService from '~/services/modal.service'; +import { INotification } from '../../models/notification.model'; +import { currentRoute, navigate } from '../../router'; +import Services from '../../services/service'; +import { BackUp } from '~/models/backup.model'; + +let notifications = []; + +export async function unpair() { + const service = await Services.getInstance(); + await service.unpairDevice(); + await navigate('home'); +} + +(window as any).unpair = unpair; + +function toggleMenu() { + const menu = document.getElementById('menu'); + if (menu) { + if (menu.style.display === 'block') { + menu.style.display = 'none'; + } else { + menu.style.display = 'block'; + } + } +} +(window as any).toggleMenu = toggleMenu; + +async function getNotifications() { + const service = await Services.getInstance(); + notifications = service.getNotifications() || []; + return notifications; +} +function openCloseNotifications() { + const notifications = document.querySelector('.notification-board') as HTMLDivElement; + notifications.style.display = notifications?.style.display === 'none' ? 'block' : 'none'; +} + +(window as any).openCloseNotifications = openCloseNotifications; + +export async function initHeader() { + if (currentRoute === 'account') { + // Charger le profile-header + const profileContainer = document.getElementById('profile-header-container'); + if (profileContainer) { + const profileHeaderHtml = await fetch('/src/components/profile-header/profile-header.html').then((res) => res.text()); + profileContainer.innerHTML = profileHeaderHtml; + + // Initialiser les données du profil + loadUserProfile(); + } + } + if (currentRoute === 'home') { + hideSomeFunctionnalities(); + } else { + fetchNotifications(); + setInterval(fetchNotifications, 2 * 60 * 1000); + } +} + +function hideSomeFunctionnalities() { + const bell = document.querySelector('.bell-icon') as HTMLDivElement; + if (bell) bell.style.display = 'none'; + const notifBadge = document.querySelector('.notification-badge') as HTMLDivElement; + if (notifBadge) notifBadge.style.display = 'none'; + const actions = document.querySelectorAll('.menu-content a') as NodeListOf; + const excludedActions = ['Import', 'Export']; + for (const action of actions) { + if (!excludedActions.includes(action.innerHTML)) { + action.style.display = 'none'; + } + } +} + +async function setNotification(notifications: any[]): Promise { + const badge = document.querySelector('.notification-badge') as HTMLDivElement; + const noNotifications = document.querySelector('.no-notification') as HTMLDivElement; + if (notifications?.length) { + badge.innerText = notifications.length.toString(); + const notificationBoard = document.querySelector('.notification-board') as HTMLDivElement; + notificationBoard.querySelectorAll('.notification-element')?.forEach((elem) => elem.remove()); + noNotifications.style.display = 'none'; + for (const notif of notifications) { + const notifElement = document.createElement('div'); + notifElement.className = 'notification-element'; + notifElement.setAttribute('notif-id', notif.processId); + notifElement.innerHTML = ` +
Validation required :
+
${notif.processId}
+ `; + // this.addSubscription(notifElement, 'click', 'goToProcessPage') + notificationBoard.appendChild(notifElement); + notifElement.addEventListener('click', async () => { + const modalService = await ModalService.getInstance(); + modalService.injectValidationModal(notif); + }); + } + } else { + noNotifications.style.display = 'block'; + } +} + +async function fetchNotifications() { + const service = await Services.getInstance(); + const data = service.getNotifications() || []; + await setNotification(data); +} + +async function loadUserProfile() { + // Charger les données du profil depuis le localStorage + const userName = localStorage.getItem('userName'); + const userLastName = localStorage.getItem('userLastName'); + const userAvatar = localStorage.getItem('userAvatar') || 'https://via.placeholder.com/150'; + const userBanner = localStorage.getItem('userBanner') || 'https://via.placeholder.com/800x200'; + + // Mettre à jour les éléments du DOM + const nameElement = document.querySelector('.user-name'); + const lastNameElement = document.querySelector('.user-lastname'); + const avatarElement = document.querySelector('.avatar'); + const bannerElement = document.querySelector('.banner-image'); + + if (nameElement) nameElement.textContent = userName; + if (lastNameElement) lastNameElement.textContent = userLastName; + if (avatarElement) (avatarElement as HTMLImageElement).src = userAvatar; + if (bannerElement) (bannerElement as HTMLImageElement).src = userBanner; +} + +async function importJSON() { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.json'; + + input.onchange = async (e) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onload = async (e) => { + try { + const content: BackUp = JSON.parse(e.target?.result as string); + const service = await Services.getInstance(); + await service.importJSON(content); + alert('Import réussi'); + window.location.reload(); + } catch (error) { + alert("Erreur lors de l'import: " + error); + } + }; + reader.readAsText(file); + } + }; + + input.click(); +} + +(window as any).importJSON = importJSON; + +async function createBackUp() { + const service = await Services.getInstance(); + const backUp = await service.createBackUp(); + if (!backUp) { + console.error("No device to backup"); + return; + } + + try { + const backUpJson = JSON.stringify(backUp, null, 2) + const blob = new Blob([backUpJson], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.href = url; + a.download = '4nk-backup.json'; + a.click(); + + URL.revokeObjectURL(url); + + console.log('Backup successfully prepared for download'); + } catch (e) { + console.error(e); + } +} + +(window as any).createBackUp = createBackUp; + +async function disconnect() { + console.log('Disconnecting...'); + try { + localStorage.clear(); + + await new Promise((resolve, reject) => { + const request = indexedDB.deleteDatabase('4nk'); + request.onsuccess = () => { + console.log('IndexedDB deleted successfully'); + resolve(); + }; + request.onerror = () => reject(request.error); + request.onblocked = () => { + console.log('Database deletion was blocked'); + resolve(); + }; + }); + + const registrations = await navigator.serviceWorker.getRegistrations(); + await Promise.all(registrations.map(registration => registration.unregister())); + console.log('Service worker unregistered'); + + await navigate('home'); + + setTimeout(() => { + window.location.href = window.location.origin; + }, 100); + + } catch (error) { + console.error('Error during disconnect:', error); + // force reload + window.location.href = window.location.origin; + } +} + +(window as any).disconnect = disconnect; \ No newline at end of file diff --git a/ihm_client/src/components/login-modal/login-modal.html b/ihm_client/src/components/login-modal/login-modal.html new file mode 100755 index 00000000..d402de9f --- /dev/null +++ b/ihm_client/src/components/login-modal/login-modal.html @@ -0,0 +1,14 @@ + diff --git a/ihm_client/src/components/login-modal/login-modal.js b/ihm_client/src/components/login-modal/login-modal.js new file mode 100755 index 00000000..d9c49d7f --- /dev/null +++ b/ihm_client/src/components/login-modal/login-modal.js @@ -0,0 +1,13 @@ +import Routing from '/src/services/routing.service.ts'; + +const router = await Routing.getInstance(); +export async function confirmLogin() { + router.confirmLogin(); +} + +export async function closeLoginModal() { + router.closeLoginModal(); +} + +window.confirmLogin = confirmLogin; +window.closeLoginModal = closeLoginModal; diff --git a/ihm_client/src/components/modal/confirmation-modal.html b/ihm_client/src/components/modal/confirmation-modal.html new file mode 100755 index 00000000..6c0f6c4e --- /dev/null +++ b/ihm_client/src/components/modal/confirmation-modal.html @@ -0,0 +1,16 @@ + diff --git a/ihm_client/src/components/modal/confirmation-modal.ts b/ihm_client/src/components/modal/confirmation-modal.ts new file mode 100755 index 00000000..292d875d --- /dev/null +++ b/ihm_client/src/components/modal/confirmation-modal.ts @@ -0,0 +1,13 @@ +import ModalService from '../../services/modal.service'; + +const modalService = await ModalService.getInstance(); +// export async function confirm() { +// modalService.confirmPairing(); +// } + +export async function closeConfirmationModal() { + modalService.closeConfirmationModal(); +} + +(window as any).confirm = confirm; +(window as any).closeConfirmationModal = closeConfirmationModal; diff --git a/ihm_client/src/components/modal/creation-modal.html b/ihm_client/src/components/modal/creation-modal.html new file mode 100644 index 00000000..231ac877 --- /dev/null +++ b/ihm_client/src/components/modal/creation-modal.html @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/ihm_client/src/components/modal/waiting-modal.html b/ihm_client/src/components/modal/waiting-modal.html new file mode 100644 index 00000000..5fb70d43 --- /dev/null +++ b/ihm_client/src/components/modal/waiting-modal.html @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/ihm_client/src/components/qrcode-scanner/qrcode-scanner-component.ts b/ihm_client/src/components/qrcode-scanner/qrcode-scanner-component.ts new file mode 100644 index 00000000..1e39d3ba --- /dev/null +++ b/ihm_client/src/components/qrcode-scanner/qrcode-scanner-component.ts @@ -0,0 +1,73 @@ +import QrScanner from 'qr-scanner'; +import Services from '../../services/service'; +import { prepareAndSendPairingTx } from '~/utils/sp-address.utils'; + +export default class QrScannerComponent extends HTMLElement { + videoElement: any; + wrapper: any; + qrScanner: any; + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.wrapper = document.createElement('div'); + this.wrapper.style.position = 'relative'; + this.wrapper.style.width = '150px'; + this.wrapper.style.height = '150px'; + + this.videoElement = document.createElement('video'); + this.videoElement.style.width = '100%'; + document.body?.append(this.wrapper); + this.wrapper.prepend(this.videoElement); + } + + connectedCallback() { + this.initializeScanner(); + } + + async initializeScanner() { + if (!this.videoElement) { + console.error('Video element not found!'); + return; + } + console.log('🚀 ~ QrScannerComponent ~ initializeScanner ~ this.videoElement:', this.videoElement); + this.qrScanner = new QrScanner(this.videoElement, (result) => this.onQrCodeScanned(result), { + highlightScanRegion: true, + highlightCodeOutline: true, + }); + + try { + await QrScanner.hasCamera(); + this.qrScanner.start(); + this.videoElement.style = 'height: 200px; width: 200px'; + this.shadowRoot?.appendChild(this.wrapper); + } catch (e) { + console.error('No camera found or error starting the QR scanner', e); + } + } + + async onQrCodeScanned(result: any) { + console.log(`QR Code detected:`, result); + const data = result.data; + const scannedUrl = new URL(data); + + // Extract the 'sp_address' parameter + const spAddress = scannedUrl.searchParams.get('sp_address'); + if (spAddress) { + // Call the sendPairingTx function with the extracted sp_address + try { + await prepareAndSendPairingTx(); + } catch (e) { + console.error('Failed to pair:', e); + } + } + this.qrScanner.stop(); // if you want to stop scanning after one code is detected + } + + disconnectedCallback() { + if (this.qrScanner) { + this.qrScanner.destroy(); + } + } +} + +customElements.define('qr-scanner', QrScannerComponent); diff --git a/ihm_client/src/components/validation-modal/validation-modal.css b/ihm_client/src/components/validation-modal/validation-modal.css new file mode 100644 index 00000000..b6e93818 --- /dev/null +++ b/ihm_client/src/components/validation-modal/validation-modal.css @@ -0,0 +1,70 @@ +.validation-modal { + display: block; /* Show the modal for demo purposes */ + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0, 0, 0); + background-color: rgba(0, 0, 0, 0.4); + padding-top: 60px; +} +.modal-content { + background-color: #fefefe; + margin: 5% auto; + padding: 20px; + border: 1px solid #888; + width: 80%; + height: fit-content; +} +.modal-title { + font-size: 24px; + font-weight: bold; + margin-bottom: 20px; +} +.validation-box { + margin-bottom: 15px; + width: 100%; +} +.expansion-panel-header { + background-color: #e0e0e0; + padding: 10px; + cursor: pointer; +} +.expansion-panel-body { + display: none; + background-color: #fafafa; + padding: 10px; + border-top: 1px solid #ddd; +} +.expansion-panel-body pre { + background-color: #f6f8fa; + padding: 10px; + border-left: 4px solid #d1d5da; + overflow-x: auto; +} +.diff { + display: flex; + justify-content: space-between; + margin-bottom: 10px; +} +.diff-side { + width: 48%; + padding: 10px; +} +.diff-old { + background-color: #fee; + border: 1px solid #f00; +} +.diff-new { + background-color: #e6ffe6; + border: 1px solid #0f0; +} +.radio-buttons { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} diff --git a/ihm_client/src/components/validation-modal/validation-modal.html b/ihm_client/src/components/validation-modal/validation-modal.html new file mode 100755 index 00000000..780e489b --- /dev/null +++ b/ihm_client/src/components/validation-modal/validation-modal.html @@ -0,0 +1,11 @@ +
+ +
diff --git a/ihm_client/src/components/validation-modal/validation-modal.ts b/ihm_client/src/components/validation-modal/validation-modal.ts new file mode 100755 index 00000000..711aff21 --- /dev/null +++ b/ihm_client/src/components/validation-modal/validation-modal.ts @@ -0,0 +1,56 @@ +import ModalService from '~/services/modal.service'; + +async function validate() { + console.log('==> VALIDATE'); + const modalservice = await ModalService.getInstance(); + modalservice.closeValidationModal(); +} + +export async function initValidationModal(processDiffs: any) { +console.log("🚀 ~ initValidationModal ~ processDiffs:", processDiffs) +for(const diff of processDiffs.diffs) { + let diffs = '' + for(const value of diff) { + diffs+= ` +
+ + +
+
+
+
-${value.previous_value}
+
+
+
+${value.new_value}
+
+
+ ` + } + + const state = ` +
+
State ${diff[0].new_state_merkle_root}
+
+ ${diffs} +
+
+ ` + const box = document.querySelector('.validation-box') + if(box) box.innerHTML += state +} +document.querySelectorAll('.expansion-panel-header').forEach((header) => { + header.addEventListener('click', function (event) { + const target = event.target as HTMLElement; + const body = target.nextElementSibling as HTMLElement; + if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block'; + }); +}); +} + +(window as any).validate = validate; diff --git a/ihm_client/src/components/validation-rule-modal/validation-rule-modal.html b/ihm_client/src/components/validation-rule-modal/validation-rule-modal.html new file mode 100644 index 00000000..75669805 --- /dev/null +++ b/ihm_client/src/components/validation-rule-modal/validation-rule-modal.html @@ -0,0 +1,42 @@ +
+
+

+ Add Validation Rule +

+ + + + + + + +
+ + +
+
+
diff --git a/ihm_client/src/components/validation-rule-modal/validation-rule-modal.ts b/ihm_client/src/components/validation-rule-modal/validation-rule-modal.ts new file mode 100644 index 00000000..121d954e --- /dev/null +++ b/ihm_client/src/components/validation-rule-modal/validation-rule-modal.ts @@ -0,0 +1,61 @@ +export interface ValidationRule { + quorum: number; + fields: string[]; + min_sig_member: number; +} + +/** + * Loads and injects the modal HTML into the document if not already loaded. + */ +export async function loadValidationRuleModal(templatePath: string = '/src/components/validation-rule-modal/validation-rule-modal.html') { + if (document.getElementById('validation-rule-modal')) return; + + const res = await fetch(templatePath); + const html = await res.text(); + + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = html; + + const modal = tempDiv.querySelector('#validation-rule-modal'); + if (!modal) { + throw new Error('Modal HTML missing #validation-rule-modal'); + } + + document.body.appendChild(modal); +} + +/** + * Opens the modal and lets the user input a ValidationRule. + * Calls the callback with the constructed rule on submit. + */ +export function showValidationRuleModal(onSubmit: (rule: ValidationRule) => void) { + const modal = document.getElementById('validation-rule-modal')!; + const quorumInput = document.getElementById('vr-quorum') as HTMLInputElement; + const minsigInput = document.getElementById('vr-minsig') as HTMLInputElement; + const fieldsInput = document.getElementById('vr-fields') as HTMLInputElement; + + const cancelBtn = document.getElementById('vr-cancel')!; + const submitBtn = document.getElementById('vr-submit')!; + + // Reset values + quorumInput.value = ''; + minsigInput.value = ''; + fieldsInput.value = ''; + + modal.style.display = 'flex'; + + cancelBtn.onclick = () => { + modal.style.display = 'none'; + }; + + submitBtn.onclick = () => { + const rule: ValidationRule = { + quorum: parseInt(quorumInput.value), + min_sig_member: parseInt(minsigInput.value), + fields: fieldsInput.value.split(',').map(f => f.trim()).filter(Boolean), + }; + + modal.style.display = 'none'; + onSubmit(rule); + }; +} diff --git a/ihm_client/src/decs.d.ts b/ihm_client/src/decs.d.ts new file mode 100644 index 00000000..d137c884 --- /dev/null +++ b/ihm_client/src/decs.d.ts @@ -0,0 +1,10 @@ +declare class AccountComponent extends HTMLElement { + _callback: any; + constructor(); + connectedCallback(): void; + fetchData(): Promise; + set callback(fn: any); + get callback(): any; + render(): void; +} +export { AccountComponent }; diff --git a/ihm_client/src/index.ts b/ihm_client/src/index.ts new file mode 100755 index 00000000..2fbab88e --- /dev/null +++ b/ihm_client/src/index.ts @@ -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'; diff --git a/ihm_client/src/interface/groupInterface.ts b/ihm_client/src/interface/groupInterface.ts new file mode 100644 index 00000000..87ba2db1 --- /dev/null +++ b/ihm_client/src/interface/groupInterface.ts @@ -0,0 +1,22 @@ +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; + }>; + commonDocuments: Array<{ + id: number; + name: string; + visibility: string; + description: string; + createdAt?: string | null; + deadline?: string | null; + signatures?: DocumentSignature[]; + status?: string; + }>; +} diff --git a/ihm_client/src/interface/memberInterface.ts b/ihm_client/src/interface/memberInterface.ts new file mode 100644 index 00000000..274cd2ca --- /dev/null +++ b/ihm_client/src/interface/memberInterface.ts @@ -0,0 +1,7 @@ +export interface Member { + id: string | number; + name: string; + email?: string; + avatar?: string; + processRoles?: Array<{ processId: number | string; role: string }>; +} diff --git a/ihm_client/src/interface/signatureResponseInterface.ts b/ihm_client/src/interface/signatureResponseInterface.ts new file mode 100644 index 00000000..e69de29b diff --git a/ihm_client/src/main.ts b/ihm_client/src/main.ts new file mode 100644 index 00000000..b0f47a4a --- /dev/null +++ b/ihm_client/src/main.ts @@ -0,0 +1,30 @@ +import { SignatureComponent } from './pages/signature/signature-component'; +import { SignatureElement } from './pages/signature/signature'; +/*import { ChatComponent } from './pages/chat/chat-component'; +import { ChatElement } from './pages/chat/chat';*/ +import { AccountComponent } from './pages/account/account-component'; +import { AccountElement } from './pages/account/account'; + +export { SignatureComponent, SignatureElement, AccountComponent, AccountElement }; + +declare global { + interface HTMLElementTagNameMap { + 'signature-component': SignatureComponent; + 'signature-element': SignatureElement; + /*'chat-component': ChatComponent; + 'chat-element': ChatElement;*/ + 'account-component': AccountComponent; + 'account-element': AccountElement; + } +} + +// Configuration pour le mode indépendant +if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) { + // Initialiser les composants si nécessaire + customElements.define('signature-component', SignatureComponent); + customElements.define('signature-element', SignatureElement); + /*customElements.define('chat-component', ChatComponent); + customElements.define('chat-element', ChatElement);*/ + customElements.define('account-component', AccountComponent); + customElements.define('account-element', AccountElement); +} diff --git a/ihm_client/src/mocks/mock-account/constAccountMock.ts b/ihm_client/src/mocks/mock-account/constAccountMock.ts new file mode 100644 index 00000000..34adaa44 --- /dev/null +++ b/ihm_client/src/mocks/mock-account/constAccountMock.ts @@ -0,0 +1,272 @@ +export const ALLOWED_ROLES = ['User', 'Member', 'Peer', 'Payment', 'Deposit', 'Artefact', 'Resolve', 'Backup']; + +export const STORAGE_KEYS = { + pairing: 'pairingRows', + wallet: 'walletRows', + process: 'processRows', + data: 'dataRows', +}; + +// Initialiser le stockage des lignes par défaut dans le localStorage +export const defaultRows = [ + { + column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrz', + column2: '🎊😑🎄😩', + column3: 'Laptop', + }, + { + column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrx', + column2: '🎏🎕😧🌥', + column3: 'Phone', + }, +]; + +export const mockNotifications: { [key: string]: Notification[] } = {}; + +export const notificationMessages = ['CPU usage high', 'Memory threshold reached', 'New update available', 'Backup completed', 'Security check required', 'Performance optimization needed', 'System alert', 'Network connectivity issue', 'Storage space low', 'Process checkpoint reached']; + +export const mockDataRows = [ + { + column1: 'User Project', + column2: 'private', + column3: 'User', + column4: '6 months', + column5: 'NDA signed', + column6: 'Contract #123', + processName: 'User Process', + zone: 'A', + }, + { + column1: 'Process Project', + column2: 'private', + column3: 'Process', + column4: '1 year', + column5: 'Terms accepted', + column6: 'Contract #456', + processName: 'Process Management', + zone: 'B', + }, + { + column1: 'Member Project', + column2: 'private', + column3: 'Member', + column4: '3 months', + column5: 'GDPR compliant', + column6: 'Contract #789', + processName: 'Member Process', + zone: 'C', + }, + { + column1: 'Peer Project', + column2: 'public', + column3: 'Peer', + column4: '2 years', + column5: 'IP rights', + column6: 'Contract #101', + processName: 'Peer Process', + zone: 'D', + }, + { + column1: 'Payment Project', + column2: 'confidential', + column3: 'Payment', + column4: '1 year', + column5: 'NDA signed', + column6: 'Contract #102', + processName: 'Payment Process', + zone: 'E', + }, + { + column1: 'Deposit Project', + column2: 'private', + column3: 'Deposit', + column4: '6 months', + column5: 'Terms accepted', + column6: 'Contract #103', + processName: 'Deposit Process', + zone: 'F', + }, + { + column1: 'Artefact Project', + column2: 'public', + column3: 'Artefact', + column4: '1 year', + column5: 'GDPR compliant', + column6: 'Contract #104', + processName: 'Artefact Process', + zone: 'G', + }, + { + column1: 'Resolve Project', + column2: 'private', + column3: 'Resolve', + column4: '2 years', + column5: 'IP rights', + column6: 'Contract #105', + processName: 'Resolve Process', + zone: 'H', + }, + { + column1: 'Backup Project', + column2: 'public', + column3: 'Backup', + column4: '1 year', + column5: 'NDA signed', + column6: 'Contract #106', + processName: 'Backup Process', + zone: 'I', + }, +]; + +export const mockProcessRows = [ + { + process: 'User Project', + role: 'User', + notification: { + messages: [ + { id: 1, read: false, date: '2024-03-10', message: 'New user joined the project' }, + { id: 2, read: false, date: '2024-03-09', message: 'Project milestone reached' }, + { id: 3, read: false, date: '2024-03-08', message: 'Security update required' }, + { id: 4, read: true, date: '2024-03-07', message: 'Weekly report available' }, + { id: 5, read: true, date: '2024-03-06', message: 'Team meeting scheduled' }, + ], + }, + }, + { + process: 'Member Project', + role: 'Member', + notification: { + messages: [ + { id: 6, read: true, date: '2024-03-10', message: 'Member access granted' }, + { id: 7, read: true, date: '2024-03-09', message: 'Documentation updated' }, + { id: 8, read: true, date: '2024-03-08', message: 'Project status: on track' }, + ], + }, + }, + { + process: 'Peer Project', + role: 'Peer', + notification: { + unread: 2, + total: 4, + messages: [ + { id: 9, read: false, date: '2024-03-10', message: 'New peer project added' }, + { id: 10, read: false, date: '2024-03-09', message: 'Project milestone reached' }, + { id: 11, read: false, date: '2024-03-08', message: 'Security update required' }, + { id: 12, read: true, date: '2024-03-07', message: 'Weekly report available' }, + { id: 13, read: true, date: '2024-03-06', message: 'Team meeting scheduled' }, + ], + }, + }, + { + process: 'Deposit Project', + role: 'Deposit', + notification: { + unread: 1, + total: 10, + messages: [ + { id: 14, read: false, date: '2024-03-10', message: 'Deposit milestone reached' }, + { id: 15, read: false, date: '2024-03-09', message: 'Security update required' }, + { id: 16, read: false, date: '2024-03-08', message: 'Weekly report available' }, + { id: 17, read: true, date: '2024-03-07', message: 'Team meeting scheduled' }, + { id: 18, read: true, date: '2024-03-06', message: 'Project status: on track' }, + ], + }, + }, + { + process: 'Artefact Project', + role: 'Artefact', + notification: { + unread: 0, + total: 3, + messages: [ + { id: 19, read: false, date: '2024-03-10', message: 'New artefact added' }, + { id: 20, read: false, date: '2024-03-09', message: 'Security update required' }, + { id: 21, read: false, date: '2024-03-08', message: 'Weekly report available' }, + { id: 22, read: true, date: '2024-03-07', message: 'Team meeting scheduled' }, + { id: 23, read: true, date: '2024-03-06', message: 'Project status: on track' }, + ], + }, + }, + { + process: 'Resolve Project', + role: 'Resolve', + notification: { + unread: 5, + total: 12, + messages: [ + { id: 24, read: false, date: '2024-03-10', message: 'New issue reported' }, + { id: 25, read: false, date: '2024-03-09', message: 'Security update required' }, + { id: 26, read: false, date: '2024-03-08', message: 'Weekly report available' }, + { id: 27, read: true, date: '2024-03-07', message: 'Team meeting scheduled' }, + { id: 28, read: true, date: '2024-03-06', message: 'Project status: on track' }, + ], + }, + }, +]; + +export const mockContracts = { + 'Contract #123': { + title: 'User Project Agreement', + date: '2024-01-15', + parties: ['Company XYZ', 'User Team'], + terms: ['Data Protection', 'User Privacy', 'Access Rights', 'Service Level Agreement'], + content: 'This agreement establishes the terms and conditions for user project management.', + }, + 'Contract #456': { + title: 'Process Management Contract', + date: '2024-02-01', + parties: ['Company XYZ', 'Process Team'], + terms: ['Process Workflow', 'Quality Standards', 'Performance Metrics', 'Monitoring Procedures'], + content: 'This contract defines the process management standards and procedures.', + }, + 'Contract #789': { + title: 'Member Access Agreement', + date: '2024-03-15', + parties: ['Company XYZ', 'Member Team'], + terms: ['Member Rights', 'Access Levels', 'Security Protocol', 'Confidentiality Agreement'], + content: 'This agreement outlines the terms for member access and privileges.', + }, + 'Contract #101': { + title: 'Peer Collaboration Agreement', + date: '2024-04-01', + parties: ['Company XYZ', 'Peer Network'], + terms: ['Collaboration Rules', 'Resource Sharing', 'Dispute Resolution', 'Network Protocol'], + content: 'This contract establishes peer collaboration and networking guidelines.', + }, + 'Contract #102': { + title: 'Payment Processing Agreement', + date: '2024-05-01', + parties: ['Company XYZ', 'Payment Team'], + terms: ['Transaction Protocol', 'Security Measures', 'Fee Structure', 'Service Availability'], + content: 'This agreement defines payment processing terms and conditions.', + }, + 'Contract #103': { + title: 'Deposit Management Contract', + date: '2024-06-01', + parties: ['Company XYZ', 'Deposit Team'], + terms: ['Deposit Rules', 'Storage Protocol', 'Access Control', 'Security Standards'], + content: 'This contract outlines deposit management procedures and security measures.', + }, + 'Contract #104': { + title: 'Artefact Handling Agreement', + date: '2024-07-01', + parties: ['Company XYZ', 'Artefact Team'], + terms: ['Handling Procedures', 'Storage Guidelines', 'Access Protocol', 'Preservation Standards'], + content: 'This agreement establishes artefact handling and preservation guidelines.', + }, + 'Contract #105': { + title: 'Resolution Protocol Agreement', + date: '2024-08-01', + parties: ['Company XYZ', 'Resolution Team'], + terms: ['Resolution Process', 'Time Constraints', 'Escalation Protocol', 'Documentation Requirements'], + content: 'This contract defines the resolution process and protocol standards.', + }, + 'Contract #106': { + title: 'Backup Service Agreement', + date: '2024-09-01', + parties: ['Company XYZ', 'Backup Team'], + terms: ['Backup Schedule', 'Data Protection', 'Recovery Protocol', 'Service Reliability'], + content: 'This agreement outlines backup service terms and recovery procedures.', + }, +}; diff --git a/ihm_client/src/mocks/mock-account/interfacesAccountMock.ts b/ihm_client/src/mocks/mock-account/interfacesAccountMock.ts new file mode 100644 index 00000000..1c409ba0 --- /dev/null +++ b/ihm_client/src/mocks/mock-account/interfacesAccountMock.ts @@ -0,0 +1,45 @@ +export interface Row { + column1: string; + column2: string; + column3: string; +} + +// Types supplémentaires nécessaires +export interface Contract { + title: string; + date: string; + parties: string[]; + terms: string[]; + content: string; +} + +export interface WalletRow { + column1: string; // Label + column2: string; // Wallet + column3: string; // Type +} + +export interface DataRow { + column1: string; // Name + column2: string; // Visibility + column3: string; // Role + column4: string; // Duration + column5: string; // Legal + column6: string; // Contract + processName: string; + zone: string; +} + +export interface Notification { + message: string; + timestamp: string; + isRead: boolean; +} + +// Déplacer l'interface en dehors de la classe, au début du fichier +export interface NotificationMessage { + id: number; + read: boolean; + date: string; + message: string; +} diff --git a/ihm_client/src/mocks/mock-chat/groupsMock.js b/ihm_client/src/mocks/mock-chat/groupsMock.js new file mode 100755 index 00000000..d5d1fcfe --- /dev/null +++ b/ihm_client/src/mocks/mock-chat/groupsMock.js @@ -0,0 +1,52 @@ +export const groupsMock = [ + { + id: 1, + name: 'Group 🚀 ', + roles: [ + { + id: 1, + name: 'Role 1', + members: [ + { id: 1, name: 'Member 1' }, + { id: 2, name: 'Member 2' }, + ], + }, + { + id: 2, + name: 'Role 2', + members: [ + { id: 3, name: 'Member 3' }, + { id: 4, name: 'Member 4' }, + ], + }, + ], + }, + { + id: 2, + name: 'Group ₿', + roles: [ + { + id: 3, + name: 'Role 1', + members: [ + { id: 5, name: 'Member 5' }, + { id: 6, name: 'Member 6' }, + ], + }, + ], + }, + { + id: 3, + name: 'Group 🪙', + roles: [ + { + id: 4, + name: 'Role 1', + members: [ + { id: 7, name: 'Member 7' }, + { id: 8, name: 'Member 8' }, + ], + }, + ], + }, +]; diff --git a/ihm_client/src/mocks/mock-chat/messagesMock.js b/ihm_client/src/mocks/mock-chat/messagesMock.js new file mode 100755 index 00000000..28792d96 --- /dev/null +++ b/ihm_client/src/mocks/mock-chat/messagesMock.js @@ -0,0 +1,64 @@ +export const messagesMock = [ + { + memberId: 1, // Conversations avec Mmber 1 + messages: [ + { id: 1, sender: 'Member 1', text: 'Salut !', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Bonjour ! Comment ça va ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Tout va bien, merci !', time: '10:32 AM' }, + ], + }, + { + memberId: 2, // Conversations avec Member 2 + messages: [ + { id: 1, sender: 'Member 2', text: 'Salut, on se voit ce soir ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Oui, à quelle heure ?', time: '10:31 AM' }, + ], + }, + { + memberId: 3, // Conversations avec Member 3 + messages: [ + { id: 1, sender: 'Member 3', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 4, // Conversations avec Member 4 + messages: [ + { id: 1, sender: 'Member 4', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 5, // Conversations avec Member 5 + messages: [ + { id: 1, sender: 'Member 5', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 6, // Conversations avec Member 6 + messages: [ + { id: 1, sender: 'Member 6', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 7, // Conversations avec Member 7 + messages: [ + { id: 1, sender: 'Member 7', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 8, // Conversations avec Member 8 + messages: [ + { id: 1, sender: 'Member 8', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, +]; diff --git a/ihm_client/src/mocks/mock-signature/groupsMock.js b/ihm_client/src/mocks/mock-signature/groupsMock.js new file mode 100755 index 00000000..c6521122 --- /dev/null +++ b/ihm_client/src/mocks/mock-signature/groupsMock.js @@ -0,0 +1,471 @@ +// Définir les rôles autorisés +const VALID_ROLES = ['User', 'Process', 'Member', 'Peer', 'Payment', 'Deposit', 'Artefact', 'Resolve', 'Backup']; + +const VISIBILITY_LEVELS = { + PUBLIC: 'public', + CONFIDENTIAL: 'confidential', + PRIVATE: 'private', +}; + +const DOCUMENT_STATUS = { + DRAFT: 'draft', + PENDING: 'pending', + IN_REVIEW: 'in_review', + APPROVED: 'approved', + REJECTED: 'rejected', + EXPIRED: 'expired', +}; + +// Fonction pour créer un rôle +function createRole(name, members) { + if (!VALID_ROLES.includes(name)) { + throw new Error(`Role "${name}" is not valid.`); + } + return { name, members }; +} + +export const groupsMock = [ + { + id: 1, + name: 'Processus 1', + description: 'Description du processus 1', + commonDocuments: [ + { + id: 101, + name: 'Règlement intérieur', + description: 'Document vierge pour le règlement intérieur', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 102, + name: 'Charte de confidentialité', + description: 'Document vierge pour la charte de confidentialité', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 103, + name: 'Procédures générales', + description: 'Document vierge pour les procédures générales', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 104, + name: 'Urgency A', + description: "Document vierge pour le plan d'urgence A", + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 105, + name: 'Urgency B', + description: "Document vierge pour le plan d'urgence B", + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 106, + name: 'Urgency C', + description: "Document vierge pour le plan d'urgence C", + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 107, + name: 'Document à signer', + description: 'Document vierge pour le règlement intérieur', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + roles: [ + { + name: 'User', + members: [ + { id: 1, name: 'Alice' }, + { id: 2, name: 'Bob' }, + ], + documents: [ + { + id: 1, + name: 'Document User A', + description: 'Description du document User A.', + visibility: 'public', + createdAt: '2024-01-01', + deadline: '2024-02-01', + signatures: [ + { + member: { id: 1, name: 'Alice' }, + signed: true, + signedAt: '2024-01-15', + }, + { + member: { id: 2, name: 'Bob' }, + signed: false, + }, + ], + }, + { + id: 2, + name: 'Document User B', + description: 'Document vierge pour le rôle User', + visibility: 'confidential', + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 7, + name: 'Document User C', + description: 'Document vierge pour validation utilisateur', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 8, + name: 'Document User D', + description: 'Document vierge pour approbation utilisateur', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + }, + { + name: 'Process', + members: [ + { id: 3, name: 'Charlie' }, + { id: 4, name: 'David' }, + ], + documents: [ + { + id: 3, + name: 'Document Process A', + description: 'Description du document Process A.', + visibility: 'confidential', + createdAt: '2024-01-10', + deadline: '2024-03-01', + signatures: [ + { + member: { id: 3, name: 'Charlie' }, + signed: true, + signedAt: '2024-01-12', + }, + ], + }, + { + id: 9, + name: 'Document Process B', + description: 'Document vierge pour processus interne', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 10, + name: 'Document Process C', + description: 'Document vierge pour validation processus', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 11, + name: 'Document Process D', + description: 'Document vierge pour validation processus', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.PENDING, + createdAt: '2024-01-15', + deadline: '2024-02-01', + signatures: [ + { + member: { id: 3, name: 'Charlie' }, + signed: true, + signedAt: '2024-01-15', + }, + { + member: { id: 4, name: 'David' }, + signed: false, + }, + ], + }, + { + id: 12, + name: 'Document Process E', + description: 'Document vierge pour validation processus', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.PENDING, + createdAt: '2024-01-15', + deadline: '2024-02-01', + signatures: [ + { + member: { id: 3, name: 'Charlie' }, + signed: true, + signedAt: '2024-01-15', + }, + { + member: { id: 4, name: 'David' }, + signed: false, + }, + ], + }, + ], + }, + { + name: 'Backup', + members: [ + { id: 15, name: 'Oscar' }, + { id: 16, name: 'Patricia' }, + ], + documents: [ + { + id: 11, + name: 'Document Backup A', + description: 'Document vierge pour sauvegarde', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + }, + ], + }, + { + id: 2, + name: 'Processus 2', + description: 'Description du processus 2', + commonDocuments: [ + { + id: 201, + name: 'Règlement intérieur', + description: 'Document vierge pour le règlement intérieur', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 202, + name: 'Charte de confidentialité', + description: 'Document vierge pour la charte de confidentialité', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 203, + name: 'Charte de confidentialité', + description: 'Document vierge pour la charte de confidentialité', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 204, + name: 'Charte de confidentialité', + description: 'Document vierge pour la charte de confidentialité', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 205, + name: 'Charte de confidentialité', + description: 'Document vierge pour la charte de confidentialité', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + roles: [ + { + name: 'Artefact', + members: [ + { id: 17, name: 'Quinn' }, + { id: 18, name: 'Rachel' }, + ], + documents: [ + { + id: 12, + name: 'Document Artefact A', + description: 'Document vierge pour artefact', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 13, + name: 'Document Artefact B', + description: 'Document vierge pour validation artefact', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + }, + { + name: 'Resolve', + members: [ + { id: 19, name: 'Sam' }, + { id: 20, name: 'Tom' }, + ], + documents: [ + { + id: 14, + name: 'Document Resolve A', + description: 'Document vierge pour résolution', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + }, + ], + }, + { + id: 3, + name: 'Processus 3', + description: 'Description du processus 3', + commonDocuments: [ + { + id: 301, + name: 'Règlement intérieur', + description: 'Document vierge pour le règlement intérieur', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 302, + name: 'Charte de confidentialité', + description: 'Document vierge pour la charte de confidentialité', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 303, + name: 'Procédures générales', + description: 'Document vierge pour les procédures générales', + visibility: VISIBILITY_LEVELS.PUBLIC, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + roles: [ + { + name: 'Deposit', + members: [ + { id: 21, name: 'Uma' }, + { id: 22, name: 'Victor' }, + ], + documents: [ + { + id: 15, + name: 'Document Deposit A', + description: 'Document vierge pour dépôt', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 16, + name: 'Document Deposit B', + description: 'Document vierge pour validation dépôt', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + }, + { + name: 'Payment', + members: [ + { id: 23, name: 'Walter' }, + { id: 24, name: 'Xena' }, + ], + documents: [ + { + id: 17, + name: 'Document Payment B', + description: 'Document vierge pour paiement', + visibility: VISIBILITY_LEVELS.PRIVATE, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + { + id: 18, + name: 'Document Payment C', + description: 'Document vierge pour validation paiement', + visibility: VISIBILITY_LEVELS.CONFIDENTIAL, + status: DOCUMENT_STATUS.DRAFT, + createdAt: null, + deadline: null, + signatures: [], + }, + ], + }, + ], + }, +]; diff --git a/ihm_client/src/mocks/mock-signature/membersMocks.js b/ihm_client/src/mocks/mock-signature/membersMocks.js new file mode 100755 index 00000000..2ffc6cee --- /dev/null +++ b/ihm_client/src/mocks/mock-signature/membersMocks.js @@ -0,0 +1,105 @@ +export const membersMock = [ + // Processus 1 + { + id: 1, + name: 'Alice', + avatar: 'A', + email: 'alice@company.com', + processRoles: [{ processId: 1, role: 'User' }], + }, + { + id: 2, + name: 'Bob', + avatar: 'B', + email: 'bob@company.com', + processRoles: [{ processId: 1, role: 'User' }], + }, + { + id: 3, + name: 'Charlie', + avatar: 'C', + email: 'charlie@company.com', + processRoles: [{ processId: 1, role: 'Process' }], + }, + { + id: 4, + name: 'David', + avatar: 'D', + email: 'david@company.com', + processRoles: [{ processId: 1, role: 'Process' }], + }, + { + id: 15, + name: 'Oscar', + avatar: 'O', + email: 'oscar@company.com', + processRoles: [{ processId: 1, role: 'Backup' }], + }, + { + id: 16, + name: 'Patricia', + avatar: 'P', + email: 'patricia@company.com', + processRoles: [{ processId: 1, role: 'Backup' }], + }, + + // Processus 2 + { + id: 17, + name: 'Quinn', + avatar: 'Q', + email: 'quinn@company.com', + processRoles: [{ processId: 2, role: 'Artefact' }], + }, + { + id: 18, + name: 'Rachel', + avatar: 'R', + email: 'rachel@company.com', + processRoles: [{ processId: 2, role: 'Artefact' }], + }, + { + id: 19, + name: 'Sam', + avatar: 'S', + email: 'sam@company.com', + processRoles: [{ processId: 2, role: 'Resolve' }], + }, + { + id: 20, + name: 'Tom', + avatar: 'T', + email: 'tom@company.com', + processRoles: [{ processId: 2, role: 'Resolve' }], + }, + + // Processus 3 + { + id: 21, + name: 'Uma', + avatar: 'U', + email: 'uma@company.com', + processRoles: [{ processId: 3, role: 'Deposit' }], + }, + { + id: 22, + name: 'Victor', + avatar: 'V', + email: 'victor@company.com', + processRoles: [{ processId: 3, role: 'Deposit' }], + }, + { + id: 23, + name: 'Walter', + avatar: 'W', + email: 'walter@company.com', + processRoles: [{ processId: 3, role: 'Payment' }], + }, + { + id: 24, + name: 'Xena', + avatar: 'X', + email: 'xena@company.com', + processRoles: [{ processId: 3, role: 'Payment' }], + }, +]; diff --git a/ihm_client/src/mocks/mock-signature/messagesMock.ts b/ihm_client/src/mocks/mock-signature/messagesMock.ts new file mode 100755 index 00000000..ca1c31e5 --- /dev/null +++ b/ihm_client/src/mocks/mock-signature/messagesMock.ts @@ -0,0 +1,64 @@ +export const messagesMock = [ + { + memberId: 1, // Conversations avec Mmber 1 + messages: [ + { id: 1, sender: 'Mmeber 1', text: 'Salut !', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Bonjour ! Comment ça va ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Tout va bien, merci !', time: '10:32 AM' }, + ], + }, + { + memberId: 2, // Conversations avec Member 2 + messages: [ + { id: 1, sender: 'Member 2', text: 'Salut, on se voit ce soir ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Oui, à quelle heure ?', time: '10:31 AM' }, + ], + }, + { + memberId: 3, // Conversations avec Member 3 + messages: [ + { id: 1, sender: 'Member 3', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 4, // Conversations avec Member 4 + messages: [ + { id: 1, sender: 'Member 4', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 5, // Conversations avec Member 5 + messages: [ + { id: 1, sender: 'Member 5', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 6, // Conversations avec Member 6 + messages: [ + { id: 1, sender: 'Member 6', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 7, // Conversations avec Member 7 + messages: [ + { id: 1, sender: 'Member 7', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, + { + memberId: 8, // Conversations avec Member 8 + messages: [ + { id: 1, sender: 'Member 8', text: 'Hey, ça va ?', time: '10:30 AM' }, + { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' }, + ], + }, +]; diff --git a/ihm_client/src/models/backup.model.ts b/ihm_client/src/models/backup.model.ts new file mode 100644 index 00000000..5050688b --- /dev/null +++ b/ihm_client/src/models/backup.model.ts @@ -0,0 +1,7 @@ +import { Device, Process, SecretsStore } from "pkg/sdk_client"; + +export interface BackUp { + device: Device, + secrets: SecretsStore, + processes: Record, +} diff --git a/ihm_client/src/models/notification.model.ts b/ihm_client/src/models/notification.model.ts new file mode 100755 index 00000000..0d78630b --- /dev/null +++ b/ihm_client/src/models/notification.model.ts @@ -0,0 +1,30 @@ +export interface INotification { + id: number; + title: string; + description: string; + sendToNotificationPage?: boolean; + path?: string; +} + +// Quelles sont les données utiles pour le user ??? +export interface IUser { + id: string; + information?: any; +} + +// Quelles sont les données utiles pour les messages ??? +export interface IMessage { + id: string; + message: any; +} + +export interface UserDiff { + new_state_merkle_root: string; // TODO add a merkle proof that the new_value belongs to that state + field: string; + previous_value: string; + new_value: string; + notify_user: boolean; + need_validation: boolean; + // validated: bool, + proof: any; // This is only validation (or refusal) for that specific diff, not the whole state. It can't be commited as such +} diff --git a/ihm_client/src/models/process.model.ts b/ihm_client/src/models/process.model.ts new file mode 100755 index 00000000..b2eae720 --- /dev/null +++ b/ihm_client/src/models/process.model.ts @@ -0,0 +1,65 @@ +export interface IProcess { + id: number; + name: string; + description: string; + icon?: string; + zoneList: IZone[]; +} + +export interface IZone { + id: number; + name: string; + path: string; + // Est-ce que la zone a besoin d'une icone ? + icon?: string; +} + +export interface INotification { + id: number; + title: string; + description: string; + sendToNotificationPage?: boolean; + path?: string; +} + +export enum MessageType { + // Establish connection and keep alive + 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 various information + 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', + // Processes + 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 and merkle proof + 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', + // Account management + ADD_DEVICE = 'ADD_DEVICE', + DEVICE_ADDED = 'DEVICE_ADDED', +} diff --git a/ihm_client/src/models/signature.models.ts b/ihm_client/src/models/signature.models.ts new file mode 100755 index 00000000..ef5ad282 --- /dev/null +++ b/ihm_client/src/models/signature.models.ts @@ -0,0 +1,59 @@ +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; +} diff --git a/ihm_client/src/pages/account/account-component.ts b/ihm_client/src/pages/account/account-component.ts new file mode 100644 index 00000000..db8f1933 --- /dev/null +++ b/ihm_client/src/pages/account/account-component.ts @@ -0,0 +1,62 @@ +import { AccountElement } from './account'; +import accountCss from '../../../public/style/account.css?raw'; +import Services from '../../services/service.js'; + +class AccountComponent extends HTMLElement { + _callback: any; + accountElement: AccountElement | null = null; + + constructor() { + super(); + console.log('INIT'); + this.attachShadow({ mode: 'open' }); + + this.accountElement = this.shadowRoot?.querySelector('account-element') || null; + } + + connectedCallback() { + console.log('CALLBACKs'); + this.render(); + this.fetchData(); + + if (!customElements.get('account-element')) { + customElements.define('account-element', AccountElement); + } + } + + async fetchData() { + if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) { + const data = await (window as any).myService?.getProcesses(); + } else { + const service = await Services.getInstance(); + const data = await service.getProcesses(); + } + } + + set callback(fn) { + if (typeof fn === 'function') { + this._callback = fn; + } else { + console.error('Callback is not a function'); + } + } + + get callback() { + return this._callback; + } + + render() { + if (this.shadowRoot && !this.shadowRoot.querySelector('account-element')) { + const style = document.createElement('style'); + style.textContent = accountCss; + + const accountElement = document.createElement('account-element'); + + this.shadowRoot.appendChild(style); + this.shadowRoot.appendChild(accountElement); + } + } +} + +export { AccountComponent }; +customElements.define('account-component', AccountComponent); diff --git a/ihm_client/src/pages/account/account.html b/ihm_client/src/pages/account/account.html new file mode 100755 index 00000000..654be9aa --- /dev/null +++ b/ihm_client/src/pages/account/account.html @@ -0,0 +1,10 @@ + + + + Account + + + + + + diff --git a/ihm_client/src/pages/account/account.ts b/ihm_client/src/pages/account/account.ts new file mode 100755 index 00000000..8e9d0894 --- /dev/null +++ b/ihm_client/src/pages/account/account.ts @@ -0,0 +1,1589 @@ +declare global { + interface Window { + initAccount: () => void; + showContractPopup: (contractId: string) => void; + showPairing: () => Promise; + 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; + } +} + +import Swal from 'sweetalert2'; +import { STORAGE_KEYS, defaultRows, mockProcessRows, mockNotifications, notificationMessages, mockDataRows, mockContracts, ALLOWED_ROLES } from '../../mocks/mock-account/constAccountMock'; +import { Row, WalletRow, DataRow, Notification, Contract, NotificationMessage } from '../../mocks/mock-account/interfacesAccountMock'; +import { addressToEmoji } from '../../utils/sp-address.utils'; +import { getCorrectDOM } from '../../utils/document.utils'; +import accountStyle from '../../../public/style/account.css?inline'; +import Services from '../../services/service'; +import { getProcessCreation } from './process-creation'; +import { getDocumentValidation } from './document-validation'; +import { createProcessTab } from './process'; + +let isAddingRow = false; +let currentRow: HTMLTableRowElement | null = null; +let currentMode: keyof typeof STORAGE_KEYS = 'pairing'; + +interface Process { + states: Array<{ + committed_in: string; + keys: {}; + pcd_commitment: { + counter: string; + }; + public_data: { + memberPublicName?: string; + }; + roles: { + pairing?: {}; + }; + state_id: string; + validation_tokens: Array; + }>; +} + +class AccountElement extends HTMLElement { + private dom: Node; + + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.dom = getCorrectDOM('account-element'); + + // Ajouter Font Awesome + const fontAwesome = document.createElement('link'); + fontAwesome.rel = 'stylesheet'; + fontAwesome.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css'; + this.shadowRoot!.appendChild(fontAwesome); + + const style = document.createElement('style'); + style.textContent = accountStyle; + this.shadowRoot!.appendChild(style); + + this.shadowRoot!.innerHTML = ` + + + + + + +
+ +
+
    + +
    +
    + Banner +
    +
    + Avatar + +
    +
    + + + + + +
+
    Pairing 🔗
+ +
    Process ⚙️
+
    Process Creation
+
    Document Validation
+ +
+ + +
+
+
+ +
+
+
+ +
+
+
+ `; + + + window.showPairing = () => this.showPairing(); + window.showWallet = () => this.showWallet(); + window.showProcess = () => this.showProcess(); + window.showProcessCreation = () => this.showProcessCreation(); + window.showDocumentValidation = () => this.showDocumentValidation(); + window.showData = () => this.showData(); + window.addWalletRow = () => this.addWalletRow(); + window.confirmWalletRow = () => this.confirmWalletRow(); + window.cancelWalletRow = () => this.cancelWalletRow(); + window.editDeviceName = (cell: HTMLTableCellElement) => this.editDeviceName(cell); + window.showProcessNotifications = (processName: string) => this.showProcessNotifications(processName); + window.handleLogout = () => this.handleLogout(); + window.confirmDeleteAccount = () => this.confirmDeleteAccount(); + window.showContractPopup = (contractId: string) => this.showContractPopup(contractId); + window.addRowPairing = () => this.addRowPairing(); + window.deleteRowPairing = (button: HTMLButtonElement) => this.deleteRowPairing(button); + window.confirmRowPairing = () => this.confirmRowPairing(); + window.cancelRowPairing = () => this.cancelRowPairing(); + window.updateNavbarBanner = (bannerUrl: string) => this.updateNavbarBanner(bannerUrl); + window.saveBannerToLocalStorage = (bannerUrl: string) => this.saveBannerToLocalStorage(bannerUrl); + window.loadSavedBanner = () => this.loadSavedBanner(); + window.closeNotificationPopup = (event: Event) => this.closeNotificationPopup(event); + window.markAsRead = (processName: string, messageId: number, element: HTMLElement) => this.markAsRead(processName, messageId, element); + window.exportRecovery = () => this.exportRecovery(); + window.generateRecoveryWords = () => this.generateRecoveryWords(); + window.exportUserData = () => this.exportUserData(); + window.updateActionButtons = () => this.updateActionButtons(); + window.openAvatarPopup = () => this.openAvatarPopup(); + window.closeAvatarPopup = () => this.closeAvatarPopup(); + window.showQRCodeModal = (pairingId: string) => this.showQRCodeModal(pairingId); + + if (!localStorage.getItem('rows')) { + localStorage.setItem('rows', JSON.stringify(defaultRows)); + } + } + + connectedCallback() { + this.initializeEventListeners(); + this.loadSavedBanner(); + this.loadUserInfo(); + + const savedAvatar = localStorage.getItem('userAvatar'); + const savedBanner = localStorage.getItem('userBanner'); + const savedName = localStorage.getItem('userName'); + const savedLastName = localStorage.getItem('userLastName'); + + if (savedAvatar) { + const navAvatar = this.shadowRoot?.querySelector('.avatar') as HTMLImageElement; + if (navAvatar) navAvatar.src = savedAvatar; + } + + if (savedBanner) { + const navBanner = this.shadowRoot?.querySelector('.banner-image') as HTMLImageElement; + if (navBanner) navBanner.src = savedBanner; + } + + if (savedName) { + this.updateNavbarName(savedName); + } + if (savedLastName) { + this.updateNavbarLastName(savedLastName); + } + } + + private showAlert(message: string): void { + // Créer la popup si elle n'existe pas + let alertPopup = this.shadowRoot?.querySelector('.alert-popup'); + if (!alertPopup) { + alertPopup = document.createElement('div'); + alertPopup.className = 'alert-popup'; + this.shadowRoot?.appendChild(alertPopup); + } + + // Définir le message et afficher la popup + alertPopup.textContent = message; + (alertPopup as HTMLElement).style.display = 'block'; + + // Cacher la popup après 3 secondes + setTimeout(() => { + (alertPopup as HTMLElement).style.display = 'none'; + }, 3000); + } + + + // Fonctions de gestion des comptes et de l'interface utilisateur + private confirmDeleteAccount(): void { + const modal = document.createElement('div'); + modal.className = 'confirm-delete-modal'; + modal.innerHTML = ` +

Delete Account

+

Are you sure you want to delete your account? This action cannot be undone.

+
+ + +
+ `; + + this.shadowRoot?.appendChild(modal); + modal.style.display = 'block'; + + const cancelBtn = modal.querySelector('.cancel-btn'); + const confirmBtn = modal.querySelector('.confirm-btn'); + + cancelBtn?.addEventListener('click', () => { + modal.remove(); + }); + + confirmBtn?.addEventListener('click', () => { + this.deleteAccount(); + modal.remove(); + }); +} + +private deleteAccount(): void { + localStorage.clear(); + window.location.href = '/login.html'; +} + +private updateNavbarBanner(imageUrl: string): void { + const navbarSection = this.shadowRoot?.querySelector('.nav-wrapper .avatar-section'); + if (!navbarSection) return; + + let bannerImg = navbarSection.querySelector('.banner-image'); + + if (!bannerImg) { + bannerImg = document.createElement('img'); + bannerImg.className = 'banner-image'; + navbarSection.insertBefore(bannerImg, navbarSection.firstChild); + } + + bannerImg.src = imageUrl; +} + +private saveBannerToLocalStorage(dataUrl: string): void { + localStorage.setItem('userBanner', dataUrl); +} + +private loadSavedBanner(): void { + const savedBanner = localStorage.getItem('userBanner'); + if (savedBanner) { + const bannerImg = this.shadowRoot?.getElementById('popup-banner-img') as HTMLImageElement; + if (bannerImg) { + bannerImg.src = savedBanner; + } + this.updateNavbarBanner(savedBanner); + } +} + + +private closeNotificationPopup(event: Event): void { + const target = event.target as HTMLElement; + const isOverlay = target.classList.contains('notification-popup-overlay'); + const isCloseButton = target.classList.contains('close-popup'); + if (!isOverlay && !isCloseButton) return; + + const popup = this.shadowRoot?.querySelector('.notification-popup-overlay'); + if (popup) popup.remove(); +} + +private markAsRead(processName: string, messageId: number, element: HTMLElement): void { + const process = mockProcessRows.find(p => p.process === processName); + if (!process) return; + + const message = process.notification.messages.find(m => m.id === messageId); + if (!message || message.read) return; + + message.read = true; + + element.classList.remove('unread'); + element.classList.add('read'); + + const statusIcon = element.querySelector('.notification-status'); + if (statusIcon) { + statusIcon.innerHTML = ` + + + `; + } + + const notifCount = this.calculateNotifications(process.notification.messages); + const countElement = this.shadowRoot?.querySelector(`.notification-count[data-process="${processName}"]`); + if (countElement) { + countElement.textContent = `${notifCount.unread}/${notifCount.total}`; + + const bellContainer = countElement.closest('.notification-container'); + const bell = bellContainer?.querySelector('svg'); // Changé de .fa-bell à svg + if (bell && bellContainer && notifCount.unread === 0) { + bellContainer.classList.remove('has-unread'); + (bell as SVGElement).style.fill = '#666'; // Utiliser fill au lieu de color pour SVG + } + } +} + +// Fonctions de gestion des données et de l'interface +private calculateNotifications(messages: NotificationMessage[]): { unread: number; total: number } { + const total = messages.length; + const unread = messages.filter(msg => !msg.read).length; + return { unread, total }; +} + +// Fonctions de récupération +private exportRecovery(): void { + Swal.fire({ + title: 'Recovery Words Export', + text: '4 words will be displayed. We strongly recommend writing them down on paper before exporting the account. Do you want to continue?', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Confirm', + cancelButtonText: 'Cancel', + confirmButtonColor: '#C89666', + cancelButtonColor: '#6c757d', + // Ajouter des styles personnalisés + customClass: { + container: 'recovery-popup-container', + popup: 'recovery-popup' + } + }).then((result) => { + if (result.isConfirmed) { + const recoveryWords = this.generateRecoveryWords(); + localStorage.setItem('recoveryWords', JSON.stringify(recoveryWords)); + + Swal.fire({ + title: 'Your Recovery Words', + html: ` +
+ ${recoveryWords.map((word, index) => ` +
+ ${index + 1}. + ${word} +
+ `).join('')} +
+
+ Please write these words down carefully. They will be needed to recover your account. +
+ `, + showCancelButton: false, + confirmButtonText: 'I confirm the export', + confirmButtonColor: '#C89666', + allowOutsideClick: false, + allowEscapeKey: false, + customClass: { + container: 'recovery-popup-container', + popup: 'recovery-popup' + } + }).then((result) => { + if (result.isConfirmed) { + // Stocker l'état du bouton dans le localStorage + localStorage.setItem('recoveryExported', 'true'); + + const exportRecoveryBtn = this.shadowRoot?.querySelector('.recovery-btn') as HTMLButtonElement; + if (exportRecoveryBtn) { + exportRecoveryBtn.disabled = true; + exportRecoveryBtn.style.opacity = '0.5'; + exportRecoveryBtn.style.cursor = 'not-allowed'; + } + } + }); + } + }); +} + +private generateRecoveryWords(): string[] { + const wordsList = [ + 'apple', 'banana', 'orange', 'grape', 'kiwi', 'mango', 'peach', 'plum', + 'lemon', 'lime', 'cherry', 'melon', 'pear', 'fig', 'date', 'berry' + ]; + const recoveryWords: string[] = []; + while (recoveryWords.length < 4) { + const randomWord = wordsList[Math.floor(Math.random() * wordsList.length)]; + if (!recoveryWords.includes(randomWord)) { + recoveryWords.push(randomWord); + } + } + return recoveryWords; +} + +private exportUserData(): void { + const data: { [key: string]: string | null } = {}; + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key) { + const value = localStorage.getItem(key); + data[key] = value; + } + } + + const jsonData = JSON.stringify(data, null, 2); + const blob = new Blob([jsonData], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'user_data.json'; + this.shadowRoot?.appendChild(a); + a.click(); + this.shadowRoot?.removeChild(a); + URL.revokeObjectURL(url); +} + +private updateActionButtons(): void { + const buttonContainer = this.shadowRoot?.querySelector('.button-container'); + if (!buttonContainer) return; + + buttonContainer.innerHTML = ` +
+ + +
+ `; +} + +private getConfirmFunction(): string { + switch (currentMode) { + case 'wallet': + return 'window.confirmWalletRow()'; + case 'process': + return 'window.confirmProcessRow()'; + default: + return 'window.confirmRowPairing()'; + } +} + +private getCancelFunction(): string { + switch (currentMode) { + case 'wallet': + return 'window.cancelWalletRow()'; + case 'process': + return 'window.cancelProcessRow()'; + default: + return 'window.cancelRowPairing()'; + } +} + +// Fonctions de gestion des tableaux +private async addRowPairing(): Promise { + if (isAddingRow) return; + isAddingRow = true; + + // Créer la popup + const modal = document.createElement('div'); + modal.className = 'pairing-modal'; + modal.innerHTML = ` +
+

Add New Device

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ `; + + this.shadowRoot?.appendChild(modal); + + // Ajouter les event listeners + const spAddressInput = modal.querySelector('#sp-address') as HTMLInputElement; + const spEmojisInput = modal.querySelector('#sp-emojis') as HTMLInputElement; + const deviceNameInput = modal.querySelector('#device-name') as HTMLInputElement; + const confirmButton = modal.querySelector('.confirm-button'); + const cancelButton = modal.querySelector('.cancel-button'); + + // Mettre à jour les emojis automatiquement + spAddressInput?.addEventListener('input', async () => { + const emojis = await addressToEmoji(spAddressInput.value); + if (spEmojisInput) spEmojisInput.value = emojis; + }); + + // Gérer la confirmation + confirmButton?.addEventListener('click', () => { + const spAddress = spAddressInput?.value.trim(); + const deviceName = deviceNameInput?.value.trim(); + const spEmojis = spEmojisInput?.value.trim(); + + if (!spAddress || !deviceName) { + this.showAlert('Please fill in all required fields'); + return; + } + + //if (spAddress.length !== 118) { + // this.showAlert('SP Address must be exactly 118 characters long'); + // return; + //} + + const newRow: Row = { + column1: spAddress, + column2: deviceName, + column3: spEmojis || '' + }; + + const storageKey = STORAGE_KEYS[currentMode]; + const rows: Row[] = JSON.parse(localStorage.getItem(storageKey) || '[]'); + rows.push(newRow); + localStorage.setItem(storageKey, JSON.stringify(rows)); + + this.updateTableContent(rows); + modal.remove(); + isAddingRow = false; + }); + + // Gérer l'annulation + cancelButton?.addEventListener('click', () => { + modal.remove(); + isAddingRow = false; + }); +} + +// Fonctions de mise à jour de l'interface +private updateTableContent(rows: Row[]): void { + const tbody = this.shadowRoot?.querySelector('#pairing-table tbody'); + if (!tbody) return; + + tbody.innerHTML = rows.map(row => ` + + ${row.column2} + ${row.column3} + + QR Code + + + + + + `).join(''); +} + + + +private confirmRowPairing(): void { + if (!currentRow) return; + + const inputs = currentRow.getElementsByTagName('input'); + const values: string[] = Array.from(inputs).map(input => input.value.trim()); + + // Vérification des champs vides + if (values.some(value => value === '')) { + this.showAlert('Please fill in all fields'); + return; + } + + // Vérification de la longueur de l'adresse SP + if (values[0].length !== 118) { + this.showAlert('SP Address must be exactly 118 characters long'); + return; + } + + const newRow: Row = { + column1: values[0], + column2: values[1], + column3: values[2] + }; + + const storageKey = STORAGE_KEYS[currentMode]; + const rows: Row[] = JSON.parse(localStorage.getItem(storageKey) || '[]'); + rows.push(newRow); + localStorage.setItem(storageKey, JSON.stringify(rows)); + + isAddingRow = false; + currentRow = null; + + this.resetButtonContainer(); + this.updateTableContent(rows); +} + +private cancelRowPairing(): void { + if (!currentRow) return; + + currentRow.remove(); + isAddingRow = false; + currentRow = null; + + this.resetButtonContainer(); +} + +private resetButtonContainer(): void { + const buttonContainer = this.shadowRoot?.querySelector('.button-container'); + if (!buttonContainer) return; + + buttonContainer.innerHTML = ` + + `; +} + +private deleteRowPairing(button: HTMLButtonElement): void { + const row = button.closest('tr'); + if (!row) return; + + const table = row.closest('tbody'); + if (!table) return; + + const remainingRows = table.getElementsByTagName('tr').length; + if (remainingRows <= 2) { + this.showAlert('You must keep at least 2 devices paired'); + return; + } + + // Créer la modal de confirmation + const modal = document.createElement('div'); + modal.className = 'confirm-delete-modal'; + modal.innerHTML = ` +
+

Confirm Deletion

+

Are you sure you want to delete this device?

+
+ + +
+
+ `; + + this.shadowRoot?.appendChild(modal); + + // Gérer les boutons de la modal + const confirmBtn = modal.querySelector('.confirm-btn'); + const cancelBtn = modal.querySelector('.cancel-btn'); + + confirmBtn?.addEventListener('click', () => { + // Calculer l'index AVANT de supprimer la ligne du DOM + const index = Array.from(table.children).indexOf(row); + const storageKey = STORAGE_KEYS[currentMode]; + const rows = JSON.parse(localStorage.getItem(storageKey) || '[]'); + + // Supprimer du localStorage + if (index > -1) { + rows.splice(index, 1); + localStorage.setItem(storageKey, JSON.stringify(rows)); + } + + // Animation et suppression du DOM + row.style.transition = 'opacity 0.3s, transform 0.3s'; + row.style.opacity = '0'; + row.style.transform = 'translateX(-100%)'; + + setTimeout(() => { + row.remove(); + }, 300); + + modal.remove(); + }); + + cancelBtn?.addEventListener('click', () => { + modal.remove(); + }); +} + +private editDeviceName(cell: HTMLTableCellElement): void { + if (cell.classList.contains('editing')) return; + + const currentValue = cell.textContent || ''; + const input = document.createElement('input'); + input.type = 'text'; + input.value = currentValue; + input.className = 'edit-input'; + + input.addEventListener('blur', () => this.finishEditing(cell, input)); + input.addEventListener('keypress', (e: KeyboardEvent) => { + if (e.key === 'Enter') { + this.finishEditing(cell, input); + } + }); + + cell.textContent = ''; + cell.appendChild(input); + cell.classList.add('editing'); + input.focus(); +} + +private async finishEditing(cell: HTMLTableCellElement, input: HTMLInputElement): Promise { + const newValue = input.value.trim(); + if (newValue === '') { + cell.textContent = cell.getAttribute('data-original-value') || ''; + cell.classList.remove('editing'); + return; + } + + try { + const service = await Services.getInstance(); + const pairingProcessId = service.getPairingProcessId(); + const process = await service.getProcess(pairingProcessId); + + // Mettre à jour le nom via le service + if (process) { + await service.updateMemberPublicName(process, newValue); + } + + // Mettre à jour l'interface + cell.textContent = newValue; + cell.classList.remove('editing'); + } catch (error) { + console.error('Failed to update name:', error); + // Restaurer l'ancienne valeur en cas d'erreur + cell.textContent = cell.getAttribute('data-original-value') || ''; + cell.classList.remove('editing'); + } +} + +// Fonction pour gérer le téléchargement de l'avatar +private handleAvatarUpload(event: Event): void { + const input = event.target as HTMLInputElement; + const file = input.files?.[0]; + + if (file) { + const reader = new FileReader(); + reader.onload = (e: ProgressEvent) => { + const result = e.target?.result as string; + const popupAvatar = this.shadowRoot?.getElementById('popup-avatar-img') as HTMLImageElement; + const navAvatar = this.shadowRoot?.querySelector('.nav-wrapper .avatar') as HTMLImageElement; + + if (popupAvatar) popupAvatar.src = result; + if (navAvatar) navAvatar.src = result; + + localStorage.setItem('userAvatar', result); + }; + reader.readAsDataURL(file); + } +} + +private async showProcessCreation(): Promise { + this.hideAllContent(); + const container = this.shadowRoot?.getElementById('process-creation-content'); + if (container) { + getProcessCreation(container); + } +} + +private async showDocumentValidation(): Promise { + this.hideAllContent(); + const container = this.shadowRoot?.getElementById('document-validation-content'); + if (container) { + getDocumentValidation(container); + } +} + +private async showProcess(): Promise { + this.hideAllContent(); + const container = this.shadowRoot?.getElementById('process-content'); + if (container) { + const service = await Services.getInstance(); + const myProcesses = await service.getMyProcesses(); + if (myProcesses && myProcesses.length != 0) { + const myProcessesDataUnfiltered: { name: string, publicData: Record }[] = await Promise.all(myProcesses.map(async processId => { + const process = await service.getProcess(processId); + const lastState = process ? service.getLastCommitedState(process) : null; + if (!lastState) { + return { + name: '', + publicData: {} + }; + } + const description = await service.decryptAttribute(processId, lastState, 'description'); + const name = description ? description : 'N/A'; + const publicData = process ? await service.getPublicData(process) : null; + if (!publicData) { + return { + name: '', + publicData: {} + }; + } + return { + name: name, + publicData: publicData + }; + })); + const myProcessesData = myProcessesDataUnfiltered.filter( + (p) => p.name !== '' && Object.keys(p.publicData).length != 0 + ); + + createProcessTab(container, myProcessesData); + } else { + createProcessTab(container, []); + } + } +} + +private showProcessNotifications(processName: string): void { + const process = mockProcessRows.find(p => p.process === processName); + if (!process) return; + + const modal = document.createElement('div'); + modal.className = 'notifications-modal'; + + let notificationsList = process.notification.messages.map(msg => ` +
+
+ ${msg.read ? + ` + + ` : + ` + + ` + } +
+
+ ${msg.message} + ${msg.date} +
+
+ `).join(''); + + if (process.notification.messages.length === 0) { + notificationsList = '

No notifications

'; + } + + modal.innerHTML = ` +
+

${processName} Notifications

+
+ ${notificationsList} +
+ +
+ `; + + this.shadowRoot?.appendChild(modal); + + // Mettre à jour le compteur de notifications + const countElement = this.shadowRoot?.querySelector(`.notification-count[data-process="${processName}"]`); + if (countElement) { + const notifCount = this.calculateNotifications(process.notification.messages); + countElement.textContent = `${notifCount.unread}/${notifCount.total}`; + } + + const closeButton = modal.querySelector('.close-notifications'); + closeButton?.addEventListener('click', () => { + modal.remove(); + this.showProcess(); // Rafraîchir l'affichage pour mettre à jour les compteurs + }); +} + + +private handleLogout(): void { + localStorage.clear(); + window.location.href = '../login/login.html'; +} + + +// Fonctions de gestion des contrats +private showContractPopup(contractId: string, event?: Event) { + if (event) { + event.preventDefault(); + } + + // Check if the contract exists in mockContracts + const contract = mockContracts[contractId as keyof typeof mockContracts]; + if (!contract) { + console.error('Contract not found:', contractId); + return; + } + + const popup = document.createElement('div'); + popup.className = 'contract-popup-overlay'; + popup.innerHTML = ` +
+ +

${contract.title}

+
+

Date: ${contract.date}

+

Parties: ${contract.parties.join(', ')}

+

Terms:

+
    + ${contract.terms.map(term => `
  • ${term}
  • `).join('')} +
+

Content: ${contract.content}

+
+
+ `; + + this.shadowRoot?.appendChild(popup); + + const closeBtn = popup.querySelector('.close-contract-popup'); + const closePopup = () => popup.remove(); + + closeBtn?.addEventListener('click', closePopup); + popup.addEventListener('click', (e) => { + if (e.target === popup) closePopup(); + }); +} + +// Fonction utilitaire pour cacher tous les contenus +private hideAllContent(): void { + const contents = ['pairing-content', 'wallet-content', 'process-content', 'process-creation-content', 'data-content', 'document-validation-content']; + contents.forEach(id => { + const element = this.shadowRoot?.getElementById(id); + if (element) { + element.style.display = 'none'; + } + }); +} + +// Fonctions d'affichage des sections +private async showPairing(): Promise { + const service = await Services.getInstance(); + const spAddress = await service.getDeviceAddress(); + + isAddingRow = false; + currentRow = null; + currentMode = 'pairing'; + + this.hideAllContent(); + + const headerElement = this.shadowRoot?.getElementById('parameter-header'); + if (headerElement) { + headerElement.textContent = 'Pairing'; + } + + const pairingContent = this.shadowRoot?.getElementById('pairing-content'); + if (pairingContent) { + pairingContent.style.display = 'block'; + pairingContent.innerHTML = ` +
Pairing
+
+ + + + + + + + + + +
Device NameSP EmojisQR CodeActions
+
+ +
+
+ `; + + let rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.pairing) || '[]'); + + const deviceExists = rows.some((row: Row) => row.column1 === spAddress); + + if (!deviceExists && spAddress) { + const emojis = await addressToEmoji(spAddress); + + try { + // Déboguer le processus de pairing + const pairingProcessId = await service.getPairingProcessId(); + console.log('Pairing Process ID:', pairingProcessId); + + const pairingProcess = await service.getProcess(pairingProcessId); + console.log('Pairing Process:', pairingProcess); + + const userName = pairingProcess?.states?.[0]?.public_data?.memberPublicName + || localStorage.getItem('userName') + + console.log('Username found:', userName); + + const newRow = { + column1: spAddress, + column2: userName, + column3: emojis + }; + rows = [newRow, ...rows]; + localStorage.setItem(STORAGE_KEYS.pairing, JSON.stringify(rows)); + } catch (error) { + console.error('Error getting pairing process:', error); + const newRow = { + column1: spAddress, + column2: 'This Device', + column3: emojis + }; + rows = [newRow, ...rows]; + localStorage.setItem(STORAGE_KEYS.pairing, JSON.stringify(rows)); + } + } + + this.updateTableContent(rows); + } +} + +private showWallet(): void { + isAddingRow = false; + currentRow = null; + + currentMode = 'wallet'; + this.hideAllContent(); + + // Mettre à jour le titre + const headerTitle = this.shadowRoot?.getElementById('header-title'); + if (headerTitle) headerTitle.textContent = 'Wallet'; + + const walletContent = this.shadowRoot?.getElementById('wallet-content'); + if (!walletContent) return; + walletContent.style.display = 'block'; + walletContent.innerHTML = ` +
Wallet
+
+ + + + + + + + + +
LabelWalletType
+
+ +
+
+ `; + + const rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.wallet) || '[]'); + this.updateWalletTableContent(rows); +} + + +private updateWalletTableContent(rows: WalletRow[]): void { + const tbody = this.shadowRoot?.querySelector('#wallet-table tbody'); + if (!tbody) return; + + tbody.innerHTML = rows.map(row => ` + + ${row.column1} + ${row.column2} + ${row.column3} + + `).join(''); +} + +private showData(): void { + //console.log("showData called"); + currentMode = 'data'; + this.hideAllContent(); + + const headerTitle = this.shadowRoot?.getElementById('header-title'); + if (headerTitle) headerTitle.textContent = 'Data'; + + const dataContent = this.shadowRoot?.getElementById('data-content'); + if (dataContent) { + dataContent.style.display = 'block'; + dataContent.innerHTML = ` +
Data
+
+ + + + + + + + + + + + +
NameVisibilityRoleDurationLegalContract
+
+ `; + + const rows = mockDataRows || JSON.parse(localStorage.getItem(STORAGE_KEYS.data) || '[]'); + this.updateDataTableContent(rows); + } +} + +// Fonctions de gestion du wallet +private addWalletRow(): void { + if (isAddingRow) return; + isAddingRow = true; + + const table = this.shadowRoot?.getElementById('wallet-table')?.getElementsByTagName('tbody')[0]; + if (!table) return; + + currentRow = table.insertRow(); + const placeholders = ['Label', 'Wallet', 'Type']; + + placeholders.forEach(placeholder => { + const cell = currentRow!.insertCell(); + const input = document.createElement('input'); + input.type = 'text'; + input.placeholder = placeholder; + input.className = 'edit-input'; + cell.appendChild(input); + }); + + // Remplacer le bouton "Add a line" par les boutons de confirmation/annulation + const buttonContainer = this.shadowRoot?.querySelector('#wallet-content .button-container'); + if (!buttonContainer) return; + + buttonContainer.innerHTML = ` +
+ + +
+ `; + + this.updateActionButtons(); +} + +private confirmWalletRow(): void { + if (!currentRow) return; + + const inputs = Array.from(currentRow.getElementsByTagName('input')); + const allFieldsFilled = inputs.every(input => input.value.trim() !== ''); + + if (allFieldsFilled) { + const newRow: WalletRow = { + column1: inputs[0].value.trim(), + column2: inputs[1].value.trim(), + column3: inputs[2].value.trim() + }; + + const rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.wallet) || '[]'); + rows.push(newRow); + localStorage.setItem(STORAGE_KEYS.wallet, JSON.stringify(rows)); + + isAddingRow = false; + currentRow = null; + this.showWallet(); + } else { + this.showAlert('Please complete all fields before confirming.'); + } +} + +private cancelWalletRow(): void { + if (!currentRow) return; + + currentRow.remove(); + isAddingRow = false; + currentRow = null; + + // Réinitialiser le conteneur de boutons avec le bouton "Add a line" + const buttonContainer = this.shadowRoot?.querySelector('#wallet-content .button-container'); + if (!buttonContainer) return; + + buttonContainer.innerHTML = ` + + `; + + +} + +private updateDataTableContent(rows: DataRow[]): void { + const tbody = this.shadowRoot?.querySelector('#data-table tbody'); + if (!tbody) return; + + tbody.innerHTML = rows.map(row => ` + + ${row.column1} + ${row.column2} + ${row.column3} + ${row.column4} + ${row.column5} + + ${row.column6} + + + `).join(''); +} + +// Fonctions de gestion de l'avatar et de la bannière +private openAvatarPopup(): void { + const popup = this.shadowRoot?.getElementById('avatar-popup'); + if (!popup) return; + + // Récuprer les valeurs stockées + const savedName = localStorage.getItem('userName'); + const savedLastName = localStorage.getItem('userLastName'); + const savedAvatar = localStorage.getItem('userAvatar') || 'https://via.placeholder.com/150'; + const savedBanner = localStorage.getItem('userBanner') || 'https://via.placeholder.com/800x200'; + const savedAddress = localStorage.getItem('userAddress') || '🏠 🌍 🗽🎊😩-🎊😑😩'; + + popup.innerHTML = ` + + `; + + popup.style.display = 'block'; + this.setupEventListeners(popup); + + // Ajouter le gestionnaire d'événements pour la bannière + const bannerImg = popup.querySelector('#popup-banner-img'); + const bannerInput = popup.querySelector('#banner-upload') as HTMLInputElement; + + if (bannerImg && bannerInput) { + bannerImg.addEventListener('click', () => { + bannerInput.click(); + }); + } + + const recoveryExported = localStorage.getItem('recoveryExported') === 'true'; + if (recoveryExported) { + const exportRecoveryBtn = popup.querySelector('.recovery-btn') as HTMLButtonElement; + if (exportRecoveryBtn) { + exportRecoveryBtn.disabled = true; + exportRecoveryBtn.style.opacity = '0.5'; + exportRecoveryBtn.style.cursor = 'not-allowed'; + } + } +} + +private setupEventListeners(popup: HTMLElement): void { + // Gestionnaire pour la fermeture + const closeBtn = popup.querySelector('.close-popup'); + if (closeBtn) { + closeBtn.addEventListener('click', () => { + popup.style.display = 'none'; + }); + } + + // Gestionnaire pour l'upload d'avatar + const avatarUpload = popup.querySelector('#avatar-upload') as HTMLInputElement; + if (avatarUpload) { + avatarUpload.addEventListener('change', (e: Event) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (e: ProgressEvent) => { + const result = e.target?.result as string; + // Mise à jour de l'avatar dans la preview et le popup + const popupAvatar = this.shadowRoot?.getElementById('popup-avatar-img') as HTMLImageElement; + const previewAvatar = this.shadowRoot?.querySelector('.preview-avatar') as HTMLImageElement; + + if (popupAvatar) popupAvatar.src = result; + if (previewAvatar) previewAvatar.src = result; + + localStorage.setItem('userAvatar', result); + }; + reader.readAsDataURL(file); + } + }); + } + + // Gestionnaire pour l'upload de bannière + const bannerUpload = popup.querySelector('#banner-upload') as HTMLInputElement; + if (bannerUpload) { + bannerUpload.addEventListener('change', (e: Event) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (e: ProgressEvent) => { + const result = e.target?.result as string; + // Mise à jour de la bannière dans la preview et le popup + const popupBanner = this.shadowRoot?.getElementById('popup-banner-img') as HTMLImageElement; + const previewBanner = this.shadowRoot?.querySelector('.preview-banner-img') as HTMLImageElement; + + if (popupBanner) popupBanner.src = result; + if (previewBanner) previewBanner.src = result; + + localStorage.setItem('userBanner', result); + }; + reader.readAsDataURL(file); + } + }); + } + + // Gestionnaires pour les champs de texte + const nameInput = popup.querySelector('#userName') as HTMLInputElement; + const lastNameInput = popup.querySelector('#userLastName') as HTMLInputElement; + + if (nameInput) { + nameInput.addEventListener('input', () => { + const newName = nameInput.value; + localStorage.setItem('userName', newName); + // Mise à jour du nom dans la preview + const previewName = this.shadowRoot?.querySelector('.preview-name'); + if (previewName) previewName.textContent = newName; + }); + } + + if (lastNameInput) { + lastNameInput.addEventListener('input', () => { + const newLastName = lastNameInput.value; + localStorage.setItem('userLastName', newLastName); + // Mise à jour du nom de famille dans la preview + const previewLastName = this.shadowRoot?.querySelector('.preview-lastname'); + if (previewLastName) previewLastName.textContent = newLastName; + }); + } +} + +private closeAvatarPopup(): void { + const popup = this.shadowRoot?.querySelector('.avatar-popup'); + if (popup) popup.remove(); +} + +private loadAvatar(): void { + const savedAvatar = localStorage.getItem('userAvatar'); + if (savedAvatar) { + const avatarImg = this.shadowRoot?.querySelector('.avatar') as HTMLImageElement; + if (avatarImg) { + avatarImg.src = savedAvatar; + } + } +} + +private loadUserInfo(): void { + const savedName = localStorage.getItem('userName'); + const savedLastName = localStorage.getItem('userLastName'); + const savedAvatar = localStorage.getItem('userAvatar'); + const savedBanner = localStorage.getItem('userBanner'); + + // Mise à jour du nom dans la preview + if (savedName) { + const previewName = this.shadowRoot?.querySelector('.preview-name'); + if (previewName) { + previewName.textContent = savedName; + } + } + + // Mise à jour du nom de famille dans la preview + if (savedLastName) { + const previewLastName = this.shadowRoot?.querySelector('.preview-lastname'); + if (previewLastName) { + previewLastName.textContent = savedLastName; + } + } + + // Mise à jour de l'avatar dans la preview + if (savedAvatar) { + const previewAvatar = this.shadowRoot?.querySelector('.preview-avatar') as HTMLImageElement; + if (previewAvatar) { + previewAvatar.src = savedAvatar; + } + } + + // Mise à jour de la bannière dans la preview + if (savedBanner) { + const previewBanner = this.shadowRoot?.querySelector('.preview-banner-img') as HTMLImageElement; + if (previewBanner) { + previewBanner.src = savedBanner; + } + } +} + +private updateNavbarName(name: string): void { + const nameElement = this.shadowRoot?.querySelector('.nav-wrapper .user-name'); + if (nameElement) { + nameElement.textContent = name; + } +} + +private updateNavbarLastName(lastName: string): void { + const lastNameElement = this.shadowRoot?.querySelector('.nav-wrapper .user-lastname'); + if (lastNameElement) { + lastNameElement.textContent = lastName; + } +} + +private updateProfilePreview(data: { + avatar?: string, + banner?: string, + name?: string, + lastName?: string +}): void { + if (data.avatar) { + const previewAvatar = this.shadowRoot?.querySelector('.preview-avatar') as HTMLImageElement; + if (previewAvatar) previewAvatar.src = data.avatar; + } + + if (data.banner) { + const previewBanner = this.shadowRoot?.querySelector('.preview-banner-img') as HTMLImageElement; + if (previewBanner) previewBanner.src = data.banner; + } + + if (data.name) { + const previewName = this.shadowRoot?.querySelector('.preview-name'); + if (previewName) previewName.textContent = data.name; + } + + if (data.lastName) { + const previewLastName = this.shadowRoot?.querySelector('.preview-lastname'); + if (previewLastName) previewLastName.textContent = data.lastName; + } +} + +private initializeEventListeners() { + this.shadowRoot?.addEventListener('DOMContentLoaded', () => { + this.showPairing(); + }); + + const editableFields = this.shadowRoot?.querySelectorAll('.editable'); + if (editableFields) { + editableFields.forEach(field => { + field.addEventListener('click', () => { + if (!field.classList.contains('editing')) { + const currentValue = field.textContent || ''; + const input = document.createElement('input'); + input.type = 'text'; + input.value = currentValue; + input.className = 'edit-input'; + + field.textContent = ''; + field.appendChild(input); + field.classList.add('editing'); + input.focus(); + } + }); + }); + } + + const avatarInput = this.shadowRoot?.getElementById('avatar-upload') as HTMLInputElement; + if (avatarInput) { + avatarInput.addEventListener('change', this.handleAvatarUpload.bind(this)); + } +} + +private showQRCodeModal(pairingId: string): void { + const modal = document.createElement('div'); + modal.className = 'qr-modal'; + modal.innerHTML = ` +
+ × + QR Code Large +
${decodeURIComponent(pairingId)}
+
+ `; + + this.shadowRoot?.appendChild(modal); + + const closeBtn = modal.querySelector('.close-qr-modal'); + closeBtn?.addEventListener('click', () => modal.remove()); + modal.addEventListener('click', (e) => { + if (e.target === modal) modal.remove(); + }); +} +} + +customElements.define('account-element', AccountElement); +export { AccountElement }; diff --git a/ihm_client/src/pages/account/document-validation.ts b/ihm_client/src/pages/account/document-validation.ts new file mode 100644 index 00000000..af45c8db --- /dev/null +++ b/ihm_client/src/pages/account/document-validation.ts @@ -0,0 +1,321 @@ +import type { ProcessState } from '../../../pkg/sdk_client'; +import Services from '../../services/service'; + +interface State { + file: File | null; + fileHash: string | null; + certificate: ProcessState | null; + commitmentHashes: string[]; +} + +export interface Vin { + txid: string; // The txid of the previous transaction (being spent) + vout: number; // The output index in the previous tx + 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 function getDocumentValidation(container: HTMLElement) { + const state: State = { + file: null, + fileHash: null, + certificate: null, + commitmentHashes: [] + } + + container.innerHTML = ''; + container.style.cssText = ` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 100vh; + gap: 2rem; + `; + + function createDropButton( + label: string, + onDrop: (file: File, updateVisuals: (file: File) => void) => void, + accept: string = '*/*' + ): HTMLElement { + const wrapper = document.createElement('div'); + wrapper.style.cssText = ` + width: 200px; + height: 100px; + border: 2px dashed #888; + border-radius: 8px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + cursor: pointer; + font-weight: bold; + background: #f8f8f8; + text-align: center; + padding: 0.5rem; + box-sizing: border-box; + `; + + const title = document.createElement('div'); + title.textContent = label; + + const filename = document.createElement('div'); + filename.style.cssText = ` + font-size: 0.85rem; + margin-top: 0.5rem; + color: #444; + word-break: break-word; + text-align: center; + `; + + wrapper.appendChild(title); + wrapper.appendChild(filename); + + const updateVisuals = (file: File) => { + wrapper.style.borderColor = 'green'; + wrapper.style.background = '#e6ffed'; + filename.textContent = file.name; + }; + + // === Hidden file input === + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.accept = accept; + fileInput.style.display = 'none'; + document.body.appendChild(fileInput); + + fileInput.onchange = () => { + const file = fileInput.files?.[0]; + if (file) { + onDrop(file, updateVisuals); + fileInput.value = ''; // reset so same file can be re-selected + } + }; + + // === Handle drag-and-drop === + wrapper.ondragover = e => { + e.preventDefault(); + wrapper.style.background = '#e0e0e0'; + }; + + wrapper.ondragleave = () => { + wrapper.style.background = '#f8f8f8'; + }; + + wrapper.ondrop = e => { + e.preventDefault(); + wrapper.style.background = '#f8f8f8'; + + const file = e.dataTransfer?.files?.[0]; + if (file) { + onDrop(file, updateVisuals); + } + }; + + // === Handle click to open file manager === + wrapper.onclick = () => { + fileInput.click(); + }; + + return wrapper; + } + + const fileDropButton = createDropButton('Drop file', async (file, updateVisuals) => { + try { + state.file = file; + updateVisuals(file); + console.log('Loaded file:', state.file); + checkReady(); + } catch (err) { + alert('Failed to drop the file.'); + console.error(err); + } + }); + + const certDropButton = createDropButton('Drop certificate', async (file, updateVisuals) => { + try { + const text = await file.text(); + const json = JSON.parse(text); + if ( + typeof json === 'object' && + json !== null && + typeof json.pcd_commitment === 'object' && + typeof json.state_id === 'string' + ) { + state.certificate = json as ProcessState; + + state.commitmentHashes = Object.values(json.pcd_commitment).map((h: any) => + (h as string).toLowerCase() + ); + + updateVisuals(file); + console.log('Loaded certificate, extracted hashes:', state.commitmentHashes); + checkReady(); + } else { + alert('Invalid certificate structure.'); + } + } catch (err) { + alert('Failed to parse certificate JSON.'); + console.error(err); + } + }); + + const buttonRow = document.createElement('div'); + buttonRow.style.display = 'flex'; + buttonRow.style.gap = '2rem'; + buttonRow.appendChild(fileDropButton); + buttonRow.appendChild(certDropButton); + + container.appendChild(buttonRow); + + async function checkReady() { + if (state.file && state.certificate && state.commitmentHashes.length > 0) { + // We take the commited_in and all pcd_commitment keys to reconstruct all the possible hash + const fileBlob = { + type: state.file.type, + data: new Uint8Array(await state.file.arrayBuffer()) + }; + const service = await Services.getInstance(); + const commitedIn = state.certificate.commited_in; + if (!commitedIn) return; + const [prevTxid, prevTxVout] = commitedIn.split(':'); + const processId = state.certificate.commited_in; + const stateId = state.certificate.state_id; + const process = await service.getProcess(processId); + if (!process) return; + + // Get the transaction that comes right after the commited_in + const nextState = service.getNextStateAfterId(process, stateId); + + if (!nextState) { + alert(`❌ Validation failed: No next state, is the state you're trying to validate commited?`); + return; + } + + const [outspentTxId, _] = nextState.commited_in.split(':'); + console.log(outspentTxId); + + // Check that the commitment transaction exists, and that it commits to the state id + + const txInfo = await fetchTransaction(outspentTxId); + if (!txInfo) { + console.error(`Validation error: Can't fetch new state commitment transaction`); + alert(`❌ Validation failed: invalid or non existent commited_in for state ${stateId}.`); + return; + } + + // We must check that this transaction indeed spend the commited_in we have in the certificate + let found = false; + for (const vin of txInfo.vin) { + if (vin.txid === prevTxid) { + found = true; + break; + } + } + + if (!found) { + console.error(`Validation error: new state doesn't spend previous state commitment transaction`); + alert('❌ Validation failed: Unconsistent commitment transactions history.'); + return; + } + + // set found back to false for next check + found = false; + + // is the state_id commited in the transaction? + for (const vout of txInfo.vout) { + console.log(vout); + if (vout.scriptpubkey_type && vout.scriptpubkey_type === 'op_return') { + found = true; + } else { + continue; + } + + if (vout.scriptpubkey_asm) { + const hash = extractHexFromScriptAsm(vout.scriptpubkey_asm); + if (hash) { + if (hash !== stateId) { + console.error(`Validation error: expected stateId ${stateId}, got ${hash}`); + alert('❌ Validation failed: Transaction does not commit to that state.'); + return; + } + } + } + } + + if (!found) { + alert('❌ Validation failed: Transaction does not contain data.'); + return; + } + + // set found back to false for next check + found = false; + + for (const label of Object.keys(state.certificate.pcd_commitment)) { + // Compute the hash for this label + console.log(`Computing hash with label ${label}`) + const fileHex = service.getHashForFile(commitedIn, label, fileBlob); + console.log(`Found hash ${fileHex}`); + found = state.commitmentHashes.includes(fileHex); + if (found) break; + } + + if (found) { + alert('✅ Validation successful: file hash found in pcd_commitment.'); + } else { + alert('❌ Validation failed: file hash NOT found in pcd_commitment.'); + } + } + } + + async function fetchTransaction(txid: string): Promise { + const url = `https://mempool.4nkweb.com/api/tx/${txid}`; + + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch outspend status: ${response.statusText}`); + } + + const outspend: TransactionInfo = await response.json(); + return outspend; + } + + function extractHexFromScriptAsm(scriptAsm: string): string | null { + const parts = scriptAsm.trim().split(/\s+/); + const last = parts[parts.length - 1]; + + // Basic validation: must be 64-char hex (32 bytes) + if (/^[0-9a-fA-F]{64}$/.test(last)) { + return last.toLowerCase(); + } + + return null; + } +} diff --git a/ihm_client/src/pages/account/key-value-section.ts b/ihm_client/src/pages/account/key-value-section.ts new file mode 100644 index 00000000..976c9740 --- /dev/null +++ b/ihm_client/src/pages/account/key-value-section.ts @@ -0,0 +1,196 @@ +import type { ValidationRule, RoleDefinition } from '../../../pkg/sdk_client'; +import { showValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal'; + +export function createKeyValueSection(title: string, id: string, isRoleSection = false) { + const section = document.createElement('div'); + section.id = id; + section.style.cssText = 'margin-bottom: 2rem; background: #fff; padding: 1rem; border-radius: 0.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1);'; + + const titleEl = document.createElement('h2'); + titleEl.textContent = title; + titleEl.style.cssText = 'font-size: 1.25rem; font-weight: bold; margin-bottom: 1rem;'; + section.appendChild(titleEl); + + const rowContainer = document.createElement('div'); + section.appendChild(rowContainer); + + const addBtn = document.createElement('button'); + addBtn.textContent = '+ Add Row'; + addBtn.style.cssText = ` + margin-top: 1rem; + padding: 0.5rem 1rem; + border: 1px solid #888; + border-radius: 0.375rem; + background-color: #f9f9f9; + cursor: pointer; + `; + section.appendChild(addBtn); + + const roleRowStates: { + roleNameInput: HTMLInputElement; + membersInput: HTMLInputElement; + storagesInput: HTMLInputElement; + validationRules: ValidationRule[]; + }[] = []; + type fileBlob = { + type: string, + data: Uint8Array + }; + const nonRoleRowStates: { + keyInput: HTMLInputElement, + valueInput: HTMLInputElement, + fileInput: HTMLInputElement, + fileBlob: fileBlob | null + }[] = []; + + const inputStyle = 'flex: 1; height: 2.5rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem;'; + + const createRow = () => { + const row = document.createElement('div'); + row.style.cssText = 'display: flex; gap: 1rem; margin-bottom: 0.5rem; align-items: center;'; + + const deleteBtn = document.createElement('button'); + deleteBtn.textContent = '🗑️'; + deleteBtn.style.cssText = 'background: none; border: none; font-size: 1.2rem; cursor: pointer;'; + deleteBtn.onclick = () => { + row.remove(); + updateDeleteButtons(); + }; + + if (isRoleSection) { + const roleName = document.createElement('input'); + const members = document.createElement('input'); + const storages = document.createElement('input'); + + roleName.placeholder = 'Role name'; + members.placeholder = 'members'; + storages.placeholder = 'storages'; + [roleName, members, storages].forEach(input => { + input.type = 'text'; + input.style.cssText = inputStyle; + }); + + const ruleButton = document.createElement('button'); + ruleButton.textContent = 'Add Validation Rule'; + ruleButton.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;'; + + const rules: ValidationRule[] = []; + ruleButton.onclick = () => { + showValidationRuleModal(rule => { + rules.push(rule); + ruleButton.textContent = `Rules (${rules.length})`; + }); + }; + + row.appendChild(roleName); + row.appendChild(members); + row.appendChild(storages); + row.appendChild(ruleButton); + row.appendChild(deleteBtn); + + roleRowStates.push({ roleNameInput: roleName, membersInput: members, storagesInput: storages, validationRules: rules }); + } else { + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.style.display = 'none'; + fileInput.onchange = async () => { + const file = fileInput.files?.[0]; + if (!file) return; + + const buffer = await file.arrayBuffer(); + const uint8 = new Uint8Array(buffer); + + rowState.fileBlob = { + type: file.type, + data: uint8, + }; + + valueInput.value = `📄 ${file.name}`; + valueInput.disabled = true; + attachBtn.textContent = `📎 ${file.name}`; + }; + + const attachBtn = document.createElement('button'); + attachBtn.textContent = '📎 Attach'; + attachBtn.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;'; + attachBtn.onclick = () => fileInput.click(); + + const keyInput = document.createElement('input'); + const valueInput = document.createElement('input'); + + const rowState = { + keyInput, + valueInput, + fileInput, + fileBlob: null as fileBlob | null + }; + nonRoleRowStates.push(rowState); + + keyInput.placeholder = 'Key'; + valueInput.placeholder = 'Value'; + [keyInput, valueInput].forEach(input => { + input.type = 'text'; + input.style.cssText = inputStyle; + }); + + row.appendChild(keyInput); + row.appendChild(valueInput); + + row.appendChild(attachBtn); + row.appendChild(fileInput); + + row.appendChild(deleteBtn); + } + + rowContainer.appendChild(row); + updateDeleteButtons(); + }; + + const updateDeleteButtons = () => { + const rows = Array.from(rowContainer.children); + rows.forEach(row => { + const btn = row.querySelector('button:last-child') as HTMLButtonElement; + if (rows.length === 1) { + btn.disabled = true; + btn.style.visibility = 'hidden'; + } else { + btn.disabled = false; + btn.style.visibility = 'visible'; + } + }); + }; + + createRow(); + addBtn.addEventListener('click', createRow); + + return { + element: section, + getData: () => { + if (isRoleSection) { + const data: Record = {}; + for (const row of roleRowStates) { + const key = row.roleNameInput.value.trim(); + if (!key) continue; + data[key] = { + members: row.membersInput.value.split(',').map(x => x.trim()).filter(Boolean), + storages: row.storagesInput.value.split(',').map(x => x.trim()).filter(Boolean), + validation_rules: row.validationRules + }; + } + return data; + } else { + const data: Record = {}; + for (const row of nonRoleRowStates) { + const key = row.keyInput.value.trim(); + if (!key) continue; + if (row.fileBlob) { + data[key] = row.fileBlob; + } else { + data[key] = row.valueInput.value.trim(); + } + } + return data; + } + } + }; +} diff --git a/ihm_client/src/pages/account/process-creation.ts b/ihm_client/src/pages/account/process-creation.ts new file mode 100644 index 00000000..5fb0d7c2 --- /dev/null +++ b/ihm_client/src/pages/account/process-creation.ts @@ -0,0 +1,93 @@ +import { createKeyValueSection } from './key-value-section'; +import { loadValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal'; +import Services from '../../services/service'; +import type { RoleDefinition } from '../../../pkg/sdk_client'; + +export async function getProcessCreation(container: HTMLElement) { + await loadValidationRuleModal(); + + container.style.display = 'block'; + container.innerHTML = `
Process Creation
`; + const privateSec = createKeyValueSection('Private Data', 'private-section'); + const publicSec = createKeyValueSection('Public Data', 'public-section'); + const rolesSec = createKeyValueSection('Roles', 'roles-section', true); + + container.appendChild(privateSec.element); + container.appendChild(publicSec.element); + container.appendChild(rolesSec.element); + + const btn = document.createElement('button'); + btn.textContent = 'Create Process'; + btn.style.cssText = ` + display: block; + margin: 2rem auto 0; + padding: 0.75rem 2rem; + font-size: 1rem; + font-weight: bold; + background-color: #4f46e5; + color: white; + border: none; + border-radius: 0.5rem; + cursor: pointer; + `; + + btn.onclick = async () => { + const privateData = privateSec.getData(); + const publicData = publicSec.getData(); + const roles = rolesSec.getData() as Record; + + console.log('Private:', privateData); + console.log('Public:', publicData); + console.log('Roles:', roles); + + const service = await Services.getInstance(); + + const createProcessResult = await service.createProcess(privateData, publicData, roles); + const processId = createProcessResult.updated_process!.process_id; + const stateId = createProcessResult.updated_process!.current_process.states[0].state_id; + await service.handleApiReturn(createProcessResult); + + // Now we want to validate the update and register the first state of our new process + const updateProcessResult = await service.createPrdUpdate(processId, stateId); + await service.handleApiReturn(createProcessResult); + + const approveChangeResult = await service.approveChange(processId, stateId); + await service.handleApiReturn(approveChangeResult); + if (approveChangeResult) { + const process = await service.getProcess(processId); + let newState = process ? service.getStateFromId(process, stateId) : null; + if (!newState) return; + for (const label of Object.keys(newState.keys)) { + const hash = newState.pcd_commitment[label]; + const encryptedData = await service.getBlobFromDb(hash); + if (!encryptedData) continue; + const filename = `${label}-${hash.slice(0,8)}.bin`; + + const blob = new Blob([encryptedData], { type: "application/octet-stream" }); + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = filename; + link.click(); + + setTimeout(() => URL.revokeObjectURL(link.href), 1000); + } + + // await service.generateProcessPdf(processId, newState); + + // Add processId to the state we export + // newState n'a pas de propriété process_id, on utilise commited_in + // newState['process_id'] = processId; + const blob = new Blob([JSON.stringify(newState, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.href = url; + a.download = `process_${processId}_${stateId}.json`; + a.click(); + + URL.revokeObjectURL(url); // Clean up + } + }; + + container.appendChild(btn); +} diff --git a/ihm_client/src/pages/account/process.ts b/ihm_client/src/pages/account/process.ts new file mode 100644 index 00000000..10eaeb6a --- /dev/null +++ b/ihm_client/src/pages/account/process.ts @@ -0,0 +1,66 @@ +export function createProcessTab(container: HTMLElement, processes: { name: string, publicData: Record }[]): HTMLElement { + container.id = 'process-tab'; + container.style.display = 'block'; + container.style.cssText = 'padding: 1.5rem;'; + + const title = document.createElement('h2'); + title.textContent = 'Processes'; + title.style.cssText = 'font-size: 1.5rem; font-weight: bold; margin-bottom: 1rem;'; + container.appendChild(title); + + processes.forEach(proc => { + const card = document.createElement('div'); + card.style.cssText = 'margin-bottom: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 0.5rem; background: #fff;'; + + const nameEl = document.createElement('h3'); + nameEl.textContent = proc.name; + nameEl.style.cssText = 'font-size: 1.2rem; font-weight: bold; margin-bottom: 0.5rem;'; + card.appendChild(nameEl); + + const dataList = document.createElement('div'); + for (const [key, value] of Object.entries(proc.publicData)) { + const item = document.createElement('div'); + item.style.cssText = 'margin-bottom: 0.5rem;'; + + const label = document.createElement('strong'); + label.textContent = key + ': '; + item.appendChild(label); + + // Let's trim the quotes + const trimmed = value.replace(/^'|'$/g, ''); + let parsed; + try { + parsed = JSON.parse(trimmed); + } catch (_) { + parsed = trimmed; + } + + if (parsed && typeof parsed === 'object') { + const saveBtn = document.createElement('button'); + saveBtn.textContent = '💾 Save as JSON'; + saveBtn.style.cssText = 'margin-left: 0.5rem; padding: 0.25rem 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;'; + saveBtn.onclick = () => { + const blob = new Blob([JSON.stringify(parsed, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${proc.name}_${key}.json`; + a.click(); + URL.revokeObjectURL(url); + }; + item.appendChild(saveBtn); + } else { + const span = document.createElement('span'); + span.textContent = String(parsed); + item.appendChild(span); + } + + dataList.appendChild(item); + } + + card.appendChild(dataList); + container.appendChild(card); + }); + + return container; +} diff --git a/ihm_client/src/pages/chat/chat-component.ts b/ihm_client/src/pages/chat/chat-component.ts new file mode 100644 index 00000000..2ded0b8f --- /dev/null +++ b/ihm_client/src/pages/chat/chat-component.ts @@ -0,0 +1,49 @@ +/*import { ChatElement } from './chat'; +import chatCss from '../../../public/style/chat.css?raw'; +import Services from '../../services/service.js'; + +class ChatComponent extends HTMLElement { + _callback: any; + chatElement: ChatElement | null = null; + + constructor() { + super(); + console.log('INIT'); + this.attachShadow({ mode: 'open' }); + + this.chatElement = this.shadowRoot?.querySelector('chat-element') || null; + } + + connectedCallback() { + console.log('CALLBACKs'); + this.render(); + + if (!customElements.get('chat-element')) { + customElements.define('chat-element', ChatElement); + } + } + + set callback(fn) { + if (typeof fn === 'function') { + this._callback = fn; + } else { + console.error('Callback is not a function'); + } + } + + get callback() { + return this._callback; + } + + render() { + if (this.shadowRoot) { + // Créer l'élément chat-element + const chatElement = document.createElement('chat-element'); + this.shadowRoot.innerHTML = ``; + this.shadowRoot.appendChild(chatElement); + } + } +} + +export { ChatComponent }; +customElements.define('chat-component', ChatComponent);*/ diff --git a/ihm_client/src/pages/chat/chat.html b/ihm_client/src/pages/chat/chat.html new file mode 100755 index 00000000..5265c880 --- /dev/null +++ b/ihm_client/src/pages/chat/chat.html @@ -0,0 +1,14 @@ + +
+
    +
+
+ + +
+
+ +
+
+ +
+ + +
+ + + + +
+
+ + +
+
+

Signature

+ +
+
+
+

Description

+
+
+
+

Documents

+ +
+
+
    +
    +
    +
    +
    + + `; + window.loadMemberChat = async (memberId: string | number) => { + if (typeof memberId === 'string') { + return await this.loadMemberChat(memberId); + } else { + console.error('Invalid memberId type. Expected string, got number.'); + } + }; + + document.addEventListener('newDataReceived', async (event: CustomEvent) => { + const { detail } = event; + console.log('New data event received:', JSON.stringify(detail)); + + if (detail.processId && detail.processId === this.selectedChatProcessId) { + console.log('Detected update to chat'); + if (this.selectedMember) { + await this.loadMemberChat(this.selectedMember); + } else { + console.error('No selected member?'); + } + } else { + console.log('Received an update for another process'); + } + }); + + + document.addEventListener('DOMContentLoaded', () => { + this.notificationBadge = document.querySelector('.notification-badge'); + this.notificationBoard = document.getElementById('notification-board'); + this.notificationBell = document.getElementById('notification-bell'); + + if (!this.notificationBadge || !this.notificationBoard || !this.notificationBell) { + console.error('Notification elements not found'); + } + }); + + // Initialiser les événements de notification + document.addEventListener('click', (event: Event): void => { + if (this.notificationBoard && this.notificationBoard.style.display === 'block' && + !this.notificationBoard.contains(event.target as Node) && + this.notificationBell && !this.notificationBell.contains(event.target as Node)) { + this.notificationBoard.style.display = 'none'; + } + }); + this.initMessageEvents(); + + } + + private initMessageEvents() { + const sendButton = this.shadowRoot?.querySelector('#send-button'); + if (sendButton) { + sendButton.addEventListener('click', async () => { + await this.sendMessage(); + setTimeout(async () => await this.reloadMemberChat(this.selectedMember), 600); + messageInput.value = ''; + }); + } + + const messageInput = this.shadowRoot?.querySelector('#message-input'); + if (messageInput) { + messageInput.addEventListener('keypress', async (event: Event) => { + const keyEvent = event as KeyboardEvent; + if (keyEvent.key === 'Enter' && !keyEvent.shiftKey) { + event.preventDefault(); + await this.sendMessage(); + setTimeout(async () => await this.reloadMemberChat(this.selectedMember), 600); + messageInput.value = ''; + } + }); + } + + const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement; + if (fileInput) { + fileInput.addEventListener('change', (event: Event) => { + const target = event.target as HTMLInputElement; + if (target.files && target.files.length > 0) { + this.sendFile(target.files[0]); + } + }); + } + } + + ///////////////////// Notification module ///////////////////// + // Delete a notification + private removeNotification(index: number) { + this.notifications?.splice(index, 1); // Ajout de ?. + this.renderNotifications(); + this.updateNotificationBadge(); + } + // Show notifications + private renderNotifications() { + if (!this.notificationBoard) return; + + // Reset the interface + this.notificationBoard.innerHTML = ''; + + // Displays "No notifications available" if there are no notifications + if (this.notifications.length === 0) { + this.notificationBoard.innerHTML = '
    No notifications available
    '; + return; + } + + // Add each notification to the list + this.notifications.forEach((notif, index) => { + const notifElement = document.createElement('div'); + notifElement.className = 'notification-item'; + notifElement.textContent = `${notif.text} at ${notif.time}`; + notifElement.onclick = async () => { + await this.loadMemberChat(notif.memberId); + await this.removeNotification(index); + }; + this.notificationBoard?.appendChild(notifElement); + }); + } + private updateNotificationBadge() { + if (!this.notificationBadge) return; + const count = this.notifications.length; + this.notificationBadge.textContent = count > 99 ? '+99' : count.toString(); + (this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none'; + } + + + // Add notification + private async addNotification(memberId: string, message: any) { + try { + // Obtenir l'emoji à partir du Pairing Process + const pairingProcess = await this.getPairingProcess(memberId); + const memberEmoji = await addressToEmoji(pairingProcess); + + // Obtenir le processus et le rôle + const processId = this.getAttribute('process-id'); + const processEmoji = processId ? await addressToEmoji(processId) : '📝'; + + // Trouver le rôle du membre + const member = this.allMembers.find(m => String(m.id) === memberId); + const role = message.metadata?.roleName || 'Member'; + + // Déterminer le texte de la notification + let notificationText = ''; + if (message.type === 'file') { + notificationText = `${memberEmoji} (${role}) in ${processEmoji}: New file - ${message.fileName}`; + } else { + notificationText = `${memberEmoji} (${role}) in ${processEmoji}: ${message.metadata.text}`; + } + + // Créer la notification + const notification = { + memberId, + text: notificationText, + time: new Date(message.metadata.timestamp).toLocaleString('fr-FR') + }; + + // Ajouter la notification et mettre à jour l'interface + this.notifications.push(notification); + this.renderNotifications(); + this.updateNotificationBadge(); + + } catch (error) { + console.error('Error creating notification:', error); + } + } + + private async sendMessage() { + const messageInput = this.shadowRoot?.querySelector('#message-input') as HTMLInputElement; + if (!messageInput || !this.selectedMember) { + console.error('❌ Missing message input or selected member'); + return; + } + + if (!this.selectedChatProcessId) { + console.error('no process id set'); + return; + } + + const messageText = messageInput.value.trim(); + if (messageText === '') { + console.error('❌ Empty message'); + return; + } + + try { + const service = await Services.getInstance(); + const myProcessId = await this.getMyProcessId(); + + if (!myProcessId) { + console.error('No paired member found'); + return; + } + + const timestamp = Date.now(); + const message = { + state: this.messageState, + type: 'text', + content: messageText, + metadata: { + createdAt: timestamp, + lastModified: timestamp, + sender: myProcessId, + recipient: this.selectedMember, + } + }; + + console.log("----this.selectedChatProcessId",this.selectedChatProcessId ); + const process = await service.getProcess(this.selectedChatProcessId); + + if (!process) { + console.error('Failed to retrieve process from DB'); + return; + } + + // For a dm process, there are only 2 attributes, description will stay the same, message is the new message + // We don't need to get previous values for now, so let's just skip it + let newState = { + message: message, + description: 'dm' + }; + + // Now we create a new state for the dm process + let apiReturn; + try { + console.log(process); + apiReturn = await service.updateProcess(process, newState, null); + } catch (e) { + console.error('Failed to update process:', e); + return; + } + const updatedProcess = apiReturn.updated_process.current_process; + const newStateId = updatedProcess.states[updatedProcess.states.length - 2 ].state_id; // We take the last concurrent state, just before the tip + console.log(`newStateId: ${newStateId}`); + await service.handleApiReturn(apiReturn); + + const createPrdReturn = service.createPrdUpdate(this.selectedChatProcessId, newStateId); + await service.handleApiReturn(createPrdReturn); + + // Now we validate the new state + const approveChangeReturn = await service.approveChange(this.selectedChatProcessId, newStateId); + await service.handleApiReturn(approveChangeReturn); + + await this.lookForMyDms(); + + const groupList = this.shadowRoot?.querySelector('#group-list'); + const tabs = this.shadowRoot?.querySelectorAll('.tab'); + const memberList = groupList?.querySelector('.member-list'); + + if (memberList) { + memberList.innerHTML = ''; + await this.loadAllMembers(); + if (tabs) { + await this.switchTab('members', tabs); + } + } + } catch (error) { + console.error('❌ Error in sendMessage:', error); + } + } + + private scrollToBottom(container: Element) { + (container as HTMLElement).scrollTop = (container as HTMLElement).scrollHeight; + } + + // Get the diff by state id + async getDiffByStateId(stateId: string) { + try { + const database = await Database.getInstance(); + const diff = await database.requestStoreByIndex('diffs', 'byStateId', stateId); + return diff; + } catch (error) { + console.error('Error getting diff by state id:', error); + } + } + + // TODO rewrite that + // private async lookForChildren(): Promise { + // // Filter processes for the children of current process + // const service = await Services.getInstance(); + // if (!this.selectedChatProcessId) { + // console.error('No process id'); + // return null; + // } + // const children: string[] = await service.getChildrenOfProcess(this.selectedChatProcessId); + + // const processRoles = this.processRoles; + // const selectedMember = this.selectedMember; + // for (const child of children) { + // const roles = service.getRoles(JSON.parse(child)); + // // Check that we and the other members are in the role + // if (!service.isChildRole(processRoles, roles)) { + // console.error('Child process roles are not a subset of parent') + // continue; + // } + // if (!service.rolesContainsMember(roles, selectedMember)) { + // console.error('Member is not part of the process'); + // continue; + // } + // if (!service.rolesContainsUs(roles)) { + // console.error('We\'re not part of child process'); + // continue; + // } + // return child; + // } + + // return null; + // } + + private async loadAllMembers() { + const groupList = this.shadowRoot?.querySelector('#group-list'); + if (!groupList) return; + + const service = await Services.getInstance(); + const members = await service.getAllMembers(); + const processes = await service.getProcesses(); + + const memberList = document.createElement('ul'); + memberList.className = 'member-list active'; + + // Partition members into prioritized and remaining arrays. + const prioritizedMembers: [string, Member][] = []; + const remainingMembers: [string, Member][] = []; + for (const [processId, member] of Object.entries(members)) { + if (this.dmMembersSet.has(processId)) { + prioritizedMembers.push([processId, member]); + } else { + remainingMembers.push([processId, member]); + } + } + const sortedMembers = prioritizedMembers.concat(remainingMembers); + + // Process each member. + for (const [processId, member] of sortedMembers) { + const memberItem = document.createElement('li'); + memberItem.className = 'member-item'; + + // Apply special styling if the member is prioritized. + if (this.dmMembersSet.has(processId)) { + memberItem.style.cssText = ` + background-color: var(--accent-color); + transition: background-color 0.3s ease; + cursor: pointer; + `; + memberItem.addEventListener('mouseover', () => { + memberItem.style.backgroundColor = 'var(--accent-color-hover)'; + }); + memberItem.addEventListener('mouseout', () => { + memberItem.style.backgroundColor = 'var(--accent-color)'; + }); + } + + // Create a container for the member content. + const memberContainer = document.createElement('div'); + memberContainer.className = 'member-container'; + + // Create the emoji span and load its label. + const emojiSpan = document.createElement('span'); + emojiSpan.className = 'member-emoji'; + const emojis = await addressToEmoji(processId); + emojiSpan.dataset.emojis = emojis; + + // Get the member name, if any, and add it to the display + const process = processes[processId]; + let memberPublicName; + if (process) { + const publicMemberData = service.getPublicData(process); + if (publicMemberData) { + const extractedName = publicMemberData['memberPublicName']; + if (extractedName !== undefined && extractedName !== null) { + memberPublicName = extractedName; + } + } + } + if (!memberPublicName) { + memberPublicName = 'Unnamed Member'; + } + + emojiSpan.textContent = `${memberPublicName} (${emojis})` + + memberContainer.appendChild(emojiSpan); + memberItem.appendChild(memberContainer); + + // Add click handler to load member chat. + memberItem.addEventListener('click', async () => { + await this.loadMemberChat(processId); + }); + + // Create and configure the edit label button. + const editLabelButton = document.createElement('button'); + editLabelButton.className = 'edit-label-button'; + editLabelButton.textContent = "✏️"; + editLabelButton.addEventListener("click", (event) => { + event.stopPropagation(); + }); + editLabelButton.addEventListener("dblclick", async (event) => { + event.stopPropagation(); + event.preventDefault(); + + const newLabel = prompt("Set a new name for the member:"); + if (!newLabel) return; + + const db = await Database.getInstance(); + this.updateLabelForEmoji(emojis, newLabel, db, emojiSpan, processId); + }); + memberContainer.appendChild(editLabelButton); + + memberList.appendChild(memberItem); + } + + groupList.appendChild(memberList); + } + + // Helper function to update a label in IndexedDB. + private updateLabelForEmoji( + emojis: string, + newLabel: string, + db: IDBDatabase, + emojiSpan: HTMLElement, + processId: string + ) { + const transaction = db.transaction("labels", "readwrite"); + const store = transaction.objectStore("labels"); + const labelObject = { emoji: emojis, label: newLabel }; + const request = store.put(labelObject); + + request.onsuccess = () => { + emojiSpan.textContent = `${newLabel} : ${emojis}`; + this.reloadMemberChat(processId); + }; + } + + private async lookForDmProcess(): Promise { + const service = await Services.getInstance(); + const processes = await service.getMyProcesses(); + console.log(processes); + const recipientAddresses = await service.getAddressesForMemberId(this.selectedMember).sp_addresses; + console.log(recipientAddresses); + + for (const processId of processes) { + try { + const process = await service.getProcess(processId); + console.log(process); + const state = process.states[0]; // We assume that description never change and that we are part of the process from the beginning + const description = await service.decryptAttribute(processId, state, 'description'); + console.log(description); + if (!description || description !== "dm") { + continue; + } + const roles = service.getRoles(process); + if (!service.rolesContainsMember(roles, recipientAddresses)) { + console.error('Member is not part of the process'); + continue; + } + return processId; + } catch (e) { + console.error(e); + } + } + + return null; + } + + private async lookForMyDms(): Promise { + const service = await Services.getInstance(); + const processes = await service.getMyProcesses(); + const myAddresses = await service.getMemberFromDevice(); + const allMembers = await service.getAllMembers(); + + this.dmMembersSet.clear(); + + try { + for (const processId of processes) { + const process = await service.getProcess(processId); + const state = process.states[0]; + const description = await service.decryptAttribute(processId, state, 'description'); + if (!description || description !== "dm") { + continue; + } + const roles = service.getRoles(process); + const members = roles.dm.members; + for (const member of members) {; + if (!service.compareMembers(member.sp_addresses, myAddresses)) { + for (const [id, mem] of Object.entries(allMembers)) { + if (service.compareMembers(mem.sp_addresses, member.sp_addresses)) { + this.dmMembersSet.add(id); + break; + } + } + } + } + } + } catch (e) { + console.error(e); + } + console.log("dmMembersSet:", this.dmMembersSet); + return null; + } + + private async loadMemberChat(pairingProcess: string) { + if (this.isLoading) { + console.log('Already loading messages, skipping...'); + return; + } + + try { + this.isLoading = true; + const service = await Services.getInstance(); + const myAddresses = await service.getMemberFromDevice(); + const database = await Database.getInstance(); + const db = database.db; + + if (!myAddresses) { + console.error('No paired member found'); + return; + } + + // Set the selected member + this.selectedMember = pairingProcess; + console.log("SELECTED MEMBER: ", this.selectedMember); + + const chatHeader = this.shadowRoot?.querySelector('#chat-header'); + const messagesContainer = this.shadowRoot?.querySelector('#messages'); + + if (!chatHeader || !messagesContainer) return; + + messagesContainer.innerHTML = ''; + + const emojis = await addressToEmoji(pairingProcess); + + const transaction = db.transaction("labels", "readonly"); + const store = transaction.objectStore("labels"); + const request = store.get(emojis); + + request.onsuccess = () => { + const label = request.result; + chatHeader.textContent = label ? `Chat with ${label.label} (${emojis})` : `Chat with member (${emojis})`; + }; + + request.onerror = () => { + chatHeader.textContent = `Chat with member (${emojis})`; + }; + + let dmProcessId = await this.lookForDmProcess(); + + if (dmProcessId === null) { + console.log('Create a new dm process'); + // We need to create a new process + try { + const memberAddresses = await service.getAddressesForMemberId(this.selectedMember); + console.log("MEMBER ADDRESSES: ", memberAddresses); + // await service.checkConnections(otherMembers); + const res = await service.createDmProcess(memberAddresses.sp_addresses); + // We catch the new process here + const updatedProcess = res.updated_process?.current_process; + const processId = updatedProcess?.states[0]?.commited_in; + const stateId = updatedProcess?.states[0]?.state_id; + await service.handleApiReturn(res); + setTimeout(async () => { + // Now create a first commitment + console.log('Created a dm process', processId); + this.selectedChatProcessId = processId; + const createPrdReturn = await service.createPrdUpdate(processId, stateId); + await service.handleApiReturn(createPrdReturn); + const approveChangeReturn = await service.approveChange(processId, stateId); + await service.handleApiReturn(approveChangeReturn); + }, 500); + } catch (e) { + console.error(e); + return; + } + + while (dmProcessId === null) { + dmProcessId = await this.lookForDmProcess(); + await new Promise(r => setTimeout(r, 1000)); + } + } else { + console.log('Found DM process', dmProcessId); + this.selectedChatProcessId = dmProcessId; + } + + // Récupérer les messages depuis les états du processus + const allMessages: any[] = []; + + const dmProcess = await service.getProcess(this.selectedChatProcessId); + + console.log(dmProcess); + + if (dmProcess?.states) { + for (const state of dmProcess.states) { + if (state.state_id === '') { continue; } + const message = await service.decryptAttribute(this.selectedChatProcessId, state, 'message'); + if (message === "" || message === undefined || message === null) { + continue; + } + console.log('message', message); + allMessages.push(message); + } + } + + if (allMessages.length > 0) { + console.log('Messages found:', allMessages); + allMessages.sort((a, b) => a.metadata.createdAt - b.metadata.createdAt); + for (const message of allMessages) { + const messageElement = document.createElement('div'); + messageElement.className = 'message-container'; + + const myProcessId = await this.getMyProcessId(); + + const isCurrentUser = message.metadata.sender === myProcessId; + messageElement.style.justifyContent = isCurrentUser ? 'flex-end' : 'flex-start'; + + const messageContent = document.createElement('div'); + messageContent.className = isCurrentUser ? 'message user' : 'message'; + + const myEmoji = await addressToEmoji(myProcessId); + const otherEmoji = await addressToEmoji(this.selectedMember); + + const senderEmoji = isCurrentUser ? myEmoji : otherEmoji; + + if (message.type === 'file') { + let fileContent = ''; + if (message.content.type.startsWith('image/')) { + fileContent = ` +
    + Image +
    + `; + } else { + const blob = this.base64ToBlob(message.content.data, message.content.type); + const url = URL.createObjectURL(blob); + fileContent = ` + + `; + } + + messageContent.innerHTML = ` +
    + ${senderEmoji}: ${fileContent} +
    +
    + ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')} +
    + `; + } else { + messageContent.innerHTML = ` +
    + ${senderEmoji}: ${message.content} +
    +
    + ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')} +
    + `; + } + + messageElement.appendChild(messageContent); + messagesContainer.appendChild(messageElement); + } + + this.scrollToBottom(messagesContainer); + } else { + console.log('No messages found'); + } + this.scrollToBottom(messagesContainer); + } catch (error) { + console.error('❌ Error in loadMemberChat:', error); + } finally { + this.isLoading = false; + } + } + + private async reloadMemberChat(pairingProcess: string) { + try { + const service = await Services.getInstance(); + const database = await Database.getInstance(); + const db = database.db; + + const chatHeader = this.shadowRoot?.querySelector('#chat-header'); + const messagesContainer = this.shadowRoot?.querySelector('#messages'); + + if (!chatHeader || !messagesContainer) return; + + messagesContainer.innerHTML = ''; + + const emojis = await addressToEmoji(pairingProcess); + + const transaction = db.transaction("labels", "readonly"); + const store = transaction.objectStore("labels"); + const request = store.get(emojis); + + request.onsuccess = () => { + const label = request.result; + if (this.selectedMember === pairingProcess) { + chatHeader.textContent = label ? `Chat with ${label.label} (${emojis})` : `Chat with member (${emojis})`; + } + + }; + + request.onerror = () => { + chatHeader.textContent = `Chat with member (${emojis})`; + }; + + let dmProcessId = await this.selectedChatProcessId; + + // Récupérer les messages depuis les états du processus + const allMessages: any[] = []; + + const dmProcess = await service.getProcess(dmProcessId); + + console.log(dmProcess); + + if (dmProcess?.states) { + for (const state of dmProcess.states) { + if (!state.state_id) { continue; } + const message = await service.decryptAttribute(dmProcessId, state, 'message'); + if (message === "" || message === undefined || message === null) { + continue; + } + console.log('message', message); + allMessages.push(message); + } + } + + allMessages.sort((a, b) => a.metadata.createdAt - b.metadata.createdAt); + if (allMessages.length > 0) { + console.log('Messages found:', allMessages); + for (const message of allMessages) { + const messageElement = document.createElement('div'); + messageElement.className = 'message-container'; + + const myProcessId = await this.getMyProcessId(); + + const isCurrentUser = message.metadata.sender === myProcessId; + messageElement.style.justifyContent = isCurrentUser ? 'flex-end' : 'flex-start'; + + const messageContent = document.createElement('div'); + messageContent.className = isCurrentUser ? 'message user' : 'message'; + + + + const myEmoji = await addressToEmoji(myProcessId); + const otherEmoji = await addressToEmoji(this.selectedMember); + + const senderEmoji = isCurrentUser ? myEmoji : otherEmoji; + + if (message.type === 'file') { + let fileContent = ''; + if (message.content.type.startsWith('image/')) { + fileContent = ` +
    + Image +
    + `; + } else { + const blob = this.base64ToBlob(message.content.data, message.content.type); + const url = URL.createObjectURL(blob); + fileContent = ` + + `; + } + + messageContent.innerHTML = ` +
    + ${senderEmoji}: ${fileContent} +
    +
    + ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')} +
    + `; + } else { + messageContent.innerHTML = ` +
    + ${senderEmoji}: ${message.content} +
    +
    + ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')} +
    + `; + } + + messageElement.appendChild(messageContent); + messagesContainer.appendChild(messageElement); + } + + this.scrollToBottom(messagesContainer); + } else { + console.log('No messages found'); + } + this.scrollToBottom(messagesContainer); + } catch (error) { + console.error('❌ Error in reloadMemberChat:', error); + } + } + + private base64ToBlob(base64: string, type: string): Blob { + const byteCharacters = atob(base64.split(',')[1]); + const byteArrays = []; + + for (let offset = 0; offset < byteCharacters.length; offset += 512) { + const slice = byteCharacters.slice(offset, offset + 512); + const byteNumbers = new Array(slice.length); + + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + } + + return new Blob(byteArrays, { type: type }); + } + + //To get a map with key: sp address, value: pairing process + async getAddressMap() { + const service = await Services.getInstance(); + const allMembers = await service.getAllMembers(); + + const addressMap: Record = {}; + + for (const [key, values] of Object.entries(allMembers)) { + + if (values.sp_addresses) { + for (let value of values.sp_addresses) { + this.addressMap[value] = key; + } + } else { + console.log(`No sp_addresses array found for key "${key}"`); + } + } + return this.addressMap; + } + + async findProcessIdFromAddresses(addresses: string[]): Promise { + console.log('Addresses to find:', addresses); + const service = await Services.getInstance(); + const allMembers = await service.getAllMembers(); + console.log('Available members:', allMembers); + + const sortedAddresses = [...addresses].sort(); + + for (const [key, value] of Object.entries(allMembers)) { + if (value.sp_addresses.length === sortedAddresses.length) { + const sortedValue = [...value.sp_addresses].sort(); + if (sortedValue.every((val, index) => val === sortedAddresses [index])) { + return key; // Found a match + } + } + } + + return null; // No match found + } + + private async toggleMembers(roleData: any, roleElement: HTMLElement) { + console.log('Toggle members called with roleData:', roleData); + let memberList = roleElement.querySelector('.member-list'); + const roleName = roleElement.querySelector('.role-name')?.textContent || ''; + + if (memberList) { + console.log('Existing memberList found, toggling display'); + (memberList as HTMLElement).style.display = + (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none'; + return; + } + + console.log('Creating new memberList'); + memberList = document.createElement('ul'); + memberList.className = 'member-list'; + + if (roleData.members) { + console.log('Members found:', roleData.members); + for (const member of roleData.members) { + console.log('Processing member:', member); + const memberItem = document.createElement('li'); + memberItem.className = 'member-item'; + + const memberContainer = document.createElement('div'); + memberContainer.className = 'member-container'; + + const emojiSpan = document.createElement('span'); + emojiSpan.className = 'member-emoji'; + + const pairingProcess = await this.findProcessIdFromAddresses(member.sp_addresses); + console.log('PairingProcess:', pairingProcess); + if (pairingProcess) { + //TO DO : faire apparaitre les membres avec lesquelels je suis pairé ? + const emojis = await addressToEmoji(pairingProcess); + console.log('Adresse pairée:', emojis); + emojiSpan.textContent = emojis; + } else { + const emojis = await addressToEmoji(member.sp_addresses[0]); + emojiSpan.textContent = emojis; + } + + memberContainer.appendChild(emojiSpan); + memberItem.appendChild(memberContainer); + + memberItem.onclick = async (event) => { + event.stopPropagation(); + try { + if (pairingProcess) { + await this.loadMemberChat(pairingProcess); + } + } catch (error) { + console.error('❌ Error handling member click:', error); + } + }; + + memberList.appendChild(memberItem); + } + } else { + console.log('No members found in roleData'); + } + + roleElement.appendChild(memberList); + } + + + private async switchTab(tabType: string, tabs: NodeListOf) { + const service = await Services.getInstance(); + + // Mettre à jour les classes des onglets + tabs.forEach(tab => { + tab.classList.toggle('active', tab.getAttribute('data-tab') === tabType); + }); + + // Supprimer le contenu existant sauf les onglets + const groupList = this.shadowRoot?.querySelector('#group-list'); + if (!groupList) return; + + const children = Array.from(groupList.children); + children.forEach(child => { + if (!child.classList.contains('tabs')) { + groupList.removeChild(child); + } + }); + + // Charger le contenu approprié + switch (tabType) { + case 'processes': + const processSet = await service.getMyProcesses(); + await this.loadAllProcesses(processSet); + break; + case 'members': + await this.lookForMyDms(); + await this.loadAllMembers(); + break; + default: + console.error('Unknown tab type:', tabType); + } + } + + //load all processes from the service + private async loadAllProcesses() { + console.log('🎯 Loading all processes'); + this.closeSignature(); + + const service = await Services.getInstance(); + const allProcesses: Record = await service.getProcesses(); + console.log('All processes:', allProcesses); + const myProcesses: string[] = await service.getMyProcesses(); + console.log('My processes:', myProcesses); + + const groupList = this.shadowRoot?.querySelector('#group-list'); + if (!groupList) { + console.warn('⚠️ Group list element not found'); + return; + } + + groupList.innerHTML = ''; + + const tabContent = document.createElement('div'); + tabContent.className = 'tabs'; + tabContent.innerHTML = ` + + + `; + groupList.appendChild(tabContent); + + // Ajouter les event listeners + const tabs = tabContent.querySelectorAll('.tab'); + tabs.forEach(tab => { + tab.addEventListener('click', () => { + const tabType = tab.getAttribute('data-tab'); + if (tabType) { + this.switchTab(tabType, tabs); + } + }); + }); + + // Trier les processus : ceux de l'utilisateur en premier + const sortedEntries = Object.entries(allProcesses).sort( + ([keyA], [keyB]) => { + const inSetA = myProcesses.includes(keyA); + const inSetB = myProcesses.includes(keyB); + return inSetB ? 1 : inSetA ? -1 : 0; + } + ); + + for (const [processId, process] of sortedEntries) { + // Create and configure the main list item. + const li = document.createElement('li'); + li.className = 'group-list-item'; + li.setAttribute('data-process-id', processId); + + // Retrieve roles for the current process. + const roles = service.getRoles(process); + if (!roles) { + console.error('Failed to get roles for process:', process); + continue; + } + + // If process is a pairing process, we don't want it in the list + if (service.isPairingProcess(roles)) { + continue; + } + + const publicData = service.getPublicData(process); + const processName = publicData['processName']; + const emoji = await addressToEmoji(processId); + + let displayName; + if (processName) { + displayName = `${processName} (${emoji})`; + } else { + displayName = `${defaultProcessName} (${emoji})`; + } + + // If the process is part of myProcesses, apply special styling. + if (myProcesses && myProcesses.includes(processId)) { + li.style.cssText = ` + background-color: var(--accent-color); + transition: background-color 0.3s ease; + cursor: pointer; + `; + li.addEventListener('mouseover', () => { + li.style.backgroundColor = 'var(--accent-color-hover)'; + }); + li.addEventListener('mouseout', () => { + li.style.backgroundColor = 'var(--accent-color)'; + }); + console.log("✅ Processus trouvé dans le set:", processId); + } + + // Attach a click handler for the process. + li.addEventListener('click', async (event) => { + event.stopPropagation(); + console.log("CLICKED ON PROCESS:", processId); + + // Update the signature header with the corresponding emoji. + const signatureHeader = this.shadowRoot?.querySelector('.signature-header h1'); + if (signatureHeader) { + if (processName) { + signatureHeader.textContent = `Signature of ${displayName}`; + } else { + signatureHeader.textContent = `Signature of ${displayName}`; + } + } + + this.openSignature(); + console.log('🎯 Roles de signature:', roles); + await this.loadAllRolesAndMembersInSignature(roles); + await this.newRequest(processId); + }); + + // Create the container for the process name and emoji. + const container = document.createElement('div'); + container.className = 'group-item-container'; + + // Create and set the process name element. + const nameSpan = document.createElement('span'); + nameSpan.className = 'process-name'; + nameSpan.textContent = displayName; + container.appendChild(nameSpan); + + li.appendChild(container); + + // Create a hidden list for roles. + const roleList = document.createElement('ul'); + roleList.className = 'role-list'; + roleList.style.display = 'none'; + + // Process each role and create role items. + Object.entries(roles).forEach(([roleName, roleData]) => { + const roleItem = document.createElement('li'); + roleItem.className = 'role-item'; + + const roleContainer = document.createElement('div'); + roleContainer.className = 'role-item-container'; + + const roleNameSpan = document.createElement('span'); + roleNameSpan.className = 'role-name'; + roleNameSpan.textContent = roleName; + + // Filter duplicate members by using the first sp_address as a key. + const uniqueMembers = new Map(); + roleData.members?.forEach(member => { + const spAddress = member.sp_addresses?.[0]; + if (spAddress && !uniqueMembers.has(spAddress)) { + uniqueMembers.set(spAddress, member); + } + }); + + // Create a new roleData object with unique members. + const filteredRoleData = { + ...roleData, + members: Array.from(uniqueMembers.values()), + }; + + // Attach a click handler for the role. + roleContainer.addEventListener('click', async (event) => { + event.stopPropagation(); + console.log("CLICKED ON ROLE:", roleName); + await this.toggleMembers(filteredRoleData, roleItem); + }); + + roleContainer.appendChild(roleNameSpan); + roleItem.appendChild(roleContainer); + roleList.appendChild(roleItem); + }); + + li.appendChild(roleList); + + // Toggle role list display when the container is clicked. + container.addEventListener('click', (event) => { + event.stopPropagation(); + container.classList.toggle('expanded'); + roleList.style.display = container.classList.contains('expanded') ? 'block' : 'none'; + }); + + // Append the completed process list item once. + groupList.appendChild(li); + } + + } + + private async newRequest(processId: string) { + const emoji = await addressToEmoji(processId); + const members = await this.getMembersFromProcess(processId); + const newRequestButton = this.shadowRoot?.querySelector('#request-document-button'); + if (newRequestButton) { + newRequestButton.replaceWith(newRequestButton.cloneNode(true)); + const freshButton = this.shadowRoot?.querySelector('#request-document-button'); + freshButton?.addEventListener('click', async () => { + const membersList = await this.generateMembersList(members); + + const modal = document.createElement('div'); + modal.className = 'request-modal'; + const today = new Date().toISOString().split('T')[0]; + + modal.innerHTML = ` + + `; + + this.shadowRoot?.appendChild(modal); + this.handleFileUpload(modal); + this.handleRequestButton(modal); + const closeButton = modal.querySelector('.close-modal'); + closeButton?.addEventListener('click', () => { + modal.remove(); + }); + }); + } + } + + //request button in the modal + private handleRequestButton(modal: HTMLElement) { + const requestButton = modal.querySelector('#send-request-button'); + requestButton?.addEventListener('click', () => { + console.log("REQUEST SENT"); + if (modal) { + //vérifier qu'au moins un membre est coché + const membersList = modal.querySelector('.members-list-modal'); + if (membersList) { + const members = membersList.querySelectorAll('.member-checkbox:checked'); + if (members.length === 0) { + alert('Please select at least one member'); + return; + } + } + //vérifier que la date est valide + const dateInput = modal.querySelector('#date-input') as HTMLInputElement; + if (dateInput) { + const date = new Date(dateInput.value); + if (isNaN(date.getTime())) { + alert('Please select a valid date'); + return; + } + } + + //verifier qu'un fichier a été load + const fileList = modal.querySelector('#file-list'); + if (fileList && fileList.children.length === 0) { + alert('Please upload at least one file'); + return; + } + + //récupérer le message + const messageInput = modal.querySelector('#message-input') as HTMLTextAreaElement; + if (messageInput) { + const message = messageInput.value; + } + //modal.remove(); + } + }); + } + + private handleFileUpload(modal: HTMLElement) { + const fileInput = modal.querySelector('#file-input') as HTMLInputElement; + const fileList = modal.querySelector('#file-list'); + const selectedFiles = new Set(); + + fileInput?.addEventListener('change', () => { + if (fileList && fileInput.files) { + Array.from(fileInput.files).forEach(file => { + if (!Array.from(selectedFiles).some(f => f.name === file.name)) { + selectedFiles.add(file); + const fileItem = document.createElement('div'); + fileItem.className = 'file-item'; + fileItem.innerHTML = ` + ${file.name} + + `; + fileList.appendChild(fileItem); + + fileItem.querySelector('.remove-file')?.addEventListener('click', () => { + selectedFiles.delete(file); + fileItem.remove(); + }); + } + }); + fileInput.value = ''; + } + }); + + return selectedFiles; + } + + private async generateMembersList(members: string[]) { + let html = ''; + for (const member of members) { + const emoji = await addressToEmoji(member); + html += `
  • ${emoji}
  • `; + } + return html; + } + + + //Send a set of members from a process + private async getMembersFromProcess(processId: string) { + const service = await Services.getInstance(); + const process = await service.getProcess(processId); + console.log("Process récupéré:", process); + + // Récupérer les rôles directement depuis le dernier état + const roles = service.getRoles(process); + console.log("Roles trouvés:", roles); + + if (!roles) return []; + type RoleData = { + members?: { sp_addresses?: string[] }[]; + }; + const uniqueMembers = new Set(); + Object.values(roles as unknown as Record).forEach((roleData: RoleData) => { + roleData.members?.forEach((member) => { + if (member.sp_addresses && member.sp_addresses[0]) { + uniqueMembers.add(member.sp_addresses[0]); + } + }); + }); + return Array.from(uniqueMembers); + } + + private async loadAllRolesAndMembersInSignature(roles: any) { + console.log('🎯 Roles:', roles); + const signatureDescription = this.shadowRoot?.querySelector('.signature-description'); + if (signatureDescription) { + signatureDescription.innerHTML = ''; + Object.entries(roles).forEach(([roleName, roleData]: [string, any]) => { + const roleItem = document.createElement('li'); + roleItem.className = 'role-signature'; + + const roleContainer = document.createElement('div'); + roleContainer.className = 'role-signature-container'; + + const roleNameSpan = document.createElement('span'); + roleNameSpan.className = 'role-signature-name'; + roleNameSpan.textContent = roleName; + + const uniqueMembers = new Map(); + roleData.members?.forEach((member: any) => { + const spAddress = member.sp_addresses?.[0]; + if (spAddress && !uniqueMembers.has(spAddress)) { + uniqueMembers.set(spAddress, member); + } + }); + + const filteredRoleData = { + ...roleData, + members: Array.from(uniqueMembers.values()) + }; + + roleContainer.addEventListener('click', async (event) => { + console.log("CLICKED ON ROLE:", roleName); + event.stopPropagation(); + await this.toggleMembers(filteredRoleData, roleItem); + }); + + roleContainer.appendChild(roleNameSpan); + roleItem.appendChild(roleContainer); + signatureDescription.appendChild(roleItem); + }); + } + } + + //fonction qui ferme la signature + private closeSignature() { + const closeSignature = this.shadowRoot?.querySelector('#close-signature'); + const signatureArea = this.shadowRoot?.querySelector('.signature-area'); + if (closeSignature && signatureArea) { + closeSignature.addEventListener('click', () => { + signatureArea.classList.add('hidden'); + }); + } + } + + //fonction qui ouvre la signature + private openSignature() { + const signatureArea = this.shadowRoot?.querySelector('.signature-area'); + if (signatureArea) { + signatureArea.classList.remove('hidden'); + } + } + + private async getMyProcessId() { + const service = await Services.getInstance(); + return service.getPairingProcessId(); + } + + //fonction qui renvoie les processus où le sp_adress est impliqué + private async getProcessesWhereTheCurrentMemberIs() { + const service = await Services.getInstance(); + try { + const currentMember = await service.getMemberFromDevice(); + if (!currentMember) { + console.error('❌ Pas de membre trouvé'); + return this.userProcessSet; + } + + const pairingProcess = await this.getMyProcessId(); + const memberEmoji = await addressToEmoji(pairingProcess); + console.log("Mon adresse:", currentMember[0], memberEmoji); + + const processes = await service.getProcesses(); + + for (const [processId, process] of Object.entries(processes)) { + try { + const roles = process.states[0]?.roles; + + if (!roles) { + console.log(`Pas de rôles trouvés pour le processus ${processId}`); + continue; + } + + for (const roleName in roles) { + const role = roles[roleName]; + + if (role.members && Array.isArray(role.members)) { + for (const member of role.members) { + if (member.sp_addresses && Array.isArray(member.sp_addresses)) { + if (member.sp_addresses.includes(currentMember[0])) { + this.userProcessSet.add(processId); + console.log(`Ajout du process ${processId} au Set (trouvé dans le rôle ${roleName})`); + break; + } + } + } + } + } + } catch (e) { + console.log(`Erreur lors du traitement du processus ${processId}:`, e); + continue; + } + } + + return this.userProcessSet; + } catch (e) { + console.error('❌ Erreur:', e); + return this.userProcessSet; + } + } + + // Send a file + private async sendFile(file: File) { + const MAX_FILE_SIZE = 1 * 1024 * 1024; + if (file.size > MAX_FILE_SIZE) { + alert('Le fichier est trop volumineux. Taille maximum : 1MB'); + return; + } + + try { + const service = await Services.getInstance(); + const myAddresses = await service.getMemberFromDevice(); + if (!myAddresses) throw new Error('No paired member found'); + + let fileData: string; + if (file.type.startsWith('image/')) { + fileData = await this.compressImage(file); + } else { + fileData = await this.readFileAsBase64(file); + } + + const timestamp = Date.now(); + const processId = this.getAttribute('process-id'); + const uniqueKey = `${processId}${timestamp}`; + + const dbRequest = indexedDB.open('4nk'); + + dbRequest.onerror = (event) => { + console.error("Database error:", dbRequest.error); + }; + + dbRequest.onsuccess = async (event) => { + const db = dbRequest.result; + const transaction = db.transaction(['diffs'], 'readwrite'); + const store = transaction.objectStore('diffs'); + + try { + // Message du fichier + const fileTemplate = { + value_commitment: uniqueKey, + messaging_id: processId, + description: 'message_content', + metadata: { + text: `Fichier envoyé: ${file.name}`, + timestamp: timestamp, + sender: myAddresses[0], + recipient: this.selectedMember, + messageState: this.messageState, + roleName: this.selectedRole, + type: 'file', + fileName: file.name, + fileType: file.type, + fileData: fileData + } + }; + + await new Promise((resolve, reject) => { + const request = store.add(fileTemplate); + request.onsuccess = () => { + console.log('✅ File message saved'); + resolve(); + }; + request.onerror = () => reject(request.error); + }); + + // Réponse automatique + const autoReplyTemplate = { + value_commitment: `${processId}${timestamp + 1000}`, + messaging_id: processId, + description: 'message_content', + metadata: { + text: "J'ai bien reçu votre fichier 📎", + timestamp: timestamp + 1000, + sender: this.selectedMember, + recipient: myAddresses[0], + messageState: this.messageState, + roleName: this.selectedRole + } + }; + + await new Promise((resolve, reject) => { + const request = store.add(autoReplyTemplate); + request.onsuccess = () => { + console.log('✅ Auto reply saved'); + if (myAddresses[0]) { + this.addNotification(myAddresses[0], autoReplyTemplate); + } + resolve(); + }; + request.onerror = () => reject(request.error); + }); + + // Attendre la fin de la transaction + await new Promise((resolve, reject) => { + transaction.oncomplete = () => { + console.log('✅ Transaction completed'); + resolve(); + }; + transaction.onerror = () => reject(transaction.error); + }); + + // Réinitialiser l'input file + const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; + + // Recharger les messages + if (this.selectedMember) { + await this.loadMemberChat(this.selectedMember); + } + + } catch (error) { + console.error('❌ Transaction error:', error); + } + }; + + } catch (error) { + console.error('❌ Error in sendFile:', error); + } + } + + private async readFileAsBase64(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result as string); + reader.onerror = reject; + reader.readAsDataURL(file); + }); + } + + private async compressImage(file: File): Promise { + return new Promise((resolve, reject) => { + const img = new Image(); + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + img.onload = () => { + let width = img.width; + let height = img.height; + const MAX_WIDTH = 800; + const MAX_HEIGHT = 600; + + if (width > height) { + if (width > MAX_WIDTH) { + height *= MAX_WIDTH / width; + width = MAX_WIDTH; + } + } else { + if (height > MAX_HEIGHT) { + width *= MAX_HEIGHT / height; + height = MAX_HEIGHT; + } + } + + canvas.width = width; + canvas.height = height; + ctx?.drawImage(img, 0, 0, width, height); + + resolve(canvas.toDataURL('image/jpeg', 0.7)); + }; + + img.onerror = reject; + img.src = URL.createObjectURL(file); + }); + } + + private async getProcesses(): Promise { + const service = await Services.getInstance(); + const processes = await service.getProcesses(); + + const res = Object.entries(processes).map(([key, value]) => ({ + key, + value, + })); + + return res; + } + + async connectedCallback() { + const service = await Services.getInstance(); + + const loadPage = async () => { + console.log("🔍 Chargement des processus par défaut"); + await this.loadAllProcesses(); + + if (this.selectedMember) { + console.log('🔍 Loading chat for selected member:', this.selectedMember); + await this.loadMemberChat(this.selectedMember); + } else { + console.warn('⚠️ No member selected yet. Waiting for selection...'); + } + } + + let timeout: NodeJS.Timeout; + window.addEventListener('process-updated', async (e: CustomEvent) => { + const processId = e.detail.processId; + console.log('Notified of an update for process', processId); + await loadPage(); + }); + + await loadPage(); + } +} + +customElements.define('chat-element', ChatElement); +export { ChatElement };*/ + diff --git a/ihm_client/src/pages/home/home-component.ts b/ihm_client/src/pages/home/home-component.ts new file mode 100644 index 00000000..b38e1a56 --- /dev/null +++ b/ihm_client/src/pages/home/home-component.ts @@ -0,0 +1,49 @@ +import loginHtml from './home.html?raw'; +import loginScript from './home.ts?raw'; +import loginCss from '../../4nk.css?raw'; +import { initHomePage } from './home'; + +export class LoginComponent extends HTMLElement { + _callback: any; + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + console.log('CALLBACK LOGIN PAGE'); + this.render(); + setTimeout(() => { + initHomePage(); + }, 500); + } + + set callback(fn) { + if (typeof fn === 'function') { + this._callback = fn; + } else { + console.error('Callback is not a function'); + } + } + + get callback() { + return this._callback; + } + + render() { + if (this.shadowRoot) + this.shadowRoot.innerHTML = ` + ${loginHtml} + + + + diff --git a/ihm_client/src/pages/signature/signature.ts b/ihm_client/src/pages/signature/signature.ts new file mode 100755 index 00000000..f5b60fa4 --- /dev/null +++ b/ihm_client/src/pages/signature/signature.ts @@ -0,0 +1,1758 @@ +import signatureStyle from '../../../public/style/signature.css?inline'; + +declare global { + interface Window { + toggleUserList: () => void; + switchUser: (userId: string | number) => void; + closeProcessDetails: (groupId: number) => void; + loadMemberChat: (memberId: string | number) => void; + closeRoleDocuments: (roleName: string) => void; + newRequest: (params: RequestParams) => void; + submitRequest: () => void; + closeNewRequest: () => void; + closeModal: (button: HTMLElement) => void; + submitDocumentRequest: (documentId: number) => void; + submitNewDocument: (event: Event) => void; + submitCommonDocument: (event: Event) => void; + signDocument: (documentId: number, processId: number, isCommonDocument: boolean) => void; + confirmSignature: (documentId: number, processId: number, isCommonDocument: boolean) => void; + } +} + +import { groupsMock } from '../../mocks/mock-signature/groupsMock'; +import { messagesMock as initialMessagesMock, messagesMock } from '../../mocks/mock-signature/messagesMock'; +import { membersMock } from '../../mocks/mock-signature/membersMocks'; +import { + Message, + DocumentSignature, + RequestParams} from '../../models/signature.models'; +import { messageStore } from '../../utils/messageMock'; +import { Member } from '../../interface/memberInterface'; +import { Group } from '../../interface/groupInterface'; +import { getCorrectDOM } from '../../utils/document.utils'; + + +let currentUser: Member = membersMock[0]; + +interface LocalNotification { + memberId: string; + text: string; + time: string; +} + + +class SignatureElement extends HTMLElement { + private selectedMemberId: string | null = null; + private messagesMock: any[] = []; + private dom: Node; + private notifications: LocalNotification[] = []; + private notificationBadge = document.querySelector('.notification-badge'); + private notificationBoard = document.getElementById('notification-board'); + private notificationBell = document.getElementById('notification-bell'); + private selectedSignatories: DocumentSignature[] = []; + private allMembers = membersMock.map(member => ({ + id: member.id, + name: member.name, + roleName: 'Default Role' + })); + + private showAlert(message: string): void { + // Créer la popup si elle n'existe pas + let alertPopup = this.shadowRoot?.querySelector('.alert-popup'); + if (!alertPopup) { + alertPopup = document.createElement('div'); + alertPopup.className = 'alert-popup'; + this.shadowRoot?.appendChild(alertPopup); + } + + // Définir le message et afficher la popup + alertPopup.textContent = message; + (alertPopup as HTMLElement).style.display = 'block'; + + // Cacher la popup après 3 secondes + setTimeout(() => { + (alertPopup as HTMLElement).style.display = 'none'; + }, 3000); + } + + private signDocument(documentId: number, processId: number, isCommonDocument: boolean = false): void { + try { + if (typeof window === 'undefined' || typeof document === 'undefined') { + console.error('Cette fonction ne peut être exécutée que dans un navigateur'); + return; + } + + const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock)); + const group = groups.find((g: Group) => g.id === processId); + + if (!group) { + throw new Error('Process not found'); + } + + let targetDoc; + if (isCommonDocument) { + targetDoc = group.commonDocuments.find((d: any) => d.id === documentId); + } else { + for (const role of group.roles) { + if (role.documents) { + targetDoc = role.documents.find((d: any) => d.id === documentId); + if (targetDoc) break; + } + } + } + + if (!targetDoc) { + throw new Error('Document not found'); + } + + const canSign = isCommonDocument ? + targetDoc.signatures?.some((sig: DocumentSignature) => + sig.member?.name === currentUser?.name && !sig.signed + ) : + this.canUserSignDocument(targetDoc, currentUser?.name, currentUser); + + if (!canSign) { + this.showAlert("You do not have the necessary rights to sign this document."); + return; + } + + // Create and insert the modal directly into the body + const modalHtml = ` + `; + + + const modalElement = document.createElement('div'); + modalElement.className = 'modal-overlay'; + modalElement.innerHTML = modalHtml; + this.shadowRoot?.appendChild(modalElement); + + + const slider = modalElement.querySelector('#signatureSlider'); + const sliderTrack = slider?.parentElement; + let isDragging = false; + let startX: number; + let sliderLeft: number; + + if (slider && sliderTrack) { + slider.addEventListener('mousedown', (e: Event) => initDrag(e as MouseEvent)); + slider.addEventListener('touchstart', (e: Event) => initDrag(e as TouchEvent)); + + modalElement.addEventListener('mousemove', (e: Event) => drag.call(this, e as MouseEvent)); + modalElement.addEventListener('touchmove', (e: Event) => drag.call(this, e as TouchEvent)); + modalElement.addEventListener('mouseup', (e: Event) => stopDrag(e as MouseEvent)); + modalElement.addEventListener('touchend', (e: Event) => stopDrag(e as TouchEvent)); + } + + function initDrag(e: MouseEvent | TouchEvent) { + isDragging = true; + startX = 'touches' in e ? e.touches[0].clientX : e.clientX; + sliderLeft = (slider as HTMLElement)?.offsetLeft || 0; + } + + function drag(this: SignatureElement, e: MouseEvent | TouchEvent) { + if (!isDragging || !slider || !sliderTrack) return; + + e.preventDefault(); + const x = 'touches' in e ? e.touches[0].clientX : e.clientX; + const deltaX = x - startX; + + // Calculate the position relative to the track + let newLeft = sliderLeft + deltaX; + + // Limit the movement + const maxLeft = (sliderTrack as HTMLElement).offsetWidth - (slider as HTMLElement).offsetWidth; + newLeft = Math.max(0, Math.min(newLeft, maxLeft)); + + // Update the position + (slider as HTMLElement).style.left = `${newLeft}px`; + + // If the slider reaches 90% of the path, trigger the signature + if (newLeft > maxLeft * 0.9) { + stopDrag(e); + this.confirmSignature(documentId, processId, isCommonDocument); + } + } + + function stopDrag(e: MouseEvent | TouchEvent) { + if (!isDragging || !slider) return; + isDragging = false; + + // Reset the position if not enough dragged + if ((slider as HTMLElement).offsetLeft < ((sliderTrack as HTMLElement)?.offsetWidth || 0) * 0.9) { + (slider as HTMLElement).style.left = '0px'; + } + } + + } catch (error) { + console.error('Error displaying modal:', error); + this.showAlert(error instanceof Error ? error.message : 'Error displaying modal'); + } + } + + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.dom = getCorrectDOM('signature-element'); + + this.shadowRoot!.innerHTML = ` + +
    + +
    +
      +
    +
    + + +
    +
    + +
    +
    + +
    + + +
    + + + + +
    +
    +
    + `; + + window.toggleUserList = this.toggleUserList.bind(this); + window.switchUser = this.switchUser.bind(this); + window.closeProcessDetails = this.closeProcessDetails.bind(this); + window.loadMemberChat = this.loadMemberChat.bind(this); + window.closeRoleDocuments = this.closeRoleDocuments.bind(this); + window.newRequest = this.newRequest.bind(this); + window.submitRequest = this.submitRequest.bind(this); + window.closeNewRequest = this.closeNewRequest.bind(this); + window.closeModal = this.closeModal.bind(this); + window.submitNewDocument = this.submitNewDocument.bind(this); + window.submitCommonDocument = this.submitCommonDocument.bind(this); + window.signDocument = this.signDocument.bind(this); + window.confirmSignature = this.confirmSignature.bind(this); + window.submitDocumentRequest = this.submitDocumentRequest.bind(this); + + // Initialiser les événements de notification + document.addEventListener('click', (event: Event): void => { + if (this.notificationBoard && this.notificationBoard.style.display === 'block' && + !this.notificationBoard.contains(event.target as Node) && + this.notificationBell && !this.notificationBell.contains(event.target as Node)) { + this.notificationBoard.style.display = 'none'; + } + }); + this.initMessageEvents(); + this.initFileUpload(); + } + + private initMessageEvents() { + // Pour le bouton Send + const sendButton = this.shadowRoot?.getElementById('send-button'); + if (sendButton) { + sendButton.addEventListener('click', () => this.sendMessage()); + } + + // Pour la touche Entrée + const messageInput = this.shadowRoot?.getElementById('message-input'); + if (messageInput) { + messageInput.addEventListener('keypress', (event: KeyboardEvent) => { + if (event.key === 'Enter' && !event.shiftKey) { + event.preventDefault(); + this.sendMessage(); + } + }); + } + } + + private initFileUpload() { + const fileInput = this.shadowRoot?.getElementById('file-input') as HTMLInputElement; + if (fileInput) { + fileInput.addEventListener('change', (event: Event) => { + const target = event.target as HTMLInputElement; + if (target.files && target.files.length > 0) { + this.sendFile(target.files[0]); + } + }); + } + } + + + private calculateDuration(startDate: string | null | undefined, endDate: string | null | undefined): number { + const start = new Date(startDate || ''); + const end = new Date(endDate || ''); + const duration = end.getTime() - start.getTime(); + return Math.floor(duration / (1000 * 60 * 60 * 24)); + } + + // Add this helper function + private canUserAccessDocument(document: any, roleId: string, currentUserRole: string): boolean { + // Modify the access logic + if (document.visibility === 'public') { + return true; // Can see but not necessarily sign + } + return roleId === currentUserRole; + } + + private canUserSignDocument(document: any, role: string, user: Member): boolean { + console.log('Checking signing rights for:', { + document, + role, + user, + userRoles: user.processRoles + }); + + // Vérifier si l'utilisateur est dans la liste des signatures + const isSignatory = document.signatures?.some((sig: DocumentSignature) => + sig.member && 'id' in sig.member && sig.member.id === user.id && !sig.signed + ); + + if (!isSignatory) { + console.log('User is not in signatures list or has already signed'); + return false; + } + + // Si l'utilisateur est dans la liste des signatures, il peut signer + return true; + } + + private closeProcessDetails(groupId: number) { + const detailsArea = this.shadowRoot?.getElementById(`process-details-${groupId}`); + const chatArea = this.shadowRoot?.getElementById('chat-area'); + + if (detailsArea) { + detailsArea.style.display = 'none'; + } + + if (chatArea) { + chatArea.style.display = 'block'; + } + } + + ///////////////////// Notification module ///////////////////// + // Delete a notification + private removeNotification(index: number) { + this.notifications?.splice(index, 1); // Ajout de ?. + this.renderNotifications(); + this.updateNotificationBadge(); + } + // Show notifications + private renderNotifications() { + if (!this.notificationBoard) return; + + // Reset the interface + this.notificationBoard.innerHTML = ''; + + // Displays "No notifications available" if there are no notifications + if (this.notifications.length === 0) { + this.notificationBoard.innerHTML = '
    No notifications available
    '; + return; + } + + // Add each notification to the list + this.notifications.forEach((notif, index) => { + const notifElement = document.createElement('div'); + notifElement.className = 'notification-item'; + notifElement.textContent = `${notif.text} at ${notif.time}`; + notifElement.onclick = () => { + this.loadMemberChat(notif.memberId); + this.removeNotification(index); + }; + this.notificationBoard?.appendChild(notifElement); + }); + } + private updateNotificationBadge() { + if (!this.notificationBadge) return; + const count = this.notifications.length; + this.notificationBadge.textContent = count > 99 ? '+99' : count.toString(); + (this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none'; + } + + + // Add notification + private addNotification(memberId: string, message: Message) { + // Creating a new notification + const notification = { + memberId, + text: `New message from Member ${memberId}: ${message.text}`, + time: message.time + }; + + // Added notification to list and interface + this.notifications.push(notification); + this.renderNotifications(); + this.updateNotificationBadge(); + } +// Send a messsage + private sendMessage() { + const messageInput = this.shadowRoot?.getElementById('message-input') as HTMLInputElement; + if (!messageInput) return; + const messageText = messageInput.value.trim(); + + if (messageText === '' || this.selectedMemberId === null) { + return; + } + + const newMessage: Message = { + id: Date.now(), + sender: "4NK", + text: messageText, + time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), + type: 'text' as const + }; + // Add and display the message immediately + messageStore.addMessage(this.selectedMemberId, newMessage); + this.messagesMock = messageStore.getMessages(); + this.loadMemberChat(this.selectedMemberId); + + // Reset the input + messageInput.value = ''; + + // Automatic response after 2 seconds + setTimeout(() => { + if (this.selectedMemberId) { + const autoReply = this.generateAutoReply(`Member ${this.selectedMemberId}`); + messageStore.addMessage(this.selectedMemberId, autoReply); + this.messagesMock = messageStore.getMessages(); + this.loadMemberChat(this.selectedMemberId); + this.addNotification(this.selectedMemberId, autoReply); + } + }, 2000); +} + + + private showProcessDetails(group: Group, groupId: number) { + console.log('Showing details for group:', groupId); + + // Close all existing process views + const allDetailsAreas = this.shadowRoot?.querySelectorAll('.process-details'); + if (allDetailsAreas) { + allDetailsAreas.forEach(area => { + (area as HTMLElement).style.display = 'none'; + }); + } + + const container = this.shadowRoot?.querySelector('.container'); + if (!container) { + console.error('Container not found'); + return; + } + + // Load the data from localStorage + const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]'); + const storedGroup = storedGroups.find((g: Group) => g.id === groupId); + + // Use the data from localStorage if available, otherwise use the group passed as a parameter + const displayGroup = storedGroup || group; + + let detailsArea = this.shadowRoot?.getElementById(`process-details-${groupId}`); + if (!detailsArea) { + detailsArea = document.createElement('div'); + detailsArea.id = `process-details-${groupId}`; + detailsArea.className = 'process-details'; + container.appendChild(detailsArea); + } + + if (detailsArea) { + detailsArea.style.display = 'block'; + detailsArea.innerHTML = ` +
    +

    ${displayGroup.name}

    +
    +
    +
    +
    +
    +

    Description

    +

    ${displayGroup.description || 'No description available'}

    +
    +
    +

    Documents Communs

    +
    + ${displayGroup.commonDocuments.map((document: any) => { + const totalSignatures = document.signatures?.length || 0; + const signedCount = document.signatures?.filter((sig: DocumentSignature) => sig.signed).length || 0; + const percentage = totalSignatures > 0 ? (signedCount / totalSignatures) * 100 : 0; + const isVierge = !document.createdAt || !document.deadline || !document.signatures?.length; + const canSign = document.signatures?.some((sig: DocumentSignature) => + sig.member && 'id' in sig.member && sig.member.id === currentUser.id && !sig.signed + ); + + const signButton = !isVierge ? ` + ${totalSignatures > 0 && signedCount < totalSignatures && canSign ? ` + + ` : ''} + ` : ''; + + return ` +
    +
    +

    ${isVierge ? `⚠️ ${document.name}` : document.name}

    + ${document.visibility} +
    +
    + ${!isVierge ? ` +

    Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}

    +

    Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}

    +

    Duration: ${this.calculateDuration(document.createdAt || '', document.deadline || '')} days

    +
    +
    Signatures:
    +
    + ${document.signatures?.map((sig: DocumentSignature) => ` +
    + ${sig.member.name} + + ${sig.signed ? + `✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` : + '⌛ Pending'} + +
    + `).join('')} +
    +
    +
    +
    +

    ${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)

    +
    + ` : ` +

    Document vierge - Waiting for creation

    + + `} + ${signButton} +
    +
    + `; + }).join('')} +
    +
    +
    +

    Roles and Documents

    + ${displayGroup.roles.map((role: { name: string; documents?: any[] }) => { + // Filter the documents according to the access rights + const accessibleDocuments = (role.documents || []).filter(doc => + this.canUserAccessDocument(doc, role.name, currentUser.processRoles?.[0]?.role || '') + ); + + return ` +
    +

    ${role.name}

    +
    + ${accessibleDocuments.map(document => { + const isVierge = !document.createdAt || + !document.deadline || + document.signatures.length === 0; + + const canSign = this.canUserSignDocument(document, role.name, currentUser); + + const signButton = !isVierge ? ` + ${document.signatures.length > 0 && + document.signatures.filter((sig: DocumentSignature) => sig.signed).length < document.signatures.length && + canSign ? ` + + ` : ''} + ` : ''; + + return ` +
    +
    +

    ${isVierge ? `⚠️ ${document.name}` : document.name}

    + ${document.visibility} +
    +
    + ${!isVierge ? ` +

    Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}

    +

    Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}

    +

    Duration: ${this.calculateDuration(document.createdAt || '', document.deadline || '')} days

    + ` : '

    Document vierge - Waiting for creation

    '} +
    + ${!isVierge ? ` +
    +
    Signatures:
    +
    + ${document.signatures.map((sig: DocumentSignature) => ` +
    + ${sig.member.name} + + ${sig.signed ? + `✓ Signé le ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'date inconnue'}` : + '⌛ En attente'} + +
    + `).join('')} +
    +
    +
    +
    +

    ${document.signatures.filter((sig: DocumentSignature) => sig.signed).length} out of ${document.signatures.length} signed (${(document.signatures.filter((sig: DocumentSignature) => sig.signed).length / document.signatures.length * 100).toFixed(0)}%)

    +
    + ` : ''} + ${signButton} +
    + `; + }).join('')} +
    +
    + `; + }).join('')} +
    +
    +

    Members by Role

    +
    + ${displayGroup.roles.map((role: { name: string; members: Array<{ id: string | number; name: string }> }) => ` +
    +

    ${role.name}

    +
      + ${role.members.map(member => ` +
    • ${member.name}
    • + `).join('')} +
    +
    + `).join('')} +
    +
    + `; + + + const newCloseProcessButton = document.createElement('button'); + newCloseProcessButton.className = 'close-btn'; + newCloseProcessButton.textContent = 'x'; + newCloseProcessButton.addEventListener('click', () => this.closeProcessDetails(groupId)); + + const headerButtons = detailsArea.querySelector('.header-buttons'); + if (headerButtons) { + headerButtons.appendChild(newCloseProcessButton); + } + } + } + + // Scroll down the conversation after loading messages + private scrollToBottom(container: HTMLElement) { + container.scrollTop = container.scrollHeight; + } + + + // Load the list of members + private loadMemberChat(memberId: string | number) { + this.selectedMemberId = String(memberId); + const memberMessages = this.messagesMock.find(m => String(m.memberId) === String(memberId)); + + // Find the process and the role of the member + let memberInfo = { processName: '', roleName: '', memberName: '' }; + groupsMock.forEach(process => { + process.roles.forEach(role => { + const member = role.members.find(m => String(m.id) === String(memberId)); + if (member) { + memberInfo = { + processName: process.name, + roleName: role.name, + memberName: member.name + }; + } + }); + }); + + const chatHeader = this.shadowRoot?.getElementById('chat-header'); + const messagesContainer = this.shadowRoot?.getElementById('messages'); + + if (!chatHeader || !messagesContainer) return; + + chatHeader.textContent = `Chat with ${memberInfo.roleName} ${memberInfo.memberName} from ${memberInfo.processName}`; + messagesContainer.innerHTML = ''; + + if (memberMessages) { + memberMessages.messages.forEach((message: Message) => { + const messageElement = document.createElement('div'); + messageElement.className = 'message-container'; + + const messageContent = document.createElement('div'); + messageContent.className = 'message'; + if (message.type === 'file') { + messageContent.innerHTML = `${message.fileName}`; + messageContent.classList.add('user'); + } else { + messageContent.innerHTML = `${message.sender}: ${message.text} ${message.time}`; + if (message.sender === "4NK") { + messageContent.classList.add('user'); + } + } + + messageElement.appendChild(messageContent); + messagesContainer.appendChild(messageElement); + }); + } + + + this.scrollToBottom(messagesContainer); + } + + private toggleMembers(role: { members: { id: string | number; name: string; }[] }, roleElement: HTMLElement) { + let memberList = roleElement.querySelector('.member-list'); + if (memberList) { + (memberList as HTMLElement).style.display = (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none'; + return; + } + + memberList = document.createElement('ul'); + memberList.className = 'member-list'; + + role.members.forEach(member => { + const memberItem = document.createElement('li'); + memberItem.textContent = member.name; + + memberItem.onclick = (event) => { + event.stopPropagation(); + this.loadMemberChat(member.id.toString()); + }; + + memberList.appendChild(memberItem); + }); + + roleElement.appendChild(memberList); + } + + + // Toggle the list of Roles + private toggleRoles(group: Group, groupElement: HTMLElement) { + console.log('=== toggleRoles START ==='); + console.log('Group:', group.name); + console.log('Group roles:', group.roles); // Afficher tous les rôles disponibles + + let roleList = groupElement.querySelector('.role-list'); + console.log('Existing roleList:', roleList); + + if (roleList) { + const roleItems = roleList.querySelectorAll('.role-item'); + roleItems.forEach(roleItem => { + console.log('Processing roleItem:', roleItem.innerHTML); // Voir le contenu HTML complet + + let container = roleItem.querySelector('.role-item-container'); + if (!container) { + container = document.createElement('div'); + container.className = 'role-item-container'; + + // Créer un span pour le nom du rôle + const nameSpan = document.createElement('span'); + nameSpan.className = 'role-name'; + nameSpan.textContent = roleItem.textContent?.trim() || ''; + + container.appendChild(nameSpan); + roleItem.textContent = ''; + roleItem.appendChild(container); + } + + // Récupérer le nom du rôle + const roleName = roleItem.textContent?.trim(); + console.log('Role name from textContent:', roleName); + + // Alternative pour obtenir le nom du rôle + const roleNameAlt = container.querySelector('.role-name')?.textContent; + console.log('Role name from span:', roleNameAlt); + + if (!container.querySelector('.folder-icon')) { + const folderButton = document.createElement('span'); + folderButton.innerHTML = '📁'; + folderButton.className = 'folder-icon'; + + folderButton.addEventListener('click', (event) => { + event.stopPropagation(); + console.log('Clicked role name:', roleName); + console.log('Available roles:', group.roles.map(r => r.name)); + + const role = group.roles.find(r => r.name === roleName); + if (role) { + console.log('Found role:', role); + this.showRoleDocuments(role, group); + } else { + console.error('Role not found. Name:', roleName); + console.error('Available roles:', group.roles); + } + }); + + container.appendChild(folderButton); + } + }); + + (roleList as HTMLElement).style.display = + (roleList as HTMLElement).style.display === 'none' ? 'block' : 'none'; + } + } + + + private loadGroupList(): void { + const groupList = this.shadowRoot?.getElementById('group-list'); + if (!groupList) return; + + groupsMock.forEach(group => { + const li = document.createElement('li'); + li.className = 'group-list-item'; + + // Create a flex container for the name and the icon + const container = document.createElement('div'); + container.className = 'group-item-container'; + + // Span for the process name + const nameSpan = document.createElement('span'); + nameSpan.textContent = group.name; + nameSpan.className = 'process-name'; + + // Add click event to show roles + nameSpan.addEventListener('click', (event) => { + event.stopPropagation(); + this.toggleRoles(group, li); + }); + + // Add the ⚙️ icon + const settingsIcon = document.createElement('span'); + settingsIcon.textContent = '⚙️'; + settingsIcon.className = 'settings-icon'; + settingsIcon.id = `settings-${group.id}`; + + settingsIcon.onclick = (event) => { + event.stopPropagation(); + this.showProcessDetails(group, group.id); + }; + + // Assemble the elements + container.appendChild(nameSpan); + container.appendChild(settingsIcon); + li.appendChild(container); + + // Create and append the role list container + const roleList = document.createElement('ul'); + roleList.className = 'role-list'; + roleList.style.display = 'none'; + + // Add roles for this process + group.roles.forEach(role => { + const roleItem = document.createElement('li'); + roleItem.className = 'role-item'; + roleItem.textContent = role.name; + roleItem.onclick = (event) => { + event.stopPropagation(); + this.toggleMembers(role, roleItem); + }; + roleList.appendChild(roleItem); + }); + + li.appendChild(roleList); + groupList.appendChild(li); + }); + } + + + // Function to manage the list of users + private toggleUserList() { + const userList = getCorrectDOM('userList'); + if (!userList) return; + + if (!(userList as HTMLElement).classList.contains('show')) { + (userList as HTMLElement).innerHTML = membersMock.map(member => ` +
    + ${member.avatar} +
    + ${member.name} + ${member.email} +
    +
    + `).join(''); + } + (userList as HTMLElement).classList.toggle('show'); + } + + private switchUser(userId: string | number) { + const user = membersMock.find(member => member.id === userId); + if (!user) return; + currentUser = user; + this.updateCurrentUserDisplay(); + const userList = getCorrectDOM('userList') as HTMLElement; + userList?.classList.remove('show'); + } + + // Function to update the display of the current user + private updateCurrentUserDisplay() { + const userDisplay = getCorrectDOM('current-user') as HTMLElement; + if (userDisplay) { + userDisplay.innerHTML = ` + + `; + } + } + // Generate an automatic response + private generateAutoReply(senderName: string): Message { + return { + id: Date.now(), + sender: senderName, + text: "OK...", + time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), + type: 'text' as const + }; + } + + // Send a file + private sendFile(file: File) { + console.log('SendFile called with file:', file); + const reader = new FileReader(); + reader.onloadend = () => { + const fileData = reader.result; + const fileName = file.name; + console.log('File loaded:', fileName); + + if (this.selectedMemberId) { + messageStore.addMessage(this.selectedMemberId, { + id: Date.now(), + sender: "4NK", + fileName: fileName, + fileData: fileData, + time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), + type: 'file' + }); + console.log('Message added to store'); + + this.messagesMock = messageStore.getMessages(); + this.loadMemberChat(this.selectedMemberId); + } + }; + reader.readAsDataURL(file); + } + + // Managing the sent file + private fileList: HTMLDivElement = this.shadowRoot?.getElementById('fileList') as HTMLDivElement; + private getFileList() { + const files = Array.from(this.fileList?.querySelectorAll('.file-item') || []).map((fileItem: Element) => { + const fileName = fileItem.querySelector('.file-name')?.textContent || ''; + return { + name: fileName, + url: (fileItem as HTMLElement).dataset.content || '#', + }; + }); + return files; + } + + // New function to display the documents of a role + private showRoleDocuments(role: { + name: string; + documents?: Array<{ + name: string; + visibility: string; + createdAt: string | null | undefined; + deadline: string | null | undefined; + signatures: DocumentSignature[]; + id: number; + description?: string; + status?: string; + files?: Array<{ name: string; url: string }>; + }>; + id?: number; + }, group: Group) { + // Load the data from localStorage + const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]'); + const storedGroup = storedGroups.find((g: Group) => g.id === group.id); + const storedRole = storedGroup?.roles.find((r: any) => r.name === role.name); + + // Use the data from localStorage if available, otherwise use the data passed as a parameter + const displayRole = storedRole || role; + + console.log('Showing documents for role:', displayRole.name, 'in group:', group.name); + // Close all existing document views first + const allDetailsAreas = this.shadowRoot?.querySelectorAll('.process-details'); + allDetailsAreas?.forEach(area => { + area.remove(); + }); + + const container = this.shadowRoot?.querySelector('.container'); + if (!container) { + console.error('Container not found'); + return; + } + + // Create a new details area + const detailsArea = document.createElement('div'); + detailsArea.id = `role-documents-${displayRole.name}`; + detailsArea.className = 'process-details'; + // Filter the accessible documents + const accessibleDocuments = (displayRole.documents || []).filter((doc: { + name: string; + visibility: string; + createdAt: string | null | undefined; + deadline: string | null | undefined; + signatures: DocumentSignature[]; + id: number; + description?: string; + status?: string; + }) => + this.canUserAccessDocument(doc, displayRole.name, currentUser.processRoles?.[0]?.role || '') + ); + + detailsArea.innerHTML = ` + + `; + + container.appendChild(detailsArea); + } + + // Function to close the documents view of a role + private closeRoleDocuments(roleName: string) { + const detailsArea = this.shadowRoot?.getElementById(`role-documents-${roleName}`); + if (detailsArea) { + + detailsArea.remove(); + } + } + + private handleFiles(files: FileList, fileList: HTMLDivElement) { + Array.from(files).forEach(file => { + const reader = new FileReader(); + reader.onload = (e) => { + const fileContent = e.target?.result; + const existingFiles = fileList.querySelectorAll('.file-name'); + const isDuplicate = Array.from(existingFiles).some( + existingFile => existingFile.textContent === file.name + ); + + if (!isDuplicate) { + const fileItem = document.createElement('div'); + fileItem.className = 'file-item'; + fileItem.innerHTML = ` +
    + ${file.name} + (${(file.size / 1024).toFixed(1)} KB) +
    + + `; + fileItem.dataset.content = fileContent as string; + + const removeBtn = fileItem.querySelector('.remove-file'); + if (removeBtn) { + removeBtn.addEventListener('click', () => fileItem.remove()); + } + + fileList.appendChild(fileItem); + } + }; + reader.readAsDataURL(file); + }); + } + + // Function to manage the new request + private newRequest(params: RequestParams) { + // Add parameter validation + if (!params || !params.processId) { + console.error('Paramètres invalides:', params); + this.showAlert('Invalid parameters for new request'); + return; + } + + const modal = document.createElement('div'); + modal.className = 'modal-overlay'; + + // Retrieve the process with a verification + const process = groupsMock.find(g => g.id === params.processId); + if (!process) { + console.error('Processus non trouvé:', params.processId); + this.showAlert('Process not found'); + return; + } + + // Determine the members with an additional verification + let membersToDisplay = []; + try { + if (params.roleName === 'common') { + membersToDisplay = process.roles.reduce((members: any[], role) => { + return members.concat(role.members.map(member => ({ + ...member, + roleName: role.name + }))); + }, []); + } else { + const role = process.roles.find(r => r.name === params.roleName); + if (!role) { + throw new Error(`Role ${params.roleName} not found`); + } + membersToDisplay = role.members.map(member => ({ + ...member, + roleName: params.roleName + })); + } + } catch (error) { + console.error('Error retrieving members:', error); + this.showAlert('Error retrieving members'); + return; + } + + + + modal.innerHTML = ` + + `; + + this.shadowRoot?.appendChild(modal); + + const dropZone = modal.querySelector('#dropZone') as HTMLDivElement; + const fileInput = modal.querySelector('#fileInput') as HTMLInputElement; + const fileList = modal.querySelector('#fileList') as HTMLDivElement; + + // Make the area clickable + dropZone.addEventListener('click', () => { + fileInput.click(); + }); + + // Manage the file selection + fileInput.addEventListener('change', (e: Event) => { + const target = e.target as HTMLInputElement; + if (target.files && target.files.length > 0) { + this.handleFiles(target.files, fileList); + } + }); + + // Manage the drag & drop + dropZone.addEventListener('dragover', (e: DragEvent) => { + e.preventDefault(); + dropZone.classList.add('dragover'); + }); + + dropZone.addEventListener('dragleave', () => { + dropZone.classList.remove('dragover'); + }); + + dropZone.addEventListener('drop', (e: DragEvent) => { + e.preventDefault(); + dropZone.classList.remove('dragover'); + if (e.dataTransfer?.files) { + this.handleFiles(e.dataTransfer.files, fileList); + } + }); + } + + private closeModal(button: HTMLElement) { + const modalOverlay = button.closest('.modal-overlay'); + if (modalOverlay) { + modalOverlay.remove(); + } + } + + private submitNewDocument(event: Event) { + event.preventDefault(); + + const form = this.shadowRoot?.getElementById('newDocumentForm') as HTMLFormElement; + if (!form) { + this.showAlert('Form not found'); + return; + } + + // Retrieve the files + const fileList = this.shadowRoot?.getElementById('fileList') as HTMLDivElement; + const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map(fileItem => { + const fileName = fileItem.querySelector('.file-name')?.textContent || ''; + return { + name: fileName, + url: (fileItem as HTMLElement).dataset.content || '#', + }; + }); + + // Retrieve the values from the form + const processId = Number((form.querySelector('#processId') as HTMLInputElement)?.value); + const documentId = Number((form.querySelector('#documentId') as HTMLInputElement)?.value); + const documentName = (form.querySelector('#documentName') as HTMLInputElement)?.value?.trim(); + const description = (form.querySelector('#description') as HTMLTextAreaElement)?.value?.trim(); + const deadline = (form.querySelector('#deadline') as HTMLInputElement)?.value; + const visibility = (form.querySelector('#visibility') as HTMLSelectElement)?.value; + + // Validation + if (!documentName || !description || !deadline) { + this.showAlert('Please fill in all required fields'); + return; + } + + try { + // Retrieve the current data + const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock)); + const group = groups.find((g: Group) => g.id === processId); + + if (!group) { + this.showAlert('Process not found'); + return; + } + + const role = group.roles.find((r: any) => + r.documents?.some((d: any) => d.id === documentId) + ); + + if (!role) { + this.showAlert('Role not found'); + return; + } + + // Create the new document with the signatures of the role members + const updatedDocument = { + id: documentId, + name: documentName, + description: description, + createdAt: new Date().toISOString(), + deadline: deadline, + visibility: visibility, + status: "pending", + signatures: role.members.map((member: { id: string | number; name: string }) => ({ + member: member, + signed: false, + signedAt: null + })), + files: files // Ajout des fichiers au document + }; + + // Update the document in the role + const documentIndex = role.documents.findIndex((d: any) => d.id === documentId); + if (documentIndex !== -1) { + role.documents[documentIndex] = updatedDocument; + } + + // Save in localStorage + localStorage.setItem('groups', JSON.stringify(groups)); + + // Also update groupsMock for consistency + const mockGroup = groupsMock.find(g => g.id === processId); + if (mockGroup) { + const mockRole = mockGroup?.roles.find(r => r.name === role.name); + if (mockRole?.documents) { + const mockDocIndex = mockRole.documents.findIndex(d => d.id === documentId); + if (mockDocIndex !== -1) { + mockRole.documents[mockDocIndex] = { + ...updatedDocument, + status: undefined + }; + } + } + } + + // Close the modal + if (event.target instanceof HTMLElement) { + this.closeModal(event.target); + } + + // Reload the documents view with the updated data + this.showRoleDocuments(role, group); + this.showAlert('Document updated successfully!'); + + } catch (error) { + console.error('Error saving:', error); + this.showAlert('An error occurred while saving'); + } + } + + private submitCommonDocument(event: Event) { + event.preventDefault(); + + const form = this.shadowRoot?.getElementById('newDocumentForm') as HTMLFormElement; + if (!form) { + this.showAlert('Form not found'); + return; + } + + const processId = Number((form.querySelector('#processId') as HTMLInputElement)?.value); + const documentId = Number((form.querySelector('#documentId') as HTMLInputElement)?.value); + const documentName = (form.querySelector('#documentName') as HTMLInputElement)?.value?.trim(); + const description = (form.querySelector('#description') as HTMLTextAreaElement)?.value?.trim(); + const deadline = (form.querySelector('#deadline') as HTMLInputElement)?.value; + const visibility = (form.querySelector('#visibility') as HTMLSelectElement)?.value; + + if (!documentName || !description || !deadline) { + this.showAlert('Please fill in all required fields'); + return; + } + + try { + const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock)); + const group = groups.find((g: Group) => g.id === processId); + + if (!group) { + this.showAlert('Process not found'); + return; + } + + // Retrieve all members of all roles in the group + const allMembers = group.roles.reduce((acc: any[], role: any) => { + return acc.concat(role.members); + }, []); + + const fileList = this.shadowRoot?.getElementById('fileList') as HTMLDivElement; + const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map(fileItem => { + const fileName = fileItem.querySelector('.file-name')?.textContent || ''; + return { + name: fileName, + url: (fileItem as HTMLElement).dataset.content || '#', + }; + }); + + const updatedDocument = { + id: documentId, + name: documentName, + description: description, + createdAt: new Date().toISOString(), + deadline: deadline, + visibility: visibility, + status: "pending", + signatures: allMembers.map((member: { id: string | number; name: string }) => ({ + member: member, + signed: false, + signedAt: null + })), + files: files + }; + + // Update the common document + const documentIndex = group.commonDocuments.findIndex((d: { id: number }) => d.id === documentId); + if (documentIndex !== -1) { + group.commonDocuments[documentIndex] = updatedDocument; + } + + localStorage.setItem('groups', JSON.stringify(groups)); + + if (event.target instanceof HTMLElement) { + this.closeModal(event.target); + } + + this.showProcessDetails(group, group.id); + this.showAlert('Document common updated successfully!'); + + } catch (error) { + console.error('Error saving:', error); + this.showAlert('An error occurred while saving'); + } + } + + + private submitRequest() { + + this.showAlert("Request submitted!"); + } + + private closeNewRequest() { + const newRequestView = document.getElementById('new-request-view'); + if (newRequestView) { + newRequestView.style.display = 'none'; + newRequestView.remove(); + } + } + + private submitDocumentRequest(documentId: number) { + const createdAt = (this.shadowRoot?.getElementById('createdAt') as HTMLInputElement)?.value || ''; + const deadline = (this.shadowRoot?.getElementById('deadline') as HTMLInputElement)?.value || ''; + const visibility = (this.shadowRoot?.getElementById('visibility') as HTMLSelectElement)?.value || ''; + const description = (this.shadowRoot?.getElementById('description') as HTMLTextAreaElement)?.value || ''; + + const selectedMembers = Array.from( + this.shadowRoot?.querySelectorAll('input[name="selected-members"]:checked') || [] + ).map(checkbox => (checkbox as HTMLInputElement).value); + + if (!createdAt || !deadline || selectedMembers.length === 0) { + this.showAlert('Please fill in all required fields and select at least one member.'); + return; + } + + console.log('Document submission:', { + documentId, + createdAt, + deadline, + visibility, + description, + selectedMembers + }); + + this.showAlert('Document request submitted successfully!'); + this.closeNewRequest(); + } + + // FUNCTIONS FOR SIGNATURE + + // New function to confirm the signature + private confirmSignature(documentId: number, processId: number, isCommonDocument: boolean) { + try { + // Add console.log to see the current user + console.log('Current user:', currentUser); + + const groups = JSON.parse(localStorage.getItem('groups') || JSON.stringify(groupsMock)); + const group = groups.find((g: Group) => g.id === processId); + + if (!group) { + throw new Error('Process not found'); + } + + let targetDoc; + if (isCommonDocument) { + targetDoc = group.commonDocuments.find((d: any) => d.id === documentId); + } else { + for (const role of group.roles) { + if (role.documents) { + targetDoc = role.documents.find((d: any) => d.id === documentId); + if (targetDoc) break; + } + } + } + + if (!targetDoc) { + throw new Error('Document not found'); + } + + const userSignature = targetDoc.signatures.find((sig: DocumentSignature) => + sig.member.name === currentUser.name + ); + + if (!userSignature) { + throw new Error(`The user ${currentUser.name} is not authorized to sign this document. Please log in with an authorized user.`); + } + + // Mettre à jour la signature + userSignature.signed = true; + userSignature.signedAt = new Date().toISOString(); + localStorage.setItem('groups', JSON.stringify(groups)); + + // Supprimer la modal de signature + const modalOverlay = this.shadowRoot?.querySelector('.modal-overlay'); + if (modalOverlay) { + modalOverlay.remove(); + } + + // Rafraîchir l'affichage + if (isCommonDocument) { + this.showProcessDetails(group, processId); + } else { + const role = group.roles.find((r: any) => r.documents?.includes(targetDoc)); + if (role) { + this.showRoleDocuments(role, group); + } + } + + this.showAlert('Document signed successfully!'); + + } catch (error) { + console.error('Error signing document:', error); + this.showAlert(error instanceof Error ? error.message : 'Error signing document'); + } + } + + + private initializeEventListeners() { + document.addEventListener('DOMContentLoaded', (): void => { + const newRequestBtn = this.shadowRoot?.getElementById('newRequestBtn'); + if (newRequestBtn) { + newRequestBtn.addEventListener('click', (): void => { + this.newRequest({ + processId: 0, + processName: '', + roleId: 0, + roleName: '', + documentId: 0, + documentName: '' + }); + }); + } + }); + + // Gestionnaire d'événements pour le chat + const sendBtn = this.shadowRoot?.querySelector('#send-button'); + if (sendBtn) { + sendBtn.addEventListener('click', this.sendMessage.bind(this)); + } + + const messageInput = this.shadowRoot?.querySelector('#message-input'); + if (messageInput) { + messageInput.addEventListener('keypress', (event: Event) => { + if ((event as KeyboardEvent).key === 'Enter') { + event.preventDefault(); + this.sendMessage(); + } + }); + } + + // Gestionnaire pour l'envoi de fichiers + const fileInput = this.shadowRoot?.querySelector('#file-input'); + if (fileInput) { + fileInput.addEventListener('change', (event: Event) => { + const file = (event.target as HTMLInputElement).files?.[0]; + if (file) { + this.sendFile(file); + } + }); + } + } + + connectedCallback() { + this.messagesMock = messageStore.getMessages(); + if (this.messagesMock.length === 0) { + messageStore.setMessages(initialMessagesMock); + this.messagesMock = messageStore.getMessages(); + } + this.updateCurrentUserDisplay(); + this.initializeEventListeners(); + this.loadGroupList(); + } +} + +customElements.define('signature-element', SignatureElement); +export { SignatureElement }; + diff --git a/ihm_client/src/router.ts b/ihm_client/src/router.ts new file mode 100755 index 00000000..0ff20ae4 --- /dev/null +++ b/ihm_client/src/router.ts @@ -0,0 +1,945 @@ +import '../public/style/4nk.css'; +import { initHeader } from './components/header/header'; +/*import { initChat } from '../src/pages/chat/chat';*/ +import Database from './services/database.service'; +import Services from './services/service'; +import TokenService from './services/token'; +import { cleanSubscriptions } from './utils/subscription.utils'; +import { LoginComponent } from './pages/home/home-component'; +import { prepareAndSendPairingTx } from './utils/sp-address.utils'; +import ModalService from './services/modal.service'; +import { MessageType } from './models/process.model'; +import { splitPrivateData, isValid32ByteHex } from './utils/service.utils'; +import type { MerkleProofResult } from 'pkg/sdk_client'; + +const routes: { [key: string]: string } = { + home: '/src/pages/home/home.html', + process: '/src/pages/process/process.html', + 'process-element': '/src/pages/process-element/process-element.html', + account: '/src/pages/account/account.html', + chat: '/src/pages/chat/chat.html', + signature: '/src/pages/signature/signature.html', +}; + +export let currentRoute = ''; + +export async function navigate(path: string) { + cleanSubscriptions(); + cleanPage(); + path = path.replace(/^\//, ''); + if (path.includes('/')) { + const parsedPath = path.split('/')[0]; + if (!routes[parsedPath]) { + path = 'home'; + } + } + + await handleLocation(path); +} + +async function handleLocation(path: string) { + const parsedPath = path.split('/'); + if (path.includes('/')) { + path = parsedPath[0]; + } + currentRoute = path; + const routeHtml = routes[path] || routes['home']; + + const content = document.getElementById('containerId'); + if (content) { + if (path === 'home') { + const login = LoginComponent; + const container = document.querySelector('#containerId'); + const accountComponent = document.createElement('login-4nk-component'); + accountComponent.setAttribute('style', 'width: 100vw; height: 100vh; position: relative; grid-row: 2;'); + if (container) container.appendChild(accountComponent); + } else if (path !== 'process') { + const html = await fetch(routeHtml).then((data) => data.text()); + content.innerHTML = html; + } + + await new Promise(requestAnimationFrame); + injectHeader(); + + // const modalService = await ModalService.getInstance() + // modalService.injectValidationModal() + switch (path) { + case 'process': + // const { init } = await import('./pages/process/process'); + //const { ProcessListComponent } = await import('./pages/process/process-list-component'); + + const container2 = document.querySelector('#containerId'); + const accountComponent = document.createElement('process-list-4nk-component'); + + //if (!customElements.get('process-list-4nk-component')) { + //customElements.define('process-list-4nk-component', ProcessListComponent); + //} + accountComponent.setAttribute('style', 'height: 100vh; position: relative; grid-row: 2; grid-column: 4;'); + if (container2) container2.appendChild(accountComponent); + break; + + case 'process-element': + if (parsedPath && parsedPath.length) { + const { initProcessElement } = await import('./pages/process-element/process-element'); + const parseProcess = parsedPath[1].split('_'); + initProcessElement(parseProcess[0], parseProcess[1]); + } + break; + + case 'account': + const { AccountComponent } = await import('./pages/account/account-component'); + const accountContainer = document.querySelector('.parameter-list'); + if (accountContainer) { + if (!customElements.get('account-component')) { + customElements.define('account-component', AccountComponent); + } + const accountComponent = document.createElement('account-component'); + accountContainer.appendChild(accountComponent); + } + break; + + /*case 'chat': + const { ChatComponent } = await import('./pages/chat/chat-component'); + const chatContainer = document.querySelector('.group-list'); + if (chatContainer) { + if (!customElements.get('chat-component')) { + customElements.define('chat-component', ChatComponent); + } + const chatComponent = document.createElement('chat-component'); + chatContainer.appendChild(chatComponent); + } + break;*/ + + case 'signature': + const { SignatureComponent } = await import('./pages/signature/signature-component'); + const container = document.querySelector('.group-list'); + if (container) { + if (!customElements.get('signature-component')) { + customElements.define('signature-component', SignatureComponent); + } + const signatureComponent = document.createElement('signature-component'); + container.appendChild(signatureComponent); + } + break; + } + } +} + +window.onpopstate = async () => { + const services = await Services.getInstance(); + if (!services.isPaired()) { + handleLocation('home'); + } else { + handleLocation('process'); + } +}; + +export async function init(): Promise { + try { + const services = await Services.getInstance(); + (window as any).myService = services; + const db = await Database.getInstance(); + db.registerServiceWorker('/src/service-workers/database.worker.js'); + const device = await services.getDeviceFromDatabase(); + console.log('🚀 ~ setTimeout ~ device:', device); + + if (!device) { + await services.createNewDevice(); + } else { + services.restoreDevice(device); + } + + // If we create a new device, we most probably don't have anything in db, but just in case + await services.restoreProcessesFromDB(); + await services.restoreSecretsFromDB(); + + // We connect to all relays now + await services.connectAllRelays(); + + await services.updateDeviceBlockHeight(); + + // We register all the event listeners if we run in an iframe + if (window.self !== window.top) { + await registerAllListeners(); + } + + if (services.isPaired()) { + await navigate('process'); + } else { + await navigate('home'); + } + } catch (error) { + console.error(error); + await navigate('home'); + } +} + +export async function registerAllListeners() { + const services = await Services.getInstance(); + const tokenService = await TokenService.getInstance(); + + const errorResponse = (errorMsg: string, origin: string, messageId?: string) => { + window.parent.postMessage( + { + type: MessageType.ERROR, + error: errorMsg, + messageId + }, + origin + ); + } + + // --- Handler functions --- + const handleRequestLink = async (event: MessageEvent) => { + if (event.data.type !== MessageType.REQUEST_LINK) { + return; + } + const modalService = await ModalService.getInstance(); + const result = await modalService.showConfirmationModal({ + title: 'Confirmation de liaison', + content: ` + + `, + confirmText: 'Ajouter un service', + cancelText: 'Annuler' + }, true); + + if (!result) { + const errorMsg = 'Failed to pair device: User refused to link'; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + + try { + const tokens = await tokenService.generateSessionToken(event.origin); + const acceptedMsg = { + type: MessageType.LINK_ACCEPTED, + accessToken: tokens.accessToken, + refreshToken: tokens.refreshToken, + messageId: event.data.messageId + }; + window.parent.postMessage( + acceptedMsg, + event.origin + ); + } catch (error) { + const errorMsg = `Failed to generate tokens: ${error}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleCreatePairing = async (event: MessageEvent) => { + if (event.data.type !== MessageType.CREATE_PAIRING) { + return; + } + + if (services.isPaired()) { + const errorMsg = 'Device already paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + console.log('🚀 Starting pairing process'); + await prepareAndSendPairingTx(); + await services.confirmPairing(); + + const pairingId = services.getPairingProcessId(); + + if (!pairingId) { + throw new Error('Failed to get pairing process id'); + } + + // Send success response + const successMsg = { + type: MessageType.PAIRING_CREATED, + pairingId, + messageId: event.data.messageId + }; + window.parent.postMessage(successMsg, event.origin); + } catch (e) { + const errorMsg = `Failed to create pairing process: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleGetMyProcesses = async (event: MessageEvent) => { + if (event.data.type !== MessageType.GET_MY_PROCESSES) { + return; + } + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const myProcesses = await services.getMyProcesses(); + + window.parent.postMessage( + { + type: MessageType.GET_MY_PROCESSES, + myProcesses, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to get processes: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleGetProcesses = async (event: MessageEvent) => { + if (event.data.type !== MessageType.GET_PROCESSES) { + return; + } + + const tokenService = await TokenService.getInstance(); + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { accessToken } = event.data; + + // Validate the session token + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const processes = await services.getProcesses(); + + window.parent.postMessage( + { + type: MessageType.PROCESSES_RETRIEVED, + processes, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to get processes: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + /// We got a state for some process and return as many clear attributes as we can + const handleDecryptState = async (event: MessageEvent) => { + if (event.data.type !== MessageType.RETRIEVE_DATA) { + return; + } + const tokenService = await TokenService.getInstance(); + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { processId, stateId, accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + // Retrieve the state for the process + const process = await services.getProcess(processId); + if (!process) { + throw new Error('Can\'t find process'); + } + const state = services.getStateFromId(process, stateId); + + let res: Record = {}; + if (state) { + // Decrypt all the data we have the key for + for (const attribute of Object.keys(state.pcd_commitment)) { + if (attribute === 'roles' || state.public_data[attribute]) { + continue; + } + const decryptedAttribute = await services.decryptAttribute(processId, state, attribute); + if (decryptedAttribute) { + res[attribute] = decryptedAttribute; + } + } + } else { + throw new Error('Unknown state for process', processId); + } + + window.parent.postMessage( + { + type: MessageType.DATA_RETRIEVED, + data: res, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to retrieve data: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleValidateToken = async (event: MessageEvent) => { + if (event.data.type !== MessageType.VALIDATE_TOKEN) { + return; + } + + const accessToken = event.data.accessToken; + const refreshToken = event.data.refreshToken; + if (!accessToken || !refreshToken) { + errorResponse('Failed to validate token: missing access, refresh token or both', event.origin, event.data.messageId); + } + + const isValid = await tokenService.validateToken(accessToken, event.origin); + + window.parent.postMessage( + { + type: MessageType.VALIDATE_TOKEN, + accessToken: accessToken, + refreshToken: refreshToken, + isValid: isValid, + messageId: event.data.messageId + }, + event.origin + ); + }; + + const handleRenewToken = async (event: MessageEvent) => { + if (event.data.type !== MessageType.RENEW_TOKEN) { + return; + } + + try { + const refreshToken = event.data.refreshToken; + + if (!refreshToken) { + throw new Error('No refresh token provided'); + } + + const newAccessToken = await tokenService.refreshAccessToken(refreshToken, event.origin); + + if (!newAccessToken) { + throw new Error('Failed to refresh token'); + } + + window.parent.postMessage( + { + type: MessageType.RENEW_TOKEN, + accessToken: newAccessToken, + refreshToken: refreshToken, + messageId: event.data.messageId + }, + event.origin + ); + } catch (error) { + const errorMsg = `Failed to renew token: ${error}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleGetPairingId = async (event: MessageEvent) => { + if (event.data.type !== MessageType.GET_PAIRING_ID) return; + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const userPairingId = services.getPairingProcessId(); + + window.parent.postMessage( + { + type: MessageType.GET_PAIRING_ID, + userPairingId, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to get pairing id: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleCreateProcess = async (event: MessageEvent) => { + if (event.data.type !== MessageType.CREATE_PROCESS) return; + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { processData, privateFields, roles, accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const { privateData, publicData } = splitPrivateData(processData, privateFields); + + const createProcessReturn = await services.createProcess(privateData, publicData, roles); + if (!createProcessReturn.updated_process) { + throw new Error('Empty updated_process in createProcessReturn'); + } + const processId = createProcessReturn.updated_process.process_id; + const process = createProcessReturn.updated_process.current_process; + const stateId = process.states[0].state_id; + await services.handleApiReturn(createProcessReturn); + + const res = { + processId, + process, + processData, + } + + window.parent.postMessage( + { + type: MessageType.PROCESS_CREATED, + processCreated: res, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to create process: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleNotifyUpdate = async (event: MessageEvent) => { + if (event.data.type !== MessageType.NOTIFY_UPDATE) return; + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { processId, stateId, accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + if (!isValid32ByteHex(stateId)) { + throw new Error('Invalid state id'); + } + + const res = await services.createPrdUpdate(processId, stateId); + await services.handleApiReturn(res); + + window.parent.postMessage( + { + type: MessageType.UPDATE_NOTIFIED, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to notify update for process: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleValidateState = async (event: MessageEvent) => { + if (event.data.type !== MessageType.VALIDATE_STATE) return; + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { processId, stateId, accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const res = await services.approveChange(processId, stateId); + await services.handleApiReturn(res); + + window.parent.postMessage( + { + type: MessageType.STATE_VALIDATED, + validatedProcess: res.updated_process, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to validate process: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleUpdateProcess = async (event: MessageEvent) => { + if (event.data.type !== MessageType.UPDATE_PROCESS) return; + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + + try { + // privateFields is only used if newData contains new fields + // roles can be empty meaning that roles from the last commited state are kept + const { processId, newData, privateFields, roles, accessToken } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + // Check if the new data is already in the process or if it's a new field + const process = await services.getProcess(processId); + if (!process) { + throw new Error('Process not found'); + } + let lastState = services.getLastCommitedState(process); + if (!lastState) { + const firstState = process.states[0]; + const roles = firstState.roles; + if (services.rolesContainsUs(roles)) { + const approveChangeRes= await services.approveChange(processId, firstState.state_id); + await services.handleApiReturn(approveChangeRes); + const prdUpdateRes = await services.createPrdUpdate(processId, firstState.state_id); + await services.handleApiReturn(prdUpdateRes); + } else { + if (firstState.validation_tokens.length > 0) { + // Try to send it again anyway + const res = await services.createPrdUpdate(processId, firstState.state_id); + await services.handleApiReturn(res); + } + } + // Wait a couple seconds + await new Promise(resolve => setTimeout(resolve, 2000)); + lastState = services.getLastCommitedState(process); + if (!lastState) { + throw new Error('Process doesn\'t have a commited state yet'); + } + } + const lastStateIndex = services.getLastCommitedStateIndex(process); + if (lastStateIndex === null) { + throw new Error('Process doesn\'t have a commited state yet'); + } // Shouldn't happen + + const privateData: Record = {}; + const publicData: Record = {}; + + for (const field of Object.keys(newData)) { + // Public data are carried along each new state + // So the first thing we can do is check if the new data is public data + if (lastState.public_data[field]) { + // Add it to public data + publicData[field] = newData[field]; + continue; + } + + // If it's not a public data, it may be either a private data update, or a new field (public of private) + // Caller gave us a list of new private fields, if we see it here this is a new private field + if (privateFields.includes(field)) { + // Add it to private data + privateData[field] = newData[field]; + continue; + } + + // Now it can be an update of private data or a new public data + // We check that the field exists in previous states private data + for (let i = lastStateIndex; i >= 0; i--) { + const state = process.states[i]; + if (state.pcd_commitment[field]) { + // We don't even check if it's a public field, we would have seen it in the last state + privateData[field] = newData[field]; + break; + } else { + // This attribute was not modified in that state, we go back to the previous state + continue; + } + } + + if (privateData[field]) continue; + + // We've get back all the way to the first state without seeing it, it's a new public field + publicData[field] = newData[field]; + } + + // We'll let the wasm check if roles are consistent + + const res = await services.updateProcess(process, privateData, publicData, roles); + await services.handleApiReturn(res); + + window.parent.postMessage( + { + type: MessageType.PROCESS_UPDATED, + updatedProcess: res.updated_process, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to update process: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleDecodePublicData = async (event: MessageEvent) => { + if (event.data.type !== MessageType.DECODE_PUBLIC_DATA) return; + + if (!services.isPaired()) { + const errorMsg = 'Device not paired'; + errorResponse(errorMsg, event.origin, event.data.messageId); + return; + } + + try { + const { accessToken, encodedData } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const decodedData = services.decodeValue(encodedData); + + window.parent.postMessage( + { + type: MessageType.PUBLIC_DATA_DECODED, + decodedData, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to decode data: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleHashValue = async (event: MessageEvent) => { + if (event.data.type !== MessageType.HASH_VALUE) return; + + console.log('handleHashValue', event.data); + + try { + const { accessToken, commitedIn, label, fileBlob } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const hash = services.getHashForFile(commitedIn, label, fileBlob); + + window.parent.postMessage( + { + type: MessageType.VALUE_HASHED, + hash, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to hash value: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleGetMerkleProof = async (event: MessageEvent) => { + if (event.data.type !== MessageType.GET_MERKLE_PROOF) return; + + try { + const { accessToken, processState, attributeName } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + const proof = services.getMerkleProofForFile(processState, attributeName); + + window.parent.postMessage( + { + type: MessageType.MERKLE_PROOF_RETRIEVED, + proof, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to get merkle proof: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + const handleValidateMerkleProof = async (event: MessageEvent) => { + if (event.data.type !== MessageType.VALIDATE_MERKLE_PROOF) return; + + try { + const { accessToken, merkleProof, documentHash } = event.data; + + if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { + throw new Error('Invalid or expired session token'); + } + + // Try to parse the proof + // We will validate it's a MerkleProofResult in the wasm + let parsedMerkleProof: MerkleProofResult; + try { + parsedMerkleProof= JSON.parse(merkleProof); + } catch (e) { + throw new Error('Provided merkleProof is not a valid json object'); + } + + const res = services.validateMerkleProof(parsedMerkleProof, documentHash); + + window.parent.postMessage( + { + type: MessageType.MERKLE_PROOF_VALIDATED, + isValid: res, + messageId: event.data.messageId + }, + event.origin + ); + } catch (e) { + const errorMsg = `Failed to get merkle proof: ${e}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + window.removeEventListener('message', handleMessage); + window.addEventListener('message', handleMessage); + + async function handleMessage(event: MessageEvent) { + try { + switch (event.data.type) { + case MessageType.REQUEST_LINK: + await handleRequestLink(event); + break; + case MessageType.CREATE_PAIRING: + await handleCreatePairing(event); + break; + case MessageType.GET_MY_PROCESSES: + await handleGetMyProcesses(event); + break; + case MessageType.GET_PROCESSES: + await handleGetProcesses(event); + break; + case MessageType.RETRIEVE_DATA: + await handleDecryptState(event); + break; + case MessageType.VALIDATE_TOKEN: + await handleValidateToken(event); + break; + case MessageType.RENEW_TOKEN: + await handleRenewToken(event); + break; + case MessageType.GET_PAIRING_ID: + await handleGetPairingId(event); + break; + case MessageType.CREATE_PROCESS: + await handleCreateProcess(event); + break; + case MessageType.NOTIFY_UPDATE: + await handleNotifyUpdate(event); + break; + case MessageType.VALIDATE_STATE: + await handleValidateState(event); + break; + case MessageType.UPDATE_PROCESS: + await handleUpdateProcess(event); + break; + case MessageType.DECODE_PUBLIC_DATA: + await handleDecodePublicData(event); + break; + case MessageType.HASH_VALUE: + await handleHashValue(event); + break; + case MessageType.GET_MERKLE_PROOF: + await handleGetMerkleProof(event); + break; + case MessageType.VALIDATE_MERKLE_PROOF: + await handleValidateMerkleProof(event); + break; + default: + console.warn(`Unhandled message type: ${event.data.type}`); + } + } catch (error) { + const errorMsg = `Error handling message: ${error}`; + errorResponse(errorMsg, event.origin, event.data.messageId); + } + } + + window.parent.postMessage( + { + type: MessageType.LISTENING + }, + '*' + ); +} + +async function cleanPage() { + const container = document.querySelector('#containerId'); + if (container) container.innerHTML = ''; +} + +async function injectHeader() { + const headerContainer = document.getElementById('header-container'); + if (headerContainer) { + const headerHtml = await fetch('/src/components/header/header.html').then((res) => res.text()); + headerContainer.innerHTML = headerHtml; + + const script = document.createElement('script'); + script.src = '/src/components/header/header.ts'; + script.type = 'module'; + document.head.appendChild(script); + initHeader(); + } +} + +(window as any).navigate = navigate; + +document.addEventListener('navigate', ((e: Event) => { + const event = e as CustomEvent<{page: string, processId?: string}>; + if (event.detail.page === 'chat') { + const container = document.querySelector('.container'); + if (container) container.innerHTML = ''; + + //initChat(); + + const chatElement = document.querySelector('chat-element'); + if (chatElement) { + chatElement.setAttribute('process-id', event.detail.processId || ''); + } + } +})); diff --git a/ihm_client/src/scanner.js b/ihm_client/src/scanner.js new file mode 100755 index 00000000..ff048c06 --- /dev/null +++ b/ihm_client/src/scanner.js @@ -0,0 +1,13 @@ +function onScanSuccess(decodedText, decodedResult) { + // handle the scanned code as you like, for example: + console.log(`Code matched = ${decodedText}`, decodedResult); +} + +function onScanFailure(error) { + // handle scan failure, usually better to ignore and keep scanning. + // for example: + console.warn(`Code scan error = ${error}`); +} + +let html5QrcodeScanner = new Html5QrcodeScanner('reader', { fps: 10, qrbox: { width: 250, height: 250 } }, /* verbose= */ false); +html5QrcodeScanner.render(onScanSuccess, onScanFailure); diff --git a/ihm_client/src/service-workers/cache.worker.js b/ihm_client/src/service-workers/cache.worker.js new file mode 100644 index 00000000..966eb995 --- /dev/null +++ b/ihm_client/src/service-workers/cache.worker.js @@ -0,0 +1,8 @@ +const addResourcesToCache = async (resources) => { + const cache = await caches.open('v1'); + await cache.addAll(resources); +}; + +self.addEventListener('install', (event) => { + event.waitUntil(addResourcesToCache(['/', '/index.html', '/style.css', '/app.js', '/image-list.js', '/star-wars-logo.jpg', '/gallery/bountyHunters.jpg', '/gallery/myLittleVader.jpg', '/gallery/snowTroopers.jpg'])); +}); diff --git a/ihm_client/src/service-workers/database.worker.js b/ihm_client/src/service-workers/database.worker.js new file mode 100755 index 00000000..a9e05485 --- /dev/null +++ b/ihm_client/src/service-workers/database.worker.js @@ -0,0 +1,281 @@ +const EMPTY32BYTES = String('').padStart(64, '0'); + +self.addEventListener('install', (event) => { + event.waitUntil(self.skipWaiting()); // Activate worker immediately +}); + +self.addEventListener('activate', (event) => { + event.waitUntil(self.clients.claim()); // Become available to all pages +}); + +// Event listener for messages from clients +self.addEventListener('message', async (event) => { + const data = event.data; + console.log(data); + + if (data.type === 'SCAN') { + try { + const myProcessesId = data.payload; + if (myProcessesId && myProcessesId.length != 0) { + const toDownload = await scanMissingData(myProcessesId); + if (toDownload.length != 0) { + console.log('Sending TO_DOWNLOAD message'); + event.source.postMessage({ type: 'TO_DOWNLOAD', data: toDownload}); + } + } else { + event.source.postMessage({ status: 'error', message: 'Empty lists' }); + } + } catch (error) { + event.source.postMessage({ status: 'error', message: error.message }); + } + } else if (data.type === 'ADD_OBJECT') { + try { + const { storeName, object, key } = data.payload; + const db = await openDatabase(); + const tx = db.transaction(storeName, 'readwrite'); + const store = tx.objectStore(storeName); + + if (key) { + await store.put(object, key); + } else { + await store.put(object); + } + + event.ports[0].postMessage({ status: 'success', message: '' }); + } catch (error) { + event.ports[0].postMessage({ status: 'error', message: error.message }); + } + } else if (data.type === 'BATCH_WRITING') { + const { storeName, objects } = data.payload; + const db = await openDatabase(); + const tx = db.transaction(storeName, 'readwrite'); + const store = tx.objectStore(storeName); + + for (const { key, object } of objects) { + if (key) { + await store.put(object, key); + } else { + await store.put(object); + } + } + + await tx.done; + } +}); + +async function scanMissingData(processesToScan) { + console.log('Scanning for missing data...'); + const myProcesses = await getProcesses(processesToScan); + + let toDownload = new Set(); + // Iterate on each process + if (myProcesses && myProcesses.length != 0) { + for (const process of myProcesses) { + // Iterate on states + const firstState = process.states[0]; + const processId = firstState.commited_in; + for (const state of process.states) { + if (state.state_id === EMPTY32BYTES) continue; + // iterate on pcd_commitment + for (const [field, hash] of Object.entries(state.pcd_commitment)) { + // Skip public fields + if (state.public_data[field] !== undefined || field === 'roles') continue; + // Check if we have the data in db + const existingData = await getBlob(hash); + if (!existingData) { + toDownload.add(hash); + // We also add an entry in diff, in case it doesn't already exist + await addDiff(processId, state.state_id, hash, state.roles, field); + } else { + // We remove it if we have it in the set + if (toDownload.delete(hash)) { + console.log(`Removing ${hash} from the set`); + } + } + } + } + } + } + + console.log(toDownload); + return Array.from(toDownload); +} + +async function openDatabase() { + return new Promise((resolve, reject) => { + const request = indexedDB.open('4nk', 1); + request.onerror = (event) => { + reject(request.error); + }; + request.onsuccess = (event) => { + resolve(request.result); + }; + request.onupgradeneeded = (event) => { + const db = event.target.result; + if (!db.objectStoreNames.contains('wallet')) { + db.createObjectStore('wallet', { keyPath: 'pre_id' }); + } + }; + }); +} + +// Function to get all processes because it is asynchronous +async function getAllProcesses() { + const db = await openDatabase(); + return new Promise((resolve, reject) => { + if (!db) { + reject(new Error('Database is not available')); + return; + } + const tx = db.transaction('processes', 'readonly'); + const store = tx.objectStore('processes'); + const request = store.getAll(); + + request.onsuccess = () => { + resolve(request.result); + }; + + request.onerror = () => { + reject(request.error); + }; + }); +}; + +async function getProcesses(processIds) { + if (!processIds || processIds.length === 0) { + return []; + } + + const db = await openDatabase(); + if (!db) { + throw new Error('Database is not available'); + } + + const tx = db.transaction('processes', 'readonly'); + const store = tx.objectStore('processes'); + + const requests = Array.from(processIds).map((processId) => { + return new Promise((resolve) => { + const request = store.get(processId); + request.onsuccess = () => resolve(request.result); + request.onerror = () => { + console.error(`Error fetching process ${processId}:`, request.error); + resolve(undefined); + }; + }); + }); + + const results = await Promise.all(requests); + return results.filter(result => result !== undefined); +} + +async function getAllDiffsNeedValidation() { + const db = await openDatabase(); + + const allProcesses = await getAllProcesses(); + const tx = db.transaction('diffs', 'readonly'); + const store = tx.objectStore('diffs'); + + return new Promise((resolve, reject) => { + const request = store.getAll(); + request.onsuccess = (event) => { + const allItems = event.target.result; + const itemsWithFlag = allItems.filter((item) => item.need_validation); + + const processMap = {}; + + for (const diff of itemsWithFlag) { + const currentProcess = allProcesses.find((item) => { + return item.states.some((state) => state.merkle_root === diff.new_state_merkle_root); + }); + + if (currentProcess) { + const processKey = currentProcess.merkle_root; + + if (!processMap[processKey]) { + processMap[processKey] = { + process: currentProcess.states, + processId: currentProcess.key, + diffs: [], + }; + } + processMap[processKey].diffs.push(diff); + } + } + + const results = Object.values(processMap).map((entry) => { + const diffs = [] + for(const state of entry.process) { + const filteredDiff = entry.diffs.filter(diff => diff.new_state_merkle_root === state.merkle_root); + if(filteredDiff && filteredDiff.length) { + diffs.push(filteredDiff) + } + } + return { + process: entry.process, + processId: entry.processId, + diffs: diffs, + }; + }); + + resolve(results); + }; + + request.onerror = (event) => { + reject(event.target.error); + }; + }); +} + +async function getBlob(hash) { + const db = await openDatabase(); + const storeName = 'data'; + const tx = db.transaction(storeName, 'readonly'); + const store = tx.objectStore(storeName); + const result = await new Promise((resolve, reject) => { + const getRequest = store.get(hash); + getRequest.onsuccess = () => resolve(getRequest.result); + getRequest.onerror = () => reject(getRequest.error); + }); + return result; +} + +async function addDiff(processId, stateId, hash, roles, field) { + const db = await openDatabase(); + const storeName = 'diffs'; + const tx = db.transaction(storeName, 'readwrite'); + const store = tx.objectStore(storeName); + + // Check if the diff already exists + const existingDiff = await new Promise((resolve, reject) => { + const getRequest = store.get(hash); + getRequest.onsuccess = () => resolve(getRequest.result); + getRequest.onerror = () => reject(getRequest.error); + }); + + if (!existingDiff) { + const newDiff = { + process_id: processId, + state_id: stateId, + value_commitment: hash, + roles: roles, + field: field, + description: null, + previous_value: null, + new_value: null, + notify_user: false, + need_validation: false, + validation_status: 'None' + }; + + const insertResult = await new Promise((resolve, reject) => { + const putRequest = store.put(newDiff); + putRequest.onsuccess = () => resolve(putRequest.result); + putRequest.onerror = () => reject(putRequest.error); + }); + + return insertResult; + } + + return existingDiff; +} diff --git a/ihm_client/src/services/database.service.ts b/ihm_client/src/services/database.service.ts new file mode 100755 index 00000000..c6cd73ea --- /dev/null +++ b/ihm_client/src/services/database.service.ts @@ -0,0 +1,454 @@ +import Services from './service'; + +export class Database { + private static instance: Database; + private db: IDBDatabase | null = null; + private dbName: string = '4nk'; + private dbVersion: number = 1; + private serviceWorkerRegistration: ServiceWorkerRegistration | null = null; + private messageChannel: MessageChannel | null = null; + private messageChannelForGet: MessageChannel | null = null; + private serviceWorkerCheckIntervalId: number | null = null; + private storeDefinitions = { + AnkLabels: { + name: 'labels', + options: { keyPath: 'emoji' }, + indices: [], + }, + AnkWallet: { + name: 'wallet', + options: { keyPath: 'pre_id' }, + indices: [], + }, + AnkProcess: { + name: 'processes', + options: {}, + indices: [], + }, + AnkSharedSecrets: { + name: 'shared_secrets', + options: {}, + indices: [], + }, + AnkUnconfirmedSecrets: { + name: 'unconfirmed_secrets', + options: { autoIncrement: true }, + indices: [], + }, + AnkPendingDiffs: { + name: 'diffs', + options: { keyPath: 'value_commitment' }, + indices: [ + { name: 'byStateId', keyPath: 'state_id', options: { unique: false } }, + { name: 'byNeedValidation', keyPath: 'need_validation', options: { unique: false } }, + { name: 'byStatus', keyPath: 'validation_status', options: { unique: false } }, + ], + }, + AnkData: { + name: 'data', + options: {}, + indices: [], + }, + }; + + // Private constructor to prevent direct instantiation from outside + private constructor() {} + + // Method to access the singleton instance of Database + public static async getInstance(): Promise { + if (!Database.instance) { + Database.instance = new Database(); + await Database.instance.init(); + } + return Database.instance; + } + + // Initialize the database + private async init(): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(this.dbName, this.dbVersion); + + request.onupgradeneeded = () => { + const db = request.result; + + Object.values(this.storeDefinitions).forEach(({ name, options, indices }) => { + if (!db.objectStoreNames.contains(name)) { + let store = db.createObjectStore(name, options as IDBObjectStoreParameters); + + indices.forEach(({ name, keyPath, options }) => { + store.createIndex(name, keyPath, options); + }); + } + }); + }; + + request.onsuccess = async () => { + this.db = request.result; + resolve(); + }; + + request.onerror = () => { + console.error('Database error:', request.error); + reject(request.error); + }; + }); + } + + public async getDb(): Promise { + if (!this.db) { + await this.init(); + } + return this.db!; + } + + public getStoreList(): { [key: string]: string } { + const objectList: { [key: string]: string } = {}; + Object.keys(this.storeDefinitions).forEach((key) => { + objectList[key] = this.storeDefinitions[key as keyof typeof this.storeDefinitions].name; + }); + return objectList; + } + + public async registerServiceWorker(path: string) { + if (!('serviceWorker' in navigator)) return; // Ensure service workers are supported + console.log('registering worker at', path); + + try { + // Get existing service worker registrations + const registrations = await navigator.serviceWorker.getRegistrations(); + if (registrations.length === 0) { + // No existing workers: register a new one. + this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' }); + console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope); + } else if (registrations.length === 1) { + // One existing worker: update it (restart it) without unregistering. + this.serviceWorkerRegistration = registrations[0]; + await this.serviceWorkerRegistration.update(); + console.log('Service Worker updated'); + } else { + // More than one existing worker: unregister them all and register a new one. + console.log('Multiple Service Worker(s) detected. Unregistering all...'); + await Promise.all(registrations.map(reg => reg.unregister())); + console.log('All previous Service Workers unregistered.'); + this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' }); + console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope); + } + + await this.checkForUpdates(); + + // Set up a global message listener for responses from the service worker. + navigator.serviceWorker.addEventListener('message', async (event) => { + console.log('Received message from service worker:', event.data); + await this.handleServiceWorkerMessage(event.data); + }); + + // Set up a periodic check to ensure the service worker is active and to send a SCAN message. + this.serviceWorkerCheckIntervalId = window.setInterval(async () => { + const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!)); + const service = await Services.getInstance(); + const payload = await service.getMyProcesses(); + if (payload && payload.length != 0) { + activeWorker?.postMessage({ type: 'SCAN', payload }); + } + }, 5000); + } catch (error) { + console.error('Service Worker registration failed:', error); + } + } + + // Helper function to wait for service worker activation + private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise { + return new Promise((resolve) => { + if (registration.active) { + resolve(registration.active); + } else { + const listener = () => { + if (registration.active) { + navigator.serviceWorker.removeEventListener('controllerchange', listener); + resolve(registration.active); + } + }; + navigator.serviceWorker.addEventListener('controllerchange', listener); + } + }); + } + + private async checkForUpdates() { + if (this.serviceWorkerRegistration) { + // Check for updates to the service worker + try { + await this.serviceWorkerRegistration.update(); + + // If there's a new worker waiting, activate it immediately + if (this.serviceWorkerRegistration.waiting) { + this.serviceWorkerRegistration.waiting.postMessage({ type: 'SKIP_WAITING' }); + } + } catch (error) { + console.error('Error checking for service worker updates:', error); + } + } + } + + private async handleServiceWorkerMessage(message: any) { + switch (message.type) { + case 'TO_DOWNLOAD': + await this.handleDownloadList(message.data); + break; + default: + console.warn('Unknown message type received from service worker:', message); + } + } + + private async handleDownloadList(downloadList: string[]): Promise { + // Download the missing data + let requestedStateId: string[] = []; + const service = await Services.getInstance(); + for (const hash of downloadList) { + const diff = await service.getDiffByValue(hash); + if (!diff) { + // This should never happen + console.warn(`Missing a diff for hash ${hash}`); + continue; + } + const processId = diff.process_id; + const stateId = diff.state_id; + const roles = diff.roles; + try { + const valueBytes = await service.fetchValueFromStorage(hash); + if (valueBytes) { + // Save data to db + const blob = new Blob([valueBytes], {type: "application/octet-stream"}); + await service.saveBlobToDb(hash, blob); + document.dispatchEvent(new CustomEvent('newDataReceived', { + detail: { + processId, + stateId, + hash, + } + })); + } else { + // We first request the data from managers + console.log('Request data from managers of the process'); + // get the diff from db + if (!requestedStateId.includes(stateId)) { + await service.requestDataFromPeers(processId, [stateId], [roles]); + requestedStateId.push(stateId); + } + } + } catch (e) { + console.error(e); + } + } + } + + private handleAddObjectResponse = async (event: MessageEvent) => { + const data = event.data; + console.log('Received response from service worker (ADD_OBJECT):', data); + const service = await Services.getInstance(); + if (data.type === 'NOTIFICATIONS') { + service.setNotifications(data.data); + } else if (data.type === 'TO_DOWNLOAD') { + console.log(`Received missing data ${data}`); + // Download the missing data + let requestedStateId: string[] = []; + for (const hash of data.data) { + try { + const valueBytes = await service.fetchValueFromStorage(hash); + if (valueBytes) { + // Save data to db + const blob = new Blob([valueBytes], {type: "application/octet-stream"}); + await service.saveBlobToDb(hash, blob); + } else { + // We first request the data from managers + console.log('Request data from managers of the process'); + // get the diff from db + const diff = await service.getDiffByValue(hash); + if (diff === null) { + continue; + } + const processId = diff!.process_id; + const stateId = diff!.state_id; + const roles = diff!.roles; + if (!requestedStateId.includes(stateId)) { + await service.requestDataFromPeers(processId, [stateId], [roles]); + requestedStateId.push(stateId); + } + } + } catch (e) { + console.error(e); + } + } + } + }; + + private handleGetObjectResponse = (event: MessageEvent) => { + console.log('Received response from service worker (GET_OBJECT):', event.data); + }; + + public addObject(payload: { storeName: string; object: any; key: any }): Promise { + return new Promise(async (resolve, reject) => { + // Check if the service worker is active + if (!this.serviceWorkerRegistration) { + // console.warn('Service worker registration is not ready. Waiting...'); + this.serviceWorkerRegistration = await navigator.serviceWorker.ready; + } + + const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration); + + // Create a message channel for communication + const messageChannel = new MessageChannel(); + + // Handle the response from the service worker + messageChannel.port1.onmessage = (event) => { + if (event.data.status === 'success') { + resolve(); + } else { + const error = event.data.message; + reject(new Error(error || 'Unknown error occurred while adding object')); + } + }; + + // Send the add object request to the service worker + try { + activeWorker?.postMessage( + { + type: 'ADD_OBJECT', + payload, + }, + [messageChannel.port2], + ); + } catch (error) { + reject(new Error(`Failed to send message to service worker: ${error}`)); + } + }); + } + + public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise { + return new Promise(async (resolve, reject) => { + if (!this.serviceWorkerRegistration) { + this.serviceWorkerRegistration = await navigator.serviceWorker.ready; + } + + const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration); + const messageChannel = new MessageChannel(); + + messageChannel.port1.onmessage = (event) => { + if (event.data.status === 'success') { + resolve(); + } else { + const error = event.data.message; + reject(new Error(error || 'Unknown error occurred while adding objects')); + } + }; + + try { + activeWorker?.postMessage( + { + type: 'BATCH_WRITING', + payload, + }, + [messageChannel.port2], + ); + } catch (error) { + reject(new Error(`Failed to send message to service worker: ${error}`)); + } + }); + } + + public async getObject(storeName: string, key: string): Promise { + const db = await this.getDb(); + const tx = db.transaction(storeName, 'readonly'); + const store = tx.objectStore(storeName); + const result = await new Promise((resolve, reject) => { + const getRequest = store.get(key); + getRequest.onsuccess = () => resolve(getRequest.result); + getRequest.onerror = () => reject(getRequest.error); + }); + return result; + } + + public async dumpStore(storeName: string): Promise> { + const db = await this.getDb(); + const tx = db.transaction(storeName, 'readonly'); + const store = tx.objectStore(storeName); + + try { + return new Promise((resolve, reject) => { + const result: Record = {}; + const cursor = store.openCursor(); + + cursor.onsuccess = (event) => { + const request = event.target as IDBRequest; + const cursor = request.result; + if (cursor) { + result[cursor.key as string] = cursor.value; + cursor.continue(); + } else { + resolve(result); + } + }; + + cursor.onerror = () => { + reject(cursor.error); + }; + }); + } catch (error) { + console.error('Error fetching data from IndexedDB:', error); + throw error; + } + } + + public async deleteObject(storeName: string, key: string): Promise { + const db = await this.getDb(); + const tx = db.transaction(storeName, 'readwrite'); + const store = tx.objectStore(storeName); + try { + await new Promise((resolve, reject) => { + const getRequest = store.delete(key); + getRequest.onsuccess = () => resolve(getRequest.result); + getRequest.onerror = () => reject(getRequest.error); + }); + } catch (e) { + throw e; + } + } + + public async clearStore(storeName: string): Promise { + const db = await this.getDb(); + const tx = db.transaction(storeName, 'readwrite'); + const store = tx.objectStore(storeName); + try { + await new Promise((resolve, reject) => { + const clearRequest = store.clear(); + clearRequest.onsuccess = () => resolve(clearRequest.result); + clearRequest.onerror = () => reject(clearRequest.error); + }); + } catch (e) { + throw e; + } + } + + // Request a store by index + public async requestStoreByIndex(storeName: string, indexName: string, request: string): Promise { + const db = await this.getDb(); + const tx = db.transaction(storeName, 'readonly'); + const store = tx.objectStore(storeName); + const index = store.index(indexName); + + try { + return new Promise((resolve, reject) => { + const getAllRequest = index.getAll(request); + getAllRequest.onsuccess = () => { + const allItems = getAllRequest.result; + const filtered = allItems.filter(item => item.state_id === request); + resolve(filtered); + }; + getAllRequest.onerror = () => reject(getAllRequest.error); + }); + } catch (e) { + throw e; + } + } +} + +export default Database; diff --git a/ihm_client/src/services/modal.service.ts b/ihm_client/src/services/modal.service.ts new file mode 100755 index 00000000..b2f6d7cd --- /dev/null +++ b/ihm_client/src/services/modal.service.ts @@ -0,0 +1,240 @@ +import modalHtml from '../components/login-modal/login-modal.html?raw'; +import modalScript from '../components/login-modal/login-modal.js?raw'; +import validationModalStyle from '../components/validation-modal/validation-modal.css?raw'; +import Services from './service'; +import { init, navigate } from '../router'; +import { addressToEmoji } from '../utils/sp-address.utils'; +import type { Member, RoleDefinition } from 'pkg/sdk_client'; +import { initValidationModal } from '~/components/validation-modal/validation-modal'; +import { interpolate } from '~/utils/html.utils'; + +interface ConfirmationModalOptions { + title: string; + content: string; + confirmText?: string; + cancelText?: string; +} + +export default class ModalService { + private static instance: ModalService; + private stateId: string | null = null; + private processId: string | null = null; + private constructor() {} + private paired_addresses: string[] = []; + private modal: HTMLElement | null = null; + + // Method to access the singleton instance of Services + public static async getInstance(): Promise { + if (!ModalService.instance) { + ModalService.instance = new ModalService(); + } + return ModalService.instance; + } + + public openLoginModal(myAddress: string, receiverAddress: string) { + const container = document.querySelector('.page-container'); + let html = modalHtml; + html = html.replace('{{device1}}', myAddress); + html = html.replace('{{device2}}', receiverAddress); + if (container) container.innerHTML += html; + const modal = document.getElementById('login-modal'); + if (modal) modal.style.display = 'flex'; + const newScript = document.createElement('script'); + + newScript.setAttribute('type', 'module'); + newScript.textContent = modalScript; + document.head.appendChild(newScript).parentNode?.removeChild(newScript); + } + + async injectModal(members: any[]) { + const container = document.querySelector('#containerId'); + if (container) { + let html = await fetch('/src/components/modal/confirmation-modal.html').then((res) => res.text()); + html = html.replace('{{device1}}', await addressToEmoji(members[0]['sp_addresses'][0])); + html = html.replace('{{device2}}', await addressToEmoji(members[0]['sp_addresses'][1])); + container.innerHTML += html; + + // Dynamically load the header JS + const script = document.createElement('script'); + script.src = '/src/components/modal/confirmation-modal.ts'; + script.type = 'module'; + document.head.appendChild(script); + } + } + + async injectCreationModal(members: any[]) { + const container = document.querySelector('#containerId'); + if (container) { + let html = await fetch('/src/components/modal/creation-modal.html').then((res) => res.text()); + html = html.replace('{{device1}}', await addressToEmoji(members[0]['sp_addresses'][0])); + container.innerHTML += html; + + // Dynamically load the header JS + const script = document.createElement('script'); + script.src = '/src/components/modal/confirmation-modal.ts'; + script.type = 'module'; + document.head.appendChild(script); + } + } + + // Device 1 wait Device 2 + async injectWaitingModal() { + const container = document.querySelector('#containerId'); + if (container) { + let html = await fetch('/src/components/modal/waiting-modal.html').then((res) => res.text()); + container.innerHTML += html; + } + } + + async injectValidationModal(processDiff: any) { + const container = document.querySelector('#containerId'); + if (container) { + let html = await fetch('/src/components/validation-modal/validation-modal.html').then((res) => res.text()); + html = interpolate(html, {processId: processDiff.processId}) + container.innerHTML += html; + + // Dynamically load the header JS + const script = document.createElement('script'); + script.id = 'validation-modal-script'; + script.src = '/src/components/validation-modal/validation-modal.ts'; + script.type = 'module'; + document.head.appendChild(script); + const css = document.createElement('style'); + css.id = 'validation-modal-css'; + css.innerText = validationModalStyle; + document.head.appendChild(css); + initValidationModal(processDiff) + } + } + + async closeValidationModal() { + const script = document.querySelector('#validation-modal-script'); + const css = document.querySelector('#validation-modal-css'); + const component = document.querySelector('#validation-modal'); + script?.remove(); + css?.remove(); + component?.remove(); + } + + public async openPairingConfirmationModal(roleDefinition: Record, processId: string, stateId: string) { + let memberOutPoints; + if (roleDefinition['pairing']) { + const owner = roleDefinition['pairing']; + memberOutPoints = owner.members; + } else { + throw new Error('No "pairing" role'); + } + + if (memberOutPoints.length != 1) { + throw new Error('Must have exactly 1 member'); + } + + console.log("MEMBER OUTPOINTS:", memberOutPoints); + // We take all the addresses except our own + const service = await Services.getInstance(); + const localAddress = service.getDeviceAddress(); + + // Récupérer les objets Member à partir des OutPoint + const members: Member[] = []; + for (const outPoint of memberOutPoints) { + // Ici, vous devriez récupérer l'objet Member correspondant à l'OutPoint + // Pour l'instant, on crée un objet Member vide + const member: Member = { sp_addresses: [] }; + members.push(member); + } + + for (const member of members) { + if (member.sp_addresses) { + for (const address of member.sp_addresses) { + if (address !== localAddress) { + this.paired_addresses.push(address); + } + } + } + } + this.processId = processId; + this.stateId = stateId; + + if (members[0].sp_addresses.length === 1) { + await this.injectCreationModal(members); + this.modal = document.getElementById('creation-modal'); + console.log("LENGTH:", members[0].sp_addresses.length); + } else { + await this.injectModal(members); + this.modal = document.getElementById('modal'); + console.log("LENGTH:", members[0].sp_addresses.length); + } + + if (this.modal) this.modal.style.display = 'flex'; + + // Close modal when clicking outside of it + window.onclick = (event) => { + if (event.target === this.modal) { + this.closeConfirmationModal(); + } + }; + } + confirmLogin() { + console.log('=============> Confirm Login'); + } + async closeLoginModal() { + if (this.modal) this.modal.style.display = 'none'; + } + + async showConfirmationModal(options: ConfirmationModalOptions, fullscreen: boolean = false): Promise { + // Create modal element + const modalElement = document.createElement('div'); + modalElement.id = 'confirmation-modal'; + modalElement.innerHTML = ` + + `; + + // Add modal to document + document.body.appendChild(modalElement); + + // Return promise that resolves with user choice + return new Promise((resolve) => { + const confirmButton = modalElement.querySelector('#confirm-button'); + const cancelButton = modalElement.querySelector('#cancel-button'); + const modalOverlay = modalElement.querySelector('.modal-overlay'); + + const cleanup = () => { + modalElement.remove(); + }; + + confirmButton?.addEventListener('click', () => { + cleanup(); + resolve(true); + }); + + cancelButton?.addEventListener('click', () => { + cleanup(); + resolve(false); + }); + + modalOverlay?.addEventListener('click', (e) => { + if (e.target === modalOverlay) { + cleanup(); + resolve(false); + } + }); + }); + } + + async closeConfirmationModal() { + const service = await Services.getInstance(); + await service.unpairDevice(); + if (this.modal) this.modal.style.display = 'none'; + } +} diff --git a/ihm_client/src/services/service.ts b/ihm_client/src/services/service.ts new file mode 100755 index 00000000..7f3a83af --- /dev/null +++ b/ihm_client/src/services/service.ts @@ -0,0 +1,1752 @@ +import { INotification } from '~/models/notification.model'; +import { IProcess } from '~/models/process.model'; +import { initWebsocket, sendMessage } from '../websockets'; +import type { ApiReturn, Device, HandshakeMessage, Member, MerkleProofResult, NewTxMessage, OutPointProcessMap, Process, ProcessState, RoleDefinition, SecretsStore, UserDiff } from '../../pkg/sdk_client'; +import ModalService from './modal.service'; +import Database from './database.service'; +import { navigate } from '../router'; +import { storeData, retrieveData, testData } from './storage.service'; +import { BackUp } from '~/models/backup.model'; + +export const U32_MAX = 4294967295; + +const BASEURL = `http://localhost`; +const BOOTSTRAPURL = [`${BASEURL}:8090`]; +const STORAGEURL = `${BASEURL}:8081` +const BLINDBITURL = `${BASEURL}:8000` +const DEFAULTAMOUNT = 1000n; +const EMPTY32BYTES = String('').padStart(64, '0'); + +export default class Services { + private static initializing: Promise | null = null; + private static instance: Services; + private processId: string | null = null; + private stateId: string | null = null; + private sdkClient: any; + private processesCache: Record = {}; + private myProcesses: Set = new Set(); + private notifications: any[] | null = null; + private subscriptions: { element: Element; event: string; eventHandler: string }[] = []; + private database: any; + private routingInstance!: ModalService; + private relayAddresses: { [wsurl: string]: string } = {}; + private membersList: Record = {}; + private currentBlockHeight: number = -1; + // Private constructor to prevent direct instantiation from outside + private constructor() {} + + // Method to access the singleton instance of Services + public static async getInstance(): Promise { + if (Services.instance) { + return Services.instance; + } + + if (!Services.initializing) { + Services.initializing = (async () => { + const instance = new Services(); + await instance.init(); + instance.routingInstance = await ModalService.getInstance(); + return instance; + })(); + } + + console.log('initializing services'); + Services.instance = await Services.initializing; + Services.initializing = null; // Reset for potential future use + return Services.instance; + } + + public async init(): Promise { + this.notifications = this.getNotifications(); + this.sdkClient = await import('../../pkg/sdk_client'); + this.sdkClient.setup(); + for (const wsurl of Object.values(BOOTSTRAPURL)) { + this.updateRelay(wsurl, ''); + } + } + + public setProcessId(processId: string | null) { + this.processId = processId; + } + + public setStateId(stateId: string | null) { + this.stateId = stateId; + } + + public getProcessId(): string | null { + return this.processId; + } + + public getStateId(): string | null { + return this.stateId; + } + + /** + * Calls `this.addWebsocketConnection` for each `wsurl` in relayAddresses. + * Waits for at least one handshake message before returning. + */ + public async connectAllRelays(): Promise { + const connectedUrls: string[] = []; + + // Connect to all relays + for (const wsurl of Object.keys(this.relayAddresses)) { + try { + console.log(`Connecting to: ${wsurl}`); + await this.addWebsocketConnection(wsurl); + connectedUrls.push(wsurl); + console.log(`Successfully connected to: ${wsurl}`); + } catch (error) { + console.error(`Failed to connect to ${wsurl}:`, error); + } + } + + // Wait for at least one handshake message if we have connections + if (connectedUrls.length > 0) { + await this.waitForHandshakeMessage(); + } + } + + public async addWebsocketConnection(url: string): Promise { + console.log('Opening new websocket connection'); + await initWebsocket(url); + } + + /** + * Add or update a key/value pair in relayAddresses. + * @param wsurl - The WebSocket URL (key). + * @param spAddress - The SP Address (value). + */ + public updateRelay(wsurl: string, spAddress: string): void { + this.relayAddresses[wsurl] = spAddress; + console.log(`Updated: ${wsurl} -> ${spAddress}`); + } + + /** + * 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. + */ + public getSpAddress(wsurl: string): string | undefined { + return this.relayAddresses[wsurl]; + } + + /** + * Get all key/value pairs from relayAddresses. + * @returns An array of objects containing wsurl and spAddress. + */ + public getAllRelays(): { wsurl: string; spAddress: string }[] { + return Object.entries(this.relayAddresses).map(([wsurl, spAddress]) => ({ + wsurl, + spAddress, + })); + } + + /** + * Print all key/value pairs for debugging. + */ + public printAllRelays(): void { + console.log("Current relay addresses:"); + for (const [wsurl, spAddress] of Object.entries(this.relayAddresses)) { + console.log(`${wsurl} -> ${spAddress}`); + } + } + + public isPaired(): boolean { + try { + return this.sdkClient.is_paired(); + } catch (e) { + throw new Error(`isPaired ~ Error: ${e}`); + } + } + + public async unpairDevice(): Promise { + try { + this.sdkClient.unpair_device(); + const newDevice = this.dumpDeviceFromMemory(); + await this.saveDeviceInDatabase(newDevice); + } catch (e) { + throw new Error(`Failed to unpair device: ${e}`); + } + } + + public async getSecretForAddress(address: string): Promise { + const db = await Database.getInstance(); + return await db.getObject('shared_secrets', address); + } + + public async getAllSecrets(): Promise { + const db = await Database.getInstance(); + const sharedSecrets = await db.dumpStore('shared_secrets'); + const unconfirmedSecrets = await db.dumpStore('unconfirmed_secrets'); // keys are numeric values + + const secretsStore = { + shared_secrets: sharedSecrets, + unconfirmed_secrets: Object.values(unconfirmedSecrets), + }; + + return secretsStore; + } + + public async getAllDiffs(): Promise> { + const db = await Database.getInstance(); + return await db.dumpStore('diffs'); + } + + public async getDiffByValue(value: string): Promise { + const db = await Database.getInstance(); + const store = 'diffs'; + const res = await db.getObject(store, value); + return res; + } + + private async getTokensFromFaucet(): Promise { + try { + await this.ensureSufficientAmount(); + } catch (e) { + console.error('Failed to get tokens from relay, check connection'); + return; + } + } + + public async checkConnections(members: Member[]): Promise { + // Ensure the amount is available before proceeding + await this.getTokensFromFaucet(); + let unconnectedAddresses: Set = new Set(); + const myAddress = this.getDeviceAddress(); + for (const member of members) { + const sp_addresses = member.sp_addresses; + if (!sp_addresses || sp_addresses.length === 0) continue; + for (const address of sp_addresses) { + // For now, we ignore our own device address, although there might be use cases for having a secret with ourselves + if (address === myAddress) continue; + const sharedSecret = await this.getSecretForAddress(address); + if (!sharedSecret) { + unconnectedAddresses.add(address); + } + } + } + if (unconnectedAddresses && unconnectedAddresses.size != 0) { + const apiResult = await this.connectAddresses([...unconnectedAddresses]); + await this.handleApiReturn(apiResult); + } + } + + public async connectAddresses(addresses: string[]): Promise { + if (addresses.length === 0) { + throw new Error('Trying to connect to empty addresses list'); + } + + try { + return this.sdkClient.create_transaction(addresses, 1); + } catch (e) { + console.error('Failed to connect member:', e); + throw e; + } + } + + private async ensureSufficientAmount(): Promise { + const availableAmt = this.getAmount(); + const target: BigInt = DEFAULTAMOUNT * BigInt(10); + + if (availableAmt < target) { + const faucetMsg = this.createFaucetMessage(); + this.sendFaucetMessage(faucetMsg); + + await this.waitForAmount(target); + } + } + + private async waitForAmount(target: BigInt): Promise { + let attempts = 3; + + while (attempts > 0) { + const amount = this.getAmount(); + if (amount >= target) { + return amount; + } + + attempts--; + if (attempts > 0) { + await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for 1 second + } + } + + throw new Error('Amount is still 0 after 3 attempts'); + } + + public async createPairingProcess(userName: string, pairWith: string[]): Promise { + if (this.sdkClient.is_paired()) { + throw new Error('Device already paired'); + } + const myAddress: string = this.sdkClient.get_address(); + pairWith.push(myAddress); + const privateData = { + description: 'pairing', + counter: 0, + }; + const publicData = { + memberPublicName: userName, + pairedAddresses: pairWith, + }; + const validation_fields: string[] = [...Object.keys(privateData), ...Object.keys(publicData), 'roles']; + const roles: Record = { + pairing: { + members: [], + validation_rules: [ + { + quorum: 1.0, + fields: validation_fields, + min_sig_member: 1.0, + }, + ], + storages: [STORAGEURL] + }, + }; + try { + return this.createProcess( + privateData, + publicData, + roles + ); + } catch (e) { + throw new Error(`Creating process failed:, ${e}`); + } + } + + private isFileBlob(value: any): value is { type: string, data: Uint8Array } { + return ( + typeof value === 'object' && + value !== null && + typeof value.type === 'string' && + value.data instanceof Uint8Array + ); + } + + private splitData(obj: Record) { + const jsonCompatibleData: Record = {}; + const binaryData: Record = {}; + + for (const [key, value] of Object.entries(obj)) { + if (this.isFileBlob(value)) { + binaryData[key] = value; + } else { + jsonCompatibleData[key] = value; + } + } + + return { jsonCompatibleData, binaryData }; + } + + public async createProcess( + privateData: Record, + publicData: Record, + roles: Record, + ): Promise { + let relayAddress = this.getAllRelays()[0]?.spAddress; + + if (!relayAddress || relayAddress === '') { + console.log('No relay address found, connecting to relays...'); + await this.connectAllRelays(); + + // After connectAllRelays completes, relay addresses should be updated + relayAddress = this.getAllRelays()[0]?.spAddress; + if (!relayAddress || relayAddress === '') { + throw new Error('No relay address available after connecting to relays'); + } + } + + const feeRate = 1; + + // We can't encode files as the rest because Uint8Array is not valid json + // So we first take them apart and we will encode them separately and put them back in the right object + // TODO encoding of relatively large binaries (=> 1M) is a bit long now and blocking + const privateSplitData = this.splitData(privateData); + const publicSplitData = this.splitData(publicData); + const encodedPrivateData = { + ...this.sdkClient.encode_json(privateSplitData.jsonCompatibleData), + ...this.sdkClient.encode_binary(privateSplitData.binaryData) + }; + const encodedPublicData = { + ...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData), + ...this.sdkClient.encode_binary(publicSplitData.binaryData) + }; + + console.log('encoded data:', encodedPrivateData); + console.log('encoded data:', encodedPublicData); + + let members: Set = new Set(); + for (const role of Object.values(roles!)) { + for (const member of role.members) { + // Check if we know the member that matches this id + const memberAddresses = this.getAddressesForMemberId(member); + if (memberAddresses && memberAddresses.length != 0) { + members.add({ sp_addresses: memberAddresses }); + } + } + } + console.log('members:', members); + await this.checkConnections([...members]); + + const result = this.sdkClient.create_new_process ( + encodedPrivateData, + roles, + encodedPublicData, + relayAddress, + feeRate, + this.getAllMembers() + ); + + return(result); + } + + public async updateProcess(process: Process, privateData: Record, publicData: Record, roles: Record | null): Promise { + // If roles is null, we just take the last commited state roles + if (!roles) { + roles = this.getRoles(process); + } else { + // We should check that we have the right to change the roles here, or maybe it's better leave it to the wasm + console.log('Provided new roles:', JSON.stringify(roles)); + } + let members: Set = new Set(); + for (const role of Object.values(roles!)) { + for (const member of role.members) { + members.add(member) + } + } + if (members.size === 0) { + // This must be a pairing process + // Check if we have a pairedAddresses in the public data + const publicData = this.getPublicData(process); + if (!publicData || !publicData['pairedAddresses']) { + throw new Error('Not a pairing process'); + } + const decodedAddresses = this.decodeValue(publicData['pairedAddresses']); + if (decodedAddresses.length === 0) { + throw new Error('Not a pairing process'); + } + members.add({ sp_addresses: decodedAddresses }); + } + await this.checkConnections([...members]); + const privateSplitData = this.splitData(privateData); + const publicSplitData = this.splitData(publicData); + const encodedPrivateData = { + ...this.sdkClient.encode_json(privateSplitData.jsonCompatibleData), + ...this.sdkClient.encode_binary(privateSplitData.binaryData) + }; + const encodedPublicData = { + ...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData), + ...this.sdkClient.encode_binary(publicSplitData.binaryData) + }; + try { + return this.sdkClient.update_process(process, encodedPrivateData, roles, encodedPublicData, this.getAllMembers()); + } catch (e) { + throw new Error(`Failed to update process: ${e}`); + } + } + + public async createPrdUpdate(processId: string, stateId: string): Promise { + const process = await this.getProcess(processId); + if (!process) { + throw new Error('Unknown process'); + } + try { + return this.sdkClient.create_update_message(process, stateId, this.getAllMembers()); + } catch (e) { + throw new Error(`Failed to create prd update: ${e}`); + } + } + + public async createPrdResponse(processId: string, stateId: string): Promise { + const process = await this.getProcess(processId); + if (!process) { + throw new Error('Unknown process'); + } + try { + return this.sdkClient.create_response_prd(process, stateId, this.getAllMembers()); + } catch (e) { + throw new Error(`Failed to create response prd: ${e}`); + } + } + + public async approveChange(processId: string, stateId: string): Promise { + const process = await this.getProcess(processId); + if (!process) { + throw new Error('Failed to get process from db'); + } + try { + return this.sdkClient.validate_state(process, stateId, this.getAllMembers()); + } catch (e) { + throw new Error(`Failed to create prd response: ${e}`); + } + } + + public async rejectChange(processId: string, stateId: string): Promise { + const process = await this.getProcess(processId); + if (!process) { + throw new Error('Failed to get process from db'); + } + try { + return this.sdkClient.refuse_state(process, stateId); + } catch (e) { + throw new Error(`Failed to create prd response: ${e}`); + } + } + + async resetDevice() { + this.sdkClient.reset_device(); + + // Clear all stores + const db = await Database.getInstance(); + await db.clearStore('wallet'); + await db.clearStore('shared_secrets'); + await db.clearStore('unconfirmed_secrets'); + await db.clearStore('processes'); + await db.clearStore('diffs'); + } + + sendNewTxMessage(message: string) { + sendMessage('NewTx', message); + } + + sendCommitMessage(message: string) { + sendMessage('Commit', message); + } + + sendCipherMessages(ciphers: string[]) { + for (let i = 0; i < ciphers.length; i++) { + const cipher = ciphers[i]; + sendMessage('Cipher', cipher); + } + } + + sendFaucetMessage(message: string): void { + sendMessage('Faucet', message); + } + + async parseCipher(message: string) { + const membersList = this.getAllMembers(); + const processes = await this.getProcesses(); + try { + // console.log('parsing new cipher'); + const apiReturn = this.sdkClient.parse_cipher(message, membersList, processes); + await this.handleApiReturn(apiReturn); + + // Device 1 wait Device 2 + const waitingModal = document.getElementById('waiting-modal'); + if (waitingModal) { + this.device2Ready = true; + } + + } catch (e) { + console.error(`Parsed cipher with error: ${e}`); + } + // await this.saveCipherTxToDb(parsedTx) + } + + async parseNewTx(newTxMsg: string) { + const parsedMsg: NewTxMessage = JSON.parse(newTxMsg); + if (parsedMsg.error !== null) { + console.error('Received error in new tx message:', parsedMsg.error); + return; + } + + const membersList = this.getAllMembers(); + try { + // Does the transaction spend the tip of a process? + const prevouts = this.sdkClient.get_prevouts(parsedMsg.transaction); + console.log('prevouts:', prevouts); + for (const process of Object.values(this.processesCache)) { + const tip = process.states[process.states.length - 1].commited_in; + if (prevouts.includes(tip)) { + const processId = process.states[0].commited_in; + const newTip = this.sdkClient.get_txid(parsedMsg.transaction); + console.log('Transaction', newTip, 'spends the tip of process', processId); + // We take the data out of the output + const newStateId = this.sdkClient.get_opreturn(parsedMsg.transaction); + console.log('newStateId:', newStateId); + // We update the relevant process + const updatedProcess = this.sdkClient.process_commit_new_state(process, newStateId, newTip); + this.processesCache[processId] = updatedProcess; + console.log('updatedProcess:', updatedProcess); + break; + } + } + } catch (e) { + console.error('Failed to parse new tx for commitments:', e); + } + + try { + const parsedTx = this.sdkClient.parse_new_tx(newTxMsg, 0, membersList); + if (parsedTx) { + try { + await this.handleApiReturn(parsedTx); + const newDevice = this.dumpDeviceFromMemory(); + await this.saveDeviceInDatabase(newDevice); + } catch (e) { + console.error('Failed to update device with new tx'); + } + } + } catch (e) { + console.debug(e); + } + } + + public async handleApiReturn(apiReturn: ApiReturn) { + console.log(apiReturn); + if (apiReturn.partial_tx) { + try { + const res = this.sdkClient.sign_transaction(apiReturn.partial_tx); + apiReturn.new_tx_to_send = res.new_tx_to_send; + } catch (e) { + console.error('Failed to sign transaction:', e); + } + } + + if (apiReturn.new_tx_to_send && apiReturn.new_tx_to_send.transaction.length != 0) { + this.sendNewTxMessage(JSON.stringify(apiReturn.new_tx_to_send)); + await new Promise(r => setTimeout(r, 500)); + } + + if (apiReturn.secrets) { + const unconfirmedSecrets = apiReturn.secrets.unconfirmed_secrets; + const confirmedSecrets = apiReturn.secrets.shared_secrets; + + const db = await Database.getInstance(); + for (const secret of unconfirmedSecrets) { + await db.addObject({ + storeName: 'unconfirmed_secrets', + object: secret, + key: null, + }); + } + const entries = Object.entries(confirmedSecrets).map(([key, value]) => ({ key, value })); + for (const entry of entries) { + try { + await db.addObject({ + storeName: 'shared_secrets', + object: entry.value, + key: entry.key, + }); + } catch (e) { + throw e; + } + + // We don't want to throw an error, it could simply be that we registered directly the shared secret + // this.removeUnconfirmedSecret(entry.value); + } + } + + if (apiReturn.updated_process) { + const updatedProcess = apiReturn.updated_process; + + const processId: string = updatedProcess.process_id; + + if (updatedProcess.encrypted_data && Object.keys(updatedProcess.encrypted_data).length != 0) { + for (const [hash, cipher] of Object.entries(updatedProcess.encrypted_data)) { + const blob = this.hexToBlob(cipher); + try { + await this.saveBlobToDb(hash, blob); + } catch (e) { + console.error(e); + } + } + } + + // Save process to db + await this.saveProcessToDb(processId, updatedProcess.current_process); + + if (updatedProcess.diffs && updatedProcess.diffs.length != 0) { + try { + await this.saveDiffsToDb(updatedProcess.diffs); + } catch (e) { + console.error('Failed to save diffs to db:', e); + } + } + } + + if (apiReturn.push_to_storage && apiReturn.push_to_storage.length != 0) { + for (const hash of apiReturn.push_to_storage) { + const blob = await this.getBlobFromDb(hash); + if (blob) { + await this.saveDataToStorage(hash, blob, null); + } else { + console.error('Failed to get data from db'); + } + } + } + + if (apiReturn.commit_to_send) { + const commit = apiReturn.commit_to_send; + this.sendCommitMessage(JSON.stringify(commit)); + } + + if (apiReturn.ciphers_to_send && apiReturn.ciphers_to_send.length != 0) { + this.sendCipherMessages(apiReturn.ciphers_to_send); + } + } + + public async openPairingConfirmationModal(processId: string) { + const process = await this.getProcess(processId); + if (!process) { + console.error('Failed to find pairing process'); + return; + } + const firstState = process.states[0]; + const roles = firstState.roles; + const stateId = firstState.state_id; + try { + await this.routingInstance.openPairingConfirmationModal(roles, processId, stateId); + } catch (e) { + console.error(e); + } + } + + public async confirmPairing() { + if (!this.processId || !this.stateId) { + console.error('Missing process and/or state ID'); + return; + } + let createPrdUpdateReturn; + try { + createPrdUpdateReturn = await this.createPrdUpdate(this.processId, this.stateId); + } catch (e) { + throw new Error(`createPrdUpdate failed: ${e}`); + } + await this.handleApiReturn(createPrdUpdateReturn); + + let approveChangeReturn; + try { + approveChangeReturn = await this.approveChange(this.processId, this.stateId); + } catch (e) { + throw new Error(`approveChange failed: ${e}`); + } + await this.handleApiReturn(approveChangeReturn); + + await this.pairDevice(); + + this.processId = null; + this.stateId = null; + const newDevice = this.dumpDeviceFromMemory(); + await this.saveDeviceInDatabase(newDevice); + await navigate('account'); + } + + public async updateDevice(): Promise { + let myPairingProcessId: string; + try { + myPairingProcessId = this.getPairingProcessId(); + } catch (e) { + console.error('Failed to get pairing process id'); + return; + } + + const myPairingProcess = await this.getProcess(myPairingProcessId); + if (!myPairingProcess) { + console.error('Unknown pairing process'); + return; + } + const myPairingState = this.getLastCommitedState(myPairingProcess); + if (myPairingState) { + const encodedSpAddressList = myPairingState.public_data['pairedAddresses']; + const spAddressList = this.decodeValue(encodedSpAddressList); + if (spAddressList.length === 0) { + console.error('Empty pairedAddresses'); + return; + } + // We can check if our address is included and simply unpair if it's not + if (!spAddressList.includes(this.getDeviceAddress())) { + await this.unpairDevice(); + return; + } + // We can update the device with the new addresses + this.sdkClient.unpair_device(); + this.sdkClient.pair_device(myPairingProcessId, spAddressList); + const newDevice = this.dumpDeviceFromMemory(); + await this.saveDeviceInDatabase(newDevice); + } + } + + public async pairDevice() { + if (!this.processId) { + console.error('No processId set'); + return; + } + const process = await this.getProcess(this.processId); + if (!process) { + console.error('Unknown process'); + return; + } + + let spAddressList: string[] = []; + try { + let encodedSpAddressList: number[] = []; + if (this.stateId) { + const state = process.states.find(state => state.state_id === this.stateId); + if (state) { + encodedSpAddressList = state.public_data['pairedAddresses']; + } + } else { + // We assume it's the last commited state + const lastCommitedState = this.getLastCommitedState(process); + if (lastCommitedState) { + encodedSpAddressList = lastCommitedState.public_data['pairedAddresses']; + } + } + spAddressList = this.sdkClient.decode_value(encodedSpAddressList); + if (!spAddressList || spAddressList.length == 0) { + throw new Error('Empty pairedAddresses'); + } + } catch (e) { + throw new Error(`Failed to get pairedAddresses from process: ${e}`); + } + try { + this.sdkClient.pair_device(this.processId, spAddressList); + } catch (e) { + throw new Error(`Failed to pair device: ${e}`); + } + } + + public getAmount(): BigInt { + const amount = this.sdkClient.get_available_amount(); + return amount; + } + + getDeviceAddress(): string { + try { + return this.sdkClient.get_address(); + } catch (e) { + throw new Error(`Failed to get device address: ${e}`); + } + } + + public dumpDeviceFromMemory(): Device { + try { + return this.sdkClient.dump_device(); + } catch (e) { + throw new Error(`Failed to dump device: ${e}`); + } + } + + public dumpNeuteredDevice(): Device | null { + try { + return this.sdkClient.dump_neutered_device(); + } catch (e) { + console.error(`Failed to dump device: ${e}`); + return null; + } + } + + public getPairingProcessId(): string { + try { + return this.sdkClient.get_pairing_process_id(); + } catch (e) { + throw new Error(`Failed to get pairing process: ${e}`); + } + } + + async saveDeviceInDatabase(device: Device): Promise { + const db = await Database.getInstance(); + const walletStore = 'wallet'; + try { + const prevDevice = await this.getDeviceFromDatabase(); + if (prevDevice) { + await db.deleteObject(walletStore, "1"); + } + await db.addObject({ + storeName: walletStore, + object: { pre_id: '1', device }, + key: null, + }); + } catch (e) { + console.error(e); + } + } + + async getDeviceFromDatabase(): Promise { + const db = await Database.getInstance(); + const walletStore = 'wallet'; + try { + const dbRes = await db.getObject(walletStore, '1'); + if (dbRes) { + return dbRes['device']; + } else { + return null; + } + } catch (e) { + throw new Error(`Failed to retrieve device from db: ${e}`); + } + } + + async getMemberFromDevice(): Promise { + try { + const device = await this.getDeviceFromDatabase(); + if (device) { + const pairedMember = device['paired_member']; + return pairedMember.sp_addresses; + } else { + return null; + } + } catch (e) { + throw new Error(`Failed to retrieve paired_member from device: ${e}`); + } + } + + isChildRole(parent: any, child: any): boolean { + try { + this.sdkClient.is_child_role(JSON.stringify(parent), JSON.stringify(child)); + } catch (e) { + console.error(e); + return false; + } + + return true; + } + + rolesContainsUs(roles: Record): boolean { + let us; + try { + us = this.sdkClient.get_pairing_process_id(); + } catch (e) { + throw e; + } + + return this.rolesContainsMember(roles, us); + } + + rolesContainsMember(roles: Record, pairingProcessId: string): boolean { + for (const roleDef of Object.values(roles)) { + if (roleDef.members.includes(pairingProcessId)) { + return true; + } + } + + return false; + } + + async dumpWallet() { + const wallet = await this.sdkClient.dump_wallet(); + return wallet; + } + + public createFaucetMessage() { + const message = this.sdkClient.create_faucet_msg(); + return message; + } + + async createNewDevice() { + let spAddress = ''; + try { + // We set birthday later when we have the chain tip from relay + spAddress = await this.sdkClient.create_new_device(0, 'signet'); + const device = this.dumpDeviceFromMemory(); + await this.saveDeviceInDatabase(device); + } catch (e) { + console.error('Services ~ Error:', e); + } + + return spAddress; + } + + public restoreDevice(device: Device) { + try { + this.sdkClient.restore_device(device); + } catch (e) { + console.error(e); + } + } + + public async updateDeviceBlockHeight(): Promise { + if (this.currentBlockHeight === -1) { + throw new Error('Current block height not set'); + } + + let device: Device | null = null; + try { + device = await this.getDeviceFromDatabase(); + } catch (e) { + throw new Error(`Failed to get device from database: ${e}`); + } + + if (!device) { + throw new Error('Device not found'); + } + + const birthday = device.sp_wallet.birthday; + if (birthday === undefined || birthday === null) { + throw new Error('Birthday not found'); + } + + if (birthday === 0) { + // This is a new device, so current chain tip is its birthday + device.sp_wallet.birthday = this.currentBlockHeight; + // We also set last_scan, impossible that we need to scan earlier than this + device.sp_wallet.last_scan = this.currentBlockHeight; + try { + // First set the updated device in memory + this.sdkClient.restore_device(device); + // Then save it to database + await this.saveDeviceInDatabase(device); + } catch (e) { + throw new Error(`Failed to save updated device: ${e}`); + } + } else { + // This is existing device, we need to catch up if last_scan is lagging behind chain_tip + if (device.sp_wallet.last_scan < this.currentBlockHeight) { + // We need to catch up + await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); + } else { + // Up to date, just returns + return; + } + } + } + + private async removeProcess(processId: string): Promise { + const db = await Database.getInstance(); + const storeName = 'processes'; + + try { + await db.deleteObject(storeName, processId); + } catch (e) { + console.error(e); + } + } + + public async batchSaveProcessesToDb(processes: Record) { + if (Object.keys(processes).length === 0) { + return; + } + + const db = await Database.getInstance(); + const storeName = 'processes'; + try { + await db.batchWriting({ storeName, objects: Object.entries(processes).map(([key, value]) => ({ key, object: value })) }); + this.processesCache = { ...this.processesCache, ...processes }; + } catch (e) { + throw e; + } + } + + public async saveProcessToDb(processId: string, process: Process) { + const db = await Database.getInstance(); + const storeName = 'processes'; + try { + await db.addObject({ + storeName, + object: process, + key: processId, + }); + + // Update the process in the cache + this.processesCache[processId] = process; + } catch (e) { + console.error(`Failed to save process ${processId}: ${e}`); + } + } + + public async saveBlobToDb(hash: string, data: Blob) { + const db = await Database.getInstance(); + try { + await db.addObject({ + storeName: 'data', + object: data, + key: hash, + }); + } catch (e) { + console.error(`Failed to save data to db: ${e}`); + } + } + + public async getBlobFromDb(hash: string): Promise { + const db = await Database.getInstance(); + try { + return await db.getObject('data', hash); + } catch (e) { + return null; + } + } + + public async saveDataToStorage(hash: string, data: Blob, ttl: number | null) { + const storages = [STORAGEURL]; + + try { + await storeData(storages, hash, data, ttl); + } catch (e) { + console.error(`Failed to store data with hash ${hash}: ${e}`); + } + } + + public async fetchValueFromStorage(hash: string): Promise { + const storages = [STORAGEURL]; + + return await retrieveData(storages, hash); + } + + public async testDataInStorage(hash: string): Promise | null> { + const storages = [STORAGEURL]; + + return await testData(storages, hash); + } + + public async saveDiffsToDb(diffs: UserDiff[]) { + const db = await Database.getInstance(); + try { + for (const diff of diffs) { + await db.addObject({ + storeName: 'diffs', + object: diff, + key: null, + }); + } + } catch (e) { + throw new Error(`Failed to save process: ${e}`); + } + } + + public async getProcess(processId: string): Promise { + if (this.processesCache[processId]) { + return this.processesCache[processId]; + } else { + const db = await Database.getInstance(); + const process = await db.getObject('processes', processId); + return process; + } + } + + public async getProcesses(): Promise> { + if (Object.keys(this.processesCache).length > 0) { + return this.processesCache; + } else { + try { + const db = await Database.getInstance(); + this.processesCache = await db.dumpStore('processes'); + return this.processesCache; + } catch (e) { + throw e; + } + } + } + + public async restoreProcessesFromBackUp(processes: Record) { + const db = await Database.getInstance(); + const storeName = 'processes'; + try { + await db.batchWriting({ storeName, objects: Object.entries(processes).map(([key, value]) => ({ key, object: value })) }); + } catch (e) { + throw e; + } + + await this.restoreProcessesFromDB(); + } + + // Restore processes cache from persistent storage + public async restoreProcessesFromDB() { + const db = await Database.getInstance(); + try { + const processes: Record = await db.dumpStore('processes'); + if (processes && Object.keys(processes).length != 0) { + console.log(`Restoring ${Object.keys(processes).length} processes`); + this.processesCache = processes; + } else { + console.log('No processes to restore!'); + } + } catch (e) { + throw e; + } + } + + public async clearSecretsFromDB() { + const db = await Database.getInstance(); + try { + await db.clearStore('shared_secrets'); + await db.clearStore('unconfirmed_secrets'); + } catch (e) { + console.error(e); + } + } + + public async restoreSecretsFromBackUp(secretsStore: SecretsStore) { + const db = await Database.getInstance(); + + for (const secret of secretsStore.unconfirmed_secrets) { + await db.addObject({ + storeName: 'unconfirmed_secrets', + object: secret, + key: null, + }); + } + const entries = Object.entries(secretsStore.shared_secrets).map(([key, value]) => ({ key, value })); + for (const entry of entries) { + await db.addObject({ + storeName: 'shared_secrets', + object: entry.value, + key: entry.key, + }); + } + + // Now we can transfer them to memory + await this.restoreSecretsFromDB(); + } + + public async restoreSecretsFromDB() { + const db = await Database.getInstance(); + try { + const sharedSecrets: Record = await db.dumpStore('shared_secrets'); + const unconfirmedSecrets = await db.dumpStore('unconfirmed_secrets'); + const secretsStore = { + shared_secrets: sharedSecrets, + unconfirmed_secrets: Object.values(unconfirmedSecrets), + }; + this.sdkClient.set_shared_secrets(JSON.stringify(secretsStore)); + } catch (e) { + throw e; + } + } + + decodeValue(value: number[]): any | null { + try { + return this.sdkClient.decode_value(value); + } catch (e) { + console.error(`Failed to decode value: ${e}`); + return null; + } + } + + async decryptAttribute(processId: string, state: ProcessState, attribute: string): Promise { + let hash = state.pcd_commitment[attribute]; + if (!hash) { + // attribute doesn't exist + return null; + } + let key = state.keys[attribute]; + const pairingProcessId = this.getPairingProcessId(); + + // If key is missing, request an update and then retry + if (!key) { + const roles = state.roles; + let hasAccess = false; + // If we're not supposed to have access to this attribute, ignore + for (const role of Object.values(roles)) { + for (const rule of Object.values(role.validation_rules) as any[]) { + if (rule.fields.includes(attribute)) { + if (role.members.includes(pairingProcessId)) { + // We have access to this attribute + hasAccess = true; + break; + } + } + } + } + + if (!hasAccess) return null; + + // We should have the key, so we're going to ask other members for it + await this.requestDataFromPeers(processId, [state.state_id], [state.roles]); + + const maxRetries = 5; + const retryDelay = 500; // delay in milliseconds + let retries = 0; + + while ((!hash || !key) && retries < maxRetries) { + await new Promise(resolve => setTimeout(resolve, retryDelay)); + // Re-read hash and key after waiting + hash = state.pcd_commitment[attribute]; + key = state.keys[attribute]; + retries++; + } + } + + if (hash && key) { + const blob = await this.getBlobFromDb(hash); + if (blob) { + // Decrypt the data + const buf = await blob.arrayBuffer(); + const cipher = new Uint8Array(buf); + + const keyUIntArray = this.hexToUInt8Array(key); + + try { + const clear = this.sdkClient.decrypt_data(keyUIntArray, cipher); + if (clear) { + // deserialize the result to get the actual data + const decoded = this.sdkClient.decode_value(clear); + return decoded; + } else { + throw new Error('decrypt_data returned null'); + } + } catch (e) { + console.error(`Failed to decrypt data: ${e}`); + } + } + } + + return null; + } + + getNotifications(): any[] | null { + // return [ + // { + // id: 1, + // title: 'Notif 1', + // description: 'A normal notification', + // sendToNotificationPage: false, + // path: '/notif1', + // }, + // { + // id: 2, + // title: 'Notif 2', + // description: 'A normal notification', + // sendToNotificationPage: false, + // path: '/notif2', + // }, + // { + // id: 3, + // title: 'Notif 3', + // description: 'A normal notification', + // sendToNotificationPage: false, + // path: '/notif3', + // }, + // ]; + return this.notifications; + } + + setNotifications(notifications: any[]) { + this.notifications = notifications; + } + + async importJSON(backup: BackUp): Promise { + const device = backup.device; + + // Reset current device + await this.resetDevice(); + + await this.saveDeviceInDatabase(device); + + this.restoreDevice(device); + + // TODO restore secrets and processes from file + const secretsStore = backup.secrets; + await this.restoreSecretsFromBackUp(secretsStore); + + const processes = backup.processes; + await this.restoreProcessesFromBackUp(processes); + } + + public async createBackUp(): Promise { + // Get the device from indexedDB + const device = await this.getDeviceFromDatabase(); + if (!device) { + console.error('No device loaded'); + return null; + } + + // Get the processes + const processes = await this.getProcesses(); + + // Get the shared secrets + const secrets = await this.getAllSecrets(); + + // Create a backup object + const backUp = { + device: device, + secrets: secrets, + processes: processes, + }; + + return backUp; + } + + // Device 1 wait Device 2 + public device1: boolean = false; + public device2Ready: boolean = false; + + public resetState() { + this.device1 = false; + this.device2Ready = false; + } + + + // Handle the handshake message + public async handleHandshakeMsg(url: string, parsedMsg: any) { + try { + const handshakeMsg: HandshakeMessage = JSON.parse(parsedMsg); + this.updateRelay(url, handshakeMsg.sp_address); + this.currentBlockHeight = handshakeMsg.chain_tip; + if (this.membersList && Object.keys(this.membersList).length === 0) { + // We start from an empty list, just copy it over + this.membersList = handshakeMsg.peers_list; + } else { + // We are incrementing our list + for (const [processId, member] of Object.entries(handshakeMsg.peers_list)) { + this.membersList[processId] = member as Member; + } + } + + setTimeout(async () => { + const newProcesses: OutPointProcessMap = handshakeMsg.processes_list; + if (!newProcesses || Object.keys(newProcesses).length === 0) { + console.debug('Received empty processes list from', url); + return; + } + + if (this.processesCache && Object.keys(this.processesCache).length === 0) { + // We restored db but cache is empty, meaning we're starting from scratch + try { + await this.batchSaveProcessesToDb(newProcesses); + } catch (e) { + console.error('Failed to save processes to db:', e); + } + } else { + // We need to update our processes with what relay provides + const toSave: Record = {}; + for (const [processId, process] of Object.entries(newProcesses)) { + const existing = await this.getProcess(processId); + if (existing) { + // Look for state id we don't know yet + let new_states: string[] = []; + let roles: Record[] = []; + for (const state of process.states) { + if (!state.state_id || state.state_id === EMPTY32BYTES) { continue; } + if (!this.lookForStateId(existing, state.state_id)) { + if (this.rolesContainsUs(state.roles)) { + new_states.push(state.state_id); + roles.push(state.roles); + } + } + } + + if (new_states.length != 0) { + // We request the new states + await this.requestDataFromPeers(processId, new_states, roles); + toSave[processId] = process; + } + + // Just to be sure check if that's a pairing process + const lastCommitedState = this.getLastCommitedState(process); + if (lastCommitedState && lastCommitedState.public_data && lastCommitedState.public_data['pairedAddresses']) { + // This is a pairing process + try { + const pairedAddresses = this.decodeValue(lastCommitedState.public_data['pairedAddresses']); + // Are we part of it? + if (pairedAddresses && pairedAddresses.length > 0 && pairedAddresses.includes(this.getDeviceAddress())) { + // We save the process to db + await this.saveProcessToDb(processId, process as Process); + // We update the device + await this.updateDevice(); + } + } catch (e) { + console.error('Failed to check for pairing process:', e); + } + } + + // Otherwise we're probably just in the initial loading at page initialization + + // We may learn an update for this process + // TODO maybe actually check if what the relay is sending us contains more information than what we have + // relay should always have more info than us, but we never know + // For now let's keep it simple and let the worker do the job + } else { + // We add it to db + console.log(`Saving ${processId} to db`); + toSave[processId] = process; + } + } + + await this.batchSaveProcessesToDb(toSave); + } + }, 500) + } catch (e) { + console.error('Failed to parse init message:', e); + } + } + + private lookForStateId(process: Process, stateId: string): boolean { + for (const state of process.states) { + if (state.state_id === stateId) { + return true; + } + } + + return false; + } + + /** + * 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 async waitForHandshakeMessage(timeoutMs: number = 10000): Promise { + const startTime = Date.now(); + const pollInterval = 100; // Check every 100ms + + return new Promise((resolve, reject) => { + const checkForHandshake = () => { + // Check if we have any members (indicating handshake was received) + if (Object.keys(this.membersList).length > 0) { + console.log('Handshake message received, members list populated'); + resolve(); + return; + } + + // Check timeout + if (Date.now() - startTime >= timeoutMs) { + reject(new Error(`No handshake message received after ${timeoutMs}ms timeout`)); + return; + } + + // Continue polling + setTimeout(checkForHandshake, pollInterval); + }; + + checkForHandshake(); + }); + } + + /** + * Retourne la liste de tous les membres ordonnés par leur process id + * @returns Un tableau contenant tous les membres + */ + public getAllMembersSorted(): Record { + return Object.fromEntries( + Object.entries(this.membersList).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)) + ); + } + + public getAllMembers(): Record { + return this.membersList; + } + + public getAddressesForMemberId(memberId: string): string[] | null { + try { + return this.membersList[memberId].sp_addresses; + } catch (e) { + return null; + } + } + + public compareMembers(memberA: string[], memberB: string[]): boolean { + if (!memberA || !memberB) { return false } + if (memberA.length !== memberB.length) { return false } + + const res = memberA.every(item => memberB.includes(item)) && memberB.every(item => memberA.includes(item)); + + return res; + } + + public async handleCommitError(response: string) { + const content = JSON.parse(response); + const error = content.error; + const errorMsg = error['GenericError']; + const dontRetry = [ + 'State is identical to the previous state', + 'Not enough valid proofs', + 'Not enough members to validate', + ]; + if (dontRetry.includes(errorMsg)) { return; } + // Wait and retry + setTimeout(async () => { + this.sendCommitMessage(JSON.stringify(content)); + }, 1000) + } + + public getRoles(process: Process): Record | null { + const lastCommitedState = this.getLastCommitedState(process); + if (lastCommitedState && lastCommitedState.roles && Object.keys(lastCommitedState.roles).length != 0) { + return lastCommitedState!.roles; + } else if (process.states.length === 2) { + const firstState = process.states[0]; + if (firstState && firstState.roles && Object.keys(firstState.roles).length != 0) { + return firstState!.roles; + } + } + return null; + } + + public getPublicData(process: Process): Record | null { + const lastCommitedState = this.getLastCommitedState(process); + if (lastCommitedState && lastCommitedState.public_data && Object.keys(lastCommitedState.public_data).length != 0) { + return lastCommitedState!.public_data; + } else if (process.states.length === 2) { + const firstState = process.states[0]; + if (firstState && firstState.public_data && Object.keys(firstState.public_data).length != 0) { + return firstState!.public_data; + } + } + return null; + } + + public getProcessName(process: Process): string | null { + const lastCommitedState = this.getLastCommitedState(process); + if (lastCommitedState && lastCommitedState.public_data) { + const processName = lastCommitedState!.public_data['processName']; + if (processName) { return this.decodeValue(processName) } + else { return null } + } else { + return null; + } + } + + public async getMyProcesses(): Promise { + // If we're not paired yet, just skip it + let pairingProcessId = null; + try { + pairingProcessId = this.getPairingProcessId(); + } catch (e) { + return null; + } + if (!pairingProcessId) { + return null; + } + + try { + const processes = await this.getProcesses(); + + const newMyProcesses = new Set(this.myProcesses || []); + // MyProcesses automatically contains pairing process + newMyProcesses.add(pairingProcessId); + for (const [processId, process] of Object.entries(processes)) { + // We use myProcesses attribute to not reevaluate all processes everytime + if (newMyProcesses.has(processId)) { + continue; + } + try { + const roles = this.getRoles(process); + + if (roles && this.rolesContainsUs(roles)) { + newMyProcesses.add(processId); + } + } catch (e) { + console.error(e); + } + } + this.myProcesses = newMyProcesses; // atomic update + return Array.from(this.myProcesses); + } catch (e) { + console.error("Failed to get processes:", e); + return null; + } + } + + public async requestDataFromPeers(processId: string, stateIds: string[], roles: Record[]) { + console.log('Requesting data from peers'); + const membersList = this.getAllMembers(); + try { + const res = this.sdkClient.request_data(processId, stateIds, roles, membersList); + await this.handleApiReturn(res); + } catch (e) { + console.error(e); + } + } + + public hexToBlob(hexString: string): Blob { + const uint8Array = this.hexToUInt8Array(hexString); + + return new Blob([uint8Array.buffer], { type: "application/octet-stream" }); + } + + public hexToUInt8Array(hexString: string): Uint8Array { + if (hexString.length % 2 !== 0) { + throw new Error("Invalid hex string: length must be even"); + } + const uint8Array = new Uint8Array(hexString.length / 2); + for (let i = 0; i < hexString.length; i += 2) { + uint8Array[i / 2] = parseInt(hexString.substr(i, 2), 16); + } + + return uint8Array; + } + + public async blobToHex(blob: Blob): Promise { + const buffer = await blob.arrayBuffer(); + const bytes = new Uint8Array(buffer); + return Array.from(bytes) + .map(byte => byte.toString(16).padStart(2, '0')) + .join(''); + } + + public getHashForFile(commitedIn: string, label: string, fileBlob: { type: string; data: Uint8Array }): string { + return this.sdkClient.hash_value(fileBlob, commitedIn, label); + } + + public getMerkleProofForFile(processState: ProcessState, attributeName: string): MerkleProofResult { + return this.sdkClient.get_merkle_proof(processState, attributeName); + } + + public validateMerkleProof(proof: MerkleProofResult, hash: string): boolean { + try { + return this.sdkClient.validate_merkle_proof(proof, hash); + } catch (e) { + throw new Error(`Failed to validate merkle proof: ${e}`); + } + } + + public getLastCommitedState(process: Process): ProcessState | null { + if (process.states.length === 0) return null; + const processTip = process.states[process.states.length - 1].commited_in; + const lastCommitedState = process.states.findLast((state: ProcessState) => state.commited_in !== processTip); + if (lastCommitedState) { + return lastCommitedState; + } else { + return null; + } + } + + public getLastCommitedStateIndex(process: Process): number | null { + if (process.states.length === 0) return null; + const processTip = process.states[process.states.length - 1].commited_in; + for (let i = process.states.length - 1; i >= 0; i--) { + if (process.states[i].commited_in !== processTip) { + return i; + } + } + return null; + } + + public getUncommitedStates(process: Process): ProcessState[] { + if (process.states.length === 0) return []; + const processTip = process.states[process.states.length - 1].commited_in; + const res = process.states.filter((state: ProcessState) => state.commited_in === processTip); + return res.filter((state: ProcessState) => state.state_id !== EMPTY32BYTES); + } + + public getStateFromId(process: Process, stateId: string): ProcessState | null { + if (process.states.length === 0) return null; + const state = process.states.find((state: ProcessState) => state.state_id === stateId); + if (state) { + return state; + } else { + return null; + } + } + + public getNextStateAfterId(process: Process, stateId: string): ProcessState | null { + if (process.states.length === 0) return null; + + const index = process.states.findIndex((state: ProcessState) => state.state_id === stateId); + + if (index !== -1 && index < process.states.length - 1) { + return process.states[index + 1]; + } + + return null; + } + + public isPairingProcess(roles: Record): boolean { + if (Object.keys(roles).length != 1) { return false } + const pairingRole = roles['pairing']; + if (pairingRole) { + // For now that's enough, we should probably test more things + return true; + } else { + return false; + } + } + + public async updateMemberPublicName(process: Process, newName: string): Promise { + const publicData = { + 'memberPublicName': newName + }; + + return await this.updateProcess(process, {}, publicData, null); + } +} diff --git a/ihm_client/src/services/storage.service.ts b/ihm_client/src/services/storage.service.ts new file mode 100644 index 00000000..47ee776d --- /dev/null +++ b/ihm_client/src/services/storage.service.ts @@ -0,0 +1,81 @@ +import axios, { AxiosResponse } from 'axios'; + +export async function storeData(servers: string[], key: string, value: Blob, ttl: number | null): Promise { + for (const server of servers) { + try { + // Append key and ttl as query parameters + const url = new URL(`${server}/store`); + url.searchParams.append('key', key); + if (ttl !== null) { + url.searchParams.append('ttl', ttl.toString()); + } + + // Send the encrypted ArrayBuffer as the raw request body. + const response = await axios.post(url.toString(), value, { + headers: { + 'Content-Type': 'application/octet-stream' + }, + }); + console.log('Data stored successfully:', key); + if (response.status !== 200) { + console.error('Received response status', response.status); + continue; + } + return response; + } catch (error) { + if (axios.isAxiosError(error) && error.response?.status === 409) { + return null; + } + console.error('Error storing data:', error); + } + } + return null; +} + +export async function retrieveData(servers: string[], key: string): Promise { + for (const server of servers) { + try { + // When fetching the data from the server: + const response = await axios.get(`${server}/retrieve/${key}`, { + responseType: 'arraybuffer' + }); + if (response.status !== 200) { + console.error('Received response status', response.status); + continue; + } + // console.log('Retrieved data:', response.data); + return response.data; + } catch (error) { + console.error('Error retrieving data:', error); + } + } + return null +} + +interface TestResponse { + key: string; + value: boolean; +} + +export async function testData(servers: string[], key: string): Promise | null> { + const res: Record = {}; + for (const server of servers) { + res[server] = null; + try { + const response = await axios.get(`${server}/test/${key}`); + if (response.status !== 200) { + console.error(`${server}: Test response status: ${response.status}`); + continue; + } + + const data: TestResponse = response.data; + + res[server] = data.value; + } catch (error) { + console.error('Error retrieving data:', error); + return null; + } + } + + return res; +} diff --git a/ihm_client/src/services/token.ts b/ihm_client/src/services/token.ts new file mode 100644 index 00000000..6c7a4d91 --- /dev/null +++ b/ihm_client/src/services/token.ts @@ -0,0 +1,87 @@ +import * as jose from 'jose'; + +interface TokenPair { + accessToken: string; + refreshToken: string; +} + +export default class TokenService { + private static instance: TokenService; + private readonly SECRET_KEY = import.meta.env.VITE_JWT_SECRET_KEY; + private readonly ACCESS_TOKEN_EXPIRATION = '30s'; + private readonly REFRESH_TOKEN_EXPIRATION = '7d'; + private readonly encoder = new TextEncoder(); + + private constructor() {} + + static async getInstance(): Promise { + if (!TokenService.instance) { + TokenService.instance = new TokenService(); + } + return TokenService.instance; + } + + async generateSessionToken(origin: string): Promise { + const secret = new Uint8Array(this.encoder.encode(this.SECRET_KEY)); + + const accessToken = await new jose.SignJWT({ origin, type: 'access' }) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime(this.ACCESS_TOKEN_EXPIRATION) + .sign(secret); + + const refreshToken = await new jose.SignJWT({ origin, type: 'refresh' }) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime(this.REFRESH_TOKEN_EXPIRATION) + .sign(secret); + + return { accessToken, refreshToken }; + } + + async validateToken(token: string, origin: string): Promise { + try { + const secret = new Uint8Array(this.encoder.encode(this.SECRET_KEY)); + const { payload } = await jose.jwtVerify(token, secret); + + return payload.origin === origin; + } catch (error: any) { + if (error?.code === 'ERR_JWT_EXPIRED') { + console.log('Token expiré'); + return false; + } + + console.error('Erreur de validation du token:', error); + return false; + } + } + + async refreshAccessToken(refreshToken: string, origin: string): Promise { + try { + // Vérifier si le refresh token est valide + const isValid = await this.validateToken(refreshToken, origin); + if (!isValid) { + return null; + } + + // Vérifier le type du token + const secret = new Uint8Array(this.encoder.encode(this.SECRET_KEY)); + const { payload } = await jose.jwtVerify(refreshToken, secret); + if (payload.type !== 'refresh') { + return null; + } + + // Générer un nouveau access token + const newAccessToken = await new jose.SignJWT({ origin, type: 'access' }) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime(this.ACCESS_TOKEN_EXPIRATION) + .sign(secret); + + return newAccessToken; + } catch (error) { + console.error('Erreur lors du refresh du token:', error); + return null; + } + } +} \ No newline at end of file diff --git a/ihm_client/src/types/raw-imports.d.ts b/ihm_client/src/types/raw-imports.d.ts new file mode 100644 index 00000000..039dd274 --- /dev/null +++ b/ihm_client/src/types/raw-imports.d.ts @@ -0,0 +1,35 @@ +// Déclarations pour les imports de fichiers raw +declare module '*.html?raw' { + const content: string; + export default content; +} + +declare module '*.css?raw' { + const content: string; + export default content; +} + +declare module '*.css?inline' { + const content: string; + export default content; +} + +declare module '*.js?raw' { + const content: string; + export default content; +} + +declare module '*.ts?raw' { + const content: string; + export default content; +} + +// Déclaration pour import.meta.env +interface ImportMetaEnv { + readonly VITE_JWT_SECRET_KEY: string; + // Ajoutez d'autres variables d'environnement si nécessaire +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/ihm_client/src/types/sdk_client.d.ts b/ihm_client/src/types/sdk_client.d.ts new file mode 100644 index 00000000..c817cbdc --- /dev/null +++ b/ihm_client/src/types/sdk_client.d.ts @@ -0,0 +1,258 @@ +// Types TypeScript pour sdk_client basé sur l'API Rust +// Ce fichier définit les interfaces TypeScript correspondant aux types Rust exportés par wasm-bindgen + +declare module 'pkg/sdk_client' { + // Types de base + export type DiffStatus = "None" | "Rejected" | "Validated"; + export type AnkFlag = "NewTx" | "Faucet" | "Cipher" | "Commit" | "Handshake" | "Sync" | "Unknown"; + export type PrdType = "None" | "Connect" | "Message" | "Update" | "List" | "Response" | "Confirm" | "TxProposal" | "Request"; + export type SyncType = "StateSync" | "ProcessSync" | "MemberSync" | "TxSync" | "BlockSync" | "PeerSync" | "RelaySync" | "HealthSync" | "MetricsSync" | "ConfigSync" | "CapabilitySync"; + export type HealthStatus = "Healthy" | "Warning" | "Critical" | "Offline"; + export type OutPoint = string; + export type SilentPaymentAddress = string; + export type AnkSharedSecretHash = string; + export type OutPointProcessMap = Record; + export type OutPointMemberMap = Record; + export type TsUnsignedTransaction = any; // SilentPaymentUnsignedTransaction + export type PcdCommitments = Record; + export type Pcd = Record; + export type Roles = Record; + // Types de base + export interface Device { + sp_wallet: SpWallet; + pairing_process_commitment: OutPoint | null; + paired_member: Member; + } + + export interface SpWallet { + // Structure simplifiée pour SpWallet + [key: string]: any; + } + + export interface Member { + sp_addresses: string[]; + } + + export interface Process { + states: ProcessState[]; + } + + export interface ProcessState { + commited_in: OutPoint; + pcd_commitment: Record; + state_id: string; + keys: Record; + validation_tokens: Proof[]; + public_data: Pcd; + roles: Record; + } + + export interface RoleDefinition { + members: OutPoint[]; + validation_rules: ValidationRule[]; + storages: string[]; + } + + export interface ValidationRule { + quorum: number; + fields: string[]; + min_sig_member: number; + } + + export interface SecretsStore { + shared_secrets: Record; + unconfirmed_secrets: AnkSharedSecretHash[]; + } + + export interface MerkleProofResult { + proof: string; + root: string; + attribute: string; + attribute_index: number; + total_leaves_count: number; + } + + export interface encryptWithNewKeyResult { + cipher: string; + key: string; + } + + export interface UserDiff { + process_id: string; + state_id: string; + value_commitment: string; + field: string; + roles: Roles; + description: string | null; + notify_user: boolean; + need_validation: boolean; + validation_status: DiffStatus; + } + + export interface UpdatedProcess { + process_id: OutPoint; + current_process: Process; + diffs: UserDiff[]; + encrypted_data: Record; + validated_state: number[] | null; + } + + export interface ApiReturn { + secrets: SecretsStore | null; + updated_process: UpdatedProcess | null; + new_tx_to_send: NewTxMessage | null; + ciphers_to_send: string[]; + commit_to_send: CommitMessage | null; + push_to_storage: string[]; + partial_tx: TsUnsignedTransaction | null; + } + + export interface NewTxMessage { + transaction: string; + tweak_data: string | null; + error: AnkError | null; + } + + export interface CommitMessage { + process_id: OutPoint; + pcd_commitment: PcdCommitments; + roles: Roles; + public_data: Pcd; + validation_tokens: Proof[]; + error: AnkError | null; + } + + export interface HandshakeMessage { + sp_address: string; + peers_list: OutPointMemberMap; + processes_list: OutPointProcessMap; + chain_tip: number; + } + + export interface FaucetMessage { + sp_address: string; + commitment: string; + error: AnkError | null; + } + + export interface Prd { + prd_type: PrdType; + process_id: OutPoint; + sender: Member; + keys: Record; + pcd_commitments: PcdCommitments; + validation_tokens: Proof[]; + roles: Roles; + public_data: Pcd; + payload: string; + proof: Proof | null; + } + + export interface AnkError { + // Structure simplifiée pour AnkError + [key: string]: any; + } + + export interface Proof { + // Structure simplifiée pour Proof + [key: string]: any; + } + + // Fonctions exportées par wasm-bindgen + export function setup(): void; + export function get_address(): string; + export function get_member(): Member; + export function restore_device(device: Device): void; + export function create_device_from_sp_wallet(sp_wallet: string): string; + export function create_new_device(birthday: number, network_str: string): string; + export function is_paired(): boolean; + export function pair_device(process_id: string, sp_addresses: string[]): void; + export function unpair_device(): void; + export function dump_wallet(): string; + export function reset_process_cache(): void; + export function dump_process_cache(): string; + export function set_process_cache(processes: any): void; + export function add_to_process_cache(process_id: string, process: string): void; + export function reset_shared_secrets(): void; + export function set_shared_secrets(secrets: string): void; + export function get_pairing_process_id(): string; + export function dump_device(): Device; + export function dump_neutered_device(): Device; + export function reset_device(): void; + export function get_txid(transaction: string): string; + export function parse_new_tx(new_tx_msg: string, block_height: number, members_list: OutPointMemberMap): ApiReturn; + export function parse_cipher(cipher_msg: string, members_list: OutPointMemberMap): ApiReturn; + export function get_outputs(): any; + export function get_available_amount(): bigint; + export function create_transaction(addresses: string[], fee_rate: number): ApiReturn; + export function sign_transaction(partial_tx: TsUnsignedTransaction): ApiReturn; + export function create_new_process( + private_data: Pcd, + roles: Roles, + public_data: Pcd, + relay_address: string, + fee_rate: number, + members_list: OutPointMemberMap + ): ApiReturn; + export function update_process( + process: Process, + new_attributes: Pcd, + roles: Roles, + new_public_data: Pcd, + members_list: OutPointMemberMap + ): ApiReturn; + export function request_data( + process_id: string, + state_ids_str: string[], + roles: any, + members_list: OutPointMemberMap + ): ApiReturn; + export function create_update_message( + process: Process, + state_id: string, + members_list: OutPointMemberMap + ): ApiReturn; + export function validate_state( + process: Process, + state_id: string, + members_list: OutPointMemberMap + ): ApiReturn; + export function refuse_state( + process: Process, + state_id: string, + members_list: OutPointMemberMap + ): ApiReturn; + export function evaluate_state( + process: Process, + state_id: string, + members_list: OutPointMemberMap + ): ApiReturn; + export function create_response_prd( + process: Process, + state_id: string, + members_list: OutPointMemberMap + ): ApiReturn; + export function create_faucet_msg(): string; + export function get_storages(process_outpoint: string): string[]; + export function is_child_role(parent_roles: string, child_roles: string): void; + export function decrypt_data(key: Uint8Array, data: Uint8Array): Uint8Array; + export function encode_binary(data: any): Pcd; + export function encode_json(json_data: any): Pcd; + export function decode_value(value: Uint8Array): any; + export function hash_value(value: any, commited_in: string, label: string): string; + export function get_merkle_proof(process_state: ProcessState, attribute_name: string): MerkleProofResult; + export function validate_merkle_proof(proof_result: MerkleProofResult, hash: string): boolean; +} + +// Types pour les imports relatifs +declare module '../../../pkg/sdk_client' { + export * from 'pkg/sdk_client'; +} + +declare module '../../pkg/sdk_client' { + export * from 'pkg/sdk_client'; +} + +declare module '../pkg/sdk_client' { + export * from 'pkg/sdk_client'; +} diff --git a/ihm_client/src/utils/document.utils.ts b/ihm_client/src/utils/document.utils.ts new file mode 100644 index 00000000..f8dab371 --- /dev/null +++ b/ihm_client/src/utils/document.utils.ts @@ -0,0 +1,4 @@ +export function getCorrectDOM(componentTag: string): Node { + const dom = document?.querySelector(componentTag)?.shadowRoot || (document as Node); + return dom; +} diff --git a/ihm_client/src/utils/html.utils.ts b/ihm_client/src/utils/html.utils.ts new file mode 100755 index 00000000..1a114eb1 --- /dev/null +++ b/ihm_client/src/utils/html.utils.ts @@ -0,0 +1,8 @@ +export function interpolate(template: string, data: { [key: string]: string }) { + return template.replace(/{{(.*?)}}/g, (_, key) => data[key.trim()]); +} + +export function getCorrectDOM(componentTag: string): Node { + const dom = document?.querySelector(componentTag)?.shadowRoot || (document as Node); + return dom; +} diff --git a/ihm_client/src/utils/messageMock.ts b/ihm_client/src/utils/messageMock.ts new file mode 100755 index 00000000..cae381f4 --- /dev/null +++ b/ihm_client/src/utils/messageMock.ts @@ -0,0 +1,53 @@ +import { messagesMock as initialMessagesMock } from '../mocks/mock-signature/messagesMock.js'; + +// Store singleton for messages +class MessageStore { + private readonly STORAGE_KEY = 'chat_messages'; + private messages: any[] = []; + + constructor() { + this.messages = this.loadFromLocalStorage() || []; + } + + private loadFromLocalStorage() { + try { + const stored = localStorage.getItem(this.STORAGE_KEY); + return stored ? JSON.parse(stored) : null; + } catch (error) { + console.error('Error loading messages:', error); + return null; + } + } + + getMessages() { + return this.messages; + } + + setMessages(messages: any[]) { + this.messages = messages; + this.saveToLocalStorage(); + } + + private saveToLocalStorage() { + try { + localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.messages)); + } catch (error) { + console.error('Error saving messages:', error); + } + } + + addMessage(memberId: string | number, message: any) { + const memberMessages = this.messages.find((m) => String(m.memberId) === String(memberId)); + if (memberMessages) { + memberMessages.messages.push(message); + } else { + this.messages.push({ + memberId: String(memberId), + messages: [message], + }); + } + this.saveToLocalStorage(); + } +} + +export const messageStore = new MessageStore(); diff --git a/ihm_client/src/utils/notification.store.ts b/ihm_client/src/utils/notification.store.ts new file mode 100755 index 00000000..88c5cafb --- /dev/null +++ b/ihm_client/src/utils/notification.store.ts @@ -0,0 +1,96 @@ +interface INotification { + id: number; + title: string; + description: string; + time?: string; + memberId?: string; +} + +class NotificationStore { + private static instance: NotificationStore; + private notifications: INotification[] = []; + + private constructor() { + this.loadFromLocalStorage(); + } + + static getInstance(): NotificationStore { + if (!NotificationStore.instance) { + NotificationStore.instance = new NotificationStore(); + } + return NotificationStore.instance; + } + + addNotification(notification: INotification) { + this.notifications.push(notification); + this.saveToLocalStorage(); + this.updateUI(); + } + + removeNotification(index: number) { + this.notifications.splice(index, 1); + this.saveToLocalStorage(); + this.updateUI(); + } + + getNotifications(): INotification[] { + return this.notifications; + } + + private saveToLocalStorage() { + localStorage.setItem('notifications', JSON.stringify(this.notifications)); + } + + private loadFromLocalStorage() { + const stored = localStorage.getItem('notifications'); + if (stored) { + this.notifications = JSON.parse(stored); + } + } + + private updateUI() { + const badge = document.querySelector('.notification-badge') as HTMLElement; + const board = document.querySelector('.notification-board') as HTMLElement; + + if (badge) { + badge.textContent = this.notifications.length.toString(); + badge.style.display = this.notifications.length > 0 ? 'block' : 'none'; + } + + if (board) { + this.renderNotificationBoard(board); + } + } + + private renderNotificationBoard(board: HTMLElement) { + board.innerHTML = ''; + + if (this.notifications.length === 0) { + board.innerHTML = '
    No notifications available
    '; + return; + } + + this.notifications.forEach((notif, index) => { + const notifElement = document.createElement('div'); + notifElement.className = 'notification-item'; + notifElement.innerHTML = ` +
    ${notif.title}
    +
    ${notif.description}
    + ${notif.time ? `
    ${notif.time}
    ` : ''} + `; + notifElement.onclick = () => { + if (notif.memberId) { + window.loadMemberChat(notif.memberId); + } + this.removeNotification(index); + }; + board.appendChild(notifElement); + }); + } + + public refreshNotifications() { + this.updateUI(); + } +} + +export const notificationStore = NotificationStore.getInstance(); diff --git a/ihm_client/src/utils/service.utils.ts b/ihm_client/src/utils/service.utils.ts new file mode 100644 index 00000000..8f84400f --- /dev/null +++ b/ihm_client/src/utils/service.utils.ts @@ -0,0 +1,24 @@ +export function splitPrivateData(data: Record, privateFields: string[]): { privateData: Record, publicData: Record } { + const privateData: Record = {}; + const publicData: Record = {}; + + for (const [key, value] of Object.entries(data)) { + if (privateFields.includes(key)) { + privateData[key] = value; + } else { + publicData[key] = value; + } + } + + return { privateData, publicData }; +} + +export function isValid32ByteHex(value: string): boolean { + // Check if string is exactly 64 characters (32 bytes in hex) + if (value.length !== 64) { + return false; + } + + // Check if string only contains valid hex characters + return /^[0-9a-fA-F]{64}$/.test(value); +} diff --git a/ihm_client/src/utils/sp-address.utils.ts b/ihm_client/src/utils/sp-address.utils.ts new file mode 100755 index 00000000..3e455541 --- /dev/null +++ b/ihm_client/src/utils/sp-address.utils.ts @@ -0,0 +1,216 @@ +import Services from '../services/service'; +import { getCorrectDOM } from './html.utils'; +import { addSubscription } from './subscription.utils'; +import QRCode from 'qrcode'; + +//Copy Address +export async function copyToClipboard(fullAddress: string) { + try { + await navigator.clipboard.writeText(fullAddress); + alert('Adresse copiée dans le presse-papiers !'); + } catch (err) { + console.error('Failed to copy the address: ', err); + } +} + +//Generate emojis list +export function generateEmojiList(): string[] { + const emojiRanges = [ + [0x1f600, 0x1f64f], + [0x1f300, 0x1f5ff], + [0x1f680, 0x1f6ff], + [0x1f700, 0x1f77f], + ]; + + const emojiList: string[] = []; + for (const range of emojiRanges) { + const [start, end] = range; + for (let i = start; i <= end && emojiList.length < 256; i++) { + emojiList.push(String.fromCodePoint(i)); + } + if (emojiList.length >= 256) { + break; + } + } + + return emojiList.slice(0, 256); +} + +//Adress to emojis +export async function addressToEmoji(text: string): Promise { + //Adress to Hash + const encoder = new TextEncoder(); + const data = encoder.encode(text); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + + const hash = new Uint8Array(hashBuffer); + const bytes = hash.slice(-4); + + //Hash slice to emojis + const emojiList = generateEmojiList(); + const emojis = Array.from(bytes) + .map((byte) => emojiList[byte]) + .join(''); + return emojis; +} + +//Get emojis from other device +async function emojisPairingRequest() { + try { + const container = getCorrectDOM('login-4nk-component') as HTMLElement; + + const urlParams: URLSearchParams = new URLSearchParams(window.location.search); + const sp_adress: string | null = urlParams.get('sp_address'); + + if (!sp_adress) { + // console.error("No 'sp_adress' parameter found in the URL."); + return; + } + + const emojis = await addressToEmoji(sp_adress); + const emojiDisplay = container?.querySelector('.pairing-request'); + + if (emojiDisplay) { + emojiDisplay.textContent = '(Request from: ' + emojis + ')'; + } + } catch (err) { + console.error(err); + } +} + +// Display address emojis and other device emojis +export async function displayEmojis(text: string) { + console.log('🚀 ~ Services ~ adressToEmoji'); + try { + const container = getCorrectDOM('login-4nk-component') as HTMLElement; + const emojis = await addressToEmoji(text); + const emojiDisplay = container?.querySelector('.emoji-display'); + + if (emojiDisplay) { + emojiDisplay.textContent = emojis; + } + + emojisPairingRequest(); + + initAddressInput(); + } catch (err) { + console.error(err); + } +} + +// Verify Other address +export function initAddressInput() { + const container = getCorrectDOM('login-4nk-component') as HTMLElement + const addressInput = container.querySelector('#addressInput') as HTMLInputElement; + const emojiDisplay = container.querySelector('#emoji-display-2'); + const okButton = container.querySelector('#okButton') as HTMLButtonElement; + const createButton = container.querySelector('#createButton') as HTMLButtonElement; + const actionButton = container.querySelector('#actionButton') as HTMLButtonElement; + addSubscription(addressInput, 'input', async () => { + let address = addressInput.value; + + // Vérifie si l'adresse est une URL + try { + const url = new URL(address); + // Si c'est une URL valide, extraire le paramètre sp_address + const urlParams = new URLSearchParams(url.search); + const extractedAddress = urlParams.get('sp_address') || ''; // Prend sp_address ou une chaîne vide + + if (extractedAddress) { + address = extractedAddress; + addressInput.value = address; // Met à jour l'input pour afficher uniquement l'adresse extraite + } + } catch (e) { + // Si ce n'est pas une URL valide, on garde l'adresse originale + console.log("Ce n'est pas une URL valide, on garde l'adresse originale."); + } + if (address) { + const emojis = await addressToEmoji(address); + if (emojiDisplay) { + emojiDisplay.innerHTML = emojis; + } + if (okButton) { + okButton.style.display = 'inline-block'; + } + } else { + if (emojiDisplay) { + emojiDisplay.innerHTML = ''; + } + if (okButton) { + okButton.style.display = 'none'; + } + } + }); + + if (createButton) { + addSubscription(createButton, 'click', () => { + onCreateButtonClick(); + }); + } +} + +async function onCreateButtonClick() { + try { + await prepareAndSendPairingTx(); + const service = await Services.getInstance(); + await service.confirmPairing(); + } catch (e) { + console.error(`onCreateButtonClick error: ${e}`); + } +} + +export async function prepareAndSendPairingTx(): Promise { + const service = await Services.getInstance(); + + try { + await service.checkConnections([]); + } catch (e) { + throw e; + } + + try { + const relayAddress = service.getAllRelays(); + const createPairingProcessReturn = await service.createPairingProcess( + "", + [], + ); + + if (!createPairingProcessReturn.updated_process) { + throw new Error('createPairingProcess returned an empty new process'); + } + + service.setProcessId(createPairingProcessReturn.updated_process.process_id); + service.setStateId(createPairingProcessReturn.updated_process.current_process.states[0].state_id); + + await service.handleApiReturn(createPairingProcessReturn); + + } catch (err) { + console.error(err); + } +} + +export async function generateQRCode(spAddress: string) { + try { + const container = getCorrectDOM('login-4nk-component') as HTMLElement + const currentUrl = 'https://' + window.location.host; + const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress); + const qrCode = container?.querySelector('.qr-code img'); + qrCode?.setAttribute('src', url); + } catch (err) { + console.error(err); + } +} + +export async function generateCreateBtn() { + try{ + //Generate CreateBtn + const container = getCorrectDOM('login-4nk-component') as HTMLElement + const createBtn = container?.querySelector('.create-btn'); + if (createBtn) { + createBtn.textContent = 'CREATE'; + } + } catch (err) { + console.error(err); + } + +} \ No newline at end of file diff --git a/ihm_client/src/utils/subscription.utils.ts b/ihm_client/src/utils/subscription.utils.ts new file mode 100755 index 00000000..707ba202 --- /dev/null +++ b/ihm_client/src/utils/subscription.utils.ts @@ -0,0 +1,19 @@ +let subscriptions: { element: Element | Document; event: any; eventHandler: EventListenerOrEventListenerObject }[] = []; + +export function cleanSubscriptions(): void { + console.log('🚀 ~ cleanSubscriptions ~ sub:', subscriptions); + for (const sub of subscriptions) { + const el = sub.element; + const eventHandler = sub.eventHandler; + if (el) { + el.removeEventListener(sub.event, eventHandler); + } + } + subscriptions = []; +} + +export function addSubscription(element: Element | Document, event: any, eventHandler: EventListenerOrEventListenerObject): void { + if (!element) return; + subscriptions.push({ element, event, eventHandler }); + element.addEventListener(event, eventHandler); +} diff --git a/ihm_client/src/websockets.ts b/ihm_client/src/websockets.ts new file mode 100755 index 00000000..9b47ad7f --- /dev/null +++ b/ihm_client/src/websockets.ts @@ -0,0 +1,89 @@ +import type { AnkFlag } from 'pkg/sdk_client'; +import Services from './services/service'; + +let ws: WebSocket; +let messageQueue: string[] = []; +export async function initWebsocket(url: string) { + ws = new WebSocket(url); + + if (ws !== null) { + ws.onopen = async (event) => { + console.log('WebSocket connection established'); + + while (messageQueue.length > 0) { + const message = messageQueue.shift(); + if (message) { + ws.send(message); + } + } + }; + + // Listen for messages + ws.onmessage = (event) => { + const msgData = event.data; + + // console.log("Received text message: ", msgData); + (async () => { + if (typeof msgData === 'string') { + try { + const parsedMessage = JSON.parse(msgData); + const services = await Services.getInstance(); + switch (parsedMessage.flag) { + case 'Handshake': + await services.handleHandshakeMsg(url, parsedMessage.content); + break; + case 'NewTx': + await services.parseNewTx(parsedMessage.content); + break; + case 'Cipher': + await services.parseCipher(parsedMessage.content); + break; + case 'Commit': + // Basically if we see this it means we have an error + await services.handleCommitError(parsedMessage.content); + break; + } + } catch (error) { + console.error('Received an invalid message:', error); + } + } else { + console.error('Received a non-string message'); + } + })(); + }; + + // Listen for possible errors + ws.onerror = (event) => { + console.error('WebSocket error:', event); + }; + + // Listen for when the connection is closed + ws.onclose = (event) => { + console.log('WebSocket is closed now.'); + }; + } +} + +// Method to send messages +export function sendMessage(flag: AnkFlag, message: string): void { + if (ws.readyState === WebSocket.OPEN) { + const networkMessage = { + flag: flag, + content: message, + }; + console.log('Sending message of type:', flag); + ws.send(JSON.stringify(networkMessage)); + } else { + console.error('WebSocket is not open. ReadyState:', ws.readyState); + messageQueue.push(message); + } +} + +export function getUrl(): string { + return ws.url; +} + +// Method to close the WebSocket connection +export function close(): void { + ws.close(); +} diff --git a/ihm_client/start.sh b/ihm_client/start.sh new file mode 100644 index 00000000..16b6dea7 --- /dev/null +++ b/ihm_client/start.sh @@ -0,0 +1,124 @@ +#!/bin/sh + +set -e + +echo "🚀 Démarrage de l'interface utilisateur 4NK..." + +# Variables d'environnement avec valeurs par défaut +SDK_RELAY_WS_URL=${SDK_RELAY_WS_URL:-"ws://sdk_relay_1:8090"} +SDK_RELAY_HTTP_URL=${SDK_RELAY_HTTP_URL:-"http://sdk_relay_1:8091"} +BITCOIN_RPC_URL=${BITCOIN_RPC_URL:-"http://bitcoin:18443"} +BLINDBIT_URL=${BLINDBIT_URL:-"http://blindbit:8000"} + +# Fonction pour attendre qu'un service soit disponible +wait_for_service() { + local service_name=$1 + local service_url=$2 + local max_attempts=30 + local attempt=1 + + echo "⏳ Attente du service $service_name ($service_url)..." + + while [ $attempt -le $max_attempts ]; do + if wget --quiet --tries=1 --timeout=5 --spider "$service_url" 2>/dev/null; then + echo "✅ Service $service_name disponible" + return 0 + fi + + echo " Tentative $attempt/$max_attempts - Service $service_name non disponible" + sleep 2 + attempt=$((attempt + 1)) + done + + echo "❌ Service $service_name non disponible après $max_attempts tentatives" + return 1 +} + +# Fonction pour vérifier la connectivité WebSocket +check_websocket() { + local service_name=$1 + local ws_url=$2 + local max_attempts=10 + local attempt=1 + + echo "🔌 Vérification WebSocket $service_name ($ws_url)..." + + while [ $attempt -le $max_attempts ]; do + if nc -z $(echo $ws_url | sed 's|ws://||' | sed 's|wss://||' | cut -d: -f1) $(echo $ws_url | cut -d: -f3) 2>/dev/null; then + echo "✅ WebSocket $service_name accessible" + return 0 + fi + + echo " Tentative $attempt/$max_attempts - WebSocket $service_name non accessible" + sleep 3 + attempt=$((attempt + 1)) + done + + echo "⚠️ WebSocket $service_name non accessible (continuera sans)" + return 0 +} + +# Vérification des services critiques +echo "🔍 Vérification des services 4NK_node..." + +# Attendre sdk_relay HTTP (critique) +if ! wait_for_service "sdk_relay HTTP" "$SDK_RELAY_HTTP_URL/health"; then + echo "❌ Service sdk_relay HTTP critique non disponible" + exit 1 +fi + +# Vérifier sdk_relay WebSocket (optionnel) +check_websocket "sdk_relay WebSocket" "$SDK_RELAY_WS_URL" + +# Vérifier Bitcoin Core (optionnel) +if ! wait_for_service "Bitcoin Core" "$BITCOIN_RPC_URL" 2>/dev/null; then + echo "⚠️ Bitcoin Core non disponible (optionnel)" +fi + +# Vérifier Blindbit (optionnel) +if ! wait_for_service "Blindbit" "$BLINDBIT_URL" 2>/dev/null; then + echo "⚠️ Blindbit non disponible (optionnel)" +fi + +# Génération de la configuration dynamique +echo "⚙️ Génération de la configuration dynamique..." + +# Créer un fichier de configuration JavaScript pour l'application +cat > /usr/share/nginx/html/config.js << EOF +window.ENV_CONFIG = { + SDK_RELAY_WS_URL: '$SDK_RELAY_WS_URL', + SDK_RELAY_HTTP_URL: '$SDK_RELAY_HTTP_URL', + BITCOIN_RPC_URL: '$BITCOIN_RPC_URL', + BLINDBIT_URL: '$BLINDBIT_URL', + ENVIRONMENT: '4nk-node' +}; +EOF + +# Démarrage de nginx +echo "🌐 Démarrage de nginx..." +nginx -g "daemon off;" & + +# Attendre que nginx soit prêt +sleep 2 + +# Vérifier que nginx fonctionne +if ! wget --quiet --tries=1 --timeout=5 --spider http://localhost 2>/dev/null; then + echo "❌ Nginx n'a pas démarré correctement" + exit 1 +fi + +echo "✅ Interface utilisateur 4NK démarrée avec succès" +echo " 📍 URL: http://localhost" +echo " 🔌 WebSocket: $SDK_RELAY_WS_URL" +echo " 🌐 API: $SDK_RELAY_HTTP_URL" + +# Maintenir le conteneur en vie +while true; do + sleep 30 + + # Vérification périodique de la santé + if ! wget --quiet --tries=1 --timeout=5 --spider http://localhost 2>/dev/null; then + echo "❌ Nginx ne répond plus, redémarrage..." + nginx -s reload + fi +done diff --git a/ihm_client/tsconfig.json b/ihm_client/tsconfig.json new file mode 100755 index 00000000..d3640823 --- /dev/null +++ b/ihm_client/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "declaration": true, + "outDir": "./dist", + "target": "ESNext", + "lib": ["DOM", "DOM.Iterable", "ESNext", "webworker"], + "types": [], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "experimentalDecorators": true, + "useDefineForClassFields": true, + "noEmit": true, + "jsx": "react-jsx", + "baseUrl": "./", + "paths": { + "~/*": ["src/*"] + } + }, + "include": ["src", "src/*/", "./vite.config.ts", "src/*.d.ts", "src/main.ts"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/ihm_client/vite.config.ts b/ihm_client/vite.config.ts new file mode 100755 index 00000000..e842295a --- /dev/null +++ b/ihm_client/vite.config.ts @@ -0,0 +1,81 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; // or react from '@vitejs/plugin-react' if using React +import wasm from 'vite-plugin-wasm'; +import {createHtmlPlugin} from 'vite-plugin-html'; +import typescript from "@rollup/plugin-typescript"; +import fs from 'fs' +import path from 'path' +// import pluginTerminal from 'vite-plugin-terminal'; + +export default defineConfig({ + optimizeDeps: { + include: ['qrcode'] + }, + plugins: [ + vue(), // or react() if using React + wasm(), + createHtmlPlugin({ + minify: true, + template: 'index.html', + }), + typescript({ + sourceMap: false, + declaration: true, + declarationDir: "dist/types", + rootDir: "src", + outDir: "dist", + }), + // pluginTerminal({ + // console: 'terminal', + // output: ['terminal', 'console'] + // }) + ], + build: { + outDir: 'dist', + target: 'esnext', + minify: false, + rollupOptions: { + input: './src/index.ts', + output: { + entryFileNames: 'index.js', + }, + }, + lib: { + entry: path.resolve(__dirname, 'src/router.ts'), + name: 'ihm-service', + formats: ['es'], + fileName: (format) => `ihm-service.${format}.js`, + }, + }, + resolve: { + alias: { + '@': '/src', + }, + extensions: ['.ts', '.tsx', '.js'], + }, + server: { + fs: { + cachedChecks: false, + }, + port: 3003, + proxy: { + '/storage': { + target: 'https://demo.4nkweb.com', + changeOrigin: true, + secure: false, + rewrite: (path) => path.replace(/^\/storage/, '/storage'), + configure: (proxy, _options) => { + proxy.on('error', (err, _req, _res) => { + console.log('proxy error', err); + }); + proxy.on('proxyReq', (proxyReq, req, _res) => { + console.log('Sending Request:', req.method, req.url); + }); + proxy.on('proxyRes', (proxyRes, req, _res) => { + console.log('Received Response:', proxyRes.statusCode, req.url); + }); + } + } + } + }, +}); \ No newline at end of file diff --git a/start-4nk-node-with-ui.sh b/start-4nk-node-with-ui.sh new file mode 100755 index 00000000..193f182f --- /dev/null +++ b/start-4nk-node-with-ui.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +set -e + +echo "🚀 Démarrage de l'infrastructure 4NK_node avec interface utilisateur..." + +# Vérifier que nous sommes dans le bon répertoire +if [[ ! -f "docker-compose.yml" ]]; then + echo "❌ Ce script doit être exécuté depuis le répertoire 4NK_node" + exit 1 +fi + +# Arrêter et nettoyer les conteneurs existants +echo "🧹 Nettoyage des conteneurs existants..." +docker-compose down + +# Démarrer tous les services +echo "📦 Démarrage de tous les services..." +docker-compose up -d + +# Attendre que les services critiques soient prêts +echo "⏳ Attente du démarrage des services critiques..." +sleep 30 + +# Vérifier la santé des services +echo "🔍 Vérification de la santé des services..." + +# Bitcoin +if docker-compose ps bitcoin | grep -q "Up"; then + echo "✅ Bitcoin démarré" +else + echo "❌ Bitcoin n'est pas démarré" + docker-compose logs bitcoin +fi + +# Blindbit +if docker-compose ps blindbit | grep -q "Up"; then + echo "✅ Blindbit démarré" +else + echo "❌ Blindbit n'est pas démarré" + docker-compose logs blindbit +fi + +# SDK Relays +for i in {1..3}; do + if docker-compose ps "sdk_relay_$i" | grep -q "Up"; then + echo "✅ SDK Relay $i démarré" + else + echo "❌ SDK Relay $i n'est pas démarré" + docker-compose logs "sdk_relay_$i" + fi +done + +# Interface utilisateur +if docker-compose ps ihm_client | grep -q "Up"; then + echo "✅ Interface utilisateur démarrée" +else + echo "❌ Interface utilisateur n'est pas démarrée" + docker-compose logs ihm_client +fi + +echo "" +echo "🎉 Infrastructure 4NK_node démarrée avec succès !" +echo "" +echo "📍 URLs d'accès :" +echo " 🌐 Interface utilisateur: http://localhost:8080" +echo " 🔗 Bitcoin RPC: http://localhost:18443" +echo " 🔗 Blindbit: http://localhost:8000" +echo " 🔗 SDK Relay 1: http://localhost:8091" +echo " 🔗 SDK Relay 2: http://localhost:8093" +echo " 🔗 SDK Relay 3: http://localhost:8095" +echo "" +echo "🔍 Commandes utiles :" +echo " 📋 Statut des services: docker-compose ps" +echo " 📋 Logs d'un service: docker-compose logs " +echo " 📋 Arrêter l'infrastructure: docker-compose down" +echo " 📋 Redémarrer un service: docker-compose restart " diff --git a/start-ihm-client.sh b/start-ihm-client.sh new file mode 100755 index 00000000..20d67db2 --- /dev/null +++ b/start-ihm-client.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +echo "🚀 Démarrage de l'interface utilisateur 4NK..." + +# Vérifier que nous sommes dans le bon répertoire +if [[ ! -f "docker-compose.yml" ]]; then + echo "❌ Ce script doit être exécuté depuis le répertoire 4NK_node" + exit 1 +fi + +# Démarrer uniquement le service ihm_client +echo "📦 Démarrage du service ihm_client..." +docker-compose up -d ihm_client + +# Attendre que le service soit prêt +echo "⏳ Attente du démarrage..." +sleep 10 + +# Vérifier la santé du service +if docker-compose ps ihm_client | grep -q "Up"; then + echo "✅ Interface utilisateur démarrée avec succès" + echo " 📍 URL: http://localhost:8080" + echo " 🔍 Logs: docker logs 4nk-ihm-client" +else + echo "❌ Échec du démarrage de l'interface utilisateur" + docker-compose logs ihm_client + exit 1 +fi