diff --git a/dist.zip b/dist.zip
new file mode 100644
index 0000000..7ec85d2
Binary files /dev/null and b/dist.zip differ
diff --git a/docs/INDEX.md b/docs/INDEX.md
index ebaf909..d681964 100644
--- a/docs/INDEX.md
+++ b/docs/INDEX.md
@@ -19,10 +19,8 @@ Description fonctionnelle complète (parcours, règles de gestion, contraintes).
Guide complet pour utiliser l'interface utilisateur ihm_client au quotidien.
- **Démarrage du serveur de développement**
- **Utilisation de l'interface utilisateur**
-- **Gestion des profils utilisateurs**
+- **Navigation Accueil et Compte**
- **Opérations de pairing et wallet**
-- **Gestion des processus et documents**
-- **Système de chat et notifications**
- **Tests et validation**
### ⚙️ [Guide de Configuration](CONFIGURATION.md)
diff --git a/docs/USAGE.md b/docs/USAGE.md
index e35a066..1c26a4c 100644
--- a/docs/USAGE.md
+++ b/docs/USAGE.md
@@ -24,12 +24,8 @@ npm run dev
### Navigation Principale
-- **🏠 Accueil** - Vue d'ensemble et statistiques
+- **🏠 Accueil** - Vue d'ensemble et navigation
- **👤 Compte** - Gestion du profil utilisateur
-- **📄 Processus** - Création et gestion des processus
-- **✍️ Signature** - Signatures de documents
-- **💬 Chat** - Communication entre membres
-- **🔗 Pairing** - Connexion avec d'autres utilisateurs
### Tableau de Bord
diff --git a/src/main.ts b/src/main.ts
index b0f47a4..80e6840 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,16 +1,13 @@
-import { SignatureComponent } from './pages/signature/signature-component';
-import { SignatureElement } from './pages/signature/signature';
/*import { ChatComponent } from './pages/chat/chat-component';
import { ChatElement } from './pages/chat/chat';*/
import { AccountComponent } from './pages/account/account-component';
import { AccountElement } from './pages/account/account';
-export { SignatureComponent, SignatureElement, AccountComponent, AccountElement };
+export { AccountComponent, AccountElement };
declare global {
interface HTMLElementTagNameMap {
- 'signature-component': SignatureComponent;
- 'signature-element': SignatureElement;
+ // Signatures supprimées
/*'chat-component': ChatComponent;
'chat-element': ChatElement;*/
'account-component': AccountComponent;
@@ -21,8 +18,7 @@ declare global {
// Configuration pour le mode indépendant
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) {
// Initialiser les composants si nécessaire
- customElements.define('signature-component', SignatureComponent);
- customElements.define('signature-element', SignatureElement);
+ // Signatures supprimées
/*customElements.define('chat-component', ChatComponent);
customElements.define('chat-element', ChatElement);*/
customElements.define('account-component', AccountComponent);
diff --git a/src/pages/chat/chat-component.ts b/src/pages/chat/chat-component.ts
deleted file mode 100644
index 2ded0b8..0000000
--- a/src/pages/chat/chat-component.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-/*import { ChatElement } from './chat';
-import chatCss from '../../../public/style/chat.css?raw';
-import Services from '../../services/service.js';
-
-class ChatComponent extends HTMLElement {
- _callback: any;
- chatElement: ChatElement | null = null;
-
- constructor() {
- super();
- console.log('INIT');
- this.attachShadow({ mode: 'open' });
-
- this.chatElement = this.shadowRoot?.querySelector('chat-element') || null;
- }
-
- connectedCallback() {
- console.log('CALLBACKs');
- this.render();
-
- if (!customElements.get('chat-element')) {
- customElements.define('chat-element', ChatElement);
- }
- }
-
- set callback(fn) {
- if (typeof fn === 'function') {
- this._callback = fn;
- } else {
- console.error('Callback is not a function');
- }
- }
-
- get callback() {
- return this._callback;
- }
-
- render() {
- if (this.shadowRoot) {
- // Créer l'élément chat-element
- const chatElement = document.createElement('chat-element');
- this.shadowRoot.innerHTML = ``;
- this.shadowRoot.appendChild(chatElement);
- }
- }
-}
-
-export { ChatComponent };
-customElements.define('chat-component', ChatComponent);*/
diff --git a/src/pages/chat/chat.html b/src/pages/chat/chat.html
deleted file mode 100755
index 5265c88..0000000
--- a/src/pages/chat/chat.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
- `;
- window.loadMemberChat = async (memberId: string | number) => {
- if (typeof memberId === 'string') {
- return await this.loadMemberChat(memberId);
- } else {
- console.error('Invalid memberId type. Expected string, got number.');
- }
- };
-
- document.addEventListener('newDataReceived', async (event: CustomEvent) => {
- const { detail } = event;
- console.log('New data event received:', JSON.stringify(detail));
-
- if (detail.processId && detail.processId === this.selectedChatProcessId) {
- console.log('Detected update to chat');
- if (this.selectedMember) {
- await this.loadMemberChat(this.selectedMember);
- } else {
- console.error('No selected member?');
- }
- } else {
- console.log('Received an update for another process');
- }
- });
-
-
- document.addEventListener('DOMContentLoaded', () => {
- this.notificationBadge = document.querySelector('.notification-badge');
- this.notificationBoard = document.getElementById('notification-board');
- this.notificationBell = document.getElementById('notification-bell');
-
- if (!this.notificationBadge || !this.notificationBoard || !this.notificationBell) {
- console.error('Notification elements not found');
- }
- });
-
- // Initialiser les événements de notification
- document.addEventListener('click', (event: Event): void => {
- if (this.notificationBoard && this.notificationBoard.style.display === 'block' &&
- !this.notificationBoard.contains(event.target as Node) &&
- this.notificationBell && !this.notificationBell.contains(event.target as Node)) {
- this.notificationBoard.style.display = 'none';
- }
- });
- this.initMessageEvents();
-
- }
-
- private initMessageEvents() {
- const sendButton = this.shadowRoot?.querySelector('#send-button');
- if (sendButton) {
- sendButton.addEventListener('click', async () => {
- await this.sendMessage();
- setTimeout(async () => await this.reloadMemberChat(this.selectedMember), 600);
- messageInput.value = '';
- });
- }
-
- const messageInput = this.shadowRoot?.querySelector('#message-input');
- if (messageInput) {
- messageInput.addEventListener('keypress', async (event: Event) => {
- const keyEvent = event as KeyboardEvent;
- if (keyEvent.key === 'Enter' && !keyEvent.shiftKey) {
- event.preventDefault();
- await this.sendMessage();
- setTimeout(async () => await this.reloadMemberChat(this.selectedMember), 600);
- messageInput.value = '';
- }
- });
- }
-
- const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement;
- if (fileInput) {
- fileInput.addEventListener('change', (event: Event) => {
- const target = event.target as HTMLInputElement;
- if (target.files && target.files.length > 0) {
- this.sendFile(target.files[0]);
- }
- });
- }
- }
-
- ///////////////////// Notification module /////////////////////
- // Delete a notification
- private removeNotification(index: number) {
- this.notifications?.splice(index, 1); // Ajout de ?.
- this.renderNotifications();
- this.updateNotificationBadge();
- }
- // Show notifications
- private renderNotifications() {
- if (!this.notificationBoard) return;
-
- // Reset the interface
- this.notificationBoard.innerHTML = '';
-
- // Displays "No notifications available" if there are no notifications
- if (this.notifications.length === 0) {
- this.notificationBoard.innerHTML = 'No notifications available
';
- return;
- }
-
- // Add each notification to the list
- this.notifications.forEach((notif, index) => {
- const notifElement = document.createElement('div');
- notifElement.className = 'notification-item';
- notifElement.textContent = `${notif.text} at ${notif.time}`;
- notifElement.onclick = async () => {
- await this.loadMemberChat(notif.memberId);
- await this.removeNotification(index);
- };
- this.notificationBoard?.appendChild(notifElement);
- });
- }
- private updateNotificationBadge() {
- if (!this.notificationBadge) return;
- const count = this.notifications.length;
- this.notificationBadge.textContent = count > 99 ? '+99' : count.toString();
- (this.notificationBadge as HTMLElement).style.display = count > 0 ? 'block' : 'none';
- }
-
-
- // Add notification
- private async addNotification(memberId: string, message: any) {
- try {
- // Obtenir l'emoji à partir du Pairing Process
- const pairingProcess = await this.getPairingProcess(memberId);
- const memberEmoji = await addressToEmoji(pairingProcess);
-
- // Obtenir le processus et le rôle
- const processId = this.getAttribute('process-id');
- const processEmoji = processId ? await addressToEmoji(processId) : '📝';
-
- // Trouver le rôle du membre
- const member = this.allMembers.find(m => String(m.id) === memberId);
- const role = message.metadata?.roleName || 'Member';
-
- // Déterminer le texte de la notification
- let notificationText = '';
- if (message.type === 'file') {
- notificationText = `${memberEmoji} (${role}) in ${processEmoji}: New file - ${message.fileName}`;
- } else {
- notificationText = `${memberEmoji} (${role}) in ${processEmoji}: ${message.metadata.text}`;
- }
-
- // Créer la notification
- const notification = {
- memberId,
- text: notificationText,
- time: new Date(message.metadata.timestamp).toLocaleString('fr-FR')
- };
-
- // Ajouter la notification et mettre à jour l'interface
- this.notifications.push(notification);
- this.renderNotifications();
- this.updateNotificationBadge();
-
- } catch (error) {
- console.error('Error creating notification:', error);
- }
- }
-
- private async sendMessage() {
- const messageInput = this.shadowRoot?.querySelector('#message-input') as HTMLInputElement;
- if (!messageInput || !this.selectedMember) {
- console.error('❌ Missing message input or selected member');
- return;
- }
-
- if (!this.selectedChatProcessId) {
- console.error('no process id set');
- return;
- }
-
- const messageText = messageInput.value.trim();
- if (messageText === '') {
- console.error('❌ Empty message');
- return;
- }
-
- try {
- const service = await Services.getInstance();
- const myProcessId = await this.getMyProcessId();
-
- if (!myProcessId) {
- console.error('No paired member found');
- return;
- }
-
- const timestamp = Date.now();
- const message = {
- state: this.messageState,
- type: 'text',
- content: messageText,
- metadata: {
- createdAt: timestamp,
- lastModified: timestamp,
- sender: myProcessId,
- recipient: this.selectedMember,
- }
- };
-
- console.log("----this.selectedChatProcessId",this.selectedChatProcessId );
- const process = await service.getProcess(this.selectedChatProcessId);
-
- if (!process) {
- console.error('Failed to retrieve process from DB');
- return;
- }
-
- // For a dm process, there are only 2 attributes, description will stay the same, message is the new message
- // We don't need to get previous values for now, so let's just skip it
- let newState = {
- message: message,
- description: 'dm'
- };
-
- // Now we create a new state for the dm process
- let apiReturn;
- try {
- console.log(process);
- apiReturn = await service.updateProcess(process, newState, null);
- } catch (e) {
- console.error('Failed to update process:', e);
- return;
- }
- const updatedProcess = apiReturn.updated_process.current_process;
- const newStateId = updatedProcess.states[updatedProcess.states.length - 2 ].state_id; // We take the last concurrent state, just before the tip
- console.log(`newStateId: ${newStateId}`);
- await service.handleApiReturn(apiReturn);
-
- const createPrdReturn = service.createPrdUpdate(this.selectedChatProcessId, newStateId);
- await service.handleApiReturn(createPrdReturn);
-
- // Now we validate the new state
- const approveChangeReturn = await service.approveChange(this.selectedChatProcessId, newStateId);
- await service.handleApiReturn(approveChangeReturn);
-
- await this.lookForMyDms();
-
- const groupList = this.shadowRoot?.querySelector('#group-list');
- const tabs = this.shadowRoot?.querySelectorAll('.tab');
- const memberList = groupList?.querySelector('.member-list');
-
- if (memberList) {
- memberList.innerHTML = '';
- await this.loadAllMembers();
- if (tabs) {
- await this.switchTab('members', tabs);
- }
- }
- } catch (error) {
- console.error('❌ Error in sendMessage:', error);
- }
- }
-
- private scrollToBottom(container: Element) {
- (container as HTMLElement).scrollTop = (container as HTMLElement).scrollHeight;
- }
-
- // Get the diff by state id
- async getDiffByStateId(stateId: string) {
- try {
- const database = await Database.getInstance();
- const diff = await database.requestStoreByIndex('diffs', 'byStateId', stateId);
- return diff;
- } catch (error) {
- console.error('Error getting diff by state id:', error);
- }
- }
-
- // TODO rewrite that
- // private async lookForChildren(): Promise {
- // // Filter processes for the children of current process
- // const service = await Services.getInstance();
- // if (!this.selectedChatProcessId) {
- // console.error('No process id');
- // return null;
- // }
- // const children: string[] = await service.getChildrenOfProcess(this.selectedChatProcessId);
-
- // const processRoles = this.processRoles;
- // const selectedMember = this.selectedMember;
- // for (const child of children) {
- // const roles = service.getRoles(JSON.parse(child));
- // // Check that we and the other members are in the role
- // if (!service.isChildRole(processRoles, roles)) {
- // console.error('Child process roles are not a subset of parent')
- // continue;
- // }
- // if (!service.rolesContainsMember(roles, selectedMember)) {
- // console.error('Member is not part of the process');
- // continue;
- // }
- // if (!service.rolesContainsUs(roles)) {
- // console.error('We\'re not part of child process');
- // continue;
- // }
- // return child;
- // }
-
- // return null;
- // }
-
- private async loadAllMembers() {
- const groupList = this.shadowRoot?.querySelector('#group-list');
- if (!groupList) return;
-
- const service = await Services.getInstance();
- const members = await service.getAllMembers();
- const processes = await service.getProcesses();
-
- const memberList = document.createElement('ul');
- memberList.className = 'member-list active';
-
- // Partition members into prioritized and remaining arrays.
- const prioritizedMembers: [string, Member][] = [];
- const remainingMembers: [string, Member][] = [];
- for (const [processId, member] of Object.entries(members)) {
- if (this.dmMembersSet.has(processId)) {
- prioritizedMembers.push([processId, member]);
- } else {
- remainingMembers.push([processId, member]);
- }
- }
- const sortedMembers = prioritizedMembers.concat(remainingMembers);
-
- // Process each member.
- for (const [processId, member] of sortedMembers) {
- const memberItem = document.createElement('li');
- memberItem.className = 'member-item';
-
- // Apply special styling if the member is prioritized.
- if (this.dmMembersSet.has(processId)) {
- memberItem.style.cssText = `
- background-color: var(--accent-color);
- transition: background-color 0.3s ease;
- cursor: pointer;
- `;
- memberItem.addEventListener('mouseover', () => {
- memberItem.style.backgroundColor = 'var(--accent-color-hover)';
- });
- memberItem.addEventListener('mouseout', () => {
- memberItem.style.backgroundColor = 'var(--accent-color)';
- });
- }
-
- // Create a container for the member content.
- const memberContainer = document.createElement('div');
- memberContainer.className = 'member-container';
-
- // Create the emoji span and load its label.
- const emojiSpan = document.createElement('span');
- emojiSpan.className = 'member-emoji';
- const emojis = await addressToEmoji(processId);
- emojiSpan.dataset.emojis = emojis;
-
- // Get the member name, if any, and add it to the display
- const process = processes[processId];
- let memberPublicName;
- if (process) {
- const publicMemberData = service.getPublicData(process);
- if (publicMemberData) {
- const extractedName = publicMemberData['memberPublicName'];
- if (extractedName !== undefined && extractedName !== null) {
- memberPublicName = extractedName;
- }
- }
- }
- if (!memberPublicName) {
- memberPublicName = 'Unnamed Member';
- }
-
- emojiSpan.textContent = `${memberPublicName} (${emojis})`
-
- memberContainer.appendChild(emojiSpan);
- memberItem.appendChild(memberContainer);
-
- // Add click handler to load member chat.
- memberItem.addEventListener('click', async () => {
- await this.loadMemberChat(processId);
- });
-
- // Create and configure the edit label button.
- const editLabelButton = document.createElement('button');
- editLabelButton.className = 'edit-label-button';
- editLabelButton.textContent = "✏️";
- editLabelButton.addEventListener("click", (event) => {
- event.stopPropagation();
- });
- editLabelButton.addEventListener("dblclick", async (event) => {
- event.stopPropagation();
- event.preventDefault();
-
- const newLabel = prompt("Set a new name for the member:");
- if (!newLabel) return;
-
- const db = await Database.getInstance();
- this.updateLabelForEmoji(emojis, newLabel, db, emojiSpan, processId);
- });
- memberContainer.appendChild(editLabelButton);
-
- memberList.appendChild(memberItem);
- }
-
- groupList.appendChild(memberList);
- }
-
- // Helper function to update a label in IndexedDB.
- private updateLabelForEmoji(
- emojis: string,
- newLabel: string,
- db: IDBDatabase,
- emojiSpan: HTMLElement,
- processId: string
- ) {
- const transaction = db.transaction("labels", "readwrite");
- const store = transaction.objectStore("labels");
- const labelObject = { emoji: emojis, label: newLabel };
- const request = store.put(labelObject);
-
- request.onsuccess = () => {
- emojiSpan.textContent = `${newLabel} : ${emojis}`;
- this.reloadMemberChat(processId);
- };
- }
-
- private async lookForDmProcess(): Promise {
- const service = await Services.getInstance();
- const processes = await service.getMyProcesses();
- console.log(processes);
- const recipientAddresses = await service.getAddressesForMemberId(this.selectedMember).sp_addresses;
- console.log(recipientAddresses);
-
- for (const processId of processes) {
- try {
- const process = await service.getProcess(processId);
- console.log(process);
- const state = process.states[0]; // We assume that description never change and that we are part of the process from the beginning
- const description = await service.decryptAttribute(processId, state, 'description');
- console.log(description);
- if (!description || description !== "dm") {
- continue;
- }
- const roles = service.getRoles(process);
- if (!service.rolesContainsMember(roles, recipientAddresses)) {
- console.error('Member is not part of the process');
- continue;
- }
- return processId;
- } catch (e) {
- console.error(e);
- }
- }
-
- return null;
- }
-
- private async lookForMyDms(): Promise {
- const service = await Services.getInstance();
- const processes = await service.getMyProcesses();
- const myAddresses = await service.getMemberFromDevice();
- const allMembers = await service.getAllMembers();
-
- this.dmMembersSet.clear();
-
- try {
- for (const processId of processes) {
- const process = await service.getProcess(processId);
- const state = process.states[0];
- const description = await service.decryptAttribute(processId, state, 'description');
- if (!description || description !== "dm") {
- continue;
- }
- const roles = service.getRoles(process);
- const members = roles.dm.members;
- for (const member of members) {;
- if (!service.compareMembers(member.sp_addresses, myAddresses)) {
- for (const [id, mem] of Object.entries(allMembers)) {
- if (service.compareMembers(mem.sp_addresses, member.sp_addresses)) {
- this.dmMembersSet.add(id);
- break;
- }
- }
- }
- }
- }
- } catch (e) {
- console.error(e);
- }
- console.log("dmMembersSet:", this.dmMembersSet);
- return null;
- }
-
- private async loadMemberChat(pairingProcess: string) {
- if (this.isLoading) {
- console.log('Already loading messages, skipping...');
- return;
- }
-
- try {
- this.isLoading = true;
- const service = await Services.getInstance();
- const myAddresses = await service.getMemberFromDevice();
- const database = await Database.getInstance();
- const db = database.db;
-
- if (!myAddresses) {
- console.error('No paired member found');
- return;
- }
-
- // Set the selected member
- this.selectedMember = pairingProcess;
- console.log("SELECTED MEMBER: ", this.selectedMember);
-
- const chatHeader = this.shadowRoot?.querySelector('#chat-header');
- const messagesContainer = this.shadowRoot?.querySelector('#messages');
-
- if (!chatHeader || !messagesContainer) return;
-
- messagesContainer.innerHTML = '';
-
- const emojis = await addressToEmoji(pairingProcess);
-
- const transaction = db.transaction("labels", "readonly");
- const store = transaction.objectStore("labels");
- const request = store.get(emojis);
-
- request.onsuccess = () => {
- const label = request.result;
- chatHeader.textContent = label ? `Chat with ${label.label} (${emojis})` : `Chat with member (${emojis})`;
- };
-
- request.onerror = () => {
- chatHeader.textContent = `Chat with member (${emojis})`;
- };
-
- let dmProcessId = await this.lookForDmProcess();
-
- if (dmProcessId === null) {
- console.log('Create a new dm process');
- // We need to create a new process
- try {
- const memberAddresses = await service.getAddressesForMemberId(this.selectedMember);
- console.log("MEMBER ADDRESSES: ", memberAddresses);
- // await service.checkConnections(otherMembers);
- const res = await service.createDmProcess(memberAddresses.sp_addresses);
- // We catch the new process here
- const updatedProcess = res.updated_process?.current_process;
- const processId = updatedProcess?.states[0]?.commited_in;
- const stateId = updatedProcess?.states[0]?.state_id;
- await service.handleApiReturn(res);
- setTimeout(async () => {
- // Now create a first commitment
- console.log('Created a dm process', processId);
- this.selectedChatProcessId = processId;
- const createPrdReturn = await service.createPrdUpdate(processId, stateId);
- await service.handleApiReturn(createPrdReturn);
- const approveChangeReturn = await service.approveChange(processId, stateId);
- await service.handleApiReturn(approveChangeReturn);
- }, 500);
- } catch (e) {
- console.error(e);
- return;
- }
-
- while (dmProcessId === null) {
- dmProcessId = await this.lookForDmProcess();
- await new Promise(r => setTimeout(r, 1000));
- }
- } else {
- console.log('Found DM process', dmProcessId);
- this.selectedChatProcessId = dmProcessId;
- }
-
- // Récupérer les messages depuis les états du processus
- const allMessages: any[] = [];
-
- const dmProcess = await service.getProcess(this.selectedChatProcessId);
-
- console.log(dmProcess);
-
- if (dmProcess?.states) {
- for (const state of dmProcess.states) {
- if (state.state_id === '') { continue; }
- const message = await service.decryptAttribute(this.selectedChatProcessId, state, 'message');
- if (message === "" || message === undefined || message === null) {
- continue;
- }
- console.log('message', message);
- allMessages.push(message);
- }
- }
-
- if (allMessages.length > 0) {
- console.log('Messages found:', allMessages);
- allMessages.sort((a, b) => a.metadata.createdAt - b.metadata.createdAt);
- for (const message of allMessages) {
- const messageElement = document.createElement('div');
- messageElement.className = 'message-container';
-
- const myProcessId = await this.getMyProcessId();
-
- const isCurrentUser = message.metadata.sender === myProcessId;
- messageElement.style.justifyContent = isCurrentUser ? 'flex-end' : 'flex-start';
-
- const messageContent = document.createElement('div');
- messageContent.className = isCurrentUser ? 'message user' : 'message';
-
- const myEmoji = await addressToEmoji(myProcessId);
- const otherEmoji = await addressToEmoji(this.selectedMember);
-
- const senderEmoji = isCurrentUser ? myEmoji : otherEmoji;
-
- if (message.type === 'file') {
- let fileContent = '';
- if (message.content.type.startsWith('image/')) {
- fileContent = `
-
-

-
- `;
- } else {
- const blob = this.base64ToBlob(message.content.data, message.content.type);
- const url = URL.createObjectURL(blob);
- fileContent = `
-
- `;
- }
-
- messageContent.innerHTML = `
-
- ${senderEmoji}: ${fileContent}
-
-
- ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')}
-
- `;
- } else {
- messageContent.innerHTML = `
-
- ${senderEmoji}: ${message.content}
-
-
- ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')}
-
- `;
- }
-
- messageElement.appendChild(messageContent);
- messagesContainer.appendChild(messageElement);
- }
-
- this.scrollToBottom(messagesContainer);
- } else {
- console.log('No messages found');
- }
- this.scrollToBottom(messagesContainer);
- } catch (error) {
- console.error('❌ Error in loadMemberChat:', error);
- } finally {
- this.isLoading = false;
- }
- }
-
- private async reloadMemberChat(pairingProcess: string) {
- try {
- const service = await Services.getInstance();
- const database = await Database.getInstance();
- const db = database.db;
-
- const chatHeader = this.shadowRoot?.querySelector('#chat-header');
- const messagesContainer = this.shadowRoot?.querySelector('#messages');
-
- if (!chatHeader || !messagesContainer) return;
-
- messagesContainer.innerHTML = '';
-
- const emojis = await addressToEmoji(pairingProcess);
-
- const transaction = db.transaction("labels", "readonly");
- const store = transaction.objectStore("labels");
- const request = store.get(emojis);
-
- request.onsuccess = () => {
- const label = request.result;
- if (this.selectedMember === pairingProcess) {
- chatHeader.textContent = label ? `Chat with ${label.label} (${emojis})` : `Chat with member (${emojis})`;
- }
-
- };
-
- request.onerror = () => {
- chatHeader.textContent = `Chat with member (${emojis})`;
- };
-
- let dmProcessId = await this.selectedChatProcessId;
-
- // Récupérer les messages depuis les états du processus
- const allMessages: any[] = [];
-
- const dmProcess = await service.getProcess(dmProcessId);
-
- console.log(dmProcess);
-
- if (dmProcess?.states) {
- for (const state of dmProcess.states) {
- if (!state.state_id) { continue; }
- const message = await service.decryptAttribute(dmProcessId, state, 'message');
- if (message === "" || message === undefined || message === null) {
- continue;
- }
- console.log('message', message);
- allMessages.push(message);
- }
- }
-
- allMessages.sort((a, b) => a.metadata.createdAt - b.metadata.createdAt);
- if (allMessages.length > 0) {
- console.log('Messages found:', allMessages);
- for (const message of allMessages) {
- const messageElement = document.createElement('div');
- messageElement.className = 'message-container';
-
- const myProcessId = await this.getMyProcessId();
-
- const isCurrentUser = message.metadata.sender === myProcessId;
- messageElement.style.justifyContent = isCurrentUser ? 'flex-end' : 'flex-start';
-
- const messageContent = document.createElement('div');
- messageContent.className = isCurrentUser ? 'message user' : 'message';
-
-
-
- const myEmoji = await addressToEmoji(myProcessId);
- const otherEmoji = await addressToEmoji(this.selectedMember);
-
- const senderEmoji = isCurrentUser ? myEmoji : otherEmoji;
-
- if (message.type === 'file') {
- let fileContent = '';
- if (message.content.type.startsWith('image/')) {
- fileContent = `
-
-

-
- `;
- } else {
- const blob = this.base64ToBlob(message.content.data, message.content.type);
- const url = URL.createObjectURL(blob);
- fileContent = `
-
- `;
- }
-
- messageContent.innerHTML = `
-
- ${senderEmoji}: ${fileContent}
-
-
- ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')}
-
- `;
- } else {
- messageContent.innerHTML = `
-
- ${senderEmoji}: ${message.content}
-
-
- ${new Date(message.metadata.createdAt).toLocaleString('fr-FR')}
-
- `;
- }
-
- messageElement.appendChild(messageContent);
- messagesContainer.appendChild(messageElement);
- }
-
- this.scrollToBottom(messagesContainer);
- } else {
- console.log('No messages found');
- }
- this.scrollToBottom(messagesContainer);
- } catch (error) {
- console.error('❌ Error in reloadMemberChat:', error);
- }
- }
-
- private base64ToBlob(base64: string, type: string): Blob {
- const byteCharacters = atob(base64.split(',')[1]);
- const byteArrays = [];
-
- for (let offset = 0; offset < byteCharacters.length; offset += 512) {
- const slice = byteCharacters.slice(offset, offset + 512);
- const byteNumbers = new Array(slice.length);
-
- for (let i = 0; i < slice.length; i++) {
- byteNumbers[i] = slice.charCodeAt(i);
- }
-
- const byteArray = new Uint8Array(byteNumbers);
- byteArrays.push(byteArray);
- }
-
- return new Blob(byteArrays, { type: type });
- }
-
- //To get a map with key: sp address, value: pairing process
- async getAddressMap() {
- const service = await Services.getInstance();
- const allMembers = await service.getAllMembers();
-
- const addressMap: Record = {};
-
- for (const [key, values] of Object.entries(allMembers)) {
-
- if (values.sp_addresses) {
- for (let value of values.sp_addresses) {
- this.addressMap[value] = key;
- }
- } else {
- console.log(`No sp_addresses array found for key "${key}"`);
- }
- }
- return this.addressMap;
- }
-
- async findProcessIdFromAddresses(addresses: string[]): Promise {
- console.log('Addresses to find:', addresses);
- const service = await Services.getInstance();
- const allMembers = await service.getAllMembers();
- console.log('Available members:', allMembers);
-
- const sortedAddresses = [...addresses].sort();
-
- for (const [key, value] of Object.entries(allMembers)) {
- if (value.sp_addresses.length === sortedAddresses.length) {
- const sortedValue = [...value.sp_addresses].sort();
- if (sortedValue.every((val, index) => val === sortedAddresses [index])) {
- return key; // Found a match
- }
- }
- }
-
- return null; // No match found
- }
-
- private async toggleMembers(roleData: any, roleElement: HTMLElement) {
- console.log('Toggle members called with roleData:', roleData);
- let memberList = roleElement.querySelector('.member-list');
- const roleName = roleElement.querySelector('.role-name')?.textContent || '';
-
- if (memberList) {
- console.log('Existing memberList found, toggling display');
- (memberList as HTMLElement).style.display =
- (memberList as HTMLElement).style.display === 'none' ? 'block' : 'none';
- return;
- }
-
- console.log('Creating new memberList');
- memberList = document.createElement('ul');
- memberList.className = 'member-list';
-
- if (roleData.members) {
- console.log('Members found:', roleData.members);
- for (const member of roleData.members) {
- console.log('Processing member:', member);
- const memberItem = document.createElement('li');
- memberItem.className = 'member-item';
-
- const memberContainer = document.createElement('div');
- memberContainer.className = 'member-container';
-
- const emojiSpan = document.createElement('span');
- emojiSpan.className = 'member-emoji';
-
- const pairingProcess = await this.findProcessIdFromAddresses(member.sp_addresses);
- console.log('PairingProcess:', pairingProcess);
- if (pairingProcess) {
- //TO DO : faire apparaitre les membres avec lesquelels je suis pairé ?
- const emojis = await addressToEmoji(pairingProcess);
- console.log('Adresse pairée:', emojis);
- emojiSpan.textContent = emojis;
- } else {
- const emojis = await addressToEmoji(member.sp_addresses[0]);
- emojiSpan.textContent = emojis;
- }
-
- memberContainer.appendChild(emojiSpan);
- memberItem.appendChild(memberContainer);
-
- memberItem.onclick = async (event) => {
- event.stopPropagation();
- try {
- if (pairingProcess) {
- await this.loadMemberChat(pairingProcess);
- }
- } catch (error) {
- console.error('❌ Error handling member click:', error);
- }
- };
-
- memberList.appendChild(memberItem);
- }
- } else {
- console.log('No members found in roleData');
- }
-
- roleElement.appendChild(memberList);
- }
-
-
- private async switchTab(tabType: string, tabs: NodeListOf) {
- const service = await Services.getInstance();
-
- // Mettre à jour les classes des onglets
- tabs.forEach(tab => {
- tab.classList.toggle('active', tab.getAttribute('data-tab') === tabType);
- });
-
- // Supprimer le contenu existant sauf les onglets
- const groupList = this.shadowRoot?.querySelector('#group-list');
- if (!groupList) return;
-
- const children = Array.from(groupList.children);
- children.forEach(child => {
- if (!child.classList.contains('tabs')) {
- groupList.removeChild(child);
- }
- });
-
- // Charger le contenu approprié
- switch (tabType) {
- case 'processes':
- const processSet = await service.getMyProcesses();
- await this.loadAllProcesses(processSet);
- break;
- case 'members':
- await this.lookForMyDms();
- await this.loadAllMembers();
- break;
- default:
- console.error('Unknown tab type:', tabType);
- }
- }
-
- //load all processes from the service
- private async loadAllProcesses() {
- console.log('🎯 Loading all processes');
- this.closeSignature();
-
- const service = await Services.getInstance();
- const allProcesses: Record = await service.getProcesses();
- console.log('All processes:', allProcesses);
- const myProcesses: string[] = await service.getMyProcesses();
- console.log('My processes:', myProcesses);
-
- const groupList = this.shadowRoot?.querySelector('#group-list');
- if (!groupList) {
- console.warn('⚠️ Group list element not found');
- return;
- }
-
- groupList.innerHTML = '';
-
- const tabContent = document.createElement('div');
- tabContent.className = 'tabs';
- tabContent.innerHTML = `
-
-
- `;
- groupList.appendChild(tabContent);
-
- // Ajouter les event listeners
- const tabs = tabContent.querySelectorAll('.tab');
- tabs.forEach(tab => {
- tab.addEventListener('click', () => {
- const tabType = tab.getAttribute('data-tab');
- if (tabType) {
- this.switchTab(tabType, tabs);
- }
- });
- });
-
- // Trier les processus : ceux de l'utilisateur en premier
- const sortedEntries = Object.entries(allProcesses).sort(
- ([keyA], [keyB]) => {
- const inSetA = myProcesses.includes(keyA);
- const inSetB = myProcesses.includes(keyB);
- return inSetB ? 1 : inSetA ? -1 : 0;
- }
- );
-
- for (const [processId, process] of sortedEntries) {
- // Create and configure the main list item.
- const li = document.createElement('li');
- li.className = 'group-list-item';
- li.setAttribute('data-process-id', processId);
-
- // Retrieve roles for the current process.
- const roles = service.getRoles(process);
- if (!roles) {
- console.error('Failed to get roles for process:', process);
- continue;
- }
-
- // If process is a pairing process, we don't want it in the list
- if (service.isPairingProcess(roles)) {
- continue;
- }
-
- const publicData = service.getPublicData(process);
- const processName = publicData['processName'];
- const emoji = await addressToEmoji(processId);
-
- let displayName;
- if (processName) {
- displayName = `${processName} (${emoji})`;
- } else {
- displayName = `${defaultProcessName} (${emoji})`;
- }
-
- // If the process is part of myProcesses, apply special styling.
- if (myProcesses && myProcesses.includes(processId)) {
- li.style.cssText = `
- background-color: var(--accent-color);
- transition: background-color 0.3s ease;
- cursor: pointer;
- `;
- li.addEventListener('mouseover', () => {
- li.style.backgroundColor = 'var(--accent-color-hover)';
- });
- li.addEventListener('mouseout', () => {
- li.style.backgroundColor = 'var(--accent-color)';
- });
- console.log("✅ Processus trouvé dans le set:", processId);
- }
-
- // Attach a click handler for the process.
- li.addEventListener('click', async (event) => {
- event.stopPropagation();
- console.log("CLICKED ON PROCESS:", processId);
-
- // Update the signature header with the corresponding emoji.
- const signatureHeader = this.shadowRoot?.querySelector('.signature-header h1');
- if (signatureHeader) {
- if (processName) {
- signatureHeader.textContent = `Signature of ${displayName}`;
- } else {
- signatureHeader.textContent = `Signature of ${displayName}`;
- }
- }
-
- this.openSignature();
- console.log('🎯 Roles de signature:', roles);
- await this.loadAllRolesAndMembersInSignature(roles);
- await this.newRequest(processId);
- });
-
- // Create the container for the process name and emoji.
- const container = document.createElement('div');
- container.className = 'group-item-container';
-
- // Create and set the process name element.
- const nameSpan = document.createElement('span');
- nameSpan.className = 'process-name';
- nameSpan.textContent = displayName;
- container.appendChild(nameSpan);
-
- li.appendChild(container);
-
- // Create a hidden list for roles.
- const roleList = document.createElement('ul');
- roleList.className = 'role-list';
- roleList.style.display = 'none';
-
- // Process each role and create role items.
- Object.entries(roles).forEach(([roleName, roleData]) => {
- const roleItem = document.createElement('li');
- roleItem.className = 'role-item';
-
- const roleContainer = document.createElement('div');
- roleContainer.className = 'role-item-container';
-
- const roleNameSpan = document.createElement('span');
- roleNameSpan.className = 'role-name';
- roleNameSpan.textContent = roleName;
-
- // Filter duplicate members by using the first sp_address as a key.
- const uniqueMembers = new Map();
- roleData.members?.forEach(member => {
- const spAddress = member.sp_addresses?.[0];
- if (spAddress && !uniqueMembers.has(spAddress)) {
- uniqueMembers.set(spAddress, member);
- }
- });
-
- // Create a new roleData object with unique members.
- const filteredRoleData = {
- ...roleData,
- members: Array.from(uniqueMembers.values()),
- };
-
- // Attach a click handler for the role.
- roleContainer.addEventListener('click', async (event) => {
- event.stopPropagation();
- console.log("CLICKED ON ROLE:", roleName);
- await this.toggleMembers(filteredRoleData, roleItem);
- });
-
- roleContainer.appendChild(roleNameSpan);
- roleItem.appendChild(roleContainer);
- roleList.appendChild(roleItem);
- });
-
- li.appendChild(roleList);
-
- // Toggle role list display when the container is clicked.
- container.addEventListener('click', (event) => {
- event.stopPropagation();
- container.classList.toggle('expanded');
- roleList.style.display = container.classList.contains('expanded') ? 'block' : 'none';
- });
-
- // Append the completed process list item once.
- groupList.appendChild(li);
- }
-
- }
-
- private async newRequest(processId: string) {
- const emoji = await addressToEmoji(processId);
- const members = await this.getMembersFromProcess(processId);
- const newRequestButton = this.shadowRoot?.querySelector('#request-document-button');
- if (newRequestButton) {
- newRequestButton.replaceWith(newRequestButton.cloneNode(true));
- const freshButton = this.shadowRoot?.querySelector('#request-document-button');
- freshButton?.addEventListener('click', async () => {
- const membersList = await this.generateMembersList(members);
-
- const modal = document.createElement('div');
- modal.className = 'request-modal';
- const today = new Date().toISOString().split('T')[0];
-
- modal.innerHTML = `
-
-
New Request for ${emoji}
-
-
-
-
-
-
Select the deadline:
-
-
-
-
- `;
-
- this.shadowRoot?.appendChild(modal);
- this.handleFileUpload(modal);
- this.handleRequestButton(modal);
- const closeButton = modal.querySelector('.close-modal');
- closeButton?.addEventListener('click', () => {
- modal.remove();
- });
- });
- }
- }
-
- //request button in the modal
- private handleRequestButton(modal: HTMLElement) {
- const requestButton = modal.querySelector('#send-request-button');
- requestButton?.addEventListener('click', () => {
- console.log("REQUEST SENT");
- if (modal) {
- //vérifier qu'au moins un membre est coché
- const membersList = modal.querySelector('.members-list-modal');
- if (membersList) {
- const members = membersList.querySelectorAll('.member-checkbox:checked');
- if (members.length === 0) {
- alert('Please select at least one member');
- return;
- }
- }
- //vérifier que la date est valide
- const dateInput = modal.querySelector('#date-input') as HTMLInputElement;
- if (dateInput) {
- const date = new Date(dateInput.value);
- if (isNaN(date.getTime())) {
- alert('Please select a valid date');
- return;
- }
- }
-
- //verifier qu'un fichier a été load
- const fileList = modal.querySelector('#file-list');
- if (fileList && fileList.children.length === 0) {
- alert('Please upload at least one file');
- return;
- }
-
- //récupérer le message
- const messageInput = modal.querySelector('#message-input') as HTMLTextAreaElement;
- if (messageInput) {
- const message = messageInput.value;
- }
- //modal.remove();
- }
- });
- }
-
- private handleFileUpload(modal: HTMLElement) {
- const fileInput = modal.querySelector('#file-input') as HTMLInputElement;
- const fileList = modal.querySelector('#file-list');
- const selectedFiles = new Set();
-
- fileInput?.addEventListener('change', () => {
- if (fileList && fileInput.files) {
- Array.from(fileInput.files).forEach(file => {
- if (!Array.from(selectedFiles).some(f => f.name === file.name)) {
- selectedFiles.add(file);
- const fileItem = document.createElement('div');
- fileItem.className = 'file-item';
- fileItem.innerHTML = `
- ${file.name}
-
- `;
- fileList.appendChild(fileItem);
-
- fileItem.querySelector('.remove-file')?.addEventListener('click', () => {
- selectedFiles.delete(file);
- fileItem.remove();
- });
- }
- });
- fileInput.value = '';
- }
- });
-
- return selectedFiles;
- }
-
- private async generateMembersList(members: string[]) {
- let html = '';
- for (const member of members) {
- const emoji = await addressToEmoji(member);
- html += `${emoji}`;
- }
- return html;
- }
-
-
- //Send a set of members from a process
- private async getMembersFromProcess(processId: string) {
- const service = await Services.getInstance();
- const process = await service.getProcess(processId);
- console.log("Process récupéré:", process);
-
- // Récupérer les rôles directement depuis le dernier état
- const roles = service.getRoles(process);
- console.log("Roles trouvés:", roles);
-
- if (!roles) return [];
- type RoleData = {
- members?: { sp_addresses?: string[] }[];
- };
- const uniqueMembers = new Set();
- Object.values(roles as unknown as Record).forEach((roleData: RoleData) => {
- roleData.members?.forEach((member) => {
- if (member.sp_addresses && member.sp_addresses[0]) {
- uniqueMembers.add(member.sp_addresses[0]);
- }
- });
- });
- return Array.from(uniqueMembers);
- }
-
- private async loadAllRolesAndMembersInSignature(roles: any) {
- console.log('🎯 Roles:', roles);
- const signatureDescription = this.shadowRoot?.querySelector('.signature-description');
- if (signatureDescription) {
- signatureDescription.innerHTML = '';
- Object.entries(roles).forEach(([roleName, roleData]: [string, any]) => {
- const roleItem = document.createElement('li');
- roleItem.className = 'role-signature';
-
- const roleContainer = document.createElement('div');
- roleContainer.className = 'role-signature-container';
-
- const roleNameSpan = document.createElement('span');
- roleNameSpan.className = 'role-signature-name';
- roleNameSpan.textContent = roleName;
-
- const uniqueMembers = new Map();
- roleData.members?.forEach((member: any) => {
- const spAddress = member.sp_addresses?.[0];
- if (spAddress && !uniqueMembers.has(spAddress)) {
- uniqueMembers.set(spAddress, member);
- }
- });
-
- const filteredRoleData = {
- ...roleData,
- members: Array.from(uniqueMembers.values())
- };
-
- roleContainer.addEventListener('click', async (event) => {
- console.log("CLICKED ON ROLE:", roleName);
- event.stopPropagation();
- await this.toggleMembers(filteredRoleData, roleItem);
- });
-
- roleContainer.appendChild(roleNameSpan);
- roleItem.appendChild(roleContainer);
- signatureDescription.appendChild(roleItem);
- });
- }
- }
-
- //fonction qui ferme la signature
- private closeSignature() {
- const closeSignature = this.shadowRoot?.querySelector('#close-signature');
- const signatureArea = this.shadowRoot?.querySelector('.signature-area');
- if (closeSignature && signatureArea) {
- closeSignature.addEventListener('click', () => {
- signatureArea.classList.add('hidden');
- });
- }
- }
-
- //fonction qui ouvre la signature
- private openSignature() {
- const signatureArea = this.shadowRoot?.querySelector('.signature-area');
- if (signatureArea) {
- signatureArea.classList.remove('hidden');
- }
- }
-
- private async getMyProcessId() {
- const service = await Services.getInstance();
- return service.getPairingProcessId();
- }
-
- //fonction qui renvoie les processus où le sp_adress est impliqué
- private async getProcessesWhereTheCurrentMemberIs() {
- const service = await Services.getInstance();
- try {
- const currentMember = await service.getMemberFromDevice();
- if (!currentMember) {
- console.error('❌ Pas de membre trouvé');
- return this.userProcessSet;
- }
-
- const pairingProcess = await this.getMyProcessId();
- const memberEmoji = await addressToEmoji(pairingProcess);
- console.log("Mon adresse:", currentMember[0], memberEmoji);
-
- const processes = await service.getProcesses();
-
- for (const [processId, process] of Object.entries(processes)) {
- try {
- const roles = process.states[0]?.roles;
-
- if (!roles) {
- console.log(`Pas de rôles trouvés pour le processus ${processId}`);
- continue;
- }
-
- for (const roleName in roles) {
- const role = roles[roleName];
-
- if (role.members && Array.isArray(role.members)) {
- for (const member of role.members) {
- if (member.sp_addresses && Array.isArray(member.sp_addresses)) {
- if (member.sp_addresses.includes(currentMember[0])) {
- this.userProcessSet.add(processId);
- console.log(`Ajout du process ${processId} au Set (trouvé dans le rôle ${roleName})`);
- break;
- }
- }
- }
- }
- }
- } catch (e) {
- console.log(`Erreur lors du traitement du processus ${processId}:`, e);
- continue;
- }
- }
-
- return this.userProcessSet;
- } catch (e) {
- console.error('❌ Erreur:', e);
- return this.userProcessSet;
- }
- }
-
- // Send a file
- private async sendFile(file: File) {
- const MAX_FILE_SIZE = 1 * 1024 * 1024;
- if (file.size > MAX_FILE_SIZE) {
- alert('Le fichier est trop volumineux. Taille maximum : 1MB');
- return;
- }
-
- try {
- const service = await Services.getInstance();
- const myAddresses = await service.getMemberFromDevice();
- if (!myAddresses) throw new Error('No paired member found');
-
- let fileData: string;
- if (file.type.startsWith('image/')) {
- fileData = await this.compressImage(file);
- } else {
- fileData = await this.readFileAsBase64(file);
- }
-
- const timestamp = Date.now();
- const processId = this.getAttribute('process-id');
- const uniqueKey = `${processId}${timestamp}`;
-
- const dbRequest = indexedDB.open('4nk');
-
- dbRequest.onerror = (event) => {
- console.error("Database error:", dbRequest.error);
- };
-
- dbRequest.onsuccess = async (event) => {
- const db = dbRequest.result;
- const transaction = db.transaction(['diffs'], 'readwrite');
- const store = transaction.objectStore('diffs');
-
- try {
- // Message du fichier
- const fileTemplate = {
- value_commitment: uniqueKey,
- messaging_id: processId,
- description: 'message_content',
- metadata: {
- text: `Fichier envoyé: ${file.name}`,
- timestamp: timestamp,
- sender: myAddresses[0],
- recipient: this.selectedMember,
- messageState: this.messageState,
- roleName: this.selectedRole,
- type: 'file',
- fileName: file.name,
- fileType: file.type,
- fileData: fileData
- }
- };
-
- await new Promise((resolve, reject) => {
- const request = store.add(fileTemplate);
- request.onsuccess = () => {
- console.log('✅ File message saved');
- resolve();
- };
- request.onerror = () => reject(request.error);
- });
-
- // Réponse automatique
- const autoReplyTemplate = {
- value_commitment: `${processId}${timestamp + 1000}`,
- messaging_id: processId,
- description: 'message_content',
- metadata: {
- text: "J'ai bien reçu votre fichier 📎",
- timestamp: timestamp + 1000,
- sender: this.selectedMember,
- recipient: myAddresses[0],
- messageState: this.messageState,
- roleName: this.selectedRole
- }
- };
-
- await new Promise((resolve, reject) => {
- const request = store.add(autoReplyTemplate);
- request.onsuccess = () => {
- console.log('✅ Auto reply saved');
- if (myAddresses[0]) {
- this.addNotification(myAddresses[0], autoReplyTemplate);
- }
- resolve();
- };
- request.onerror = () => reject(request.error);
- });
-
- // Attendre la fin de la transaction
- await new Promise((resolve, reject) => {
- transaction.oncomplete = () => {
- console.log('✅ Transaction completed');
- resolve();
- };
- transaction.onerror = () => reject(transaction.error);
- });
-
- // Réinitialiser l'input file
- const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement;
- if (fileInput) fileInput.value = '';
-
- // Recharger les messages
- if (this.selectedMember) {
- await this.loadMemberChat(this.selectedMember);
- }
-
- } catch (error) {
- console.error('❌ Transaction error:', error);
- }
- };
-
- } catch (error) {
- console.error('❌ Error in sendFile:', error);
- }
- }
-
- private async readFileAsBase64(file: File): Promise {
- return new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onload = () => resolve(reader.result as string);
- reader.onerror = reject;
- reader.readAsDataURL(file);
- });
- }
-
- private async compressImage(file: File): Promise {
- return new Promise((resolve, reject) => {
- const img = new Image();
- const canvas = document.createElement('canvas');
- const ctx = canvas.getContext('2d');
-
- img.onload = () => {
- let width = img.width;
- let height = img.height;
- const MAX_WIDTH = 800;
- const MAX_HEIGHT = 600;
-
- if (width > height) {
- if (width > MAX_WIDTH) {
- height *= MAX_WIDTH / width;
- width = MAX_WIDTH;
- }
- } else {
- if (height > MAX_HEIGHT) {
- width *= MAX_HEIGHT / height;
- height = MAX_HEIGHT;
- }
- }
-
- canvas.width = width;
- canvas.height = height;
- ctx?.drawImage(img, 0, 0, width, height);
-
- resolve(canvas.toDataURL('image/jpeg', 0.7));
- };
-
- img.onerror = reject;
- img.src = URL.createObjectURL(file);
- });
- }
-
- private async getProcesses(): Promise {
- const service = await Services.getInstance();
- const processes = await service.getProcesses();
-
- const res = Object.entries(processes).map(([key, value]) => ({
- key,
- value,
- }));
-
- return res;
- }
-
- async connectedCallback() {
- const service = await Services.getInstance();
-
- const loadPage = async () => {
- console.log("🔍 Chargement des processus par défaut");
- await this.loadAllProcesses();
-
- if (this.selectedMember) {
- console.log('🔍 Loading chat for selected member:', this.selectedMember);
- await this.loadMemberChat(this.selectedMember);
- } else {
- console.warn('⚠️ No member selected yet. Waiting for selection...');
- }
- }
-
- let timeout: NodeJS.Timeout;
- window.addEventListener('process-updated', async (e: CustomEvent) => {
- const processId = e.detail.processId;
- console.log('Notified of an update for process', processId);
- await loadPage();
- });
-
- await loadPage();
- }
-}
-
-customElements.define('chat-element', ChatElement);
-export { ChatElement };*/
-
diff --git a/src/pages/process-element/process-component.ts b/src/pages/process-element/process-component.ts
deleted file mode 100644
index 31ba6e6..0000000
--- a/src/pages/process-element/process-component.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import processHtml from './process-element.html?raw';
-import processScript from './process-element.ts?raw';
-import processCss from '../../4nk.css?raw';
-import { initProcessElement } from './process-element';
-
-export class ProcessListComponent extends HTMLElement {
- _callback: any;
- id: string = '';
- zone: string = '';
-
- constructor() {
- super();
- this.attachShadow({ mode: 'open' });
- }
-
- connectedCallback() {
- console.log('CALLBACK PROCESS LIST PAGE');
- this.render();
- setTimeout(() => {
- initProcessElement(this.id, this.zone);
- }, 500);
- }
-
- set callback(fn) {
- if (typeof fn === 'function') {
- this._callback = fn;
- } else {
- console.error('Callback is not a function');
- }
- }
-
- get callback() {
- return this._callback;
- }
-
- render() {
- if (this.shadowRoot)
- this.shadowRoot.innerHTML = `
- ${processHtml}
-
-