link diffs to validation modal and show and prettify

This commit is contained in:
AnisHADJARAB 2024-12-17 08:28:39 +00:00 committed by Sosthene
parent d64efbd6a0
commit 2124388cc5
46 changed files with 6581 additions and 6658 deletions

View File

@ -1,12 +1,9 @@
:host { :host {
--primary-color --primary-color: #3a506b;
: #3A506B;
/* Bleu métallique */ /* Bleu métallique */
--secondary-color --secondary-color: #b0bec5;
: #B0BEC5;
/* Gris acier */ /* Gris acier */
--accent-color --accent-color: #d68c45;
: #D68C45;
/* Cuivre */ /* Cuivre */
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
height: 100vh; height: 100vh;
@ -30,7 +27,7 @@ body {
} }
.message strong { .message strong {
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif; font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
font-size: 20px; font-size: 20px;
} }
@ -80,7 +77,6 @@ body {
position: relative; position: relative;
} }
.nav-wrapper { .nav-wrapper {
position: fixed; position: fixed;
background: radial-gradient(circle, white, var(--primary-color)); background: radial-gradient(circle, white, var(--primary-color));
@ -88,12 +84,15 @@ body {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
color: #37474F; color: #37474f;
height: 9vh; height: 9vh;
width: 100vw; width: 100vw;
left: 0; left: 0;
top: 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); 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 { .nav-right-icons {
display: flex; display: flex;
@ -101,7 +100,8 @@ body {
position: relative; position: relative;
display: inline-block; display: inline-block;
} }
.notification-bell, .burger-menu { .notification-bell,
.burger-menu {
z-index: 3; z-index: 3;
height: 20px; height: 20px;
width: 20px; width: 20px;
@ -109,8 +109,8 @@ body {
} }
.notification-badge { .notification-badge {
position: absolute; position: absolute;
top: -.7rem; top: -0.7rem;
left: -.8rem; left: -0.8rem;
background-color: red; background-color: red;
color: white; color: white;
border-radius: 50%; border-radius: 50%;
@ -135,10 +135,10 @@ body {
display: none; display: none;
.notification-element { .notification-element {
padding: .8rem 0; padding: 0.8rem 0;
width: 100%; width: 100%;
&:hover { &:hover {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
} }
.notification-element:not(:last-child) { .notification-element:not(:last-child) {
@ -205,7 +205,7 @@ body {
} }
.separator { .separator {
width: 2px; width: 2px;
background-color: #78909C; background-color: #78909c;
height: 80%; height: 80%;
margin: 0 0.5em; margin: 0 0.5em;
} }
@ -244,7 +244,7 @@ body {
z-index: 1; z-index: 1;
border-bottom-style: solid; border-bottom-style: solid;
border-bottom-width: 1px; border-bottom-width: 1px;
border-bottom-color: #E0E4D6; border-bottom-color: #e0e4d6;
} }
.tab { .tab {
@ -255,7 +255,7 @@ body {
font-size: 1rem; font-size: 1rem;
color: #6200ea; color: #6200ea;
&:hover { &:hover {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
} }
.tab.active { .tab.active {
@ -288,21 +288,20 @@ body {
} }
.emoji-display { .emoji-display {
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif; font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
font-size: 20px; font-size: 20px;
} }
#emoji-display-2 { #emoji-display-2 {
margin-top: 30px; margin-top: 30px;
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif; font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
font-size: 20px; font-size: 20px;
} }
#okButton { #okButton {
margin-bottom: 2em; margin-bottom: 2em;
cursor: pointer; cursor: pointer;
background-color: #D0D0D7; background-color: #d0d0d7;
color: white; color: white;
border-style: none; border-style: none;
border-radius: 5px; border-radius: 5px;
@ -312,7 +311,7 @@ body {
} }
.pairing-request { .pairing-request {
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif; font-family: 'Segoe UI Emoji', 'Noto Color Emoji', 'Apple Color Emoji', sans-serif;
font-size: 14px; font-size: 14px;
margin-top: 0px; margin-top: 0px;
} }
@ -320,13 +319,12 @@ body {
.sp-address-btn { .sp-address-btn {
margin-bottom: 2em; margin-bottom: 2em;
cursor: pointer; cursor: pointer;
background-color: #D0D0D7; background-color: #d0d0d7;
color: white; color: white;
border-style: none; border-style: none;
border-radius: 5px; border-radius: 5px;
color: #000; color: #000;
padding: 2px; padding: 2px;
} }
.camera-card { .camera-card {
@ -352,7 +350,6 @@ body {
background-color: #3700b3; background-color: #3700b3;
} }
.card { .card {
min-width: 300px; min-width: 300px;
border: 1px solid #e0e0e0; border: 1px solid #e0e0e0;
@ -370,7 +367,6 @@ body {
justify-content: flex-start; justify-content: flex-start;
padding: 1rem; padding: 1rem;
overflow-y: auto; overflow-y: auto;
} }
.card-content { .card-content {
@ -380,7 +376,7 @@ body {
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
text-align: left; text-align: left;
font-size: .8em; font-size: 0.8em;
position: relative; position: relative;
left: 2vw; left: 2vw;
width: 90%; width: 90%;
@ -389,12 +385,12 @@ body {
padding: 1rem 0; padding: 1rem 0;
} }
.process-element { .process-element {
padding: .4rem 0; padding: 0.4rem 0;
&:hover { &:hover {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
&.selected { &.selected {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
} }
} }
@ -411,7 +407,6 @@ body {
margin-bottom: 0px; margin-bottom: 0px;
} }
.card-action { .card-action {
width: 100%; width: 100%;
} }
@ -434,7 +429,7 @@ body {
color: #333; color: #333;
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;
&:hover { &:hover {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
} }
@ -446,7 +441,6 @@ body {
display: none; display: none;
} }
/* QR READER */ /* QR READER */
#qr-reader div { #qr-reader div {
position: inherit; position: inherit;
@ -458,12 +452,11 @@ body {
margin-top: 5px; margin-top: 5px;
} }
/* INPUT CSS **/ /* INPUT CSS **/
.input-container { .input-container {
position: relative; position: relative;
width: 100%; width: 100%;
background-color: #ECEFF1; background-color: #eceff1;
} }
.input-field { .input-field {
@ -490,7 +483,10 @@ body {
font-size: 1rem; font-size: 1rem;
color: #999; color: #999;
pointer-events: none; pointer-events: none;
transition: transform 0.3s, color 0.3s, font-size 0.3s; transition:
transform 0.3s,
color 0.3s,
font-size 0.3s;
} }
.input-field:focus + .input-label, .input-field:focus + .input-label,
@ -507,7 +503,9 @@ body {
width: 0; width: 0;
height: 2px; height: 2px;
background-color: #6200ea; background-color: #6200ea;
transition: width 0.3s, left 0.3s; transition:
width 0.3s,
left 0.3s;
} }
.input-field:focus ~ .input-underline { .input-field:focus ~ .input-underline {
@ -541,9 +539,6 @@ body {
background-color: #f0f0f0; background-color: #f0f0f0;
} }
/** AUTOCOMPLETE **/ /** AUTOCOMPLETE **/
select[data-multi-select-plugin] { select[data-multi-select-plugin] {
@ -562,8 +557,12 @@ select[data-multi-select-plugin] {
flex-direction: row; flex-direction: row;
height: auto; height: auto;
width: 100%; width: 100%;
-o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; -o-transition:
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; 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 { .autocomplete-list {
@ -571,7 +570,7 @@ select[data-multi-select-plugin] {
} }
.multi-select-component:focus-within { .multi-select-component:focus-within {
box-shadow: inset 0px 0px 0px 2px #78ABFE; box-shadow: inset 0px 0px 0px 2px #78abfe;
} }
.multi-select-component .btn-group { .multi-select-component .btn-group {
@ -650,7 +649,7 @@ select[data-multi-select-plugin] {
} }
.dropdown-icon.active { .dropdown-icon.active {
transform: rotateX(180deg) transform: rotateX(180deg);
} }
.search-container .dropdown-icon { .search-container .dropdown-icon {
@ -666,7 +665,7 @@ select[data-multi-select-plugin] {
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
/* SVG background image */ /* 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-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-position: center;
background-size: 10px; background-size: 10px;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -684,8 +683,8 @@ select[data-multi-select-plugin] {
border: 1px solid #ccc; border: 1px solid #ccc;
border-top: none; border-top: none;
border-bottom: none; border-bottom: none;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
} }
.search-container ul :focus { .search-container ul :focus {
@ -710,7 +709,6 @@ select[data-multi-select-plugin] {
border-radius: 4px 0px 0 0; border-radius: 4px 0px 0 0;
} }
.search-container ul li:hover.not-cursor { .search-container ul li:hover.not-cursor {
cursor: default; cursor: default;
} }
@ -718,7 +716,6 @@ select[data-multi-select-plugin] {
.search-container ul li:hover { .search-container ul li:hover {
color: #333; color: #333;
background-color: #f0f0f0; background-color: #f0f0f0;
;
border-color: #adadad; border-color: #adadad;
cursor: pointer; cursor: pointer;
} }
@ -729,8 +726,6 @@ select[data-multi-select-plugin] {
overflow-y: auto; overflow-y: auto;
} }
/**************************************** Process page card ******************************************************/ /**************************************** Process page card ******************************************************/
.process-card { .process-card {
min-width: 300px; min-width: 300px;
@ -748,12 +743,11 @@ select[data-multi-select-plugin] {
justify-content: space-between; justify-content: space-between;
padding: 1rem; padding: 1rem;
overflow-y: auto; overflow-y: auto;
} }
.process-card-content { .process-card-content {
text-align: left; text-align: left;
font-size: .8em; font-size: 0.8em;
position: relative; position: relative;
left: 2vw; left: 2vw;
width: 90%; width: 90%;
@ -762,16 +756,16 @@ select[data-multi-select-plugin] {
padding: 1rem 0; padding: 1rem 0;
} }
.process-element { .process-element {
padding: .4rem 0; padding: 0.4rem 0;
&:hover { &:hover {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
&.selected { &.selected {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
} }
.selected-process-zone { .selected-process-zone {
background-color: rgba(26, 28, 24, .08); background-color: rgba(26, 28, 24, 0.08);
} }
} }
@ -782,7 +776,6 @@ select[data-multi-select-plugin] {
width: 90%; width: 90%;
} }
.process-card-action { .process-card-action {
width: 100%; width: 100%;
} }

View File

@ -42,8 +42,7 @@ export async function initHeader() {
// Charger le profile-header // Charger le profile-header
const profileContainer = document.getElementById('profile-header-container'); const profileContainer = document.getElementById('profile-header-container');
if (profileContainer) { if (profileContainer) {
const profileHeaderHtml = await fetch('/src/components/profile-header/profile-header.html') const profileHeaderHtml = await fetch('/src/components/profile-header/profile-header.html').then((res) => res.text());
.then(res => res.text());
profileContainer.innerHTML = profileHeaderHtml; profileContainer.innerHTML = profileHeaderHtml;
// Initialiser les données du profil // Initialiser les données du profil
@ -77,7 +76,7 @@ async function setNotification(notifications: any[]): Promise<void> {
if (notifications?.length) { if (notifications?.length) {
badge.innerText = notifications.length.toString(); badge.innerText = notifications.length.toString();
const notificationBoard = document.querySelector('.notification-board') as HTMLDivElement; const notificationBoard = document.querySelector('.notification-board') as HTMLDivElement;
notificationBoard.querySelectorAll('.notification-element')?.forEach(elem => elem.remove()) notificationBoard.querySelectorAll('.notification-element')?.forEach((elem) => elem.remove());
noNotifications.style.display = 'none'; noNotifications.style.display = 'none';
for (const notif of notifications) { for (const notif of notifications) {
const notifElement = document.createElement('div'); const notifElement = document.createElement('div');
@ -90,9 +89,9 @@ async function setNotification(notifications: any[]): Promise<void> {
// this.addSubscription(notifElement, 'click', 'goToProcessPage') // this.addSubscription(notifElement, 'click', 'goToProcessPage')
notificationBoard.appendChild(notifElement); notificationBoard.appendChild(notifElement);
notifElement.addEventListener('click', async () => { notifElement.addEventListener('click', async () => {
const modalService = await ModalService.getInstance() const modalService = await ModalService.getInstance();
modalService.injectValidationModal(notif) modalService.injectValidationModal(notif);
}) });
} }
} else { } else {
noNotifications.style.display = 'block'; noNotifications.style.display = 'block';
@ -140,7 +139,7 @@ input.onchange = async (e) => {
await service.importJSON(content); await service.importJSON(content);
alert('Import réussi'); alert('Import réussi');
} catch (error) { } catch (error) {
alert('Erreur lors de l\'import: ' + error); alert("Erreur lors de l'import: " + error);
} }
}; };
reader.readAsText(file); reader.readAsText(file);

View File

@ -1,8 +1,8 @@
<div class="avatar-section"> <div class="avatar-section">
<img src="https://via.placeholder.com/800x200" alt="Banner" class="banner-image"> <img src="https://via.placeholder.com/800x200" alt="Banner" class="banner-image" />
<div class="banner-content"> <div class="banner-content">
<div class="avatar-container"> <div class="avatar-container">
<img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" onclick="window.openAvatarPopup()"> <img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" onclick="window.openAvatarPopup()" />
</div> </div>
<div class="user-info"> <div class="user-info">
<span class="user-name">John</span> <span class="user-name">John</span>

View File

@ -4,8 +4,8 @@ import { prepareAndSendPairingTx } from '~/utils/sp-address.utils';
export default class QrScannerComponent extends HTMLElement { export default class QrScannerComponent extends HTMLElement {
videoElement: any; videoElement: any;
wrapper: any wrapper: any;
qrScanner: any qrScanner: any;
constructor() { constructor() {
super(); super();
this.attachShadow({ mode: 'open' }); this.attachShadow({ mode: 'open' });
@ -29,8 +29,8 @@ import { prepareAndSendPairingTx } from '~/utils/sp-address.utils';
console.error('Video element not found!'); console.error('Video element not found!');
return; return;
} }
console.log("🚀 ~ QrScannerComponent ~ initializeScanner ~ this.videoElement:", this.videoElement) console.log('🚀 ~ QrScannerComponent ~ initializeScanner ~ this.videoElement:', this.videoElement);
this.qrScanner = new QrScanner(this.videoElement, result => this.onQrCodeScanned(result),{ this.qrScanner = new QrScanner(this.videoElement, (result) => this.onQrCodeScanned(result), {
highlightScanRegion: true, highlightScanRegion: true,
highlightCodeOutline: true, highlightCodeOutline: true,
}); });
@ -38,9 +38,8 @@ import { prepareAndSendPairingTx } from '~/utils/sp-address.utils';
try { try {
await QrScanner.hasCamera(); await QrScanner.hasCamera();
this.qrScanner.start(); this.qrScanner.start();
this.videoElement.style = 'height: 200px; width: 200px' this.videoElement.style = 'height: 200px; width: 200px';
this.shadowRoot?.appendChild(this.wrapper) this.shadowRoot?.appendChild(this.wrapper);
} catch (e) { } catch (e) {
console.error('No camera found or error starting the QR scanner', e); console.error('No camera found or error starting the QR scanner', e);
} }
@ -56,7 +55,7 @@ import { prepareAndSendPairingTx } from '~/utils/sp-address.utils';
if (spAddress) { if (spAddress) {
// Call the sendPairingTx function with the extracted sp_address // Call the sendPairingTx function with the extracted sp_address
try { try {
await prepareAndSendPairingTx(spAddress) await prepareAndSendPairingTx(spAddress);
} catch (e) { } catch (e) {
console.error('Failed to pair:', e); console.error('Failed to pair:', e);
} }

View File

@ -1,55 +1,7 @@
<div id="validation-modal" class="validation-modal"> <div id="validation-modal" class="validation-modal">
<div class="modal-content"> <div class="modal-content">
<div class="modal-title">Validate</div> <div class="modal-title">Validate Process {{processId}}</div>
<div class="validation-box"> <div class="validation-box">
<div class="expansion-panel">
<div class="expansion-panel-header">Validation 1</div>
<div class="expansion-panel-body">
<div class="radio-buttons">
<label>
<input type="radio" name="validation1" value="old">
Keep Old
</label>
<label>
<input type="radio" name="validation1" value="new">
Keep New
</label>
</div>
<div class="diff">
<div class="diff-side diff-old">
<pre>-old line</pre>
</div>
<div class="diff-side diff-new">
<pre>+new line</pre>
</div>
</div>
</div>
</div>
<div class="expansion-panel">
<div class="expansion-panel-header">Validation 2</div>
<div class="expansion-panel-body">
<div class="radio-buttons">
<label>
<input type="radio" name="validation2" value="old">
Keep Old
</label>
<label>
<input type="radio" name="validation2" value="new">
Keep New
</label>
</div>
<div class="diff">
<div class="diff-side diff-old">
<pre>-foo\n-bar</pre>
</div>
<div class="diff-side diff-new">
<pre>+baz</pre>
</div>
</div>
</div>
</div>
</div> </div>
<div class="modal-action"> <div class="modal-action">

View File

@ -1,17 +1,56 @@
import ModalService from "~/services/modal.service"; import ModalService from '~/services/modal.service';
document.querySelectorAll('.expansion-panel-header').forEach(header => { async function validate() {
console.log('==> VALIDATE');
const modalservice = await ModalService.getInstance();
modalservice.closeValidationModal();
}
export async function initValidationModal(processDiffs: any) {
console.log("🚀 ~ initValidationModal ~ processDiffs:", processDiffs)
for(const diff of processDiffs.diffs) {
let diffs = ''
for(const value of diff) {
diffs+= `
<div class="radio-buttons">
<label>
<input type="radio" name="validation1" value="old" />
Keep Old
</label>
<label>
<input type="radio" name="validation1" value="new" />
Keep New
</label>
</div>
<div class="diff">
<div class="diff-side diff-old">
<pre>-${value.previous_value}</pre>
</div>
<div class="diff-side diff-new">
<pre>+${value.new_value}</pre>
</div>
</div>
`
}
const state = `
<div class="expansion-panel">
<div class="expansion-panel-header">State ${diff[0].new_state_merkle_root}</div>
<div class="expansion-panel-body">
${diffs}
</div>
</div>
`
const box = document.querySelector('.validation-box')
if(box) box.innerHTML += state
}
document.querySelectorAll('.expansion-panel-header').forEach((header) => {
header.addEventListener('click', function (event) { header.addEventListener('click', function (event) {
const target = event.target as HTMLElement const target = event.target as HTMLElement;
const body = target.nextElementSibling as HTMLElement; const body = target.nextElementSibling as HTMLElement;
if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block'; if (body?.style) body.style.display = body.style.display === 'block' ? 'none' : 'block';
}); });
}); });
async function validate() {
console.log('==> VALIDATE')
const modalservice = await ModalService.getInstance()
modalservice.closeValidationModal()
} }
(window as any).validate = validate (window as any).validate = validate;

View File

@ -1,4 +1,4 @@
import { DocumentSignature } from "~/models/signature.models"; import { DocumentSignature } from '~/models/signature.models';
export interface Group { export interface Group {
id: number; id: number;

View File

@ -5,15 +5,7 @@ import { ChatElement } from './pages/chat/chat';
import { AccountComponent } from './pages/account/account-component'; import { AccountComponent } from './pages/account/account-component';
import { AccountElement } from './pages/account/account'; import { AccountElement } from './pages/account/account';
export { export { SignatureComponent, SignatureElement, ChatComponent, ChatElement, AccountComponent, AccountElement };
SignatureComponent,
SignatureElement,
ChatComponent,
ChatElement,
AccountComponent,
AccountElement
};
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {

View File

@ -4,325 +4,269 @@ export const STORAGE_KEYS = {
pairing: 'pairingRows', pairing: 'pairingRows',
wallet: 'walletRows', wallet: 'walletRows',
process: 'processRows', process: 'processRows',
data: 'dataRows' data: 'dataRows',
}; };
// Initialiser le stockage des lignes par défaut dans le localStorage // Initialiser le stockage des lignes par défaut dans le localStorage
export const defaultRows = [ export const defaultRows = [
{ {
column1: "sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrz", column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrz',
column2: "🎊😑🎄😩", column2: '🎊😑🎄😩',
column3: "Laptop" column3: 'Laptop',
}, },
{ {
column1: "sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrx", column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrx',
column2: "🎏🎕😧🌥", column2: '🎏🎕😧🌥',
column3: "Phone" } column3: 'Phone',
},
]; ];
export const mockNotifications: { [key: string]: Notification[] } = {}; export const mockNotifications: { [key: string]: Notification[] } = {};
export const notificationMessages = [ 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'];
"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 = [ export const mockDataRows = [
{ {
column1: "User Project", column1: 'User Project',
column2: "private", column2: 'private',
column3: "User", column3: 'User',
column4: "6 months", column4: '6 months',
column5: "NDA signed", column5: 'NDA signed',
column6: "Contract #123", column6: 'Contract #123',
processName: "User Process", processName: 'User Process',
zone: "A" zone: 'A',
}, },
{ {
column1: "Process Project", column1: 'Process Project',
column2: "private", column2: 'private',
column3: "Process", column3: 'Process',
column4: "1 year", column4: '1 year',
column5: "Terms accepted", column5: 'Terms accepted',
column6: "Contract #456", column6: 'Contract #456',
processName: "Process Management", processName: 'Process Management',
zone: "B" zone: 'B',
}, },
{ {
column1: "Member Project", column1: 'Member Project',
column2: "private", column2: 'private',
column3: "Member", column3: 'Member',
column4: "3 months", column4: '3 months',
column5: "GDPR compliant", column5: 'GDPR compliant',
column6: "Contract #789", column6: 'Contract #789',
processName: "Member Process", processName: 'Member Process',
zone: "C" zone: 'C',
}, },
{ {
column1: "Peer Project", column1: 'Peer Project',
column2: "public", column2: 'public',
column3: "Peer", column3: 'Peer',
column4: "2 years", column4: '2 years',
column5: "IP rights", column5: 'IP rights',
column6: "Contract #101", column6: 'Contract #101',
processName: "Peer Process", processName: 'Peer Process',
zone: "D" zone: 'D',
}, },
{ {
column1: "Payment Project", column1: 'Payment Project',
column2: "confidential", column2: 'confidential',
column3: "Payment", column3: 'Payment',
column4: "1 year", column4: '1 year',
column5: "NDA signed", column5: 'NDA signed',
column6: "Contract #102", column6: 'Contract #102',
processName: "Payment Process", processName: 'Payment Process',
zone: "E" zone: 'E',
}, },
{ {
column1: "Deposit Project", column1: 'Deposit Project',
column2: "private", column2: 'private',
column3: "Deposit", column3: 'Deposit',
column4: "6 months", column4: '6 months',
column5: "Terms accepted", column5: 'Terms accepted',
column6: "Contract #103", column6: 'Contract #103',
processName: "Deposit Process", processName: 'Deposit Process',
zone: "F" zone: 'F',
}, },
{ {
column1: "Artefact Project", column1: 'Artefact Project',
column2: "public", column2: 'public',
column3: "Artefact", column3: 'Artefact',
column4: "1 year", column4: '1 year',
column5: "GDPR compliant", column5: 'GDPR compliant',
column6: "Contract #104", column6: 'Contract #104',
processName: "Artefact Process", processName: 'Artefact Process',
zone: "G" zone: 'G',
}, },
{ {
column1: "Resolve Project", column1: 'Resolve Project',
column2: "private", column2: 'private',
column3: "Resolve", column3: 'Resolve',
column4: "2 years", column4: '2 years',
column5: "IP rights", column5: 'IP rights',
column6: "Contract #105", column6: 'Contract #105',
processName: "Resolve Process", processName: 'Resolve Process',
zone: "H" zone: 'H',
}, },
{ {
column1: "Backup Project", column1: 'Backup Project',
column2: "public", column2: 'public',
column3: "Backup", column3: 'Backup',
column4: "1 year", column4: '1 year',
column5: "NDA signed", column5: 'NDA signed',
column6: "Contract #106", column6: 'Contract #106',
processName: "Backup Process", processName: 'Backup Process',
zone: "I" zone: 'I',
} },
]; ];
export const mockProcessRows = [ export const mockProcessRows = [
{ {
process: "User Project", process: 'User Project',
role: "User", role: 'User',
notification: { notification: {
messages: [ messages: [
{ id: 1, read: false, date: "2024-03-10", message: "New user joined the project" }, { 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: 2, read: false, date: '2024-03-09', message: 'Project milestone reached' },
{ id: 3, read: false, date: "2024-03-08", message: "Security update required" }, { 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: 4, read: true, date: '2024-03-07', message: 'Weekly report available' },
{ id: 5, read: true, date: "2024-03-06", message: "Team meeting scheduled" } { id: 5, read: true, date: '2024-03-06', message: 'Team meeting scheduled' },
] ],
} },
}, },
{ {
process: "Member Project", process: 'Member Project',
role: "Member", role: 'Member',
notification: { notification: {
messages: [ messages: [
{ id: 6, read: true, date: "2024-03-10", message: "Member access granted" }, { id: 6, read: true, date: '2024-03-10', message: 'Member access granted' },
{ id: 7, read: true, date: "2024-03-09", message: "Documentation updated" }, { id: 7, read: true, date: '2024-03-09', message: 'Documentation updated' },
{ id: 8, read: true, date: "2024-03-08", message: "Project status: on track" } { id: 8, read: true, date: '2024-03-08', message: 'Project status: on track' },
] ],
} },
}, },
{ {
process: "Peer Project", process: 'Peer Project',
role: "Peer", role: 'Peer',
notification: { notification: {
unread: 2, unread: 2,
total: 4, total: 4,
messages: [ messages: [
{ id: 9, read: false, date: "2024-03-10", message: "New peer project added" }, { 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: 10, read: false, date: '2024-03-09', message: 'Project milestone reached' },
{ id: 11, read: false, date: "2024-03-08", message: "Security update required" }, { 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: 12, read: true, date: '2024-03-07', message: 'Weekly report available' },
{ id: 13, read: true, date: "2024-03-06", message: "Team meeting scheduled" } { id: 13, read: true, date: '2024-03-06', message: 'Team meeting scheduled' },
] ],
} },
}, },
{ {
process: "Deposit Project", process: 'Deposit Project',
role: "Deposit", role: 'Deposit',
notification: { notification: {
unread: 1, unread: 1,
total: 10, total: 10,
messages: [ messages: [
{ id: 14, read: false, date: "2024-03-10", message: "Deposit milestone reached" }, { 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: 15, read: false, date: '2024-03-09', message: 'Security update required' },
{ id: 16, read: false, date: "2024-03-08", message: "Weekly report available" }, { 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: 17, read: true, date: '2024-03-07', message: 'Team meeting scheduled' },
{ id: 18, read: true, date: "2024-03-06", message: "Project status: on track" } { id: 18, read: true, date: '2024-03-06', message: 'Project status: on track' },
] ],
} },
}, },
{ {
process: "Artefact Project", process: 'Artefact Project',
role: "Artefact", role: 'Artefact',
notification: { notification: {
unread: 0, unread: 0,
total: 3, total: 3,
messages: [ messages: [
{ id: 19, read: false, date: "2024-03-10", message: "New artefact added" }, { 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: 20, read: false, date: '2024-03-09', message: 'Security update required' },
{ id: 21, read: false, date: "2024-03-08", message: "Weekly report available" }, { 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: 22, read: true, date: '2024-03-07', message: 'Team meeting scheduled' },
{ id: 23, read: true, date: "2024-03-06", message: "Project status: on track" } { id: 23, read: true, date: '2024-03-06', message: 'Project status: on track' },
] ],
} },
}, },
{ {
process: "Resolve Project", process: 'Resolve Project',
role: "Resolve", role: 'Resolve',
notification: { notification: {
unread: 5, unread: 5,
total: 12, total: 12,
messages: [ messages: [
{ id: 24, read: false, date: "2024-03-10", message: "New issue reported" }, { 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: 25, read: false, date: '2024-03-09', message: 'Security update required' },
{ id: 26, read: false, date: "2024-03-08", message: "Weekly report available" }, { 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: 27, read: true, date: '2024-03-07', message: 'Team meeting scheduled' },
{ id: 28, read: true, date: "2024-03-06", message: "Project status: on track" } { id: 28, read: true, date: '2024-03-06', message: 'Project status: on track' },
] ],
} },
} },
]; ];
export const mockContracts = { export const mockContracts = {
'Contract #123': { 'Contract #123': {
title: "User Project Agreement", title: 'User Project Agreement',
date: "2024-01-15", date: '2024-01-15',
parties: ["Company XYZ", "User Team"], parties: ['Company XYZ', 'User Team'],
terms: [ terms: ['Data Protection', 'User Privacy', 'Access Rights', 'Service Level Agreement'],
"Data Protection", content: 'This agreement establishes the terms and conditions for user project management.',
"User Privacy",
"Access Rights",
"Service Level Agreement"
],
content: "This agreement establishes the terms and conditions for user project management."
}, },
'Contract #456': { 'Contract #456': {
title: "Process Management Contract", title: 'Process Management Contract',
date: "2024-02-01", date: '2024-02-01',
parties: ["Company XYZ", "Process Team"], parties: ['Company XYZ', 'Process Team'],
terms: [ terms: ['Process Workflow', 'Quality Standards', 'Performance Metrics', 'Monitoring Procedures'],
"Process Workflow", content: 'This contract defines the process management standards and procedures.',
"Quality Standards",
"Performance Metrics",
"Monitoring Procedures"
],
content: "This contract defines the process management standards and procedures."
}, },
'Contract #789': { 'Contract #789': {
title: "Member Access Agreement", title: 'Member Access Agreement',
date: "2024-03-15", date: '2024-03-15',
parties: ["Company XYZ", "Member Team"], parties: ['Company XYZ', 'Member Team'],
terms: [ terms: ['Member Rights', 'Access Levels', 'Security Protocol', 'Confidentiality Agreement'],
"Member Rights", content: 'This agreement outlines the terms for member access and privileges.',
"Access Levels",
"Security Protocol",
"Confidentiality Agreement"
],
content: "This agreement outlines the terms for member access and privileges."
}, },
'Contract #101': { 'Contract #101': {
title: "Peer Collaboration Agreement", title: 'Peer Collaboration Agreement',
date: "2024-04-01", date: '2024-04-01',
parties: ["Company XYZ", "Peer Network"], parties: ['Company XYZ', 'Peer Network'],
terms: [ terms: ['Collaboration Rules', 'Resource Sharing', 'Dispute Resolution', 'Network Protocol'],
"Collaboration Rules", content: 'This contract establishes peer collaboration and networking guidelines.',
"Resource Sharing",
"Dispute Resolution",
"Network Protocol"
],
content: "This contract establishes peer collaboration and networking guidelines."
}, },
'Contract #102': { 'Contract #102': {
title: "Payment Processing Agreement", title: 'Payment Processing Agreement',
date: "2024-05-01", date: '2024-05-01',
parties: ["Company XYZ", "Payment Team"], parties: ['Company XYZ', 'Payment Team'],
terms: [ terms: ['Transaction Protocol', 'Security Measures', 'Fee Structure', 'Service Availability'],
"Transaction Protocol", content: 'This agreement defines payment processing terms and conditions.',
"Security Measures",
"Fee Structure",
"Service Availability"
],
content: "This agreement defines payment processing terms and conditions."
}, },
'Contract #103': { 'Contract #103': {
title: "Deposit Management Contract", title: 'Deposit Management Contract',
date: "2024-06-01", date: '2024-06-01',
parties: ["Company XYZ", "Deposit Team"], parties: ['Company XYZ', 'Deposit Team'],
terms: [ terms: ['Deposit Rules', 'Storage Protocol', 'Access Control', 'Security Standards'],
"Deposit Rules", content: 'This contract outlines deposit management procedures and security measures.',
"Storage Protocol",
"Access Control",
"Security Standards"
],
content: "This contract outlines deposit management procedures and security measures."
}, },
'Contract #104': { 'Contract #104': {
title: "Artefact Handling Agreement", title: 'Artefact Handling Agreement',
date: "2024-07-01", date: '2024-07-01',
parties: ["Company XYZ", "Artefact Team"], parties: ['Company XYZ', 'Artefact Team'],
terms: [ terms: ['Handling Procedures', 'Storage Guidelines', 'Access Protocol', 'Preservation Standards'],
"Handling Procedures", content: 'This agreement establishes artefact handling and preservation guidelines.',
"Storage Guidelines",
"Access Protocol",
"Preservation Standards"
],
content: "This agreement establishes artefact handling and preservation guidelines."
}, },
'Contract #105': { 'Contract #105': {
title: "Resolution Protocol Agreement", title: 'Resolution Protocol Agreement',
date: "2024-08-01", date: '2024-08-01',
parties: ["Company XYZ", "Resolution Team"], parties: ['Company XYZ', 'Resolution Team'],
terms: [ terms: ['Resolution Process', 'Time Constraints', 'Escalation Protocol', 'Documentation Requirements'],
"Resolution Process", content: 'This contract defines the resolution process and protocol standards.',
"Time Constraints",
"Escalation Protocol",
"Documentation Requirements"
],
content: "This contract defines the resolution process and protocol standards."
}, },
'Contract #106': { 'Contract #106': {
title: "Backup Service Agreement", title: 'Backup Service Agreement',
date: "2024-09-01", date: '2024-09-01',
parties: ["Company XYZ", "Backup Team"], parties: ['Company XYZ', 'Backup Team'],
terms: [ terms: ['Backup Schedule', 'Data Protection', 'Recovery Protocol', 'Service Reliability'],
"Backup Schedule", content: 'This agreement outlines backup service terms and recovery procedures.',
"Data Protection", },
"Recovery Protocol",
"Service Reliability"
],
content: "This agreement outlines backup service terms and recovery procedures."
}
}; };

View File

@ -1,40 +1,52 @@
export const groupsMock = [ export const groupsMock = [
{ {
id: 1, id: 1,
name: "Group 🚀 ", name: 'Group 🚀 ',
roles: [ roles: [
{ {
id: 1, id: 1,
name: "Role 1", name: 'Role 1',
members: [{ id: 1, name: "Member 1" }, { id: 2, name: "Member 2" }] members: [
{ id: 1, name: 'Member 1' },
{ id: 2, name: 'Member 2' },
],
}, },
{ {
id: 2, id: 2,
name: "Role 2", name: 'Role 2',
members: [{ id: 3, name: "Member 3" }, { id: 4, name: "Member 4" }] members: [
} { id: 3, name: 'Member 3' },
] { id: 4, name: 'Member 4' },
],
},
],
}, },
{ {
id: 2, id: 2,
name: "Group ₿", name: 'Group ₿',
roles: [ roles: [
{ {
id: 3, id: 3,
name: "Role 1", name: 'Role 1',
members: [{ id: 5, name: "Member 5" }, { id: 6, name: "Member 6" }] members: [
} { id: 5, name: 'Member 5' },
] { id: 6, name: 'Member 6' },
],
},
],
}, },
{ {
id: 3, id: 3,
name: "Group 🪙", name: 'Group 🪙',
roles: [ roles: [
{ {
id: 4, id: 4,
name: "Role 1", name: 'Role 1',
members: [{ id: 7, name: "Member 7" }, { id: 8, name: "Member 8" }] members: [
} { id: 7, name: 'Member 7' },
] { id: 8, name: 'Member 8' },
} ],
},
],
},
]; ];

View File

@ -2,64 +2,63 @@ export const messagesMock = [
{ {
memberId: 1, // Conversations avec Mmber 1 memberId: 1, // Conversations avec Mmber 1
messages: [ messages: [
{ id: 1, sender: "Member 1", text: "Salut !", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Tout va bien, merci !', time: '10:32 AM' },
] ],
}, },
{ {
memberId: 2, // Conversations avec Member 2 memberId: 2, // Conversations avec Member 2
messages: [ messages: [
{ id: 1, sender: "Member 2", text: "Salut, on se voit ce soir ?", time: "10:30 AM" }, { 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" } { id: 2, sender: '4NK', text: 'Oui, à quelle heure ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 3, // Conversations avec Member 3 memberId: 3, // Conversations avec Member 3
messages: [ messages: [
{ id: 1, sender: "Member 3", text: "Hey, ça va ?", time: "10:30 AM" }, { 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" } { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 4, // Conversations avec Member 4 memberId: 4, // Conversations avec Member 4
messages: [ messages: [
{ id: 1, sender: "Member 4", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 5, // Conversations avec Member 5 memberId: 5, // Conversations avec Member 5
messages: [ messages: [
{ id: 1, sender: "Member 5", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 6, // Conversations avec Member 6 memberId: 6, // Conversations avec Member 6
messages: [ messages: [
{ id: 1, sender: "Member 6", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 7, // Conversations avec Member 7 memberId: 7, // Conversations avec Member 7
messages: [ messages: [
{ id: 1, sender: "Member 7", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 8, // Conversations avec Member 8 memberId: 8, // Conversations avec Member 8
messages: [ messages: [
{ id: 1, sender: "Member 8", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
} },
]; ];

View File

@ -1,29 +1,19 @@
// Définir les rôles autorisés // Définir les rôles autorisés
const VALID_ROLES = [ const VALID_ROLES = ['User', 'Process', 'Member', 'Peer', 'Payment', 'Deposit', 'Artefact', 'Resolve', 'Backup'];
"User",
"Process",
"Member",
"Peer",
"Payment",
"Deposit",
"Artefact",
"Resolve",
"Backup"
];
const VISIBILITY_LEVELS = { const VISIBILITY_LEVELS = {
PUBLIC: "public", PUBLIC: 'public',
CONFIDENTIAL: "confidential", CONFIDENTIAL: 'confidential',
PRIVATE: "private", PRIVATE: 'private',
}; };
const DOCUMENT_STATUS = { const DOCUMENT_STATUS = {
DRAFT: "draft", DRAFT: 'draft',
PENDING: "pending", PENDING: 'pending',
IN_REVIEW: "in_review", IN_REVIEW: 'in_review',
APPROVED: "approved", APPROVED: 'approved',
REJECTED: "rejected", REJECTED: 'rejected',
EXPIRED: "expired" EXPIRED: 'expired',
}; };
// Fonction pour créer un rôle // Fonction pour créer un rôle
@ -37,424 +27,445 @@ function createRole(name, members) {
export const groupsMock = [ export const groupsMock = [
{ {
id: 1, id: 1,
name: "Processus 1", name: 'Processus 1',
description: "Description du processus 1", description: 'Description du processus 1',
commonDocuments: [ commonDocuments: [
{ {
id: 101, id: 101,
name: "Règlement intérieur", name: 'Règlement intérieur',
description: "Document vierge pour le règlement intérieur", description: 'Document vierge pour le règlement intérieur',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 102, id: 102,
name: "Charte de confidentialité", name: 'Charte de confidentialité',
description: "Document vierge pour la charte de confidentialité", description: 'Document vierge pour la charte de confidentialité',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 103, id: 103,
name: "Procédures générales", name: 'Procédures générales',
description: "Document vierge pour les procédures générales", description: 'Document vierge pour les procédures générales',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 104, id: 104,
name: "Urgency A", name: 'Urgency A',
description: "Document vierge pour le plan d'urgence A", description: "Document vierge pour le plan d'urgence A",
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 105, id: 105,
name: "Urgency B", name: 'Urgency B',
description: "Document vierge pour le plan d'urgence B", description: "Document vierge pour le plan d'urgence B",
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 106, id: 106,
name: "Urgency C", name: 'Urgency C',
description: "Document vierge pour le plan d'urgence C", description: "Document vierge pour le plan d'urgence C",
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 107, id: 107,
name: "Document à signer", name: 'Document à signer',
description: "Document vierge pour le règlement intérieur", description: 'Document vierge pour le règlement intérieur',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
], ],
roles: [ roles: [
{ {
name: "User", name: 'User',
members: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }], members: [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
],
documents: [ documents: [
{ {
id: 1, id: 1,
name: "Document User A", name: 'Document User A',
description: "Description du document User A.", description: 'Description du document User A.',
visibility: "public", visibility: 'public',
createdAt: "2024-01-01", createdAt: '2024-01-01',
deadline: "2024-02-01", deadline: '2024-02-01',
signatures: [ signatures: [
{ {
member: { id: 1, name: "Alice" }, member: { id: 1, name: 'Alice' },
signed: true, signed: true,
signedAt: "2024-01-15" signedAt: '2024-01-15',
}, },
{ {
member: { id: 2, name: "Bob" }, member: { id: 2, name: 'Bob' },
signed: false signed: false,
} },
] ],
}, },
{ {
id: 2, id: 2,
name: "Document User B", name: 'Document User B',
description: "Document vierge pour le rôle User", description: 'Document vierge pour le rôle User',
visibility: "confidential", visibility: 'confidential',
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 7, id: 7,
name: "Document User C", name: 'Document User C',
description: "Document vierge pour validation utilisateur", description: 'Document vierge pour validation utilisateur',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 8, id: 8,
name: "Document User D", name: 'Document User D',
description: "Document vierge pour approbation utilisateur", description: 'Document vierge pour approbation utilisateur',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
] ],
}, },
{ {
name: "Process", name: 'Process',
members: [{ id: 3, name: "Charlie" }, { id: 4, name: "David" }], members: [
{ id: 3, name: 'Charlie' },
{ id: 4, name: 'David' },
],
documents: [ documents: [
{ {
id: 3, id: 3,
name: "Document Process A", name: 'Document Process A',
description: "Description du document Process A.", description: 'Description du document Process A.',
visibility: "confidential", visibility: 'confidential',
createdAt: "2024-01-10", createdAt: '2024-01-10',
deadline: "2024-03-01", deadline: '2024-03-01',
signatures: [ signatures: [
{ {
member: { id: 3, name: "Charlie" }, member: { id: 3, name: 'Charlie' },
signed: true, signed: true,
signedAt: "2024-01-12" signedAt: '2024-01-12',
} },
] ],
}, },
{ {
id: 9, id: 9,
name: "Document Process B", name: 'Document Process B',
description: "Document vierge pour processus interne", description: 'Document vierge pour processus interne',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 10, id: 10,
name: "Document Process C", name: 'Document Process C',
description: "Document vierge pour validation processus", description: 'Document vierge pour validation processus',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 11, id: 11,
name: "Document Process D", name: 'Document Process D',
description: "Document vierge pour validation processus", description: 'Document vierge pour validation processus',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.PENDING, status: DOCUMENT_STATUS.PENDING,
createdAt: "2024-01-15", createdAt: '2024-01-15',
deadline: "2024-02-01", deadline: '2024-02-01',
signatures: [ signatures: [
{ {
member: { id: 3, name: "Charlie" }, member: { id: 3, name: 'Charlie' },
signed: true, signed: true,
signedAt: "2024-01-15" signedAt: '2024-01-15',
}, },
{ {
member: { id: 4, name: "David" }, member: { id: 4, name: 'David' },
signed: false signed: false,
} },
] ],
}, },
{ {
id: 12, id: 12,
name: "Document Process E", name: 'Document Process E',
description: "Document vierge pour validation processus", description: 'Document vierge pour validation processus',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.PENDING, status: DOCUMENT_STATUS.PENDING,
createdAt: "2024-01-15", createdAt: '2024-01-15',
deadline: "2024-02-01", deadline: '2024-02-01',
signatures: [ signatures: [
{ {
member: { id: 3, name: "Charlie" }, member: { id: 3, name: 'Charlie' },
signed: true, signed: true,
signedAt: "2024-01-15" signedAt: '2024-01-15',
}, },
{ {
member: { id: 4, name: "David" }, member: { id: 4, name: 'David' },
signed: false signed: false,
} },
] ],
} },
] ],
}, },
{ {
name: "Backup", name: 'Backup',
members: [{ id: 15, name: "Oscar" }, { id: 16, name: "Patricia" }], members: [
{ id: 15, name: 'Oscar' },
{ id: 16, name: 'Patricia' },
],
documents: [ documents: [
{ {
id: 11, id: 11,
name: "Document Backup A", name: 'Document Backup A',
description: "Document vierge pour sauvegarde", description: 'Document vierge pour sauvegarde',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
] ],
} },
] ],
}, },
{ {
id: 2, id: 2,
name: "Processus 2", name: 'Processus 2',
description: "Description du processus 2", description: 'Description du processus 2',
commonDocuments: [ commonDocuments: [
{ {
id: 201, id: 201,
name: "Règlement intérieur", name: 'Règlement intérieur',
description: "Document vierge pour le règlement intérieur", description: 'Document vierge pour le règlement intérieur',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 202, id: 202,
name: "Charte de confidentialité", name: 'Charte de confidentialité',
description: "Document vierge pour la charte de confidentialité", description: 'Document vierge pour la charte de confidentialité',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 203, id: 203,
name: "Charte de confidentialité", name: 'Charte de confidentialité',
description: "Document vierge pour la charte de confidentialité", description: 'Document vierge pour la charte de confidentialité',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 204, id: 204,
name: "Charte de confidentialité", name: 'Charte de confidentialité',
description: "Document vierge pour la charte de confidentialité", description: 'Document vierge pour la charte de confidentialité',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 205, id: 205,
name: "Charte de confidentialité", name: 'Charte de confidentialité',
description: "Document vierge pour la charte de confidentialité", description: 'Document vierge pour la charte de confidentialité',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
], ],
roles: [ roles: [
{ {
name: "Artefact", name: 'Artefact',
members: [{ id: 17, name: "Quinn" }, { id: 18, name: "Rachel" }], members: [
{ id: 17, name: 'Quinn' },
{ id: 18, name: 'Rachel' },
],
documents: [ documents: [
{ {
id: 12, id: 12,
name: "Document Artefact A", name: 'Document Artefact A',
description: "Document vierge pour artefact", description: 'Document vierge pour artefact',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 13, id: 13,
name: "Document Artefact B", name: 'Document Artefact B',
description: "Document vierge pour validation artefact", description: 'Document vierge pour validation artefact',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
] ],
}, },
{ {
name: "Resolve", name: 'Resolve',
members: [{ id: 19, name: "Sam" }, { id: 20, name: "Tom" }], members: [
{ id: 19, name: 'Sam' },
{ id: 20, name: 'Tom' },
],
documents: [ documents: [
{ {
id: 14, id: 14,
name: "Document Resolve A", name: 'Document Resolve A',
description: "Document vierge pour résolution", description: 'Document vierge pour résolution',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
] ],
} },
] ],
}, },
{ {
id: 3, id: 3,
name: "Processus 3", name: 'Processus 3',
description: "Description du processus 3", description: 'Description du processus 3',
commonDocuments: [ commonDocuments: [
{ {
id: 301, id: 301,
name: "Règlement intérieur", name: 'Règlement intérieur',
description: "Document vierge pour le règlement intérieur", description: 'Document vierge pour le règlement intérieur',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 302, id: 302,
name: "Charte de confidentialité", name: 'Charte de confidentialité',
description: "Document vierge pour la charte de confidentialité", description: 'Document vierge pour la charte de confidentialité',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 303, id: 303,
name: "Procédures générales", name: 'Procédures générales',
description: "Document vierge pour les procédures générales", description: 'Document vierge pour les procédures générales',
visibility: VISIBILITY_LEVELS.PUBLIC, visibility: VISIBILITY_LEVELS.PUBLIC,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
], ],
roles: [ roles: [
{ {
name: "Deposit", name: 'Deposit',
members: [{ id: 21, name: "Uma" }, { id: 22, name: "Victor" }], members: [
{ id: 21, name: 'Uma' },
{ id: 22, name: 'Victor' },
],
documents: [ documents: [
{ {
id: 15, id: 15,
name: "Document Deposit A", name: 'Document Deposit A',
description: "Document vierge pour dépôt", description: 'Document vierge pour dépôt',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 16, id: 16,
name: "Document Deposit B", name: 'Document Deposit B',
description: "Document vierge pour validation dépôt", description: 'Document vierge pour validation dépôt',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
] ],
}, },
{ {
name: "Payment", name: 'Payment',
members: [{ id: 23, name: "Walter" }, { id: 24, name: "Xena" }], members: [
{ id: 23, name: 'Walter' },
{ id: 24, name: 'Xena' },
],
documents: [ documents: [
{ {
id: 17, id: 17,
name: "Document Payment B", name: 'Document Payment B',
description: "Document vierge pour paiement", description: 'Document vierge pour paiement',
visibility: VISIBILITY_LEVELS.PRIVATE, visibility: VISIBILITY_LEVELS.PRIVATE,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
}, },
{ {
id: 18, id: 18,
name: "Document Payment C", name: 'Document Payment C',
description: "Document vierge pour validation paiement", description: 'Document vierge pour validation paiement',
visibility: VISIBILITY_LEVELS.CONFIDENTIAL, visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
status: DOCUMENT_STATUS.DRAFT, status: DOCUMENT_STATUS.DRAFT,
createdAt: null, createdAt: null,
deadline: null, deadline: null,
signatures: [] signatures: [],
} },
] ],
} },
] ],
} },
]; ];

View File

@ -2,104 +2,104 @@ export const membersMock = [
// Processus 1 // Processus 1
{ {
id: 1, id: 1,
name: "Alice", name: 'Alice',
avatar: "A", avatar: 'A',
email: "alice@company.com", email: 'alice@company.com',
processRoles: [{ processId: 1, role: "User" }] processRoles: [{ processId: 1, role: 'User' }],
}, },
{ {
id: 2, id: 2,
name: "Bob", name: 'Bob',
avatar: "B", avatar: 'B',
email: "bob@company.com", email: 'bob@company.com',
processRoles: [{ processId: 1, role: "User" }] processRoles: [{ processId: 1, role: 'User' }],
}, },
{ {
id: 3, id: 3,
name: "Charlie", name: 'Charlie',
avatar: "C", avatar: 'C',
email: "charlie@company.com", email: 'charlie@company.com',
processRoles: [{ processId: 1, role: "Process" }] processRoles: [{ processId: 1, role: 'Process' }],
}, },
{ {
id: 4, id: 4,
name: "David", name: 'David',
avatar: "D", avatar: 'D',
email: "david@company.com", email: 'david@company.com',
processRoles: [{ processId: 1, role: "Process" }] processRoles: [{ processId: 1, role: 'Process' }],
}, },
{ {
id: 15, id: 15,
name: "Oscar", name: 'Oscar',
avatar: "O", avatar: 'O',
email: "oscar@company.com", email: 'oscar@company.com',
processRoles: [{ processId: 1, role: "Backup" }] processRoles: [{ processId: 1, role: 'Backup' }],
}, },
{ {
id: 16, id: 16,
name: "Patricia", name: 'Patricia',
avatar: "P", avatar: 'P',
email: "patricia@company.com", email: 'patricia@company.com',
processRoles: [{ processId: 1, role: "Backup" }] processRoles: [{ processId: 1, role: 'Backup' }],
}, },
// Processus 2 // Processus 2
{ {
id: 17, id: 17,
name: "Quinn", name: 'Quinn',
avatar: "Q", avatar: 'Q',
email: "quinn@company.com", email: 'quinn@company.com',
processRoles: [{ processId: 2, role: "Artefact" }] processRoles: [{ processId: 2, role: 'Artefact' }],
}, },
{ {
id: 18, id: 18,
name: "Rachel", name: 'Rachel',
avatar: "R", avatar: 'R',
email: "rachel@company.com", email: 'rachel@company.com',
processRoles: [{ processId: 2, role: "Artefact" }] processRoles: [{ processId: 2, role: 'Artefact' }],
}, },
{ {
id: 19, id: 19,
name: "Sam", name: 'Sam',
avatar: "S", avatar: 'S',
email: "sam@company.com", email: 'sam@company.com',
processRoles: [{ processId: 2, role: "Resolve" }] processRoles: [{ processId: 2, role: 'Resolve' }],
}, },
{ {
id: 20, id: 20,
name: "Tom", name: 'Tom',
avatar: "T", avatar: 'T',
email: "tom@company.com", email: 'tom@company.com',
processRoles: [{ processId: 2, role: "Resolve" }] processRoles: [{ processId: 2, role: 'Resolve' }],
}, },
// Processus 3 // Processus 3
{ {
id: 21, id: 21,
name: "Uma", name: 'Uma',
avatar: "U", avatar: 'U',
email: "uma@company.com", email: 'uma@company.com',
processRoles: [{ processId: 3, role: "Deposit" }] processRoles: [{ processId: 3, role: 'Deposit' }],
}, },
{ {
id: 22, id: 22,
name: "Victor", name: 'Victor',
avatar: "V", avatar: 'V',
email: "victor@company.com", email: 'victor@company.com',
processRoles: [{ processId: 3, role: "Deposit" }] processRoles: [{ processId: 3, role: 'Deposit' }],
}, },
{ {
id: 23, id: 23,
name: "Walter", name: 'Walter',
avatar: "W", avatar: 'W',
email: "walter@company.com", email: 'walter@company.com',
processRoles: [{ processId: 3, role: "Payment" }] processRoles: [{ processId: 3, role: 'Payment' }],
}, },
{ {
id: 24, id: 24,
name: "Xena", name: 'Xena',
avatar: "X", avatar: 'X',
email: "xena@company.com", email: 'xena@company.com',
processRoles: [{ processId: 3, role: "Payment" }] processRoles: [{ processId: 3, role: 'Payment' }],
} },
]; ];

View File

@ -2,64 +2,63 @@ export const messagesMock = [
{ {
memberId: 1, // Conversations avec Mmber 1 memberId: 1, // Conversations avec Mmber 1
messages: [ messages: [
{ id: 1, sender: "Mmeber 1", text: "Salut !", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Tout va bien, merci !', time: '10:32 AM' },
] ],
}, },
{ {
memberId: 2, // Conversations avec Member 2 memberId: 2, // Conversations avec Member 2
messages: [ messages: [
{ id: 1, sender: "Member 2", text: "Salut, on se voit ce soir ?", time: "10:30 AM" }, { 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" } { id: 2, sender: '4NK', text: 'Oui, à quelle heure ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 3, // Conversations avec Member 3 memberId: 3, // Conversations avec Member 3
messages: [ messages: [
{ id: 1, sender: "Member 3", text: "Hey, ça va ?", time: "10:30 AM" }, { 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" } { id: 2, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 4, // Conversations avec Member 4 memberId: 4, // Conversations avec Member 4
messages: [ messages: [
{ id: 1, sender: "Member 4", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 5, // Conversations avec Member 5 memberId: 5, // Conversations avec Member 5
messages: [ messages: [
{ id: 1, sender: "Member 5", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 6, // Conversations avec Member 6 memberId: 6, // Conversations avec Member 6
messages: [ messages: [
{ id: 1, sender: "Member 6", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 7, // Conversations avec Member 7 memberId: 7, // Conversations avec Member 7
messages: [ messages: [
{ id: 1, sender: "Member 7", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
}, },
{ {
memberId: 8, // Conversations avec Member 8 memberId: 8, // Conversations avec Member 8
messages: [ messages: [
{ id: 1, sender: "Member 8", text: "Hey, ça va ?", time: "10:30 AM" }, { 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: 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" } { id: 3, sender: '4NK', text: 'Ça va et toi ?', time: '10:31 AM' },
] ],
} },
]; ];

View File

@ -19,12 +19,12 @@ export interface IMessage {
} }
export interface UserDiff { export interface UserDiff {
new_state_merkle_root: string, // TODO add a merkle proof that the new_value belongs to that state new_state_merkle_root: string; // TODO add a merkle proof that the new_value belongs to that state
field: string, field: string;
previous_value: string, previous_value: string;
new_value: string, new_value: string;
notify_user: boolean, notify_user: boolean;
need_validation: boolean, need_validation: boolean;
// validated: bool, // 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 proof: any; // This is only validation (or refusal) for that specific diff, not the whole state. It can't be commited as such
} }

View File

@ -5,7 +5,7 @@ export interface Group {
roles: { roles: {
id?: number; id?: number;
name: string; name: string;
members: { id: string | number; name: string; }[]; members: { id: string | number; name: string }[];
documents?: { documents?: {
id: number; id: number;
name: string; name: string;

View File

@ -1,21 +1,21 @@
import { AccountElement } from './account'; import { AccountElement } from './account';
import accountCss from '../../../public/style/account.css?raw' import accountCss from '../../../public/style/account.css?raw';
import Services from '../../services/service.js' import Services from '../../services/service.js';
class AccountComponent extends HTMLElement { class AccountComponent extends HTMLElement {
_callback: any _callback: any;
accountElement: AccountElement | null = null; accountElement: AccountElement | null = null;
constructor() { constructor() {
super(); super();
console.log('INIT') console.log('INIT');
this.attachShadow({ mode: 'open' }); this.attachShadow({ mode: 'open' });
this.accountElement = this.shadowRoot?.querySelector('account-element') || null; this.accountElement = this.shadowRoot?.querySelector('account-element') || null;
} }
connectedCallback() { connectedCallback() {
console.log('CALLBACKs') console.log('CALLBACKs');
this.render(); this.render();
this.fetchData(); this.fetchData();
@ -28,7 +28,7 @@ class AccountComponent extends HTMLElement {
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) { if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) {
const data = await (window as any).myService?.getProcesses(); const data = await (window as any).myService?.getProcesses();
} else { } else {
const service = await Services.getInstance() const service = await Services.getInstance();
const data = await service.getProcesses(); const data = await service.getProcesses();
} }
} }
@ -54,10 +54,9 @@ class AccountComponent extends HTMLElement {
this.shadowRoot.appendChild(style); this.shadowRoot.appendChild(style);
this.shadowRoot.appendChild(accountElement); this.shadowRoot.appendChild(accountElement);
} }
} }
} }
export { AccountComponent } export { AccountComponent };
customElements.define('account-component', AccountComponent); customElements.define('account-component', AccountComponent);

View File

@ -1,11 +1,11 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Account</title> <title>Account</title>
<link rel="stylesheet" href="../../public/style/account.css"> <link rel="stylesheet" href="../../public/style/account.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
</head> </head>
<body> <body>
<!-- Header Container --> <!-- Header Container -->
@ -20,10 +20,10 @@
<!-- Banner Preview Section --> <!-- Banner Preview Section -->
<div class="banner-preview"> <div class="banner-preview">
<div class="banner-image-container"> <div class="banner-image-container">
<img src="https://via.placeholder.com/800x200" alt="Banner" class="banner-image" id="popup-banner-img"> <img src="https://via.placeholder.com/800x200" alt="Banner" class="banner-image" id="popup-banner-img" />
<div class="banner-content"> <div class="banner-content">
<div class="avatar-container"> <div class="avatar-container">
<img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" id="popup-avatar-img"> <img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" id="popup-avatar-img" />
</div> </div>
<div class="user-info"> <div class="user-info">
<span class="editable" id="popup-name"></span> <span class="editable" id="popup-name"></span>
@ -34,7 +34,7 @@
<div class="banner-controls"> <div class="banner-controls">
<label for="banner-upload" class="banner-upload-label button-style"> <label for="banner-upload" class="banner-upload-label button-style">
Change Banner Image Change Banner Image
<input type="file" id="banner-upload" accept="image/*" style="display: none;"> <input type="file" id="banner-upload" accept="image/*" style="display: none" />
</label> </label>
</div> </div>
</div> </div>
@ -42,12 +42,12 @@
<!-- Avatar Upload Section --> <!-- Avatar Upload Section -->
<div class="popup-avatar"> <div class="popup-avatar">
<label for="avatar-upload" class="avatar-upload-label"> <label for="avatar-upload" class="avatar-upload-label">
<img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" id="popup-avatar-img"> <img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" id="popup-avatar-img" />
<div class="avatar-overlay"> <div class="avatar-overlay">
<span>Change Avatar</span> <span>Change Avatar</span>
</div> </div>
</label> </label>
<input type="file" id="avatar-upload" accept="image/*" style="display: none;"> <input type="file" id="avatar-upload" accept="image/*" style="display: none" />
</div> </div>
<!-- User Info Section --> <!-- User Info Section -->
@ -68,10 +68,18 @@
<div class="container"> <div class="container">
<!-- Parameter List --> <!-- Parameter List -->
<div class="parameter-list"> <div class="parameter-list">
<ul class="parameter-list-ul" onclick="window.showPairing()">Pairing 🔗</ul> <ul class="parameter-list-ul" onclick="window.showPairing()">
<ul class="parameter-list-ul" onclick="window.showWallet()">Wallet 👛</ul> Pairing 🔗
<ul class="parameter-list-ul" onclick="window.showProcess()">Process ⚙️</ul> </ul>
<ul class="parameter-list-ul" onclick="window.showData()">Data 💾</ul> <ul class="parameter-list-ul" onclick="window.showWallet()">
Wallet 👛
</ul>
<ul class="parameter-list-ul" onclick="window.showProcess()">
Process ⚙️
</ul>
<ul class="parameter-list-ul" onclick="window.showData()">
Data 💾
</ul>
</div> </div>
<!-- Parameter Area --> <!-- Parameter Area -->

View File

@ -71,15 +71,11 @@ export function showAlert(message: string): void {
class AccountElement extends HTMLElement { class AccountElement extends HTMLElement {
private dom: Node; private dom: Node;
constructor() { constructor() {
super(); super();
this.attachShadow({ mode: 'open' }); this.attachShadow({ mode: 'open' });
this.dom = getCorrectDOM('account-element'); this.dom = getCorrectDOM('account-element');
window.showPairing = () => this.showPairing(); window.showPairing = () => this.showPairing();
window.showWallet = () => this.showWallet(); window.showWallet = () => this.showWallet();
window.showProcess = () => this.showProcess(); window.showProcess = () => this.showProcess();
@ -177,7 +173,6 @@ private loadSavedBanner(): void {
} }
} }
private closeNotificationPopup(event: Event): void { private closeNotificationPopup(event: Event): void {
const target = event.target as HTMLElement; const target = event.target as HTMLElement;
const isOverlay = target.classList.contains('notification-popup-overlay'); const isOverlay = target.classList.contains('notification-popup-overlay');
@ -189,10 +184,10 @@ private closeNotificationPopup(event: Event): void {
} }
private markAsRead(processName: string, messageId: number, element: HTMLElement): void { private markAsRead(processName: string, messageId: number, element: HTMLElement): void {
const process = mockProcessRows.find(p => p.process === processName); const process = mockProcessRows.find((p) => p.process === processName);
if (!process) return; if (!process) return;
const message = process.notification.messages.find(m => m.id === messageId); const message = process.notification.messages.find((m) => m.id === messageId);
if (!message || message.read) return; if (!message || message.read) return;
message.read = true; message.read = true;
@ -222,7 +217,7 @@ private markAsRead(processName: string, messageId: number, element: HTMLElement)
// Fonctions de gestion des données et de l'interface // Fonctions de gestion des données et de l'interface
private calculateNotifications(messages: NotificationMessage[]): { unread: number; total: number } { private calculateNotifications(messages: NotificationMessage[]): { unread: number; total: number } {
const total = messages.length; const total = messages.length;
const unread = messages.filter(msg => !msg.read).length; const unread = messages.filter((msg) => !msg.read).length;
return { unread, total }; return { unread, total };
} }
@ -236,7 +231,7 @@ private exportRecovery(): void {
confirmButtonText: 'Confirm', confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel', cancelButtonText: 'Cancel',
confirmButtonColor: '#C89666', confirmButtonColor: '#C89666',
cancelButtonColor: '#6c757d' cancelButtonColor: '#6c757d',
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
const recoveryWords = this.generateRecoveryWords(); const recoveryWords = this.generateRecoveryWords();
@ -246,12 +241,16 @@ private exportRecovery(): void {
title: 'Your Recovery Words', title: 'Your Recovery Words',
html: ` html: `
<div class="recovery-words-container"> <div class="recovery-words-container">
${recoveryWords.map((word, index) => ` ${recoveryWords
.map(
(word, index) => `
<div class="recovery-word"> <div class="recovery-word">
<span class="word-number">${index + 1}.</span> <span class="word-number">${index + 1}.</span>
<span class="word">${word}</span> <span class="word">${word}</span>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
<div class="recovery-warning"> <div class="recovery-warning">
Please write these words down carefully. They will be needed to recover your account. Please write these words down carefully. They will be needed to recover your account.
@ -261,7 +260,7 @@ private exportRecovery(): void {
confirmButtonText: 'I confirm the export', confirmButtonText: 'I confirm the export',
confirmButtonColor: '#C89666', confirmButtonColor: '#C89666',
allowOutsideClick: false, allowOutsideClick: false,
allowEscapeKey: false allowEscapeKey: false,
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
// Stocker l'état du bouton dans le localStorage // Stocker l'état du bouton dans le localStorage
@ -280,10 +279,7 @@ private exportRecovery(): void {
} }
private generateRecoveryWords(): string[] { private generateRecoveryWords(): string[] {
const wordsList = [ const wordsList = ['apple', 'banana', 'orange', 'grape', 'kiwi', 'mango', 'peach', 'plum', 'lemon', 'lime', 'cherry', 'melon', 'pear', 'fig', 'date', 'berry'];
'apple', 'banana', 'orange', 'grape', 'kiwi', 'mango', 'peach', 'plum',
'lemon', 'lime', 'cherry', 'melon', 'pear', 'fig', 'date', 'berry'
];
const recoveryWords: string[] = []; const recoveryWords: string[] = [];
while (recoveryWords.length < 4) { while (recoveryWords.length < 4) {
const randomWord = wordsList[Math.floor(Math.random() * wordsList.length)]; const randomWord = wordsList[Math.floor(Math.random() * wordsList.length)];
@ -397,7 +393,9 @@ private updateTableContent(rows: Row[]): void {
const tbody = document.querySelector('#pairing-table tbody'); const tbody = document.querySelector('#pairing-table tbody');
if (!tbody) return; if (!tbody) return;
tbody.innerHTML = rows.map(row => ` tbody.innerHTML = rows
.map(
(row) => `
<tr> <tr>
<td>${row.column1}</td> <td>${row.column1}</td>
<td class="device-name" onclick="window.editDeviceName(this)">${row.column2}</td> <td class="device-name" onclick="window.editDeviceName(this)">${row.column2}</td>
@ -408,19 +406,19 @@ private updateTableContent(rows: Row[]): void {
</button> </button>
</td> </td>
</tr> </tr>
`).join(''); `,
)
.join('');
} }
private confirmRow(): void { private confirmRow(): void {
if (!currentRow) return; if (!currentRow) return;
const inputs = currentRow.getElementsByTagName('input'); const inputs = currentRow.getElementsByTagName('input');
const values: string[] = Array.from(inputs).map(input => input.value.trim()); const values: string[] = Array.from(inputs).map((input) => input.value.trim());
// Vérification des champs vides // Vérification des champs vides
if (values.some(value => value === '')) { if (values.some((value) => value === '')) {
showAlert('Please fill in all fields'); showAlert('Please fill in all fields');
return; return;
} }
@ -434,7 +432,7 @@ private confirmRow(): void {
const newRow: Row = { const newRow: Row = {
column1: values[0], column1: values[0],
column2: values[1], column2: values[1],
column3: values[2] column3: values[2],
}; };
const storageKey = STORAGE_KEYS[currentMode]; const storageKey = STORAGE_KEYS[currentMode];
@ -570,7 +568,6 @@ private handleAvatarUpload(event: Event): void {
} }
} }
private showProcess(): void { private showProcess(): void {
//console.log("showProcess called"); //console.log("showProcess called");
currentMode = 'process'; currentMode = 'process';
@ -608,7 +605,9 @@ private updateProcessTableContent(rows: any[]): void {
const tbody = document.querySelector('#process-table tbody'); const tbody = document.querySelector('#process-table tbody');
if (!tbody) return; if (!tbody) return;
tbody.innerHTML = rows.map(row => ` tbody.innerHTML = rows
.map(
(row) => `
<tr> <tr>
<td>${row.process}</td> <td>${row.process}</td>
<td>${row.role}</td> <td>${row.role}</td>
@ -621,19 +620,21 @@ private updateProcessTableContent(rows: any[]): void {
</div> </div>
</td> </td>
</tr> </tr>
`).join(''); `,
)
.join('');
} }
private showProcessNotifications(processName: string): void { private showProcessNotifications(processName: string): void {
const process = mockProcessRows.find(p => p.process === processName); const process = mockProcessRows.find((p) => p.process === processName);
if (!process) return; if (!process) return;
const modal = document.createElement('div'); const modal = document.createElement('div');
modal.className = 'notifications-modal'; modal.className = 'notifications-modal';
let notificationsList = process.notification.messages.map(msg => ` let notificationsList = process.notification.messages
.map(
(msg) => `
<div class="notification-item ${msg.read ? 'read' : 'unread'}" <div class="notification-item ${msg.read ? 'read' : 'unread'}"
onclick="window.markAsRead('${processName}', ${msg.id}, this)"> onclick="window.markAsRead('${processName}', ${msg.id}, this)">
<div class="notification-status"> <div class="notification-status">
@ -644,7 +645,9 @@ private showProcessNotifications(processName: string): void {
<small>${msg.date}</small> <small>${msg.date}</small>
</div> </div>
</div> </div>
`).join(''); `,
)
.join('');
if (process.notification.messages.length === 0) { if (process.notification.messages.length === 0) {
notificationsList = '<p>No notifications</p>'; notificationsList = '<p>No notifications</p>';
@ -676,13 +679,11 @@ private showProcessNotifications(processName: string): void {
}); });
} }
private handleLogout(): void { private handleLogout(): void {
localStorage.clear(); localStorage.clear();
window.location.href = '../login/login.html'; window.location.href = '../login/login.html';
} }
// Fonctions de gestion des contrats // Fonctions de gestion des contrats
private showContractPopup(contractId: string) { private showContractPopup(contractId: string) {
// Empêcher la navigation par défaut // Empêcher la navigation par défaut
@ -706,7 +707,7 @@ private showContractPopup(contractId: string) {
<p><strong>Parties:</strong> ${contract.parties.join(', ')}</p> <p><strong>Parties:</strong> ${contract.parties.join(', ')}</p>
<p><strong>Terms:</strong></p> <p><strong>Terms:</strong></p>
<ul> <ul>
${contract.terms.map(term => `<li>${term}</li>`).join('')} ${contract.terms.map((term) => `<li>${term}</li>`).join('')}
</ul> </ul>
<p><strong>Content:</strong> ${contract.content}</p> <p><strong>Content:</strong> ${contract.content}</p>
</div> </div>
@ -728,11 +729,10 @@ private showContractPopup(contractId: string) {
// Ajouter à l'objet window // Ajouter à l'objet window
// Fonction utilitaire pour cacher tous les contenus // Fonction utilitaire pour cacher tous les contenus
private hideAllContent(): void { private hideAllContent(): void {
const contents = ['pairing-content', 'wallet-content', 'process-content', 'data-content']; const contents = ['pairing-content', 'wallet-content', 'process-content', 'data-content'];
contents.forEach(id => { contents.forEach((id) => {
const element = document.getElementById(id); const element = document.getElementById(id);
if (element) { if (element) {
element.style.display = 'none'; element.style.display = 'none';
@ -742,7 +742,6 @@ private hideAllContent(): void {
// Fonctions d'affichage des sections // Fonctions d'affichage des sections
private showPairing(): void { private showPairing(): void {
isAddingRow = false; isAddingRow = false;
currentRow = null; currentRow = null;
@ -756,7 +755,6 @@ private showPairing(): void {
headerElement.textContent = 'Pairing'; headerElement.textContent = 'Pairing';
} }
// Afficher le contenu de pairing // Afficher le contenu de pairing
const pairingContent = document.getElementById('pairing-content'); const pairingContent = document.getElementById('pairing-content');
@ -825,18 +823,21 @@ private showWallet(): void {
this.updateWalletTableContent(rows); this.updateWalletTableContent(rows);
} }
private updateWalletTableContent(rows: WalletRow[]): void { private updateWalletTableContent(rows: WalletRow[]): void {
const tbody = document.querySelector('#wallet-table tbody'); const tbody = document.querySelector('#wallet-table tbody');
if (!tbody) return; if (!tbody) return;
tbody.innerHTML = rows.map(row => ` tbody.innerHTML = rows
.map(
(row) => `
<tr> <tr>
<td>${row.column1}</td> <td>${row.column1}</td>
<td>${row.column2}</td> <td>${row.column2}</td>
<td class="device-name" onclick="editDeviceName(this)">${row.column3}</td> <td class="device-name" onclick="editDeviceName(this)">${row.column3}</td>
</tr> </tr>
`).join(''); `,
)
.join('');
} }
private showData(): void { private showData(): void {
@ -885,7 +886,7 @@ private addWalletRow(): void {
currentRow = table.insertRow(); currentRow = table.insertRow();
const placeholders = ['Label', 'Wallet', 'Type']; const placeholders = ['Label', 'Wallet', 'Type'];
placeholders.forEach(placeholder => { placeholders.forEach((placeholder) => {
const cell = currentRow!.insertCell(); const cell = currentRow!.insertCell();
const input = document.createElement('input'); const input = document.createElement('input');
input.type = 'text'; input.type = 'text';
@ -912,13 +913,13 @@ private confirmWalletRow(): void {
if (!currentRow) return; if (!currentRow) return;
const inputs = Array.from(currentRow.getElementsByTagName('input')); const inputs = Array.from(currentRow.getElementsByTagName('input'));
const allFieldsFilled = inputs.every(input => input.value.trim() !== ''); const allFieldsFilled = inputs.every((input) => input.value.trim() !== '');
if (allFieldsFilled) { if (allFieldsFilled) {
const newRow: WalletRow = { const newRow: WalletRow = {
column1: inputs[0].value.trim(), column1: inputs[0].value.trim(),
column2: inputs[1].value.trim(), column2: inputs[1].value.trim(),
column3: inputs[2].value.trim() column3: inputs[2].value.trim(),
}; };
const rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.wallet) || '[]'); const rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.wallet) || '[]');
@ -947,15 +948,15 @@ private cancelWalletRow(): void {
buttonContainer.innerHTML = ` buttonContainer.innerHTML = `
<button class="add-row-button button-style" onclick="window.addWalletRow()">Add a line</button> <button class="add-row-button button-style" onclick="window.addWalletRow()">Add a line</button>
`; `;
} }
private updateDataTableContent(rows: DataRow[]): void { private updateDataTableContent(rows: DataRow[]): void {
const tbody = document.querySelector('#data-table tbody'); const tbody = document.querySelector('#data-table tbody');
if (!tbody) return; if (!tbody) return;
tbody.innerHTML = rows.map(row => ` tbody.innerHTML = rows
.map(
(row) => `
<tr> <tr>
<td>${row.column1}</td> <td>${row.column1}</td>
<td>${row.column2}</td> <td>${row.column2}</td>
@ -966,7 +967,9 @@ private updateDataTableContent(rows: DataRow[]): void {
<a href="#" onclick="showContractPopup('${row.column6}')">${row.column6}</a> <a href="#" onclick="showContractPopup('${row.column6}')">${row.column6}</a>
</td> </td>
</tr> </tr>
`).join(''); `,
)
.join('');
} }
// Fonctions de gestion de l'avatar et de la bannière // Fonctions de gestion de l'avatar et de la bannière
@ -1183,7 +1186,6 @@ private loadUserInfo(): void {
this.loadSavedBanner(); this.loadSavedBanner();
} }
private updateNavbarName(name: string): void { private updateNavbarName(name: string): void {
const nameElement = document.querySelector('.nav-wrapper .user-name'); const nameElement = document.querySelector('.nav-wrapper .user-name');
if (nameElement) { if (nameElement) {
@ -1198,15 +1200,13 @@ private loadUserInfo(): void {
} }
} }
private initializeEventListeners() { private initializeEventListeners() {
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
this.showPairing(); this.showPairing();
}); });
const editableFields = document.querySelectorAll<HTMLElement>('.editable'); const editableFields = document.querySelectorAll<HTMLElement>('.editable');
editableFields.forEach(field => { editableFields.forEach((field) => {
field.addEventListener('click', () => { field.addEventListener('click', () => {
if (!field.classList.contains('editing')) { if (!field.classList.contains('editing')) {
const currentValue = field.textContent || ''; const currentValue = field.textContent || '';
@ -1234,7 +1234,6 @@ private loadUserInfo(): void {
this.loadSavedBanner(); this.loadSavedBanner();
this.loadUserInfo(); this.loadUserInfo();
const savedAvatar = localStorage.getItem('userAvatar'); const savedAvatar = localStorage.getItem('userAvatar');
const savedBanner = localStorage.getItem('userBanner'); const savedBanner = localStorage.getItem('userBanner');
const savedName = localStorage.getItem('userName'); const savedName = localStorage.getItem('userName');
@ -1261,6 +1260,3 @@ private loadUserInfo(): void {
customElements.define('account-element', AccountElement); customElements.define('account-element', AccountElement);
export { AccountElement }; export { AccountElement };

View File

@ -1,21 +1,21 @@
import { ChatElement } from './chat'; import { ChatElement } from './chat';
import chatCss from '../../../public/style/chat.css?raw' import chatCss from '../../../public/style/chat.css?raw';
import Services from '../../services/service.js' import Services from '../../services/service.js';
class ChatComponent extends HTMLElement { class ChatComponent extends HTMLElement {
_callback: any _callback: any;
chatElement: ChatElement | null = null; chatElement: ChatElement | null = null;
constructor() { constructor() {
super(); super();
console.log('INIT') console.log('INIT');
this.attachShadow({ mode: 'open' }); this.attachShadow({ mode: 'open' });
this.chatElement = this.shadowRoot?.querySelector('chat-element') || null; this.chatElement = this.shadowRoot?.querySelector('chat-element') || null;
} }
connectedCallback() { connectedCallback() {
console.log('CALLBACKs') console.log('CALLBACKs');
this.render(); this.render();
this.fetchData(); this.fetchData();
@ -28,7 +28,7 @@ class ChatComponent extends HTMLElement {
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) { if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) {
const data = await (window as any).myService?.getProcesses(); const data = await (window as any).myService?.getProcesses();
} else { } else {
const service = await Services.getInstance() const service = await Services.getInstance();
const data = await service.getProcesses(); const data = await service.getProcesses();
} }
} }
@ -55,5 +55,5 @@ class ChatComponent extends HTMLElement {
} }
} }
export { ChatComponent } export { ChatComponent };
customElements.define('chat-component', ChatComponent); customElements.define('chat-component', ChatComponent);

View File

@ -1,15 +1,13 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Messagerie</title> <title>Messagerie</title>
<link rel="stylesheet" href="../../public/style/chat.css"> <link rel="stylesheet" href="../../public/style/chat.css" />
</head> </head>
<body> <body>
<!-- Main content--> <!-- Main content-->
<div class="container"> <div class="container">
<!-- List of groups --> <!-- List of groups -->
@ -33,21 +31,18 @@
<label for="file-input" class="attachment-icon"> <label for="file-input" class="attachment-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path <path
d="M13.514 2.444l-10.815 10.785c-.449.449-.678 1.074-.625 1.707l.393 4.696c.041.479.422.86.9.9l4.697.394c.633.053 1.258-.177 1.707-.626l11.875-11.844c.196-.196.195-.512 0-.707l-3.536-3.536c-.195-.195-.511-.196-.707 0l-8.878 8.848c-.162.162-.253.382-.253.611v.725c0 .184.148.332.332.332h.725c.229 0 .448-.092.61-.254l7.11-7.08 1.415 1.415-7.386 7.354c-.375.375-.885.586-1.414.586h-2.414c-.555 0-1-.448-1-1v-2.414c0-.53.211-1.039.586-1.414l9.506-9.477c.781-.781 2.049-.781 2.829-.001l4.243 4.243c.391.391.586.902.586 1.414 0 .512-.196 1.025-.587 1.416l-12.35 12.319c-.748.747-1.76 1.164-2.81 1.164-.257 0-6.243-.467-6.499-.487-.664-.052-1.212-.574-1.268-1.267-.019-.242-.486-6.246-.486-6.499 0-1.05.416-2.062 1.164-2.811l10.936-10.936 1.414 1.444z" /> d="M13.514 2.444l-10.815 10.785c-.449.449-.678 1.074-.625 1.707l.393 4.696c.041.479.422.86.9.9l4.697.394c.633.053 1.258-.177 1.707-.626l11.875-11.844c.196-.196.195-.512 0-.707l-3.536-3.536c-.195-.195-.511-.196-.707 0l-8.878 8.848c-.162.162-.253.382-.253.611v.725c0 .184.148.332.332.332h.725c.229 0 .448-.092.61-.254l7.11-7.08 1.415 1.415-7.386 7.354c-.375.375-.885.586-1.414.586h-2.414c-.555 0-1-.448-1-1v-2.414c0-.53.211-1.039.586-1.414l9.506-9.477c.781-.781 2.049-.781 2.829-.001l4.243 4.243c.391.391.586.902.586 1.414 0 .512-.196 1.025-.587 1.416l-12.35 12.319c-.748.747-1.76 1.164-2.81 1.164-.257 0-6.243-.467-6.499-.487-.664-.052-1.212-.574-1.268-1.267-.019-.242-.486-6.246-.486-6.499 0-1.05.416-2.062 1.164-2.811l10.936-10.936 1.414 1.444z"
/>
</svg> </svg>
</label> </label>
<input type="file" id="file-input" style="display: none;" /> <input type="file" id="file-input" style="display: none" />
<textarea id="message-input" rows="3" placeholder="Type your message..."></textarea> <textarea id="message-input" rows="3" placeholder="Type your message..."></textarea>
<button id="send-button">Send</button> <button id="send-button">Send</button>
</div> </div>
</div> </div>
</div> </div>
<script type="module" src="./chat.ts?ts"></script> <script type="module" src="./chat.ts?ts"></script>
</body> </body>
</html> </html>

View File

@ -9,16 +9,12 @@ declare global {
import { groupsMock } from '../../mocks/mock-signature/groupsMock'; import { groupsMock } from '../../mocks/mock-signature/groupsMock';
import { messagesMock as initialMessagesMock, messagesMock } from '../../mocks/mock-signature/messagesMock'; import { messagesMock as initialMessagesMock, messagesMock } from '../../mocks/mock-signature/messagesMock';
import { membersMock } from '../../mocks/mock-signature/membersMocks'; import { membersMock } from '../../mocks/mock-signature/membersMocks';
import { import { Message, DocumentSignature } from '../../models/signature.models';
Message,
DocumentSignature,
} from '../../models/signature.models';
import { messageStore } from '../../utils/messageMock'; import { messageStore } from '../../utils/messageMock';
import { Member } from '../../interface/memberInterface'; import { Member } from '../../interface/memberInterface';
import { Group } from '../../interface/groupInterface'; import { Group } from '../../interface/groupInterface';
import { getCorrectDOM } from '../../utils/document.utils'; import { getCorrectDOM } from '../../utils/document.utils';
let currentUser: Member = membersMock[0]; let currentUser: Member = membersMock[0];
interface LocalNotification { interface LocalNotification {
@ -44,13 +40,12 @@ class ChatElement extends HTMLElement {
private notificationBoard = document.getElementById('notification-board'); private notificationBoard = document.getElementById('notification-board');
private notificationBell = document.getElementById('notification-bell'); private notificationBell = document.getElementById('notification-bell');
private selectedSignatories: DocumentSignature[] = []; private selectedSignatories: DocumentSignature[] = [];
private allMembers = membersMock.map(member => ({ private allMembers = membersMock.map((member) => ({
id: member.id, id: member.id,
name: member.name, name: member.name,
roleName: 'Default Role' roleName: 'Default Role',
})); }));
constructor() { constructor() {
super(); super();
this.attachShadow({ mode: 'open' }); this.attachShadow({ mode: 'open' });
@ -62,9 +57,7 @@ class ChatElement extends HTMLElement {
// Initialiser les événements de notification // Initialiser les événements de notification
document.addEventListener('click', (event: Event): void => { document.addEventListener('click', (event: Event): void => {
if (this.notificationBoard && this.notificationBoard.style.display === 'block' && 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.contains(event.target as Node) &&
this.notificationBell && !this.notificationBell.contains(event.target as Node)) {
this.notificationBoard.style.display = 'none'; this.notificationBoard.style.display = 'none';
} }
}); });
@ -142,14 +135,13 @@ class ChatElement extends HTMLElement {
(this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none'; (this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none';
} }
// Add notification // Add notification
private addNotification(memberId: string, message: Message) { private addNotification(memberId: string, message: Message) {
// Creating a new notification // Creating a new notification
const notification = { const notification = {
memberId, memberId,
text: `New message from Member ${memberId}: ${message.text}`, text: `New message from Member ${memberId}: ${message.text}`,
time: message.time time: message.time,
}; };
// Added notification to list and interface // Added notification to list and interface
@ -170,10 +162,10 @@ class ChatElement extends HTMLElement {
const newMessage: Message = { const newMessage: Message = {
id: Date.now(), id: Date.now(),
sender: "4NK", sender: '4NK',
text: messageText, text: messageText,
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'text' as const type: 'text' as const,
}; };
// Add and display the message immediately // Add and display the message immediately
messageStore.addMessage(this.selectedMemberId, newMessage); messageStore.addMessage(this.selectedMemberId, newMessage);
@ -200,22 +192,21 @@ class ChatElement extends HTMLElement {
container.scrollTop = container.scrollHeight; container.scrollTop = container.scrollHeight;
} }
// Load the list of members // Load the list of members
private loadMemberChat(memberId: string | number) { private loadMemberChat(memberId: string | number) {
this.selectedMemberId = String(memberId); this.selectedMemberId = String(memberId);
const memberMessages = this.messagesMock.find(m => String(m.memberId) === String(memberId)); const memberMessages = this.messagesMock.find((m) => String(m.memberId) === String(memberId));
// Find the process and the role of the member // Find the process and the role of the member
let memberInfo = { processName: '', roleName: '', memberName: '' }; let memberInfo = { processName: '', roleName: '', memberName: '' };
groupsMock.forEach(process => { groupsMock.forEach((process) => {
process.roles.forEach(role => { process.roles.forEach((role) => {
const member = role.members.find(m => String(m.id) === String(memberId)); const member = role.members.find((m) => String(m.id) === String(memberId));
if (member) { if (member) {
memberInfo = { memberInfo = {
processName: process.name, processName: process.name,
roleName: role.name, roleName: role.name,
memberName: member.name memberName: member.name,
}; };
} }
}); });
@ -241,7 +232,7 @@ class ChatElement extends HTMLElement {
messageContent.classList.add('user'); messageContent.classList.add('user');
} else { } else {
messageContent.innerHTML = `<strong>${message.sender}</strong>: ${message.text} <span style="float: right;">${message.time}</span>`; messageContent.innerHTML = `<strong>${message.sender}</strong>: ${message.text} <span style="float: right;">${message.time}</span>`;
if (message.sender === "4NK") { if (message.sender === '4NK') {
messageContent.classList.add('user'); messageContent.classList.add('user');
} }
} }
@ -251,11 +242,10 @@ class ChatElement extends HTMLElement {
}); });
} }
this.scrollToBottom(messagesContainer); this.scrollToBottom(messagesContainer);
} }
private toggleMembers(role: { members: { id: string | number; name: string; }[] }, roleElement: HTMLElement) { private toggleMembers(role: { members: { id: string | number; name: string }[] }, roleElement: HTMLElement) {
let memberList = roleElement.querySelector('.member-list'); let memberList = roleElement.querySelector('.member-list');
if (memberList) { if (memberList) {
(memberList as HTMLElement).style.display = (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none'; (memberList as HTMLElement).style.display = (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none';
@ -265,7 +255,7 @@ class ChatElement extends HTMLElement {
memberList = document.createElement('ul'); memberList = document.createElement('ul');
memberList.className = 'member-list'; memberList.className = 'member-list';
role.members.forEach(member => { role.members.forEach((member) => {
const memberItem = document.createElement('li'); const memberItem = document.createElement('li');
memberItem.textContent = member.name; memberItem.textContent = member.name;
@ -280,7 +270,6 @@ class ChatElement extends HTMLElement {
roleElement.appendChild(memberList); roleElement.appendChild(memberList);
} }
// Toggle the list of Roles // Toggle the list of Roles
private toggleRoles(group: Group, groupElement: HTMLElement) { private toggleRoles(group: Group, groupElement: HTMLElement) {
console.log('=== toggleRoles START ==='); console.log('=== toggleRoles START ===');
@ -292,7 +281,7 @@ class ChatElement extends HTMLElement {
if (roleList) { if (roleList) {
const roleItems = roleList.querySelectorAll('.role-item'); const roleItems = roleList.querySelectorAll('.role-item');
roleItems.forEach(roleItem => { roleItems.forEach((roleItem) => {
console.log('Processing roleItem:', roleItem.innerHTML); // Voir le contenu HTML complet console.log('Processing roleItem:', roleItem.innerHTML); // Voir le contenu HTML complet
let container = roleItem.querySelector('.role-item-container'); let container = roleItem.querySelector('.role-item-container');
@ -325,9 +314,12 @@ class ChatElement extends HTMLElement {
folderButton.addEventListener('click', (event) => { folderButton.addEventListener('click', (event) => {
event.stopPropagation(); event.stopPropagation();
console.log('Clicked role name:', roleName); console.log('Clicked role name:', roleName);
console.log('Available roles:', group.roles.map(r => r.name)); console.log(
'Available roles:',
group.roles.map((r) => r.name),
);
const role = group.roles.find(r => r.name === roleName); const role = group.roles.find((r) => r.name === roleName);
if (role) { if (role) {
console.log('Found role:', role); console.log('Found role:', role);
} else { } else {
@ -340,17 +332,15 @@ class ChatElement extends HTMLElement {
} }
}); });
(roleList as HTMLElement).style.display = (roleList as HTMLElement).style.display = (roleList as HTMLElement).style.display === 'none' ? 'block' : 'none';
(roleList as HTMLElement).style.display === 'none' ? 'block' : 'none';
} }
} }
private loadGroupList(): void { private loadGroupList(): void {
const groupList = document.getElementById('group-list'); const groupList = document.getElementById('group-list');
if (!groupList) return; if (!groupList) return;
groupsMock.forEach(group => { groupsMock.forEach((group) => {
const li = document.createElement('li'); const li = document.createElement('li');
li.className = 'group-list-item'; li.className = 'group-list-item';
@ -379,7 +369,7 @@ class ChatElement extends HTMLElement {
roleList.style.display = 'none'; roleList.style.display = 'none';
// Add roles for this process // Add roles for this process
group.roles.forEach(role => { group.roles.forEach((role) => {
const roleItem = document.createElement('li'); const roleItem = document.createElement('li');
roleItem.className = 'role-item'; roleItem.className = 'role-item';
roleItem.textContent = role.name; roleItem.textContent = role.name;
@ -395,14 +385,15 @@ class ChatElement extends HTMLElement {
}); });
} }
// Function to manage the list of users // Function to manage the list of users
private toggleUserList() { private toggleUserList() {
const userList = getCorrectDOM('userList'); const userList = getCorrectDOM('userList');
if (!userList) return; if (!userList) return;
if (!(userList as HTMLElement).classList.contains('show')) { if (!(userList as HTMLElement).classList.contains('show')) {
(userList as HTMLElement).innerHTML = membersMock.map(member => ` (userList as HTMLElement).innerHTML = membersMock
.map(
(member) => `
<div class="user-list-item" onclick="switchUser('${member.id}')"> <div class="user-list-item" onclick="switchUser('${member.id}')">
<span class="user-avatar">${member.avatar}</span> <span class="user-avatar">${member.avatar}</span>
<div> <div>
@ -410,13 +401,15 @@ class ChatElement extends HTMLElement {
<span class="user-email">${member.email}</span> <span class="user-email">${member.email}</span>
</div> </div>
</div> </div>
`).join(''); `,
)
.join('');
} }
(userList as HTMLElement).classList.toggle('show'); (userList as HTMLElement).classList.toggle('show');
} }
private switchUser(userId: string | number) { private switchUser(userId: string | number) {
const user = membersMock.find(member => member.id === userId); const user = membersMock.find((member) => member.id === userId);
if (!user) return; if (!user) return;
currentUser = user; currentUser = user;
this.updateCurrentUserDisplay(); this.updateCurrentUserDisplay();
@ -441,9 +434,9 @@ class ChatElement extends HTMLElement {
return { return {
id: Date.now(), id: Date.now(),
sender: senderName, sender: senderName,
text: "OK...", text: 'OK...',
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'text' as const type: 'text' as const,
}; };
} }
@ -459,11 +452,11 @@ class ChatElement extends HTMLElement {
if (this.selectedMemberId) { if (this.selectedMemberId) {
messageStore.addMessage(this.selectedMemberId, { messageStore.addMessage(this.selectedMemberId, {
id: Date.now(), id: Date.now(),
sender: "4NK", sender: '4NK',
fileName: fileName, fileName: fileName,
fileData: fileData, fileData: fileData,
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'file' type: 'file',
}); });
console.log('Message added to store'); console.log('Message added to store');
@ -475,8 +468,7 @@ class ChatElement extends HTMLElement {
} }
private initializeEventListeners() { private initializeEventListeners() {
document.addEventListener('DOMContentLoaded', (): void => { document.addEventListener('DOMContentLoaded', (): void => {});
});
// Gestionnaire d'événements pour le chat // Gestionnaire d'événements pour le chat
const sendBtn = this.shadowRoot?.querySelector('#send-button'); const sendBtn = this.shadowRoot?.querySelector('#send-button');
@ -533,4 +525,3 @@ class ChatElement extends HTMLElement {
customElements.define('chat-element', ChatElement); customElements.define('chat-element', ChatElement);
export { ChatElement }; export { ChatElement };

View File

@ -1,6 +1,6 @@
import loginHtml from './home.html?raw' import loginHtml from './home.html?raw';
import loginScript from './home.ts?raw' import loginScript from './home.ts?raw';
import loginCss from '../../4nk.css?raw' import loginCss from '../../4nk.css?raw';
import { initHomePage } from './home'; import { initHomePage } from './home';
export class LoginComponent extends HTMLElement { export class LoginComponent extends HTMLElement {
@ -11,7 +11,7 @@ export class LoginComponent extends HTMLElement {
} }
connectedCallback() { connectedCallback() {
console.log('CALLBACK LOGIN PAGE') console.log('CALLBACK LOGIN PAGE');
this.render(); this.render();
setTimeout(() => { setTimeout(() => {
initHomePage(); initHomePage();
@ -31,7 +31,8 @@ export class LoginComponent extends HTMLElement {
} }
render() { render() {
if(this.shadowRoot) this.shadowRoot.innerHTML = ` if (this.shadowRoot)
this.shadowRoot.innerHTML = `
<style> <style>
${loginCss} ${loginCss}
</style>${loginHtml} </style>${loginHtml}

View File

@ -4,10 +4,10 @@ import { addSubscription } from '../../utils/subscription.utils';
import { displayEmojis, generateQRCode } from '../../utils/sp-address.utils'; import { displayEmojis, generateQRCode } from '../../utils/sp-address.utils';
import { getCorrectDOM } from '../../utils/html.utils'; import { getCorrectDOM } from '../../utils/html.utils';
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component'; import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
export {QrScannerComponent} export { QrScannerComponent };
export async function initHomePage(): Promise<void> { export async function initHomePage(): Promise<void> {
console.log('INIT-HOME'); console.log('INIT-HOME');
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
container.querySelectorAll('.tab').forEach((tab) => { container.querySelectorAll('.tab').forEach((tab) => {
addSubscription(tab, 'click', () => { addSubscription(tab, 'click', () => {
container.querySelectorAll('.tab').forEach((t) => t.classList.remove('active')); container.querySelectorAll('.tab').forEach((t) => t.classList.remove('active'));
@ -34,17 +34,15 @@ export async function openModal(myAddress: string, receiverAddress: string) {
// service.setNotification() // service.setNotification()
function scanDevice() { function scanDevice() {
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const scannerImg = container.querySelector('#scanner') as HTMLElement; const scannerImg = container.querySelector('#scanner') as HTMLElement;
if (scannerImg) scannerImg.style.display = 'none'; if (scannerImg) scannerImg.style.display = 'none';
const scannerQrCode = container.querySelector('.qr-code-scanner') as HTMLElement; const scannerQrCode = container.querySelector('.qr-code-scanner') as HTMLElement;
if (scannerQrCode) scannerQrCode.style.display = 'block'; if (scannerQrCode) scannerQrCode.style.display = 'block';
const scanButton = container?.querySelector('#scan-btn') as HTMLElement; const scanButton = container?.querySelector('#scan-btn') as HTMLElement;
if (scanButton) scanButton.style.display = 'none'; if (scanButton) scanButton.style.display = 'none';
const reader = container?.querySelector('#qr-reader') const reader = container?.querySelector('#qr-reader');
if(reader) reader.innerHTML = '<qr-scanner></qr-scanner>' if (reader) reader.innerHTML = '<qr-scanner></qr-scanner>';
} }
(window as any).scanDevice = scanDevice; (window as any).scanDevice = scanDevice;

View File

@ -1,6 +1,6 @@
import processHtml from './process-element.html?raw' import processHtml from './process-element.html?raw';
import processScript from './process-element.ts?raw' import processScript from './process-element.ts?raw';
import processCss from '../../4nk.css?raw' import processCss from '../../4nk.css?raw';
import { initProcessElement } from './process-element'; import { initProcessElement } from './process-element';
export class ProcessListComponent extends HTMLElement { export class ProcessListComponent extends HTMLElement {
@ -14,7 +14,7 @@ export class ProcessListComponent extends HTMLElement {
} }
connectedCallback() { connectedCallback() {
console.log('CALLBACK PROCESS LIST PAGE') console.log('CALLBACK PROCESS LIST PAGE');
this.render(); this.render();
setTimeout(() => { setTimeout(() => {
initProcessElement(this.id, this.zone); initProcessElement(this.id, this.zone);
@ -34,7 +34,8 @@ export class ProcessListComponent extends HTMLElement {
} }
render() { render() {
if(this.shadowRoot) this.shadowRoot.innerHTML = ` if (this.shadowRoot)
this.shadowRoot.innerHTML = `
<style> <style>
${processCss} ${processCss}
</style>${processHtml} </style>${processHtml}

View File

@ -1,6 +1,6 @@
import processHtml from './process.html?raw' import processHtml from './process.html?raw';
import processScript from './process.ts?raw' import processScript from './process.ts?raw';
import processCss from '../../4nk.css?raw' import processCss from '../../4nk.css?raw';
import { init } from './process'; import { init } from './process';
export class ProcessListComponent extends HTMLElement { export class ProcessListComponent extends HTMLElement {
@ -11,7 +11,7 @@ export class ProcessListComponent extends HTMLElement {
} }
connectedCallback() { connectedCallback() {
console.log('CALLBACK PROCESS LIST PAGE') console.log('CALLBACK PROCESS LIST PAGE');
this.render(); this.render();
setTimeout(() => { setTimeout(() => {
init(); init();
@ -31,7 +31,8 @@ export class ProcessListComponent extends HTMLElement {
} }
render() { render() {
if(this.shadowRoot) this.shadowRoot.innerHTML = ` if (this.shadowRoot)
this.shadowRoot.innerHTML = `
<style> <style>
${processCss} ${processCss}
</style>${processHtml} </style>${processHtml}

View File

@ -4,7 +4,7 @@ import { getCorrectDOM } from '~/utils/html.utils';
// Initialize function, create initial tokens with itens that are already selected by the user // Initialize function, create initial tokens with itens that are already selected by the user
export async function init() { export async function init() {
const container = getCorrectDOM('process-list-4nk-component') as HTMLElement const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
const element = container.querySelector('select') as HTMLSelectElement; const element = container.querySelector('select') as HTMLSelectElement;
// Create div that wroaps all the elements inside (select, elements selected, search div) to put select inside // Create div that wroaps all the elements inside (select, elements selected, search div) to put select inside
const wrapper = document.createElement('div'); const wrapper = document.createElement('div');
@ -118,7 +118,7 @@ function openOptions(e: Event) {
// Function that create a token inside of a wrapper with the given value // Function that create a token inside of a wrapper with the given value
function createToken(wrapper: HTMLElement, value: any) { function createToken(wrapper: HTMLElement, value: any) {
const container = getCorrectDOM('process-list-4nk-component') as HTMLElement const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
const search = wrapper.querySelector('.search-container'); const search = wrapper.querySelector('.search-container');
const inputInderline = container.querySelector('.selected-processes'); const inputInderline = container.querySelector('.selected-processes');
// Create token wrapper // Create token wrapper
@ -299,7 +299,7 @@ function removeToken(e: Event) {
// Remove token attribute // Remove token attribute
(target.parentNode as any)?.remove(); (target.parentNode as any)?.remove();
dropdown?.classList.remove('active'); dropdown?.classList.remove('active');
const container = getCorrectDOM('process-list-4nk-component') as HTMLElement const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
const process = container.querySelector('#' + target.dataset.option); const process = container.querySelector('#' + target.dataset.option);
process?.remove(); process?.remove();
@ -355,7 +355,7 @@ addSubscription(document, 'click', () => {
}); });
async function showSelectedProcess(elem: MouseEvent) { async function showSelectedProcess(elem: MouseEvent) {
const container = getCorrectDOM('process-list-4nk-component') as HTMLElement const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
if (elem) { if (elem) {
const cardContent = container.querySelector('.process-card-content'); const cardContent = container.querySelector('.process-card-content');
@ -387,7 +387,7 @@ async function showSelectedProcess(elem: MouseEvent) {
} }
function select(event: Event) { function select(event: Event) {
const container = getCorrectDOM('process-list-4nk-component') as HTMLElement const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
const target = event.target as HTMLElement; const target = event.target as HTMLElement;
const oldSelectedProcess = container.querySelector('.selected-process-zone'); const oldSelectedProcess = container.querySelector('.selected-process-zone');
oldSelectedProcess?.classList.remove('selected-process-zone'); oldSelectedProcess?.classList.remove('selected-process-zone');
@ -399,7 +399,7 @@ function select(event: Event) {
} }
function goToProcessPage() { function goToProcessPage() {
const container = getCorrectDOM('process-list-4nk-component') as HTMLElement const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
const target = container.querySelector('.selected-process-zone'); const target = container.querySelector('.selected-process-zone');
console.log('🚀 ~ goToProcessPage ~ event:', target); console.log('🚀 ~ goToProcessPage ~ event:', target);
@ -426,8 +426,8 @@ async function getProcesses(): Promise<any[]> {
const res = Object.entries(processes).map(([key, value]) => ({ const res = Object.entries(processes).map(([key, value]) => ({
key, key,
value value,
})) }));
return res; return res;
} }

View File

@ -1,21 +1,21 @@
import { SignatureElement } from './signature'; import { SignatureElement } from './signature';
import signatureCss from '../../../public/style/signature.css?raw' import signatureCss from '../../../public/style/signature.css?raw';
import Services from '../../services/service.js' import Services from '../../services/service.js';
class SignatureComponent extends HTMLElement { class SignatureComponent extends HTMLElement {
_callback: any _callback: any;
signatureElement: SignatureElement | null = null; signatureElement: SignatureElement | null = null;
constructor() { constructor() {
super(); super();
console.log('INIT') console.log('INIT');
this.attachShadow({ mode: 'open' }); this.attachShadow({ mode: 'open' });
this.signatureElement = this.shadowRoot?.querySelector('signature-element') || null; this.signatureElement = this.shadowRoot?.querySelector('signature-element') || null;
} }
connectedCallback() { connectedCallback() {
console.log('CALLBACKs') console.log('CALLBACKs');
this.render(); this.render();
this.fetchData(); this.fetchData();
@ -28,7 +28,7 @@ class SignatureComponent extends HTMLElement {
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) { if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) {
const data = await (window as any).myService?.getProcesses(); const data = await (window as any).myService?.getProcesses();
} else { } else {
const service = await Services.getInstance() const service = await Services.getInstance();
const data = await service.getProcesses(); const data = await service.getProcesses();
} }
} }
@ -55,5 +55,5 @@ class SignatureComponent extends HTMLElement {
} }
} }
export { SignatureComponent } export { SignatureComponent };
customElements.define('signature-component', SignatureComponent); customElements.define('signature-component', SignatureComponent);

View File

@ -1,22 +1,18 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Signatures</title> <title>Signatures</title>
<link rel="stylesheet" href="../../../public/style/signature.css"> <link rel="stylesheet" href="../../../public/style/signature.css" />
</head> </head>
<body> <body>
<!-- Main content--> <!-- Main content-->
<div class="container"> <div class="container">
<!-- List of groups --> <!-- List of groups -->
<div class="group-list"> <div class="group-list">
<ul id="group-list"> <ul id="group-list"></ul>
</ul>
</div> </div>
<!-- Chat area --> <!-- Chat area -->
@ -33,21 +29,18 @@
<label for="file-input" class="attachment-icon"> <label for="file-input" class="attachment-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path <path
d="M13.514 2.444l-10.815 10.785c-.449.449-.678 1.074-.625 1.707l.393 4.696c.041.479.422.86.9.9l4.697.394c.633.053 1.258-.177 1.707-.626l11.875-11.844c.196-.196.195-.512 0-.707l-3.536-3.536c-.195-.195-.511-.196-.707 0l-8.878 8.848c-.162.162-.253.382-.253.611v.725c0 .184.148.332.332.332h.725c.229 0 .448-.092.61-.254l7.11-7.08 1.415 1.415-7.386 7.354c-.375.375-.885.586-1.414.586h-2.414c-.555 0-1-.448-1-1v-2.414c0-.53.211-1.039.586-1.414l9.506-9.477c.781-.781 2.049-.781 2.829-.001l4.243 4.243c.391.391.586.902.586 1.414 0 .512-.196 1.025-.587 1.416l-12.35 12.319c-.748.747-1.76 1.164-2.81 1.164-.257 0-6.243-.467-6.499-.487-.664-.052-1.212-.574-1.268-1.267-.019-.242-.486-6.246-.486-6.499 0-1.05.416-2.062 1.164-2.811l10.936-10.936 1.414 1.444z" /> d="M13.514 2.444l-10.815 10.785c-.449.449-.678 1.074-.625 1.707l.393 4.696c.041.479.422.86.9.9l4.697.394c.633.053 1.258-.177 1.707-.626l11.875-11.844c.196-.196.195-.512 0-.707l-3.536-3.536c-.195-.195-.511-.196-.707 0l-8.878 8.848c-.162.162-.253.382-.253.611v.725c0 .184.148.332.332.332h.725c.229 0 .448-.092.61-.254l7.11-7.08 1.415 1.415-7.386 7.354c-.375.375-.885.586-1.414.586h-2.414c-.555 0-1-.448-1-1v-2.414c0-.53.211-1.039.586-1.414l9.506-9.477c.781-.781 2.049-.781 2.829-.001l4.243 4.243c.391.391.586.902.586 1.414 0 .512-.196 1.025-.587 1.416l-12.35 12.319c-.748.747-1.76 1.164-2.81 1.164-.257 0-6.243-.467-6.499-.487-.664-.052-1.212-.574-1.268-1.267-.019-.242-.486-6.246-.486-6.499 0-1.05.416-2.062 1.164-2.811l10.936-10.936 1.414 1.444z"
/>
</svg> </svg>
</label> </label>
<input type="file" id="file-input" style="display: none;" /> <input type="file" id="file-input" style="display: none" />
<textarea id="message-input" rows="3" placeholder="Type your message..."></textarea> <textarea id="message-input" rows="3" placeholder="Type your message..."></textarea>
<button id="send-button">Send</button> <button id="send-button">Send</button>
</div> </div>
</div> </div>
</div> </div>
<script type="module" src="./signature.ts?ts"></script> <script type="module" src="./signature.ts?ts"></script>
</body> </body>
</html> </html>

View File

@ -20,17 +20,13 @@ declare global {
import { groupsMock } from '../../mocks/mock-signature/groupsMock'; import { groupsMock } from '../../mocks/mock-signature/groupsMock';
import { messagesMock as initialMessagesMock, messagesMock } from '../../mocks/mock-signature/messagesMock'; import { messagesMock as initialMessagesMock, messagesMock } from '../../mocks/mock-signature/messagesMock';
import { membersMock } from '../../mocks/mock-signature/membersMocks'; import { membersMock } from '../../mocks/mock-signature/membersMocks';
import { import { Message, DocumentSignature, RequestParams } from '../../models/signature.models';
Message,
DocumentSignature,
RequestParams} from '../../models/signature.models';
import { messageStore } from '../../utils/messageMock'; import { messageStore } from '../../utils/messageMock';
import { showAlert } from '../account/account'; import { showAlert } from '../account/account';
import { Member } from '../../interface/memberInterface'; import { Member } from '../../interface/memberInterface';
import { Group } from '../../interface/groupInterface'; import { Group } from '../../interface/groupInterface';
import { getCorrectDOM } from '../../utils/document.utils'; import { getCorrectDOM } from '../../utils/document.utils';
let currentUser: Member = membersMock[0]; let currentUser: Member = membersMock[0];
interface LocalNotification { interface LocalNotification {
@ -39,7 +35,6 @@ interface LocalNotification {
time: string; time: string;
} }
class SignatureElement extends HTMLElement { class SignatureElement extends HTMLElement {
private selectedMemberId: string | null = null; private selectedMemberId: string | null = null;
private messagesMock: any[] = []; private messagesMock: any[] = [];
@ -49,10 +44,10 @@ class SignatureElement extends HTMLElement {
private notificationBoard = document.getElementById('notification-board'); private notificationBoard = document.getElementById('notification-board');
private notificationBell = document.getElementById('notification-bell'); private notificationBell = document.getElementById('notification-bell');
private selectedSignatories: DocumentSignature[] = []; private selectedSignatories: DocumentSignature[] = [];
private allMembers = membersMock.map(member => ({ private allMembers = membersMock.map((member) => ({
id: member.id, id: member.id,
name: member.name, name: member.name,
roleName: 'Default Role' roleName: 'Default Role',
})); }));
private signDocument(documentId: number, processId: number, isCommonDocument: boolean = false): void { private signDocument(documentId: number, processId: number, isCommonDocument: boolean = false): void {
@ -85,14 +80,10 @@ class SignatureElement extends HTMLElement {
throw new Error('Document not found'); throw new Error('Document not found');
} }
const canSign = isCommonDocument ? const canSign = isCommonDocument ? targetDoc.signatures?.some((sig: DocumentSignature) => sig.member?.name === currentUser?.name && !sig.signed) : this.canUserSignDocument(targetDoc, currentUser?.name, currentUser);
targetDoc.signatures?.some((sig: DocumentSignature) =>
sig.member?.name === currentUser?.name && !sig.signed
) :
this.canUserSignDocument(targetDoc, currentUser?.name, currentUser);
if (!canSign) { if (!canSign) {
showAlert("You do not have the necessary rights to sign this document."); showAlert('You do not have the necessary rights to sign this document.');
return; return;
} }
@ -132,24 +123,30 @@ class SignatureElement extends HTMLElement {
<div class="signatures-section"> <div class="signatures-section">
<h4>Signatures status:</h4> <h4>Signatures status:</h4>
<div class="signatures-list"> <div class="signatures-list">
${targetDoc.signatures.map((sig: DocumentSignature) => ` ${targetDoc.signatures
.map(
(sig: DocumentSignature) => `
<div class="signature-item ${sig.signed ? 'signed' : 'pending'}"> <div class="signature-item ${sig.signed ? 'signed' : 'pending'}">
<span class="signer-name">${sig.member.name}</span> <span class="signer-name">${sig.member.name}</span>
<span class="signature-status"> <span class="signature-status">
${sig.signed ? ${sig.signed ? `✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` : '⌛ Pending'}
`✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` :
'⌛ Pending'}
</span> </span>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
</div> </div>
${this.getFileList().length > 0 ? ` ${
this.getFileList().length > 0
? `
<div class="files-section"> <div class="files-section">
<h4>Files attached:</h4> <h4>Files attached:</h4>
<div class="files-list"> <div class="files-list">
${this.getFileList().map(file => ` ${this.getFileList()
.map(
(file) => `
<div class="file-item"> <div class="file-item">
<span class="file-icon"></span> <span class="file-icon"></span>
<span class="file-name">${file.name}</span> <span class="file-name">${file.name}</span>
@ -157,10 +154,14 @@ class SignatureElement extends HTMLElement {
<span class="download-icon"></span> <span class="download-icon"></span>
</a> </a>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
</div> </div>
` : ''} `
: ''
}
<div class="confirmation-section"> <div class="confirmation-section">
<p class="warning-text">By signing this document, you confirm that you have read its contents.</p> <p class="warning-text">By signing this document, you confirm that you have read its contents.</p>
@ -211,10 +212,8 @@ class SignatureElement extends HTMLElement {
const rect = sliderTrack.getBoundingClientRect(); const rect = sliderTrack.getBoundingClientRect();
const x = 'touches' in e ? e.touches[0].clientX : e.clientX; const x = 'touches' in e ? e.touches[0].clientX : e.clientX;
// Calculate the position relative to the track // Calculate the position relative to the track
let newLeft = x - rect.left - (slider.offsetWidth / 2); let newLeft = x - rect.left - slider.offsetWidth / 2;
// Limit the movement // Limit the movement
const maxLeft = sliderTrack.offsetWidth - slider.offsetWidth; const maxLeft = sliderTrack.offsetWidth - slider.offsetWidth;
@ -239,7 +238,6 @@ class SignatureElement extends HTMLElement {
slider.style.left = '0px'; slider.style.left = '0px';
} }
} }
} catch (error) { } catch (error) {
console.error('Error displaying modal:', error); console.error('Error displaying modal:', error);
showAlert(error instanceof Error ? error.message : 'Error displaying modal'); showAlert(error instanceof Error ? error.message : 'Error displaying modal');
@ -268,9 +266,7 @@ class SignatureElement extends HTMLElement {
// Initialiser les événements de notification // Initialiser les événements de notification
document.addEventListener('click', (event: Event): void => { document.addEventListener('click', (event: Event): void => {
if (this.notificationBoard && this.notificationBoard.style.display === 'block' && 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.contains(event.target as Node) &&
this.notificationBell && !this.notificationBell.contains(event.target as Node)) {
this.notificationBoard.style.display = 'none'; this.notificationBoard.style.display = 'none';
} }
}); });
@ -309,7 +305,6 @@ class SignatureElement extends HTMLElement {
} }
} }
private calculateDuration(startDate: string | null | undefined, endDate: string | null | undefined): number { private calculateDuration(startDate: string | null | undefined, endDate: string | null | undefined): number {
const start = new Date(startDate || ''); const start = new Date(startDate || '');
const end = new Date(endDate || ''); const end = new Date(endDate || '');
@ -331,13 +326,11 @@ class SignatureElement extends HTMLElement {
document, document,
role, role,
user, user,
userRoles: user.processRoles userRoles: user.processRoles,
}); });
// Vérifier si l'utilisateur est dans la liste des signatures // Vérifier si l'utilisateur est dans la liste des signatures
const isSignatory = document.signatures?.some((sig: DocumentSignature) => const isSignatory = document.signatures?.some((sig: DocumentSignature) => sig.member && 'id' in sig.member && sig.member.id === user.id && !sig.signed);
sig.member && 'id' in sig.member && sig.member.id === user.id && !sig.signed
);
if (!isSignatory) { if (!isSignatory) {
console.log('User is not in signatures list or has already signed'); console.log('User is not in signatures list or has already signed');
@ -400,14 +393,13 @@ class SignatureElement extends HTMLElement {
(this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none'; (this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none';
} }
// Add notification // Add notification
private addNotification(memberId: string, message: Message) { private addNotification(memberId: string, message: Message) {
// Creating a new notification // Creating a new notification
const notification = { const notification = {
memberId, memberId,
text: `New message from Member ${memberId}: ${message.text}`, text: `New message from Member ${memberId}: ${message.text}`,
time: message.time time: message.time,
}; };
// Added notification to list and interface // Added notification to list and interface
@ -427,10 +419,10 @@ class SignatureElement extends HTMLElement {
const newMessage: Message = { const newMessage: Message = {
id: Date.now(), id: Date.now(),
sender: "4NK", sender: '4NK',
text: messageText, text: messageText,
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'text' as const type: 'text' as const,
}; };
// Add and display the message immediately // Add and display the message immediately
messageStore.addMessage(this.selectedMemberId, newMessage); messageStore.addMessage(this.selectedMemberId, newMessage);
@ -452,13 +444,12 @@ class SignatureElement extends HTMLElement {
}, 2000); }, 2000);
} }
private showProcessDetails(group: Group, groupId: number) { private showProcessDetails(group: Group, groupId: number) {
console.log('Showing details for group:', groupId); console.log('Showing details for group:', groupId);
// Close all existing process views // Close all existing process views
const allDetailsAreas = document.querySelectorAll('.process-details'); const allDetailsAreas = document.querySelectorAll('.process-details');
allDetailsAreas.forEach(area => { allDetailsAreas.forEach((area) => {
(area as HTMLElement).style.display = 'none'; (area as HTMLElement).style.display = 'none';
}); });
@ -499,22 +490,27 @@ class SignatureElement extends HTMLElement {
<div class="details-section"> <div class="details-section">
<h3>Documents Communs</h3> <h3>Documents Communs</h3>
<div class="documents-grid"> <div class="documents-grid">
${displayGroup.commonDocuments.map((document: any) => { ${displayGroup.commonDocuments
.map((document: any) => {
const totalSignatures = document.signatures?.length || 0; const totalSignatures = document.signatures?.length || 0;
const signedCount = document.signatures?.filter((sig: DocumentSignature) => sig.signed).length || 0; const signedCount = document.signatures?.filter((sig: DocumentSignature) => sig.signed).length || 0;
const percentage = totalSignatures > 0 ? (signedCount / totalSignatures) * 100 : 0; const percentage = totalSignatures > 0 ? (signedCount / totalSignatures) * 100 : 0;
const isVierge = !document.createdAt || !document.deadline || !document.signatures?.length; const isVierge = !document.createdAt || !document.deadline || !document.signatures?.length;
const canSign = document.signatures?.some((sig: DocumentSignature) => const canSign = document.signatures?.some((sig: DocumentSignature) => sig.member && 'id' in sig.member && sig.member.id === currentUser.id && !sig.signed);
sig.member && 'id' in sig.member && sig.member.id === currentUser.id && !sig.signed
);
const signButton = !isVierge ? ` const signButton = !isVierge
${totalSignatures > 0 && signedCount < totalSignatures && canSign ? ` ? `
${
totalSignatures > 0 && signedCount < totalSignatures && canSign
? `
<button class="sign-button" onclick="signDocument(${document.id}, ${groupId}, true)"> <button class="sign-button" onclick="signDocument(${document.id}, ${groupId}, true)">
Sign the document Sign the document
</button> </button>
` : ''} `
` : ''; : ''
}
`
: '';
return ` return `
<div class="document-card ${document.visibility} ${isVierge ? 'vierge' : ''}"> <div class="document-card ${document.visibility} ${isVierge ? 'vierge' : ''}">
@ -523,30 +519,35 @@ class SignatureElement extends HTMLElement {
<span class="document-visibility">${document.visibility}</span> <span class="document-visibility">${document.visibility}</span>
</div> </div>
<div class="document-info"> <div class="document-info">
${!isVierge ? ` ${
!isVierge
? `
<p class="document-date">Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}</p> <p class="document-date">Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}</p>
<p class="document-deadline">Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}</p> <p class="document-deadline">Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}</p>
<p class="document-duration">Duration: ${this.calculateDuration(document.createdAt || '', document.deadline || '')} days</p> <p class="document-duration">Duration: ${this.calculateDuration(document.createdAt || '', document.deadline || '')} days</p>
<div class="document-signatures"> <div class="document-signatures">
<h5>Signatures:</h5> <h5>Signatures:</h5>
<div class="signatures-list"> <div class="signatures-list">
${document.signatures?.map((sig: DocumentSignature) => ` ${document.signatures
?.map(
(sig: DocumentSignature) => `
<div class="signature-item ${sig.signed ? 'signed' : 'pending'}"> <div class="signature-item ${sig.signed ? 'signed' : 'pending'}">
<span class="signer-name">${sig.member.name}</span> <span class="signer-name">${sig.member.name}</span>
<span class="signature-status"> <span class="signature-status">
${sig.signed ? ${sig.signed ? `✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` : '⌛ Pending'}
`✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` :
'⌛ Pending'}
</span> </span>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress" style="width: ${percentage}%;"></div> <div class="progress" style="width: ${percentage}%;"></div>
</div> </div>
<p>${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)</p> <p>${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)</p>
</div> </div>
` : ` `
: `
<p>Document vierge - Waiting for creation</p> <p>Document vierge - Waiting for creation</p>
<button class="new-request-btn" onclick="newRequest({ <button class="new-request-btn" onclick="newRequest({
processId: ${displayGroup.id}, processId: ${displayGroup.id},
@ -556,42 +557,46 @@ class SignatureElement extends HTMLElement {
documentId: ${document.id}, documentId: ${document.id},
documentName: '${document.name}' documentName: '${document.name}'
})">New request</button> })">New request</button>
`} `
}
${signButton} ${signButton}
</div> </div>
</div> </div>
`; `;
}).join('')} })
.join('')}
</div> </div>
</div> </div>
<div class="details-section"> <div class="details-section">
<h3>Roles and Documents</h3> <h3>Roles and Documents</h3>
${displayGroup.roles.map((role: { name: string; documents?: any[] }) => { ${displayGroup.roles
.map((role: { name: string; documents?: any[] }) => {
// Filter the documents according to the access rights // Filter the documents according to the access rights
const accessibleDocuments = (role.documents || []).filter(doc => const accessibleDocuments = (role.documents || []).filter((doc) => this.canUserAccessDocument(doc, role.name, currentUser.processRoles?.[0]?.role || ''));
this.canUserAccessDocument(doc, role.name, currentUser.processRoles?.[0]?.role || '')
);
return ` return `
<div class="role-section"> <div class="role-section">
<h4>${role.name}</h4> <h4>${role.name}</h4>
<div class="documents-grid"> <div class="documents-grid">
${accessibleDocuments.map(document => { ${accessibleDocuments
const isVierge = !document.createdAt || .map((document) => {
!document.deadline || const isVierge = !document.createdAt || !document.deadline || document.signatures.length === 0;
document.signatures.length === 0;
const canSign = this.canUserSignDocument(document, role.name, currentUser); const canSign = this.canUserSignDocument(document, role.name, currentUser);
const signButton = !isVierge ? ` const signButton = !isVierge
${document.signatures.length > 0 && ? `
document.signatures.filter((sig: DocumentSignature) => sig.signed).length < document.signatures.length && ${
canSign ? ` document.signatures.length > 0 && document.signatures.filter((sig: DocumentSignature) => sig.signed).length < document.signatures.length && canSign
? `
<button class="sign-button" onclick="signDocument(${document.id}, ${groupId}, false)"> <button class="sign-button" onclick="signDocument(${document.id}, ${groupId}, false)">
Sign the document Sign the document
</button> </button>
` : ''} `
` : ''; : ''
}
`
: '';
return ` return `
<div class="document-card ${document.visibility} ${isVierge ? 'vierge' : ''}"> <div class="document-card ${document.visibility} ${isVierge ? 'vierge' : ''}">
@ -600,60 +605,79 @@ class SignatureElement extends HTMLElement {
<span class="document-visibility">${document.visibility}</span> <span class="document-visibility">${document.visibility}</span>
</div> </div>
<div class="document-info"> <div class="document-info">
${!isVierge ? ` ${
!isVierge
? `
<p class="document-date">Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}</p> <p class="document-date">Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}</p>
<p class="document-deadline">Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}</p> <p class="document-deadline">Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}</p>
<p class="document-duration">Duration: ${this.calculateDuration(document.createdAt || '', document.deadline || '')} days</p> <p class="document-duration">Duration: ${this.calculateDuration(document.createdAt || '', document.deadline || '')} days</p>
` : '<p>Document vierge - En attente de création</p>'} `
: '<p>Document vierge - En attente de création</p>'
}
</div> </div>
${!isVierge ? ` ${
!isVierge
? `
<div class="document-signatures"> <div class="document-signatures">
<h5>Signatures:</h5> <h5>Signatures:</h5>
<div class="signatures-list"> <div class="signatures-list">
${document.signatures.map((sig: DocumentSignature) => ` ${document.signatures
.map(
(sig: DocumentSignature) => `
<div class="signature-item ${sig.signed ? 'signed' : 'pending'}"> <div class="signature-item ${sig.signed ? 'signed' : 'pending'}">
<span class="signer-name">${sig.member.name}</span> <span class="signer-name">${sig.member.name}</span>
<span class="signature-status"> <span class="signature-status">
${sig.signed ? ${sig.signed ? `✓ Signé le ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'date inconnue'}` : '⌛ En attente'}
`✓ Signé le ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'date inconnue'}` :
'⌛ En attente'}
</span> </span>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress" style="width: ${document.signatures.filter((sig: DocumentSignature) => sig.signed).length / document.signatures.length * 100}%;"></div> <div class="progress" style="width: ${(document.signatures.filter((sig: DocumentSignature) => sig.signed).length / document.signatures.length) * 100}%;"></div>
</div> </div>
<p>${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)}%)</p> <p>${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)}%)</p>
</div> </div>
` : ''} `
: ''
}
${signButton} ${signButton}
</div> </div>
`; `;
}).join('')} })
.join('')}
</div> </div>
</div> </div>
`; `;
}).join('')} })
.join('')}
</div> </div>
<div class="details-section"> <div class="details-section">
<h3>Members by Role</h3> <h3>Members by Role</h3>
<div class="roles-grid"> <div class="roles-grid">
${displayGroup.roles.map((role: { name: string; members: Array<{ id: string | number; name: string }> }) => ` ${displayGroup.roles
.map(
(role: { name: string; members: Array<{ id: string | number; name: string }> }) => `
<div class="role-block"> <div class="role-block">
<h4>${role.name}</h4> <h4>${role.name}</h4>
<ul class="members-list"> <ul class="members-list">
${role.members.map(member => ` ${role.members
.map(
(member) => `
<li onclick="loadMemberChat(${member.id})">${member.name}</li> <li onclick="loadMemberChat(${member.id})">${member.name}</li>
`).join('')} `,
)
.join('')}
</ul> </ul>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
</div> </div>
`; `;
const newCloseProcessButton = document.createElement('button'); const newCloseProcessButton = document.createElement('button');
newCloseProcessButton.className = 'close-btn'; newCloseProcessButton.className = 'close-btn';
newCloseProcessButton.textContent = 'x'; newCloseProcessButton.textContent = 'x';
@ -671,22 +695,21 @@ class SignatureElement extends HTMLElement {
container.scrollTop = container.scrollHeight; container.scrollTop = container.scrollHeight;
} }
// Load the list of members // Load the list of members
private loadMemberChat(memberId: string | number) { private loadMemberChat(memberId: string | number) {
this.selectedMemberId = String(memberId); this.selectedMemberId = String(memberId);
const memberMessages = this.messagesMock.find(m => String(m.memberId) === String(memberId)); const memberMessages = this.messagesMock.find((m) => String(m.memberId) === String(memberId));
// Find the process and the role of the member // Find the process and the role of the member
let memberInfo = { processName: '', roleName: '', memberName: '' }; let memberInfo = { processName: '', roleName: '', memberName: '' };
groupsMock.forEach(process => { groupsMock.forEach((process) => {
process.roles.forEach(role => { process.roles.forEach((role) => {
const member = role.members.find(m => String(m.id) === String(memberId)); const member = role.members.find((m) => String(m.id) === String(memberId));
if (member) { if (member) {
memberInfo = { memberInfo = {
processName: process.name, processName: process.name,
roleName: role.name, roleName: role.name,
memberName: member.name memberName: member.name,
}; };
} }
}); });
@ -712,7 +735,7 @@ class SignatureElement extends HTMLElement {
messageContent.classList.add('user'); messageContent.classList.add('user');
} else { } else {
messageContent.innerHTML = `<strong>${message.sender}</strong>: ${message.text} <span style="float: right;">${message.time}</span>`; messageContent.innerHTML = `<strong>${message.sender}</strong>: ${message.text} <span style="float: right;">${message.time}</span>`;
if (message.sender === "4NK") { if (message.sender === '4NK') {
messageContent.classList.add('user'); messageContent.classList.add('user');
} }
} }
@ -722,11 +745,10 @@ class SignatureElement extends HTMLElement {
}); });
} }
this.scrollToBottom(messagesContainer); this.scrollToBottom(messagesContainer);
} }
private toggleMembers(role: { members: { id: string | number; name: string; }[] }, roleElement: HTMLElement) { private toggleMembers(role: { members: { id: string | number; name: string }[] }, roleElement: HTMLElement) {
let memberList = roleElement.querySelector('.member-list'); let memberList = roleElement.querySelector('.member-list');
if (memberList) { if (memberList) {
(memberList as HTMLElement).style.display = (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none'; (memberList as HTMLElement).style.display = (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none';
@ -736,7 +758,7 @@ class SignatureElement extends HTMLElement {
memberList = document.createElement('ul'); memberList = document.createElement('ul');
memberList.className = 'member-list'; memberList.className = 'member-list';
role.members.forEach(member => { role.members.forEach((member) => {
const memberItem = document.createElement('li'); const memberItem = document.createElement('li');
memberItem.textContent = member.name; memberItem.textContent = member.name;
@ -751,7 +773,6 @@ class SignatureElement extends HTMLElement {
roleElement.appendChild(memberList); roleElement.appendChild(memberList);
} }
// Toggle the list of Roles // Toggle the list of Roles
private toggleRoles(group: Group, groupElement: HTMLElement) { private toggleRoles(group: Group, groupElement: HTMLElement) {
console.log('=== toggleRoles START ==='); console.log('=== toggleRoles START ===');
@ -763,7 +784,7 @@ class SignatureElement extends HTMLElement {
if (roleList) { if (roleList) {
const roleItems = roleList.querySelectorAll('.role-item'); const roleItems = roleList.querySelectorAll('.role-item');
roleItems.forEach(roleItem => { roleItems.forEach((roleItem) => {
console.log('Processing roleItem:', roleItem.innerHTML); // Voir le contenu HTML complet console.log('Processing roleItem:', roleItem.innerHTML); // Voir le contenu HTML complet
let container = roleItem.querySelector('.role-item-container'); let container = roleItem.querySelector('.role-item-container');
@ -797,9 +818,12 @@ class SignatureElement extends HTMLElement {
folderButton.addEventListener('click', (event) => { folderButton.addEventListener('click', (event) => {
event.stopPropagation(); event.stopPropagation();
console.log('Clicked role name:', roleName); console.log('Clicked role name:', roleName);
console.log('Available roles:', group.roles.map(r => r.name)); console.log(
'Available roles:',
group.roles.map((r) => r.name),
);
const role = group.roles.find(r => r.name === roleName); const role = group.roles.find((r) => r.name === roleName);
if (role) { if (role) {
console.log('Found role:', role); console.log('Found role:', role);
this.showRoleDocuments(role, group); this.showRoleDocuments(role, group);
@ -813,17 +837,15 @@ class SignatureElement extends HTMLElement {
} }
}); });
(roleList as HTMLElement).style.display = (roleList as HTMLElement).style.display = (roleList as HTMLElement).style.display === 'none' ? 'block' : 'none';
(roleList as HTMLElement).style.display === 'none' ? 'block' : 'none';
} }
} }
private loadGroupList(): void { private loadGroupList(): void {
const groupList = document.getElementById('group-list'); const groupList = document.getElementById('group-list');
if (!groupList) return; if (!groupList) return;
groupsMock.forEach(group => { groupsMock.forEach((group) => {
const li = document.createElement('li'); const li = document.createElement('li');
li.className = 'group-list-item'; li.className = 'group-list-item';
@ -864,7 +886,7 @@ class SignatureElement extends HTMLElement {
roleList.style.display = 'none'; roleList.style.display = 'none';
// Add roles for this process // Add roles for this process
group.roles.forEach(role => { group.roles.forEach((role) => {
const roleItem = document.createElement('li'); const roleItem = document.createElement('li');
roleItem.className = 'role-item'; roleItem.className = 'role-item';
roleItem.textContent = role.name; roleItem.textContent = role.name;
@ -880,14 +902,15 @@ class SignatureElement extends HTMLElement {
}); });
} }
// Function to manage the list of users // Function to manage the list of users
private toggleUserList() { private toggleUserList() {
const userList = getCorrectDOM('userList'); const userList = getCorrectDOM('userList');
if (!userList) return; if (!userList) return;
if (!(userList as HTMLElement).classList.contains('show')) { if (!(userList as HTMLElement).classList.contains('show')) {
(userList as HTMLElement).innerHTML = membersMock.map(member => ` (userList as HTMLElement).innerHTML = membersMock
.map(
(member) => `
<div class="user-list-item" onclick="switchUser('${member.id}')"> <div class="user-list-item" onclick="switchUser('${member.id}')">
<span class="user-avatar">${member.avatar}</span> <span class="user-avatar">${member.avatar}</span>
<div> <div>
@ -895,13 +918,15 @@ class SignatureElement extends HTMLElement {
<span class="user-email">${member.email}</span> <span class="user-email">${member.email}</span>
</div> </div>
</div> </div>
`).join(''); `,
)
.join('');
} }
(userList as HTMLElement).classList.toggle('show'); (userList as HTMLElement).classList.toggle('show');
} }
private switchUser(userId: string | number) { private switchUser(userId: string | number) {
const user = membersMock.find(member => member.id === userId); const user = membersMock.find((member) => member.id === userId);
if (!user) return; if (!user) return;
currentUser = user; currentUser = user;
this.updateCurrentUserDisplay(); this.updateCurrentUserDisplay();
@ -926,9 +951,9 @@ class SignatureElement extends HTMLElement {
return { return {
id: Date.now(), id: Date.now(),
sender: senderName, sender: senderName,
text: "OK...", text: 'OK...',
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'text' as const type: 'text' as const,
}; };
} }
@ -944,11 +969,11 @@ class SignatureElement extends HTMLElement {
if (this.selectedMemberId) { if (this.selectedMemberId) {
messageStore.addMessage(this.selectedMemberId, { messageStore.addMessage(this.selectedMemberId, {
id: Date.now(), id: Date.now(),
sender: "4NK", sender: '4NK',
fileName: fileName, fileName: fileName,
fileData: fileData, fileData: fileData,
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'file' type: 'file',
}); });
console.log('Message added to store'); console.log('Message added to store');
@ -973,7 +998,8 @@ class SignatureElement extends HTMLElement {
} }
// New function to display the documents of a role // New function to display the documents of a role
private showRoleDocuments(role: { private showRoleDocuments(
role: {
name: string; name: string;
documents?: Array<{ documents?: Array<{
name: string; name: string;
@ -987,7 +1013,9 @@ class SignatureElement extends HTMLElement {
files?: Array<{ name: string; url: string }>; files?: Array<{ name: string; url: string }>;
}>; }>;
id?: number; id?: number;
}, group: Group) { },
group: Group,
) {
// Load the data from localStorage // Load the data from localStorage
const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]'); const storedGroups = JSON.parse(localStorage.getItem('groups') || '[]');
const storedGroup = storedGroups.find((g: Group) => g.id === group.id); const storedGroup = storedGroups.find((g: Group) => g.id === group.id);
@ -999,7 +1027,7 @@ class SignatureElement extends HTMLElement {
console.log('Showing documents for role:', displayRole.name, 'in group:', group.name); console.log('Showing documents for role:', displayRole.name, 'in group:', group.name);
// Close all existing document views first // Close all existing document views first
const allDetailsAreas = document.querySelectorAll('.process-details'); const allDetailsAreas = document.querySelectorAll('.process-details');
allDetailsAreas.forEach(area => { allDetailsAreas.forEach((area) => {
area.remove(); area.remove();
}); });
@ -1014,17 +1042,8 @@ class SignatureElement extends HTMLElement {
detailsArea.id = `role-documents-${displayRole.name}`; detailsArea.id = `role-documents-${displayRole.name}`;
detailsArea.className = 'process-details'; detailsArea.className = 'process-details';
// Filter the accessible documents // Filter the accessible documents
const accessibleDocuments = (displayRole.documents || []).filter((doc: { 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 }) =>
name: string; this.canUserAccessDocument(doc, displayRole.name, currentUser.processRoles?.[0]?.role || ''),
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 = ` detailsArea.innerHTML = `
@ -1039,22 +1058,12 @@ class SignatureElement extends HTMLElement {
<div class="details-section"> <div class="details-section">
<h3>Documents</h3> <h3>Documents</h3>
<div class="documents-grid"> <div class="documents-grid">
${accessibleDocuments.map((document: { ${accessibleDocuments
name: string; .map((document: { name: string; visibility: string; createdAt: string | null | undefined; deadline: string | null | undefined; signatures: DocumentSignature[]; id: number; description?: string; status?: string }) => {
visibility: string;
createdAt: string | null | undefined;
deadline: string | null | undefined;
signatures: DocumentSignature[];
id: number;
description?: string;
status?: string;
}) => {
const totalSignatures = document.signatures.length; const totalSignatures = document.signatures.length;
const signedCount = document.signatures.filter((sig: DocumentSignature) => sig.signed).length; const signedCount = document.signatures.filter((sig: DocumentSignature) => sig.signed).length;
const percentage = totalSignatures > 0 ? (signedCount / totalSignatures) * 100 : 0; const percentage = totalSignatures > 0 ? (signedCount / totalSignatures) * 100 : 0;
const isVierge = !document.createdAt || const isVierge = !document.createdAt || !document.deadline || document.signatures.length === 0;
!document.deadline ||
document.signatures.length === 0;
const canSign = this.canUserSignDocument(document, role.name, currentUser); const canSign = this.canUserSignDocument(document, role.name, currentUser);
@ -1065,32 +1074,39 @@ class SignatureElement extends HTMLElement {
<span class="document-visibility">${document.visibility}</span> <span class="document-visibility">${document.visibility}</span>
</div> </div>
<div class="document-info"> <div class="document-info">
${!isVierge ? ` ${
!isVierge
? `
<p class="document-date">Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}</p> <p class="document-date">Created on: ${document.createdAt ? new Date(document.createdAt).toLocaleDateString() : 'N/A'}</p>
<p class="document-deadline">Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}</p> <p class="document-deadline">Deadline: ${document.deadline ? new Date(document.deadline).toLocaleDateString() : 'N/A'}</p>
<p class="document-duration">Duration: ${this.calculateDuration(document.createdAt, document.deadline)} days</p> <p class="document-duration">Duration: ${this.calculateDuration(document.createdAt, document.deadline)} days</p>
<div class="document-signatures"> <div class="document-signatures">
<h5>Signatures:</h5> <h5>Signatures:</h5>
<div class="signatures-list"> <div class="signatures-list">
${document.signatures.map((sig: DocumentSignature) => ` ${document.signatures
.map(
(sig: DocumentSignature) => `
<div class="signature-item ${sig.signed ? 'signed' : 'pending'}"> <div class="signature-item ${sig.signed ? 'signed' : 'pending'}">
<span class="signer-name">${sig.member.name}</span> <span class="signer-name">${sig.member.name}</span>
<span class="signature-status"> <span class="signature-status">
${sig.signed ? ${sig.signed ? `✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` : '⌛ Pending'}
`✓ Signed on ${sig.signedAt ? new Date(sig.signedAt).toLocaleDateString() : 'unknown date'}` :
'⌛ Pending'}
</span> </span>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress" style="width: ${percentage}%;"></div> <div class="progress" style="width: ${percentage}%;"></div>
</div> </div>
<p>${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)</p> <p>${signedCount} out of ${totalSignatures} signed (${percentage.toFixed(0)}%)</p>
</div> </div>
` : ` `
: `
<p>Blank document - Waiting for creation</p> <p>Blank document - Waiting for creation</p>
${this.canUserAccessDocument(document, displayRole.name, currentUser.processRoles?.[0]?.role || '') ? ` ${
this.canUserAccessDocument(document, displayRole.name, currentUser.processRoles?.[0]?.role || '')
? `
<button class="new-request-btn" onclick="newRequest({ <button class="new-request-btn" onclick="newRequest({
processId: ${group.id}, processId: ${group.id},
processName: '${group.name}', processName: '${group.name}',
@ -1099,12 +1115,16 @@ class SignatureElement extends HTMLElement {
documentId: ${document.id}, documentId: ${document.id},
documentName: '${document.name}' documentName: '${document.name}'
})">New request</button> })">New request</button>
` : ''} `
`} : ''
}
`
}
</div> </div>
</div> </div>
`; `;
}).join('')} })
.join('')}
</div> </div>
</div> </div>
</div> </div>
@ -1118,20 +1138,17 @@ class SignatureElement extends HTMLElement {
private closeRoleDocuments(roleName: string) { private closeRoleDocuments(roleName: string) {
const detailsArea = document.getElementById(`role-documents-${roleName}`); const detailsArea = document.getElementById(`role-documents-${roleName}`);
if (detailsArea) { if (detailsArea) {
detailsArea.remove(); detailsArea.remove();
} }
} }
private handleFiles(files: FileList, fileList: HTMLDivElement) { private handleFiles(files: FileList, fileList: HTMLDivElement) {
Array.from(files).forEach(file => { Array.from(files).forEach((file) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
const fileContent = e.target?.result; const fileContent = e.target?.result;
const existingFiles = fileList.querySelectorAll('.file-name'); const existingFiles = fileList.querySelectorAll('.file-name');
const isDuplicate = Array.from(existingFiles).some( const isDuplicate = Array.from(existingFiles).some((existingFile) => existingFile.textContent === file.name);
existingFile => existingFile.textContent === file.name
);
if (!isDuplicate) { if (!isDuplicate) {
const fileItem = document.createElement('div'); const fileItem = document.createElement('div');
@ -1170,7 +1187,7 @@ class SignatureElement extends HTMLElement {
modal.className = 'modal-overlay'; modal.className = 'modal-overlay';
// Retrieve the process with a verification // Retrieve the process with a verification
const process = groupsMock.find(g => g.id === params.processId); const process = groupsMock.find((g) => g.id === params.processId);
if (!process) { if (!process) {
console.error('Processus non trouvé:', params.processId); console.error('Processus non trouvé:', params.processId);
showAlert('Process not found'); showAlert('Process not found');
@ -1182,19 +1199,21 @@ class SignatureElement extends HTMLElement {
try { try {
if (params.roleName === 'common') { if (params.roleName === 'common') {
membersToDisplay = process.roles.reduce((members: any[], role) => { membersToDisplay = process.roles.reduce((members: any[], role) => {
return members.concat(role.members.map(member => ({ return members.concat(
role.members.map((member) => ({
...member, ...member,
roleName: role.name roleName: role.name,
}))); })),
);
}, []); }, []);
} else { } else {
const role = process.roles.find(r => r.name === params.roleName); const role = process.roles.find((r) => r.name === params.roleName);
if (!role) { if (!role) {
throw new Error(`Role ${params.roleName} not found`); throw new Error(`Role ${params.roleName} not found`);
} }
membersToDisplay = role.members.map(member => ({ membersToDisplay = role.members.map((member) => ({
...member, ...member,
roleName: params.roleName roleName: params.roleName,
})); }));
} }
} catch (error) { } catch (error) {
@ -1203,8 +1222,6 @@ class SignatureElement extends HTMLElement {
return; return;
} }
modal.innerHTML = ` modal.innerHTML = `
<div class="modal-document"> <div class="modal-document">
<div class="modal-content-document"> <div class="modal-content-document">
@ -1269,12 +1286,16 @@ class SignatureElement extends HTMLElement {
<div class="form-group"> <div class="form-group">
<label>Required Signatories:</label> <label>Required Signatories:</label>
<div class="required-signatories"> <div class="required-signatories">
${membersToDisplay.map(member => ` ${membersToDisplay
.map(
(member) => `
<div class="signatory-item"> <div class="signatory-item">
<span class="member-name">${member.name}</span> <span class="member-name">${member.name}</span>
<span class="role-info">${member.roleName}</span> <span class="role-info">${member.roleName}</span>
</div> </div>
`).join('')} `,
)
.join('')}
</div> </div>
</div> </div>
@ -1284,10 +1305,7 @@ class SignatureElement extends HTMLElement {
<div class="modal-footer"> <div class="modal-footer">
<button class="cancel-btn" onclick="closeModal(this)">Cancel</button> <button class="cancel-btn" onclick="closeModal(this)">Cancel</button>
${params.roleName === 'common' ${params.roleName === 'common' ? '<button class="confirm-btn" onclick="submitCommonDocument(event)">Request</button>' : '<button class="confirm-btn" onclick="submitNewDocument(event)">Request</button>'}
? '<button class="confirm-btn" onclick="submitCommonDocument(event)">Request</button>'
: '<button class="confirm-btn" onclick="submitNewDocument(event)">Request</button>'
}
</div> </div>
</div> </div>
</div> </div>
@ -1349,7 +1367,7 @@ class SignatureElement extends HTMLElement {
// Retrieve the files // Retrieve the files
const fileList = document.getElementById('fileList') as HTMLDivElement; const fileList = document.getElementById('fileList') as HTMLDivElement;
const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map(fileItem => { const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map((fileItem) => {
const fileName = fileItem.querySelector('.file-name')?.textContent || ''; const fileName = fileItem.querySelector('.file-name')?.textContent || '';
return { return {
name: fileName, name: fileName,
@ -1381,9 +1399,7 @@ class SignatureElement extends HTMLElement {
return; return;
} }
const role = group.roles.find((r: any) => const role = group.roles.find((r: any) => r.documents?.some((d: any) => d.id === documentId));
r.documents?.some((d: any) => d.id === documentId)
);
if (!role) { if (!role) {
showAlert('Role not found'); showAlert('Role not found');
@ -1398,13 +1414,13 @@ class SignatureElement extends HTMLElement {
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
deadline: deadline, deadline: deadline,
visibility: visibility, visibility: visibility,
status: "pending", status: 'pending',
signatures: role.members.map((member: { id: string | number; name: string }) => ({ signatures: role.members.map((member: { id: string | number; name: string }) => ({
member: member, member: member,
signed: false, signed: false,
signedAt: null signedAt: null,
})), })),
files: files // Ajout des fichiers au document files: files, // Ajout des fichiers au document
}; };
// Update the document in the role // Update the document in the role
@ -1417,15 +1433,15 @@ class SignatureElement extends HTMLElement {
localStorage.setItem('groups', JSON.stringify(groups)); localStorage.setItem('groups', JSON.stringify(groups));
// Also update groupsMock for consistency // Also update groupsMock for consistency
const mockGroup = groupsMock.find(g => g.id === processId); const mockGroup = groupsMock.find((g) => g.id === processId);
if (mockGroup) { if (mockGroup) {
const mockRole = mockGroup?.roles.find(r => r.name === role.name); const mockRole = mockGroup?.roles.find((r) => r.name === role.name);
if (mockRole?.documents) { if (mockRole?.documents) {
const mockDocIndex = mockRole.documents.findIndex(d => d.id === documentId); const mockDocIndex = mockRole.documents.findIndex((d) => d.id === documentId);
if (mockDocIndex !== -1) { if (mockDocIndex !== -1) {
mockRole.documents[mockDocIndex] = { mockRole.documents[mockDocIndex] = {
...updatedDocument, ...updatedDocument,
status: undefined status: undefined,
}; };
} }
} }
@ -1439,7 +1455,6 @@ class SignatureElement extends HTMLElement {
// Reload the documents view with the updated data // Reload the documents view with the updated data
this.showRoleDocuments(role, group); this.showRoleDocuments(role, group);
showAlert('Document updated successfully!'); showAlert('Document updated successfully!');
} catch (error) { } catch (error) {
console.error('Error saving:', error); console.error('Error saving:', error);
showAlert('An error occurred while saving'); showAlert('An error occurred while saving');
@ -1482,7 +1497,7 @@ class SignatureElement extends HTMLElement {
}, []); }, []);
const fileList = document.getElementById('fileList') as HTMLDivElement; const fileList = document.getElementById('fileList') as HTMLDivElement;
const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map(fileItem => { const files = Array.from(fileList?.querySelectorAll('.file-item') || []).map((fileItem) => {
const fileName = fileItem.querySelector('.file-name')?.textContent || ''; const fileName = fileItem.querySelector('.file-name')?.textContent || '';
return { return {
name: fileName, name: fileName,
@ -1497,13 +1512,13 @@ class SignatureElement extends HTMLElement {
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
deadline: deadline, deadline: deadline,
visibility: visibility, visibility: visibility,
status: "pending", status: 'pending',
signatures: allMembers.map((member: { id: string | number; name: string }) => ({ signatures: allMembers.map((member: { id: string | number; name: string }) => ({
member: member, member: member,
signed: false, signed: false,
signedAt: null signedAt: null,
})), })),
files: files files: files,
}; };
// Update the common document // Update the common document
@ -1520,17 +1535,14 @@ class SignatureElement extends HTMLElement {
this.showProcessDetails(group, group.id); this.showProcessDetails(group, group.id);
showAlert('Document common updated successfully!'); showAlert('Document common updated successfully!');
} catch (error) { } catch (error) {
console.error('Error saving:', error); console.error('Error saving:', error);
showAlert('An error occurred while saving'); showAlert('An error occurred while saving');
} }
} }
private submitRequest() { private submitRequest() {
showAlert('Request submitted!');
showAlert("Request submitted!");
} }
private closeNewRequest() { private closeNewRequest() {
@ -1547,9 +1559,7 @@ class SignatureElement extends HTMLElement {
const visibility = (document.getElementById('visibility') as HTMLSelectElement)?.value || ''; const visibility = (document.getElementById('visibility') as HTMLSelectElement)?.value || '';
const description = (document.getElementById('description') as HTMLTextAreaElement)?.value || ''; const description = (document.getElementById('description') as HTMLTextAreaElement)?.value || '';
const selectedMembers = Array.from( const selectedMembers = Array.from(document.querySelectorAll('input[name="selected-members"]:checked')).map((checkbox) => (checkbox as HTMLInputElement).value);
document.querySelectorAll('input[name="selected-members"]:checked')
).map(checkbox => (checkbox as HTMLInputElement).value);
if (!createdAt || !deadline || selectedMembers.length === 0) { if (!createdAt || !deadline || selectedMembers.length === 0) {
showAlert('Please fill in all required fields and select at least one member.'); showAlert('Please fill in all required fields and select at least one member.');
@ -1562,7 +1572,7 @@ class SignatureElement extends HTMLElement {
deadline, deadline,
visibility, visibility,
description, description,
selectedMembers selectedMembers,
}); });
showAlert('Document request submitted successfully!'); showAlert('Document request submitted successfully!');
@ -1600,9 +1610,7 @@ class SignatureElement extends HTMLElement {
throw new Error('Document not found'); throw new Error('Document not found');
} }
const userSignature = targetDoc.signatures.find((sig: DocumentSignature) => const userSignature = targetDoc.signatures.find((sig: DocumentSignature) => sig.member.name === currentUser.name);
sig.member.name === currentUser.name
);
if (!userSignature) { if (!userSignature) {
throw new Error(`The user ${currentUser.name} is not authorized to sign this document. Please log in with an authorized user.`); throw new Error(`The user ${currentUser.name} is not authorized to sign this document. Please log in with an authorized user.`);
@ -1628,14 +1636,12 @@ class SignatureElement extends HTMLElement {
} }
showAlert('Document signed successfully!'); showAlert('Document signed successfully!');
} catch (error) { } catch (error) {
console.error('Error signing document:', error); console.error('Error signing document:', error);
showAlert(error instanceof Error ? error.message : 'Error signing document'); showAlert(error instanceof Error ? error.message : 'Error signing document');
} }
} }
private initializeEventListeners() { private initializeEventListeners() {
document.addEventListener('DOMContentLoaded', (): void => { document.addEventListener('DOMContentLoaded', (): void => {
const newRequestBtn = document.getElementById('newRequestBtn'); const newRequestBtn = document.getElementById('newRequestBtn');
@ -1647,7 +1653,7 @@ class SignatureElement extends HTMLElement {
roleId: 0, roleId: 0,
roleName: '', roleName: '',
documentId: 0, documentId: 0,
documentName: '' documentName: '',
}); });
}); });
} }
@ -1708,4 +1714,3 @@ class SignatureElement extends HTMLElement {
customElements.define('signature-element', SignatureElement); customElements.define('signature-element', SignatureElement);
export { SignatureElement }; export { SignatureElement };

View File

@ -20,7 +20,7 @@ export let currentRoute = '';
export async function navigate(path: string) { export async function navigate(path: string) {
cleanSubscriptions(); cleanSubscriptions();
cleanPage() cleanPage();
path = path.replace(/^\//, ''); path = path.replace(/^\//, '');
if (path.includes('/')) { if (path.includes('/')) {
const parsedPath = path.split('/')[0]; const parsedPath = path.split('/')[0];
@ -42,13 +42,12 @@ async function handleLocation(path: string) {
const content = document.getElementById('containerId'); const content = document.getElementById('containerId');
if (content) { if (content) {
if (path === 'home') { if (path === 'home') {
const login = LoginComponent const login = LoginComponent;
const container = document.querySelector('#containerId'); const container = document.querySelector('#containerId');
const accountComponent = document.createElement('login-4nk-component'); const accountComponent = document.createElement('login-4nk-component');
accountComponent.setAttribute('style', 'width: 100vw; height: 100vh; position: relative; grid-row: 2;') accountComponent.setAttribute('style', 'width: 100vw; height: 100vh; position: relative; grid-row: 2;');
if(container) container.appendChild(accountComponent) if (container) container.appendChild(accountComponent);
} else if (path !== 'process') { } else if (path !== 'process') {
const html = await fetch(routeHtml).then((data) => data.text()); const html = await fetch(routeHtml).then((data) => data.text());
content.innerHTML = html; content.innerHTML = html;
@ -70,8 +69,8 @@ async function handleLocation(path: string) {
if (!customElements.get('process-list-4nk-component')) { if (!customElements.get('process-list-4nk-component')) {
customElements.define('process-list-4nk-component', ProcessListComponent); customElements.define('process-list-4nk-component', ProcessListComponent);
} }
accountComponent.setAttribute('style', 'height: 100vh; position: relative; grid-row: 2; grid-column: 4;') accountComponent.setAttribute('style', 'height: 100vh; position: relative; grid-row: 2; grid-column: 4;');
if(container2) container2.appendChild(accountComponent) if (container2) container2.appendChild(accountComponent);
break; break;
case 'process-element': case 'process-element':
@ -157,7 +156,7 @@ export async function init(): Promise<void> {
setTimeout(async () => { setTimeout(async () => {
try { try {
// check if we have a shared secret with that address // check if we have a shared secret with that address
await prepareAndSendPairingTx(pairingAddress) await prepareAndSendPairingTx(pairingAddress);
} catch (e) { } catch (e) {
console.error('Failed to pair:', e); console.error('Failed to pair:', e);
} }
@ -174,7 +173,7 @@ export async function init(): Promise<void> {
async function cleanPage() { async function cleanPage() {
const container = document.querySelector('#containerId'); const container = document.querySelector('#containerId');
if(container) container.innerHTML = '' if (container) container.innerHTML = '';
} }
async function injectHeader() { async function injectHeader() {

View File

@ -1,20 +1,8 @@
const addResourcesToCache = async (resources) => { const addResourcesToCache = async (resources) => {
const cache = await caches.open("v1"); const cache = await caches.open('v1');
await cache.addAll(resources); await cache.addAll(resources);
}; };
self.addEventListener("install", (event) => { self.addEventListener('install', (event) => {
event.waitUntil( 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']));
addResourcesToCache([
"/",
"/index.html",
"/style.css",
"/app.js",
"/image-list.js",
"/star-wars-logo.jpg",
"/gallery/bountyHunters.jpg",
"/gallery/myLittleVader.jpg",
"/gallery/snowTroopers.jpg",
]),
);
}); });

View File

@ -14,16 +14,16 @@ self.addEventListener('message', async (event) => {
const itemsWithFlag = await getAllItemsWithFlag(); const itemsWithFlag = await getAllItemsWithFlag();
// Process items with the specific flag // Process items with the specific flag
itemsWithFlag?.forEach(item => { itemsWithFlag?.forEach((item) => {
console.log(item); // Do something with each flagged item console.log(item); // Do something with each flagged item
}); });
event.ports[0].postMessage({ event.ports[0].postMessage({
type: "NOTIFICATIONS", type: 'NOTIFICATIONS',
data: itemsWithFlag data: itemsWithFlag,
}); });
} };
fetchNotifications() fetchNotifications();
setInterval(fetchNotifications, 2 * 60 * 1000); setInterval(fetchNotifications, 2 * 60 * 1000);
} }
@ -100,13 +100,13 @@ async function getAllItemsWithFlag() {
const request = store.getAll(); const request = store.getAll();
request.onsuccess = (event) => { request.onsuccess = (event) => {
const allItems = event.target.result; const allItems = event.target.result;
const itemsWithFlag = allItems.filter(item => !item.need_validation); const itemsWithFlag = allItems.filter((item) => item.need_validation);
const processMap = {}; const processMap = {};
for (const diff of itemsWithFlag) { for (const diff of itemsWithFlag) {
const currentProcess = allProcesses.find(item => { const currentProcess = allProcesses.find((item) => {
return item.states.some(state => state.merkle_root === diff.new_state_merkle_root); return item.states.some((state) => state.merkle_root === diff.new_state_merkle_root);
}); });
if (currentProcess) { if (currentProcess) {
@ -116,18 +116,25 @@ async function getAllItemsWithFlag() {
processMap[processKey] = { processMap[processKey] = {
process: currentProcess.states, process: currentProcess.states,
processId: currentProcess.key, processId: currentProcess.key,
diffs: [] diffs: [],
}; };
} }
processMap[processKey].diffs.push(diff); processMap[processKey].diffs.push(diff);
} }
} }
const results = Object.values(processMap).map(entry => { 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 { return {
process: entry.process, process: entry.process,
processId: entry.processId, processId: entry.processId,
diffs: entry.diffs diffs: diffs,
}; };
}); });
@ -139,4 +146,3 @@ async function getAllItemsWithFlag() {
}; };
}); });
} }

View File

@ -1,4 +1,4 @@
import Services from "./service"; import Services from './service';
class Database { class Database {
private static instance: Database; private static instance: Database;
@ -32,8 +32,8 @@ class Database {
AnkDiff: { AnkDiff: {
name: 'diffs', name: 'diffs',
options: { key: 'new_state_merkle_root' }, options: { key: 'new_state_merkle_root' },
indices: [] indices: [],
} },
}; };
// Private constructor to prevent direct instantiation from outside // Private constructor to prevent direct instantiation from outside
@ -144,11 +144,11 @@ class Database {
} }
private handleAddObjectResponse = async (event: MessageEvent) => { private handleAddObjectResponse = async (event: MessageEvent) => {
const data = event.data const data = event.data;
console.log('Received response from service worker (ADD_OBJECT):', data); console.log('Received response from service worker (ADD_OBJECT):', data);
if (data.type === 'NOTIFICATIONS') { if (data.type === 'NOTIFICATIONS') {
const service = await Services.getInstance() const service = await Services.getInstance();
service.setNotifications(data.data) service.setNotifications(data.data);
} }
}; };
@ -201,7 +201,7 @@ class Database {
getRequest.onsuccess = () => resolve(getRequest.result); getRequest.onsuccess = () => resolve(getRequest.result);
getRequest.onerror = () => reject(getRequest.error); getRequest.onerror = () => reject(getRequest.error);
}); });
return result return result;
} }
public async dumpStore(storeName: string): Promise<Record<string, any>> { public async dumpStore(storeName: string): Promise<Record<string, any>> {
@ -227,9 +227,8 @@ class Database {
// Combine keys and values into an object // Combine keys and values into an object
const result: Record<string, any> = Object.fromEntries(keys.map((key, index) => [key, values[index]])); const result: Record<string, any> = Object.fromEntries(keys.map((key, index) => [key, values[index]]));
return result; return result;
} catch (error) { } catch (error) {
console.error("Error fetching data from IndexedDB:", error); console.error('Error fetching data from IndexedDB:', error);
throw error; throw error;
} }
} }

View File

@ -2,9 +2,11 @@ import modalHtml from '../components/login-modal/login-modal.html?raw';
import modalScript from '../components/login-modal/login-modal.js?raw'; import modalScript from '../components/login-modal/login-modal.js?raw';
import validationModalStyle from '../components/validation-modal/validation-modal.css?raw'; import validationModalStyle from '../components/validation-modal/validation-modal.css?raw';
import Services from './service'; import Services from './service';
import { navigate } from '../router'; import { init, navigate } from '../router';
import { addressToEmoji } from '../utils/sp-address.utils'; import { addressToEmoji } from '../utils/sp-address.utils';
import { RoleDefinition } from 'pkg/sdk_client'; import { RoleDefinition } from 'pkg/sdk_client';
import { initValidationModal } from '~/components/validation-modal/validation-modal';
import { interpolate } from '~/utils/html.utils';
export default class ModalService { export default class ModalService {
private static instance: ModalService; private static instance: ModalService;
@ -56,28 +58,30 @@ export default class ModalService {
const container = document.querySelector('#containerId'); const container = document.querySelector('#containerId');
if (container) { if (container) {
let html = await fetch('/src/components/validation-modal/validation-modal.html').then((res) => res.text()); let html = await fetch('/src/components/validation-modal/validation-modal.html').then((res) => res.text());
html = interpolate(html, {processId: processDiff.processId})
container.innerHTML += html; container.innerHTML += html;
// Dynamically load the header JS // Dynamically load the header JS
const script = document.createElement('script'); const script = document.createElement('script');
script.id = 'validation-modal-script' script.id = 'validation-modal-script';
script.src = '/src/components/validation-modal/validation-modal.ts'; script.src = '/src/components/validation-modal/validation-modal.ts';
script.type = 'module'; script.type = 'module';
document.head.appendChild(script); document.head.appendChild(script);
const css = document.createElement('style'); const css = document.createElement('style');
css.id = 'validation-modal-css' css.id = 'validation-modal-css';
css.innerText = validationModalStyle; css.innerText = validationModalStyle;
document.head.appendChild(css); document.head.appendChild(css);
initValidationModal(processDiff)
} }
} }
async closeValidationModal() { async closeValidationModal() {
const script = document.querySelector('#validation-modal-script') const script = document.querySelector('#validation-modal-script');
const css = document.querySelector('#validation-modal-css') const css = document.querySelector('#validation-modal-css');
const component = document.querySelector('#validation-modal') const component = document.querySelector('#validation-modal');
script?.remove() script?.remove();
css?.remove() css?.remove();
component?.remove() component?.remove();
} }
// this is kind of too specific for pairing though // this is kind of too specific for pairing though
@ -88,7 +92,7 @@ export default class ModalService {
const owner = roleDefinition['owner']; const owner = roleDefinition['owner'];
members = owner.members; members = owner.members;
} else { } else {
throw new Error('No \"owner\" role'); throw new Error('No "owner" role');
} }
// pairing specifics // pairing specifics
@ -145,7 +149,7 @@ export default class ModalService {
const createPrdUpdateReturn = service.createPrdUpdate(this.currentPcdCommitment); const createPrdUpdateReturn = service.createPrdUpdate(this.currentPcdCommitment);
await service.handleApiReturn(createPrdUpdateReturn); await service.handleApiReturn(createPrdUpdateReturn);
} catch (e) { } catch (e) {
throw e throw e;
} }
} else { } else {
throw new Error('No currentPcdCommitment'); throw new Error('No currentPcdCommitment');
@ -156,7 +160,7 @@ export default class ModalService {
const approveChangeReturn = service.approveChange(this.currentPcdCommitment!); const approveChangeReturn = service.approveChange(this.currentPcdCommitment!);
await service.handleApiReturn(approveChangeReturn); await service.handleApiReturn(approveChangeReturn);
} catch (e) { } catch (e) {
throw e throw e;
} }
try { try {

View File

@ -11,6 +11,8 @@ import { storeData, retrieveData } from './storage.service';
export const U32_MAX = 4294967295; export const U32_MAX = 4294967295;
const storageUrl = `http://localhost:8080`; const storageUrl = `http://localhost:8080`;
const RELAY_ADDRESS = 'sprt1qqdg4x69xdyhxpz4weuel0985qyswa0x9ycl4q6xc0fngf78jtj27gqj5vff4fvlt3fydx4g7vv0mh7vqv8jncgusp6n2zv860nufdzkyy59pqrdr';
const wsurl = `https://demo.4nkweb.com/ws/`;
export default class Services { export default class Services {
private static initializing: Promise<Services> | null = null; private static initializing: Promise<Services> | null = null;
@ -95,7 +97,7 @@ export default class Services {
throw new Error('Trying to connect to empty members list'); throw new Error('Trying to connect to empty members list');
} }
const members_str = members.map(member => JSON.stringify(member)); const members_str = members.map((member) => JSON.stringify(member));
const waitForAmount = async (): Promise<BigInt> => { const waitForAmount = async (): Promise<BigInt> => {
let attempts = 3; let attempts = 3;
@ -186,7 +188,7 @@ export default class Services {
try { try {
return this.sdkClient.create_response_prd(this.currentProcess, pcdMerkleRoot); return this.sdkClient.create_response_prd(this.currentProcess, pcdMerkleRoot);
} catch (e) { } catch (e) {
throw e throw e;
} }
} }
@ -344,7 +346,7 @@ export default class Services {
try { try {
await this.openConfirmationModal(); await this.openConfirmationModal();
} catch (e) { } catch (e) {
throw new Error(`Error while evaluating pending updates for process ${this.currentProcess}: ${e}`) throw new Error(`Error while evaluating pending updates for process ${this.currentProcess}: ${e}`);
} }
} }
@ -479,7 +481,7 @@ export default class Services {
key: commitedIn, key: commitedIn,
}); });
} catch (e) { } catch (e) {
throw new Error(`Failed to save process: ${e}`) throw new Error(`Failed to save process: ${e}`);
} }
// We check how many copies in storage nodes // We check how many copies in storage nodes
@ -510,7 +512,7 @@ export default class Services {
}); });
} }
} catch (e) { } catch (e) {
throw new Error(`Failed to save process: ${e}`) throw new Error(`Failed to save process: ${e}`);
} }
} }
@ -540,7 +542,6 @@ export default class Services {
} catch (e) { } catch (e) {
throw e; throw e;
} }
} }
public async restoreSecrets() { public async restoreSecrets() {
@ -549,14 +550,13 @@ export default class Services {
const sharedSecrets: Record<string, string> = await db.dumpStore('shared_secrets'); const sharedSecrets: Record<string, string> = await db.dumpStore('shared_secrets');
const unconfirmedSecrets = await db.dumpStore('unconfirmed_secrets'); const unconfirmedSecrets = await db.dumpStore('unconfirmed_secrets');
const secretsStore = { const secretsStore = {
'shared_secrets': sharedSecrets, shared_secrets: sharedSecrets,
'unconfirmed_secrets': Object.values(unconfirmedSecrets), unconfirmed_secrets: Object.values(unconfirmedSecrets),
}; };
this.sdkClient.set_shared_secrets(JSON.stringify(secretsStore)); this.sdkClient.set_shared_secrets(JSON.stringify(secretsStore));
} catch (e) { } catch (e) {
throw e; throw e;
} }
} }
getNotifications(): any[] | null { getNotifications(): any[] | null {
@ -583,11 +583,11 @@ export default class Services {
// path: '/notif3', // path: '/notif3',
// }, // },
// ]; // ];
return this.notifications return this.notifications;
} }
setNotifications(notifications: any[]) { setNotifications(notifications: any[]) {
this.notifications = notifications this.notifications = notifications;
} }
async importJSON(content: any): Promise<void> { async importJSON(content: any): Promise<void> {

View File

@ -1,4 +1,4 @@
export function getCorrectDOM(componentTag: string): Node { export function getCorrectDOM(componentTag: string): Node {
const dom = document?.querySelector(componentTag)?.shadowRoot || document as Node const dom = document?.querySelector(componentTag)?.shadowRoot || (document as Node);
return dom return dom;
} }

View File

@ -3,6 +3,6 @@ export function interpolate(template: string, data: { [key: string]: string }) {
} }
export function getCorrectDOM(componentTag: string): Node { export function getCorrectDOM(componentTag: string): Node {
const dom = document?.querySelector(componentTag)?.shadowRoot || document as Node const dom = document?.querySelector(componentTag)?.shadowRoot || (document as Node);
return dom return dom;
} }

View File

@ -37,13 +37,13 @@ class MessageStore {
} }
addMessage(memberId: string | number, message: any) { addMessage(memberId: string | number, message: any) {
const memberMessages = this.messages.find(m => String(m.memberId) === String(memberId)); const memberMessages = this.messages.find((m) => String(m.memberId) === String(memberId));
if (memberMessages) { if (memberMessages) {
memberMessages.messages.push(message); memberMessages.messages.push(message);
} else { } else {
this.messages.push({ this.messages.push({
memberId: String(memberId), memberId: String(memberId),
messages: [message] messages: [message],
}); });
} }
this.saveToLocalStorage(); this.saveToLocalStorage();

View File

@ -100,7 +100,7 @@ export async function displayEmojis(text: string) {
// Verify Other address // Verify Other address
export function initAddressInput() { export function initAddressInput() {
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const addressInput = container.querySelector('#addressInput') as HTMLInputElement; const addressInput = container.querySelector('#addressInput') as HTMLInputElement;
const emojiDisplay = container.querySelector('#emoji-display-2'); const emojiDisplay = container.querySelector('#emoji-display-2');
const okButton = container.querySelector('#okButton') as HTMLButtonElement; const okButton = container.querySelector('#okButton') as HTMLButtonElement;
@ -148,7 +148,7 @@ export function initAddressInput() {
} }
async function onOkButtonClick() { async function onOkButtonClick() {
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const secondDeviceAddress = (container.querySelector('#addressInput') as HTMLInputElement).value; const secondDeviceAddress = (container.querySelector('#addressInput') as HTMLInputElement).value;
try { try {
// Connect to target, if necessary // Connect to target, if necessary
@ -184,7 +184,7 @@ export async function prepareAndSendPairingTx(secondDeviceAddress: string) {
export async function generateQRCode(spAddress: string) { export async function generateQRCode(spAddress: string) {
try { try {
const container = getCorrectDOM('login-4nk-component') as HTMLElement const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const currentUrl = 'https://' + window.location.host; const currentUrl = 'https://' + window.location.host;
const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress); const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress);
const qrCode = container?.querySelector('.qr-code img'); const qrCode = container?.querySelector('.qr-code img');