fix(ihm_client): favicon via chemin relatif /favicon.svg pour HTTPS
All checks were successful
Build and Push Docker image (ext) / docker (push) Successful in 51s

This commit is contained in:
4NK CI Bot 2025-09-18 16:26:06 +00:00
parent a40416a248
commit a6f54dc8f5
5 changed files with 91 additions and 91 deletions

View File

@ -9,6 +9,7 @@
<link rel="stylesheet" href="./style/4nk.css">
<script src="https://unpkg.com/html5-qrcode"></script>
<title>4NK Application</title>
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
</head>
<body>
<div id="header-container"></div>

View File

@ -29,8 +29,8 @@ export interface TransactionInfo {
txid: string;
version: number;
locktime: number;
vin: Vin[];
vout: any[];
vin: Vin[];
vout: any[];
size: number;
weight: number;
fee: number;
@ -63,7 +63,7 @@ export function getDocumentValidation(container: HTMLElement) {
function createDropButton(
label: string,
onDrop: (file: File, updateVisuals: (file: File) => void) => void,
accept: string = '*/*'
accept: string = '*/*'
): HTMLElement {
const wrapper = document.createElement('div');
wrapper.style.cssText = `
@ -161,7 +161,7 @@ export function getDocumentValidation(container: HTMLElement) {
const certDropButton = createDropButton('Drop certificate', async (file, updateVisuals) => {
try {
const text = await file.text();
const text = await file.text();
const json = JSON.parse(text);
if (
typeof json === 'object' &&
@ -257,7 +257,7 @@ export function getDocumentValidation(container: HTMLElement) {
} else {
continue;
}
if (vout.scriptpubkey_asm) {
const hash = extractHexFromScriptAsm(vout.scriptpubkey_asm);
if (hash) {
@ -279,7 +279,7 @@ export function getDocumentValidation(container: HTMLElement) {
found = false;
for (const label of Object.keys(state.certificate.pcd_commitment)) {
// Compute the hash for this label
// Compute the hash for this label
console.log(`Computing hash with label ${label}`)
const fileHex = service.getHashForFile(commitedIn, label, fileBlob);
console.log(`Found hash ${fileHex}`);

View File

@ -36,10 +36,10 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
type: string,
data: Uint8Array
};
const nonRoleRowStates: {
keyInput: HTMLInputElement,
valueInput: HTMLInputElement,
fileInput: HTMLInputElement,
const nonRoleRowStates: {
keyInput: HTMLInputElement,
valueInput: HTMLInputElement,
fileInput: HTMLInputElement,
fileBlob: fileBlob | null
}[] = [];
@ -102,7 +102,7 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
rowState.fileBlob = {
type: file.type,
data: uint8,
data: uint8,
};
valueInput.value = `📄 ${file.name}`;
@ -184,7 +184,7 @@ export function createKeyValueSection(title: string, id: string, isRoleSection =
const key = row.keyInput.value.trim();
if (!key) continue;
if (row.fileBlob) {
data[key] = row.fileBlob;
data[key] = row.fileBlob;
} else {
data[key] = row.valueInput.value.trim();
}

View File

@ -45,15 +45,15 @@ class ChatElement extends HTMLElement {
private allMembers = membersMock.map(member => ({
id: member.id,
name: member.name,
roleName: 'Default Role'
roleName: 'Default Role'
}));
private messageState: number = 0;
private messageState: number = 0;
private selectedRole: string | null = null;
private dmMembersSet: Set<string> = new Set();
private addressMap: Record<string, string> = {};
private isLoading = false;
constructor() {
super();
this.attachShadow({ mode: 'open' });
@ -144,12 +144,12 @@ class ChatElement extends HTMLElement {
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' &&
@ -206,16 +206,16 @@ class ChatElement extends HTMLElement {
// 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 = '<div class="no-notification">No notifications available</div>';
return;
}
// Add each notification to the list
this.notifications.forEach((notif, index) => {
const notifElement = document.createElement('div');
@ -234,7 +234,7 @@ class ChatElement extends HTMLElement {
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) {
@ -242,11 +242,11 @@ class ChatElement extends HTMLElement {
// 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';
@ -270,7 +270,7 @@ class ChatElement extends HTMLElement {
this.notifications.push(notification);
this.renderNotifications();
this.updateNotificationBadge();
} catch (error) {
console.error('Error creating notification:', error);
}
@ -287,7 +287,7 @@ class ChatElement extends HTMLElement {
console.error('no process id set');
return;
}
const messageText = messageInput.value.trim();
if (messageText === '') {
console.error('❌ Empty message');
@ -353,13 +353,13 @@ class ChatElement extends HTMLElement {
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 = '';
memberList.innerHTML = '';
await this.loadAllMembers();
if (tabs) {
await this.switchTab('members', tabs);
@ -385,7 +385,7 @@ class ChatElement extends HTMLElement {
}
}
// TODO rewrite that
// TODO rewrite that
// private async lookForChildren(): Promise<string | null> {
// // Filter processes for the children of current process
// const service = await Services.getInstance();
@ -478,8 +478,8 @@ class ChatElement extends HTMLElement {
const publicMemberData = service.getPublicData(process);
if (publicMemberData) {
const extractedName = publicMemberData['memberPublicName'];
if (extractedName !== undefined && extractedName !== null) {
memberPublicName = extractedName;
if (extractedName !== undefined && extractedName !== null) {
memberPublicName = extractedName;
}
}
}
@ -577,9 +577,9 @@ class ChatElement extends HTMLElement {
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);
@ -591,7 +591,7 @@ class ChatElement extends HTMLElement {
const roles = service.getRoles(process);
const members = roles.dm.members;
for (const member of members) {;
if (!service.compareMembers(member.sp_addresses, myAddresses)) {
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);
@ -607,7 +607,7 @@ class ChatElement extends HTMLElement {
console.log("dmMembersSet:", this.dmMembersSet);
return null;
}
private async loadMemberChat(pairingProcess: string) {
if (this.isLoading) {
console.log('Already loading messages, skipping...');
@ -629,14 +629,14 @@ class ChatElement extends HTMLElement {
// 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");
@ -647,7 +647,7 @@ class ChatElement extends HTMLElement {
const label = request.result;
chatHeader.textContent = label ? `Chat with ${label.label} (${emojis})` : `Chat with member (${emojis})`;
};
request.onerror = () => {
chatHeader.textContent = `Chat with member (${emojis})`;
};
@ -717,18 +717,18 @@ class ChatElement extends HTMLElement {
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/')) {
@ -748,7 +748,7 @@ class ChatElement extends HTMLElement {
</div>
`;
}
messageContent.innerHTML = `
<div class="message-content">
<strong>${senderEmoji}</strong>: ${fileContent}
@ -767,11 +767,11 @@ class ChatElement extends HTMLElement {
</div>
`;
}
messageElement.appendChild(messageContent);
messagesContainer.appendChild(messageElement);
}
this.scrollToBottom(messagesContainer);
} else {
console.log('No messages found');
@ -789,16 +789,16 @@ class ChatElement extends HTMLElement {
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);
@ -808,9 +808,9 @@ class ChatElement extends HTMLElement {
if (this.selectedMember === pairingProcess) {
chatHeader.textContent = label ? `Chat with ${label.label} (${emojis})` : `Chat with member (${emojis})`;
}
};
request.onerror = () => {
chatHeader.textContent = `Chat with member (${emojis})`;
};
@ -844,20 +844,20 @@ class ChatElement extends HTMLElement {
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/')) {
@ -877,7 +877,7 @@ class ChatElement extends HTMLElement {
</div>
`;
}
messageContent.innerHTML = `
<div class="message-content">
<strong>${senderEmoji}</strong>: ${fileContent}
@ -896,11 +896,11 @@ class ChatElement extends HTMLElement {
</div>
`;
}
messageElement.appendChild(messageContent);
messagesContainer.appendChild(messageElement);
}
this.scrollToBottom(messagesContainer);
} else {
console.log('No messages found');
@ -918,7 +918,7 @@ class ChatElement extends HTMLElement {
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);
}
@ -934,9 +934,9 @@ class ChatElement extends HTMLElement {
async getAddressMap() {
const service = await Services.getInstance();
const allMembers = await service.getAllMembers();
const addressMap: Record<string, string> = {};
for (const [key, values] of Object.entries(allMembers)) {
if (values.sp_addresses) {
@ -955,9 +955,9 @@ class ChatElement extends HTMLElement {
const service = await Services.getInstance();
const allMembers = await service.getAllMembers();
console.log('Available members:', allMembers);
const sortedAddresses = [...addresses].sort();
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();
@ -966,7 +966,7 @@ class ChatElement extends HTMLElement {
}
}
}
return null; // No match found
}
@ -974,10 +974,10 @@ class ChatElement extends 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 =
(memberList as HTMLElement).style.display === 'none' ? 'block' : 'none';
return;
}
@ -992,7 +992,7 @@ class ChatElement extends HTMLElement {
console.log('Processing member:', member);
const memberItem = document.createElement('li');
memberItem.className = 'member-item';
const memberContainer = document.createElement('div');
memberContainer.className = 'member-container';
@ -1016,7 +1016,7 @@ class ChatElement extends HTMLElement {
memberItem.onclick = async (event) => {
event.stopPropagation();
try {
try {
if (pairingProcess) {
await this.loadMemberChat(pairingProcess);
}
@ -1033,7 +1033,7 @@ class ChatElement extends HTMLElement {
roleElement.appendChild(memberList);
}
private async switchTab(tabType: string, tabs: NodeListOf<Element>) {
const service = await Services.getInstance();
@ -1079,13 +1079,13 @@ class ChatElement extends HTMLElement {
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');
@ -1284,9 +1284,9 @@ class ChatElement extends HTMLElement {
<div id="file-list"></div>
</div>
<span>Select the deadline:</span>
<input type="date"
id="date-input"
min="${today}"
<input type="date"
id="date-input"
min="${today}"
value="${today}">
<button id="send-request-button">Send</button>
</div>
@ -1392,11 +1392,11 @@ class ChatElement extends HTMLElement {
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[] }[];
@ -1420,7 +1420,7 @@ class ChatElement extends HTMLElement {
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';
@ -1446,7 +1446,7 @@ class ChatElement extends HTMLElement {
event.stopPropagation();
await this.toggleMembers(filteredRoleData, roleItem);
});
roleContainer.appendChild(roleNameSpan);
roleItem.appendChild(roleContainer);
signatureDescription.appendChild(roleItem);
@ -1456,7 +1456,7 @@ class ChatElement extends HTMLElement {
//fonction qui ferme la signature
private closeSignature() {
const closeSignature = this.shadowRoot?.querySelector('#close-signature');
const closeSignature = this.shadowRoot?.querySelector('#close-signature');
const signatureArea = this.shadowRoot?.querySelector('.signature-area');
if (closeSignature && signatureArea) {
closeSignature.addEventListener('click', () => {
@ -1475,7 +1475,7 @@ class ChatElement extends HTMLElement {
private async getMyProcessId() {
const service = await Services.getInstance();
return service.getPairingProcessId();
return service.getPairingProcessId();
}
//fonction qui renvoie les processus où le sp_adress est impliqué
@ -1493,11 +1493,11 @@ class ChatElement extends HTMLElement {
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;
@ -1505,7 +1505,7 @@ class ChatElement extends HTMLElement {
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)) {
@ -1523,7 +1523,7 @@ class ChatElement extends HTMLElement {
continue;
}
}
return this.userProcessSet;
} catch (e) {
console.error('❌ Erreur:', e);
@ -1533,7 +1533,7 @@ class ChatElement extends HTMLElement {
// Send a file
private async sendFile(file: File) {
const MAX_FILE_SIZE = 1 * 1024 * 1024;
const MAX_FILE_SIZE = 1 * 1024 * 1024;
if (file.size > MAX_FILE_SIZE) {
alert('Le fichier est trop volumineux. Taille maximum : 1MB');
return;
@ -1553,10 +1553,10 @@ class ChatElement extends HTMLElement {
const timestamp = Date.now();
const processId = this.getAttribute('process-id');
const uniqueKey = `${processId}${timestamp}`;
const uniqueKey = `${processId}${timestamp}`;
const dbRequest = indexedDB.open('4nk');
dbRequest.onerror = (event) => {
console.error("Database error:", dbRequest.error);
};
@ -1698,12 +1698,12 @@ class ChatElement extends HTMLElement {
private async getProcesses(): Promise<any[]> {
const service = await Services.getInstance();
const processes = await service.getProcesses();
const res = Object.entries(processes).map(([key, value]) => ({
key,
value,
}));
return res;
}
@ -1735,4 +1735,3 @@ class ChatElement extends HTMLElement {
customElements.define('chat-element', ChatElement);
export { ChatElement };*/

View File

@ -83,7 +83,7 @@ export default class ModalService {
if (container) {
let html = await fetch('/src/components/modal/waiting-modal.html').then((res) => res.text());
container.innerHTML += html;
}
}
}
async injectValidationModal(processDiff: any) {