add prettify to project

This commit is contained in:
AnisHADJARAB 2024-10-29 12:49:13 +00:00
parent 9e327f6c08
commit 29f09e92b7
13 changed files with 1867 additions and 1754 deletions

5
.prettierignore Normal file
View File

@ -0,0 +1,5 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage
/.nx/cache
.angular

14
.prettierrc Normal file
View File

@ -0,0 +1,14 @@
{
"printWidth": 300,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always",
"requirePragma": false,
"insertPragma": false,
"endOfLine": "crlf"
}

135
package-lock.json generated
View File

@ -17,11 +17,13 @@
"vite": "^5.4.9", "vite": "^5.4.9",
"vite-plugin-copy": "^0.1.6", "vite-plugin-copy": "^0.1.6",
"vite-plugin-html": "^3.2.2", "vite-plugin-html": "^3.2.2",
"vite-plugin-terminal": "^1.2.0",
"vite-plugin-wasm": "^3.3.0" "vite-plugin-wasm": "^3.3.0"
}, },
"devDependencies": { "devDependencies": {
"copy-webpack-plugin": "^12.0.2", "copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0", "html-webpack-plugin": "^5.6.0",
"prettier": "^3.3.3",
"ts-loader": "^9.5.1", "ts-loader": "^9.5.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite-plugin-static-copy": "^1.0.6", "vite-plugin-static-copy": "^1.0.6",
@ -902,6 +904,56 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/@polka/url": {
"version": "1.0.0-next.28",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz",
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
"license": "MIT"
},
"node_modules/@rollup/plugin-strip": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-strip/-/plugin-strip-3.0.4.tgz",
"integrity": "sha512-LDRV49ZaavxUo2YoKKMQjCxzCxugu1rCPQa0lDYBOWLj6vtzBMr8DcoJjsmg+s450RbKbe3qI9ZLaSO+O1oNbg==",
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-strip/node_modules/@rollup/pluginutils": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz",
"integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==",
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": { "node_modules/@rollup/pluginutils": {
"version": "4.2.1", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
@ -4136,6 +4188,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/kolorist": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
"integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
"license": "MIT"
},
"node_modules/launch-editor": { "node_modules/launch-editor": {
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz",
@ -4192,7 +4250,6 @@
"version": "0.30.10", "version": "0.30.10",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
"peer": true,
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15" "@jridgewell/sourcemap-codec": "^1.4.15"
} }
@ -4334,6 +4391,15 @@
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
} }
}, },
"node_modules/mrmime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
"integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -4739,6 +4805,22 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/prettier": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/pretty-error": { "node_modules/pretty-error": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
@ -5430,6 +5512,20 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true "dev": true
}, },
"node_modules/sirv": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
"license": "MIT",
"dependencies": {
"@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0",
"totalist": "^3.0.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/slash": { "node_modules/slash": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
@ -5808,6 +5904,15 @@
"node": ">=0.6" "node": ">=0.6"
} }
}, },
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/tree-dump": { "node_modules/tree-dump": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz",
@ -5966,6 +6071,12 @@
"node": ">=14.17" "node": ">=14.17"
} }
}, },
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"license": "MIT"
},
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "5.26.5", "version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
@ -6201,6 +6312,28 @@
"node": ">=14.14" "node": ">=14.14"
} }
}, },
"node_modules/vite-plugin-terminal": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/vite-plugin-terminal/-/vite-plugin-terminal-1.2.0.tgz",
"integrity": "sha512-IIw1V+IySth8xlrGmH4U7YmfTp681vTzYpa7b8A3KNCJ2oW1BGPPwW8tSz6BQTvSgbRmrP/9NsBLsfXkN4e8sA==",
"license": "MIT",
"dependencies": {
"@rollup/plugin-strip": "^3.0.2",
"debug": "^4.3.4",
"kolorist": "^1.7.0",
"sirv": "^2.0.2",
"ufo": "^1.1.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/patak-dev"
},
"peerDependencies": {
"vite": "^2.0.0||^3.0.0||^4.0.0||^5.0.0"
}
},
"node_modules/vite-plugin-wasm": { "node_modules/vite-plugin-wasm": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.3.0.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.3.0.tgz",

View File

@ -8,7 +8,8 @@
"build_wasm": "wasm-pack build --out-dir ../ihm_client/dist/pkg ../sdk_client --target bundler --dev", "build_wasm": "wasm-pack build --out-dir ../ihm_client/dist/pkg ../sdk_client --target bundler --dev",
"start": "vite --host 0.0.0.0", "start": "vite --host 0.0.0.0",
"build": "tsc && vite build", "build": "tsc && vite build",
"deploy": "sudo cp -r dist/* /var/www/html/" "deploy": "sudo cp -r dist/* /var/www/html/",
"prettify": "prettier --config ./.prettierrc --write \"src/**/*{.ts,.html.scss}\""
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
@ -16,6 +17,7 @@
"devDependencies": { "devDependencies": {
"copy-webpack-plugin": "^12.0.2", "copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0", "html-webpack-plugin": "^5.6.0",
"prettier": "^3.3.3",
"ts-loader": "^9.5.1", "ts-loader": "^9.5.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite-plugin-static-copy": "^1.0.6", "vite-plugin-static-copy": "^1.0.6",

View File

@ -1,40 +1,39 @@
// import Services from './services/service'; // import Services from './services/service';
// document.addEventListener('DOMContentLoaded', async () => { // document.addEventListener('DOMContentLoaded', async () => {
// try { // try {
// const services = await Services.getInstance(); // const services = await Services.getInstance();
// setTimeout( async () => { // setTimeout( async () => {
// let device = await services.getDevice() // let device = await services.getDevice()
// console.log("🚀 ~ setTimeout ~ device:", device) // console.log("🚀 ~ setTimeout ~ device:", device)
// if(!device) { // if(!device) {
// device = await services.createNewDevice(); // device = await services.createNewDevice();
// } else { // } else {
// await services.restoreDevice(device) // await services.restoreDevice(device)
// } // }
// await services.restoreProcesses(); // await services.restoreProcesses();
// await services.restoreMessages(); // await services.restoreMessages();
// const amount = await services.getAmount(); // const amount = await services.getAmount();
// if (amount === 0n) { // if (amount === 0n) {
// const faucetMsg = await services.createFaucetMessage(); // const faucetMsg = await services.createFaucetMessage();
// await services.sendFaucetMessage(faucetMsg); // await services.sendFaucetMessage(faucetMsg);
// } // }
// if (services.isPaired()) { await services.injectProcessListPage() } // if (services.isPaired()) { await services.injectProcessListPage() }
// else { // else {
// const queryString = window.location.search; // const queryString = window.location.search;
// const urlParams = new URLSearchParams(queryString) // const urlParams = new URLSearchParams(queryString)
// const pairingAddress = urlParams.get('sp_address') // const pairingAddress = urlParams.get('sp_address')
// if(pairingAddress) { // if(pairingAddress) {
// setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000) // setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000)
// } // }
// } // }
// }, 500); // }, 500);
// } catch (error) { // } catch (error) {
// console.error(error); // console.error(error);
// } // }
// }); // });

View File

@ -1,22 +1,19 @@
export interface INotification { export interface INotification {
id: number; id: number;
title: string; title: string;
description: string; description: string;
sendToNotificationPage?: boolean; sendToNotificationPage?: boolean;
path?: string; path?: string;
}
}
// Quelles sont les données utiles pour le user ???
export interface IUser {
// Quelles sont les données utiles pour le user ??? id: string;
export interface IUser { information?: any;
id: string; }
information?: any
} // Quelles sont les données utiles pour les messages ???
export interface IMessage {
id: string;
// Quelles sont les données utiles pour les messages ??? message: any;
export interface IMessage { }
id: string;
message: any
}

View File

@ -1,23 +1,23 @@
export interface IProcess { export interface IProcess {
id: number; id: number;
name: string; name: string;
description: string; description: string;
icon?: string; icon?: string;
zoneList: IZone[], zoneList: IZone[];
} }
export interface IZone { export interface IZone {
id: number; id: number;
name: string; name: string;
path: string; path: string;
// Est-ce que la zone a besoin d'une icone ? // Est-ce que la zone a besoin d'une icone ?
icon?: string; icon?: string;
} }
export interface INotification { export interface INotification {
id: number; id: number;
title: string; title: string;
description: string; description: string;
sendToNotificationPage?: boolean; sendToNotificationPage?: boolean;
path?: string; path?: string;
} }

View File

@ -1,114 +1,107 @@
import { Html5QrcodeScanner } from "html5-qrcode"; import { Html5QrcodeScanner } from 'html5-qrcode';
import Routing from "../../services/routing.service"; import Routing from '../../services/routing.service';
import Services from "../../services/service"; import Services from '../../services/service';
let resultContainer = document.getElementById('qr-reader-results'); let resultContainer = document.getElementById('qr-reader-results');
let lastResult: any, countResults = 0; let lastResult: any,
countResults = 0;
export function initHomePage(): void {
console.log('INIT') export function initHomePage(): void {
document.querySelectorAll('.tab').forEach(tab => { console.log('INIT');
document.querySelectorAll('.tab').forEach((tab) => {
tab.addEventListener('click', () => { tab.addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); document.querySelectorAll('.tab').forEach((t) => t.classList.remove('active'));
tab.classList.add('active'); tab.classList.add('active');
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active')); document.querySelectorAll('.tab-content').forEach((content) => content.classList.remove('active'));
document.getElementById(tab.getAttribute('data-tab') as string)?.classList.add('active'); document.getElementById(tab.getAttribute('data-tab') as string)?.classList.add('active');
});
}); });
});
document.getElementById('notification-bell')?.addEventListener('click', openCloseNotifications);
document.getElementById('notification-bell')?.addEventListener('click', openCloseNotifications);
var html5QrcodeScanner = new Html5QrcodeScanner('qr-reader', { fps: 10, qrbox: 250 }, undefined);
var html5QrcodeScanner = new Html5QrcodeScanner( html5QrcodeScanner.render(onScanSuccess, undefined);
"qr-reader", { fps: 10, qrbox: 250 }, undefined);
html5QrcodeScanner.render(onScanSuccess, undefined); docReady(() => {
scanDevice();
docReady(() => { });
scanDevice(); }
async function onScanSuccess(decodedText: any, decodedResult: any) {
}); if (lastResult === decodedText) {
} return;
}
lastResult = decodedText;
async function onScanSuccess(decodedText: any, decodedResult: any) { ++countResults;
if (lastResult === decodedText) { return; } // Handle on success condition with the decoded message.
lastResult = decodedText; console.log(`Scan result ${decodedText}`, decodedResult);
++countResults; try {
// Handle on success condition with the decoded message. // Attempt to parse the decoded text as a URL
console.log(`Scan result ${decodedText}`, decodedResult); const scannedUrl = new URL(decodedText);
try {
// Attempt to parse the decoded text as a URL // Extract the 'sp_address' parameter
const scannedUrl = new URL(decodedText); const spAddress = scannedUrl.searchParams.get('sp_address');
// Extract the 'sp_address' parameter if (spAddress) {
const spAddress = scannedUrl.searchParams.get('sp_address'); html5QrcodeScanner.clear();
const service = await Services.getInstance();
if (spAddress) { // Call the sendPairingTx function with the extracted sp_address
html5QrcodeScanner.clear(); await service.sendPairingTx(spAddress);
const service = await Services.getInstance() } else {
// Call the sendPairingTx function with the extracted sp_address console.error('The scanned URL does not contain the sp_address parameter.');
await service.sendPairingTx(spAddress); alert('Invalid QR code: sp_address parameter missing.');
} else { }
console.error('The scanned URL does not contain the sp_address parameter.'); } catch (error) {
alert('Invalid QR code: sp_address parameter missing.'); // Handle cases where decodedText is not a valid URL
} console.error('Scanned text is not a valid URL:', error);
} catch (error) { alert('Invalid QR code: Unable to parse URL.');
// Handle cases where decodedText is not a valid URL }
console.error('Scanned text is not a valid URL:', error); }
alert('Invalid QR code: Unable to parse URL.'); export function toggleMenu() {
} let menu = document.getElementById('menu');
} if (menu) {
export function toggleMenu() { if (menu.style.display === 'block') {
let menu = document.getElementById('menu'); menu.style.display = 'none';
if(menu) { } else {
if (menu.style.display === 'block') { menu.style.display = 'block';
menu.style.display = 'none'; }
} else { }
menu.style.display = 'block'; }
}
} //// Modal
} export async function openModal(myAddress: string, receiverAddress: string) {
const router = await Routing.getInstance();
//// Modal router.openLoginModal(myAddress, receiverAddress);
export async function openModal(myAddress: string, receiverAddress: string) { }
const router = await Routing.getInstance();
router.openLoginModal(myAddress, receiverAddress) function openCloseNotifications() {
} const notifications = document.querySelector('.notification-board') as HTMLDivElement;
notifications.style.display = notifications?.style.display === 'none' ? 'block' : 'none';
}
function openCloseNotifications() {
const notifications = document.querySelector('.notification-board') as HTMLDivElement // const service = await Services.getInstance()
notifications.style.display = notifications?.style.display === 'none' ? 'block' : 'none' // service.setNotification()
}
(window as any).toggleMenu = toggleMenu;
// const service = await Services.getInstance() (window as any).openModal = openModal;
// service.setNotification()
/// Scan QR Code
(window as any).toggleMenu = toggleMenu; function docReady(fn: any) {
(window as any).openModal = openModal; // see if DOM is already available
if (document.readyState === 'complete' || document.readyState === 'interactive') {
/// Scan QR Code // call on next available tick
function docReady(fn: any) { setTimeout(fn, 1);
// see if DOM is already available } else {
if (document.readyState === "complete" document.addEventListener('DOMContentLoaded', fn);
|| document.readyState === "interactive") { }
// call on next available tick }
setTimeout(fn, 1);
} else { function scanDevice() {
document.addEventListener("DOMContentLoaded", fn); const scannerImg = document.querySelector('#scanner') as HTMLElement;
} if (scannerImg) scannerImg.style.display = 'none';
} const scannerQrCode = document.querySelector('.qr-code-scanner') as HTMLElement;
if (scannerQrCode) scannerQrCode.style.display = 'block';
}
function scanDevice() { (window as any).scanDevice = scanDevice;
const scannerImg = document.querySelector('#scanner') as HTMLElement
if(scannerImg) scannerImg.style.display = 'none'
const scannerQrCode = document.querySelector('.qr-code-scanner') as HTMLElement
if(scannerQrCode) scannerQrCode.style.display = 'block'
}
(window as any).scanDevice = scanDevice

View File

@ -1,476 +1,461 @@
import Services from "../../services/service"; import Services from '../../services/service';
import {IProcess } from "~/models/process.model"; import { IProcess } from '~/models/process.model';
function toggleMenu() { function toggleMenu() {
const menu = document.getElementById("menu") as HTMLDivElement; const menu = document.getElementById('menu') as HTMLDivElement;
if (menu.style.display === "block") { if (menu.style.display === 'block') {
menu.style.display = "none"; menu.style.display = 'none';
} else { } else {
menu.style.display = "block"; menu.style.display = 'block';
} }
} }
// 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 function init(element: HTMLElement) {
function init(element: HTMLElement) { // 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"); wrapper.addEventListener('click', clickOnWrapper);
wrapper.addEventListener("click", clickOnWrapper); wrapper.classList.add('multi-select-component');
wrapper.classList.add("multi-select-component"); wrapper.classList.add('input-field');
wrapper.classList.add("input-field");
// Create elements of search
// Create elements of search const search_div = document.createElement('div');
const search_div = document.createElement("div"); search_div.classList.add('search-container');
search_div.classList.add("search-container"); const input = document.createElement('input');
const input = document.createElement("input"); input.classList.add('selected-input');
input.classList.add("selected-input"); input.setAttribute('autocomplete', 'off');
input.setAttribute("autocomplete", "off"); input.setAttribute('tabindex', '0');
input.setAttribute("tabindex", "0"); input.addEventListener('keyup', inputChange);
input.addEventListener("keyup", inputChange); input.addEventListener('keydown', deletePressed);
input.addEventListener("keydown", deletePressed); input.addEventListener('click', openOptions);
input.addEventListener("click", openOptions);
const dropdown_icon = document.createElement('a');
const dropdown_icon = document.createElement("a"); dropdown_icon.classList.add('dropdown-icon');
dropdown_icon.classList.add("dropdown-icon");
dropdown_icon.addEventListener('click', clickDropdown);
dropdown_icon.addEventListener("click", clickDropdown); const autocomplete_list = document.createElement('ul');
const autocomplete_list = document.createElement("ul"); autocomplete_list.classList.add('autocomplete-list');
autocomplete_list.classList.add("autocomplete-list"); search_div.appendChild(input);
search_div.appendChild(input); search_div.appendChild(autocomplete_list);
search_div.appendChild(autocomplete_list); search_div.appendChild(dropdown_icon);
search_div.appendChild(dropdown_icon);
// set the wrapper as child (instead of the element)
// set the wrapper as child (instead of the element) element.parentNode?.replaceChild(wrapper, element);
element.parentNode?.replaceChild(wrapper, element); // set element as child of wrapper
// set element as child of wrapper wrapper.appendChild(element);
wrapper.appendChild(element); wrapper.appendChild(search_div);
wrapper.appendChild(search_div);
addPlaceholder(wrapper);
addPlaceholder(wrapper);
// const select = document.querySelector(".select-field");
// const select = document.querySelector(".select-field"); // for (const process of processeList) {
// for (const process of processeList) { // const option = document.createElement("option");
// const option = document.createElement("option"); // option.setAttribute("value", process.name);
// option.setAttribute("value", process.name); // option.innerText = process.name;
// option.innerText = process.name;
// select.appendChild(option);
// select.appendChild(option); // }
// } }
}
function removePlaceholder(wrapper: HTMLElement) {
function removePlaceholder(wrapper: HTMLElement) { const input_search = wrapper.querySelector('.selected-input');
const input_search = wrapper.querySelector(".selected-input"); input_search?.removeAttribute('placeholder');
input_search?.removeAttribute("placeholder"); }
}
function addPlaceholder(wrapper: HTMLElement) {
function addPlaceholder(wrapper: HTMLElement) { const input_search = wrapper.querySelector('.selected-input');
const input_search = wrapper.querySelector(".selected-input"); const tokens = wrapper.querySelectorAll('.selected-wrapper');
const tokens = wrapper.querySelectorAll(".selected-wrapper"); if (!tokens.length && !(document.activeElement === input_search)) input_search?.setAttribute('placeholder', '---------');
if (!tokens.length && !(document.activeElement === input_search)) }
input_search?.setAttribute("placeholder", "---------");
} // Listener of user search
function inputChange(e: Event) {
// Listener of user search const target = e.target as HTMLInputElement;
function inputChange(e: Event) { const wrapper = target?.parentNode?.parentNode;
const target = e.target as HTMLInputElement const select = wrapper?.querySelector('select') as HTMLSelectElement;
const wrapper = target?.parentNode?.parentNode; const dropdown = wrapper?.querySelector('.dropdown-icon');
const select = wrapper?.querySelector("select") as HTMLSelectElement;
const dropdown = wrapper?.querySelector(".dropdown-icon"); const input_val = target?.value;
const input_val = target?.value; if (input_val) {
dropdown?.classList.add('active');
if (input_val) { populateAutocompleteList(select, input_val.trim());
dropdown?.classList.add("active"); } else {
populateAutocompleteList(select, input_val.trim()); dropdown?.classList.remove('active');
} else { const event = new Event('click');
dropdown?.classList.remove("active"); dropdown?.dispatchEvent(event);
const event = new Event("click"); }
dropdown?.dispatchEvent(event); }
}
} // Listen for clicks on the wrapper, if click happens focus on the input
function clickOnWrapper(e: Event) {
// Listen for clicks on the wrapper, if click happens focus on the input const wrapper = e.target as HTMLElement;
function clickOnWrapper(e: Event) { if (wrapper.tagName == 'DIV') {
const wrapper = e.target as HTMLElement; const input_search = wrapper.querySelector('.selected-input');
if (wrapper.tagName == "DIV") { const dropdown = wrapper.querySelector('.dropdown-icon');
const input_search = wrapper.querySelector(".selected-input"); if (!dropdown?.classList.contains('active')) {
const dropdown = wrapper.querySelector(".dropdown-icon"); const event = new Event('click');
if (!dropdown?.classList.contains("active")) { dropdown?.dispatchEvent(event);
const event = new Event("click"); }
dropdown?.dispatchEvent(event); (input_search as HTMLInputElement)?.focus();
} removePlaceholder(wrapper);
(input_search as HTMLInputElement)?.focus(); }
removePlaceholder(wrapper); }
}
} function openOptions(e: Event) {
const input_search = e.target as HTMLElement;
function openOptions(e: Event) { const wrapper = input_search?.parentElement?.parentElement;
const input_search = e.target as HTMLElement; const dropdown = wrapper?.querySelector('.dropdown-icon');
const wrapper = input_search?.parentElement?.parentElement; if (!dropdown?.classList.contains('active')) {
const dropdown = wrapper?.querySelector(".dropdown-icon"); const event = new Event('click');
if (!dropdown?.classList.contains("active")) { dropdown?.dispatchEvent(event);
const event = new Event("click"); }
dropdown?.dispatchEvent(event); e.stopPropagation();
} }
e.stopPropagation();
} // Function that create a token inside of a wrapper with the given value
function createToken(wrapper: HTMLElement, value: any) {
// Function that create a token inside of a wrapper with the given value const search = wrapper.querySelector('.search-container');
function createToken(wrapper: HTMLElement, value: any) { const inputInderline = document.querySelector('.selected-processes');
const search = wrapper.querySelector(".search-container"); // Create token wrapper
const inputInderline = document.querySelector(".selected-processes"); const token = document.createElement('div');
// Create token wrapper token.classList.add('selected-wrapper');
const token = document.createElement("div"); const token_span = document.createElement('span');
token.classList.add("selected-wrapper"); token_span.classList.add('selected-label');
const token_span = document.createElement("span"); token_span.innerText = value;
token_span.classList.add("selected-label"); const close = document.createElement('a');
token_span.innerText = value; close.classList.add('selected-close');
const close = document.createElement("a"); close.setAttribute('tabindex', '-1');
close.classList.add("selected-close"); close.setAttribute('data-option', value);
close.setAttribute("tabindex", "-1"); close.setAttribute('data-hits', '0');
close.setAttribute("data-option", value); close.setAttribute('href', '#');
close.setAttribute("data-hits", '0'); close.innerText = 'x';
close.setAttribute("href", "#"); close.addEventListener('click', removeToken);
close.innerText = "x"; token.appendChild(token_span);
close.addEventListener("click", removeToken); token.appendChild(close);
token.appendChild(token_span); inputInderline?.appendChild(token);
token.appendChild(close); }
inputInderline?.appendChild(token);
} // Listen for clicks in the dropdown option
function clickDropdown(e: Event) {
// Listen for clicks in the dropdown option const dropdown = e.target as HTMLElement;
function clickDropdown(e: Event) { const wrapper = dropdown?.parentNode?.parentNode;
const dropdown = e.target as HTMLElement; const input_search = wrapper?.querySelector('.selected-input') as HTMLInputElement;
const wrapper = dropdown?.parentNode?.parentNode; const select = wrapper?.querySelector('select') as HTMLSelectElement;
const input_search = wrapper?.querySelector(".selected-input") as HTMLInputElement; dropdown.classList.toggle('active');
const select = wrapper?.querySelector("select") as HTMLSelectElement;
dropdown.classList.toggle("active"); if (dropdown.classList.contains('active')) {
removePlaceholder(wrapper as HTMLElement);
if (dropdown.classList.contains("active")) { input_search?.focus();
removePlaceholder(wrapper as HTMLElement);
input_search?.focus(); if (!input_search?.value) {
populateAutocompleteList(select, '', true);
if (!input_search?.value) { } else {
populateAutocompleteList(select, "", true); populateAutocompleteList(select, input_search.value);
} else { }
populateAutocompleteList(select, input_search.value); } else {
} clearAutocompleteList(select);
} else { addPlaceholder(wrapper as HTMLElement);
clearAutocompleteList(select); }
addPlaceholder(wrapper as HTMLElement); }
}
} // Clears the results of the autocomplete list
function clearAutocompleteList(select: HTMLSelectElement) {
// Clears the results of the autocomplete list const wrapper = select.parentNode;
function clearAutocompleteList(select: HTMLSelectElement) {
const wrapper = select.parentNode; const autocomplete_list = wrapper?.querySelector('.autocomplete-list');
if (autocomplete_list) autocomplete_list.innerHTML = '';
const autocomplete_list = wrapper?.querySelector(".autocomplete-list"); }
if(autocomplete_list) autocomplete_list.innerHTML = "";
} // Populate the autocomplete list following a given query from the user
function populateAutocompleteList(select: HTMLSelectElement, query: string, dropdown = false) {
// Populate the autocomplete list following a given query from the user const { autocomplete_options } = getOptions(select);
function populateAutocompleteList(select: HTMLSelectElement, query: string, dropdown = false) {
const { autocomplete_options } = getOptions(select); let options_to_show;
let options_to_show; if (dropdown) options_to_show = autocomplete_options;
else options_to_show = autocomplete(query, autocomplete_options);
if (dropdown) options_to_show = autocomplete_options;
else options_to_show = autocomplete(query, autocomplete_options); const wrapper = select.parentNode;
const input_search = wrapper?.querySelector('.search-container');
const wrapper = select.parentNode; const autocomplete_list = wrapper?.querySelector('.autocomplete-list');
const input_search = wrapper?.querySelector(".search-container"); if (autocomplete_list) autocomplete_list.innerHTML = '';
const autocomplete_list = wrapper?.querySelector(".autocomplete-list"); const result_size = options_to_show.length;
if(autocomplete_list) autocomplete_list.innerHTML = "";
const result_size = options_to_show.length; if (result_size == 1) {
const li = document.createElement('li');
if (result_size == 1) { li.innerText = options_to_show[0];
const li = document.createElement("li"); li.setAttribute('data-value', options_to_show[0]);
li.innerText = options_to_show[0]; li.addEventListener('click', selectOption);
li.setAttribute("data-value", options_to_show[0]); autocomplete_list?.appendChild(li);
li.addEventListener("click", selectOption); if (query.length == options_to_show[0].length) {
autocomplete_list?.appendChild(li); const event = new Event('click');
if (query.length == options_to_show[0].length) { li.dispatchEvent(event);
const event = new Event("click"); }
li.dispatchEvent(event); } else if (result_size > 1) {
} for (let i = 0; i < result_size; i++) {
} else if (result_size > 1) { const li = document.createElement('li');
for (let i = 0; i < result_size; i++) { li.innerText = options_to_show[i];
const li = document.createElement("li"); li.setAttribute('data-value', options_to_show[i]);
li.innerText = options_to_show[i]; li.addEventListener('click', selectOption);
li.setAttribute("data-value", options_to_show[i]); autocomplete_list?.appendChild(li);
li.addEventListener("click", selectOption); }
autocomplete_list?.appendChild(li); } else {
} const li = document.createElement('li');
} else { li.classList.add('not-cursor');
const li = document.createElement("li"); li.innerText = 'No options found';
li.classList.add("not-cursor"); autocomplete_list?.appendChild(li);
li.innerText = "No options found"; }
autocomplete_list?.appendChild(li); }
}
} // Listener to autocomplete results when clicked set the selected property in the select option
function selectOption(e: any) {
// Listener to autocomplete results when clicked set the selected property in the select option const wrapper = e.target.parentNode.parentNode.parentNode;
function selectOption(e: any) { const input_search = wrapper.querySelector('.selected-input');
const wrapper = e.target.parentNode.parentNode.parentNode; const option = wrapper.querySelector(`select option[value="${e.target.dataset.value}"]`);
const input_search = wrapper.querySelector(".selected-input");
const option = wrapper.querySelector( option.setAttribute('selected', '');
`select option[value="${e.target.dataset.value}"]` createToken(wrapper, e.target.dataset.value);
); if (input_search.value) {
input_search.value = '';
option.setAttribute("selected", ""); }
createToken(wrapper, e.target.dataset.value);
if (input_search.value) { // showSelectedProcess(e.target.dataset.value);
input_search.value = "";
} input_search.focus();
// showSelectedProcess(e.target.dataset.value); e.target.remove();
const autocomplete_list = wrapper.querySelector('.autocomplete-list');
input_search.focus();
if (!autocomplete_list.children.length) {
e.target.remove(); const li = document.createElement('li');
const autocomplete_list = wrapper.querySelector(".autocomplete-list"); li.classList.add('not-cursor');
li.innerText = 'No options found';
if (!autocomplete_list.children.length) { autocomplete_list.appendChild(li);
const li = document.createElement("li"); }
li.classList.add("not-cursor");
li.innerText = "No options found"; const event = new Event('keyup');
autocomplete_list.appendChild(li); input_search.dispatchEvent(event);
} e.stopPropagation();
}
const event = new Event("keyup");
input_search.dispatchEvent(event); // function that returns a list with the autcomplete list of matches
e.stopPropagation(); function autocomplete(query: string, options: any) {
} // No query passed, just return entire list
if (!query) {
// function that returns a list with the autcomplete list of matches return options;
function autocomplete(query: string, options: any) { }
// No query passed, just return entire list let options_return = [];
if (!query) {
return options; for (let i = 0; i < options.length; i++) {
} if (query.toLowerCase() === options[i].slice(0, query.length).toLowerCase()) {
let options_return = []; options_return.push(options[i]);
}
for (let i = 0; i < options.length; i++) { }
if ( return options_return;
query.toLowerCase() === options[i].slice(0, query.length).toLowerCase() }
) {
options_return.push(options[i]); // Returns the options that are selected by the user and the ones that are not
} function getOptions(select: HTMLSelectElement) {
} // Select all the options available
return options_return; const all_options = Array.from(select.querySelectorAll('option')).map((el) => el.value);
}
// Get the options that are selected from the user
// Returns the options that are selected by the user and the ones that are not const options_selected = Array.from(select.querySelectorAll('option:checked')).map((el: any) => el.value);
function getOptions(select: HTMLSelectElement) {
// Select all the options available // Create an autocomplete options array with the options that are not selected by the user
const all_options = Array.from(select.querySelectorAll("option")).map( const autocomplete_options: any[] = [];
(el) => el.value all_options.forEach((option) => {
); if (!options_selected.includes(option)) {
autocomplete_options.push(option);
// Get the options that are selected from the user }
const options_selected = Array.from( });
select.querySelectorAll("option:checked")
).map((el: any) => el.value); autocomplete_options.sort();
// Create an autocomplete options array with the options that are not selected by the user return {
const autocomplete_options: any[] = []; options_selected,
all_options.forEach((option) => { autocomplete_options,
if (!options_selected.includes(option)) { };
autocomplete_options.push(option); }
}
}); // Listener for when the user wants to remove a given token.
function removeToken(e: Event) {
autocomplete_options.sort(); // Get the value to remove
const target = e.target as HTMLSelectElement;
return { const value_to_remove = target.dataset.option;
options_selected, const wrapper = target.parentNode?.parentNode?.parentNode;
autocomplete_options, const input_search = wrapper?.querySelector('.selected-input');
}; const dropdown = wrapper?.querySelector('.dropdown-icon');
} // Get the options in the select to be unselected
const option_to_unselect = wrapper?.querySelector(`select option[value="${value_to_remove}"]`);
// Listener for when the user wants to remove a given token. option_to_unselect?.removeAttribute('selected');
function removeToken(e: Event) { // Remove token attribute
// Get the value to remove (target.parentNode as any)?.remove();
const target = e.target as HTMLSelectElement dropdown?.classList.remove('active');
const value_to_remove = target.dataset.option; const process = document.querySelector('#' + target.dataset.option);
const wrapper = target.parentNode?.parentNode?.parentNode; process?.remove();
const input_search = wrapper?.querySelector(".selected-input"); }
const dropdown = wrapper?.querySelector(".dropdown-icon");
// Get the options in the select to be unselected // Listen for 2 sequence of hits on the delete key, if this happens delete the last token if exist
const option_to_unselect = wrapper?.querySelector( function deletePressed(e: KeyboardEvent) {
`select option[value="${value_to_remove}"]` const input_search = e.target as HTMLInputElement;
); const wrapper = input_search?.parentNode?.parentNode;
option_to_unselect?.removeAttribute("selected"); const key = e.keyCode || e.charCode;
// Remove token attribute const tokens = wrapper?.querySelectorAll('.selected-wrapper');
(target.parentNode as any)?.remove();
dropdown?.classList.remove("active"); if (tokens?.length) {
const process = document.querySelector("#" + target.dataset.option); const last_token_x = tokens[tokens.length - 1].querySelector('a');
process?.remove(); let hits = +(last_token_x?.dataset?.hits || 0);
}
if (key == 8 || key == 46) {
// Listen for 2 sequence of hits on the delete key, if this happens delete the last token if exist if (!input_search.value) {
function deletePressed(e: KeyboardEvent) { if (hits > 1) {
const input_search = e.target as HTMLInputElement; // Trigger delete event
const wrapper = input_search?.parentNode?.parentNode; const event = new Event('click');
const key = e.keyCode || e.charCode; last_token_x?.dispatchEvent(event);
const tokens = wrapper?.querySelectorAll(".selected-wrapper"); } else {
if (last_token_x?.dataset.hits) last_token_x.dataset.hits = '2';
if (tokens?.length) { }
const last_token_x = tokens[tokens.length - 1].querySelector("a"); }
let hits = +(last_token_x?.dataset?.hits || 0); } else {
if (last_token_x?.dataset.hits) last_token_x.dataset.hits = '0';
if (key == 8 || key == 46) { }
if (!input_search.value) { }
if (hits > 1) { return true;
// Trigger delete event }
const event = new Event("click");
last_token_x?.dispatchEvent(event); // function addOption(target, val, text) {
} else { // const select = document.querySelector(target);
if(last_token_x?.dataset.hits) last_token_x.dataset.hits = '2'; // let opt = document.createElement("option");
} // opt.value = val;
} // opt.innerHTML = text;
} else { // select.appendChild(opt);
if(last_token_x?.dataset.hits) last_token_x.dataset.hits = '0'; // }
}
} // get select that has the options available
return true; const select = document.querySelectorAll('[data-multi-select-plugin]') as NodeListOf<HTMLElement>;
} select.forEach((select) => {
console.log(select);
// function addOption(target, val, text) { init(select);
// const select = document.querySelector(target); });
// let opt = document.createElement("option");
// opt.value = val; // Dismiss on outside click
// opt.innerHTML = text; document.addEventListener('click', () => {
// select.appendChild(opt); // get select that has the options available
// } const select = document.querySelectorAll('[data-multi-select-plugin]');
for (let i = 0; i < select.length; i++) {
// get select that has the options available if (event) {
const select = document.querySelectorAll("[data-multi-select-plugin]") as NodeListOf<HTMLElement>; var isClickInside = select[i].parentElement?.parentElement?.contains(event.target as Node);
select.forEach((select) => {
console.log(select); if (!isClickInside) {
init(select); const wrapper = select[i].parentElement?.parentElement;
}); const dropdown = wrapper?.querySelector('.dropdown-icon');
const autocomplete_list = wrapper?.querySelector('.autocomplete-list');
// Dismiss on outside click //the click was outside the specifiedElement, do something
document.addEventListener("click", () => { dropdown?.classList.remove('active');
// get select that has the options available if (autocomplete_list) autocomplete_list.innerHTML = '';
const select = document.querySelectorAll("[data-multi-select-plugin]"); addPlaceholder(wrapper as HTMLElement);
for (let i = 0; i < select.length; i++) { }
if (event) { }
var isClickInside = select[i].parentElement?.parentElement?.contains( }
event.target as Node });
);
export async function unpair() {
if (!isClickInside) { const service = await Services.getInstance();
const wrapper = select[i].parentElement?.parentElement; await service.unpairDevice();
const dropdown = wrapper?.querySelector(".dropdown-icon"); }
const autocomplete_list = wrapper?.querySelector(".autocomplete-list");
//the click was outside the specifiedElement, do something (window as any).unpair = unpair;
dropdown?.classList.remove("active");
if(autocomplete_list) autocomplete_list.innerHTML = ""; async function showSelectedProcess(event: MouseEvent) {
addPlaceholder(wrapper as HTMLElement); const elem = event.target;
} if (elem) {
} const cardContent = document.querySelector('.card-content');
}
}); const processes = await getProcesses();
console.log('🚀 ~ Services ~ showSelectedProcess ~ processes:', processes);
const process = processes.find((process: any) => process.name === (elem as any).dataset.value);
export async function unpair() { if (process) {
const service = await Services.getInstance() const processDiv = document.createElement('div');
await service.unpairDevice() processDiv.className = 'process';
} processDiv.id = process.name;
const titleDiv = document.createElement('div');
(window as any).unpair = unpair; titleDiv.className = 'process-title';
titleDiv.innerHTML = `${process.name} : ${process.description}`;
processDiv.appendChild(titleDiv);
async function showSelectedProcess(event: MouseEvent) { for (const zone of process.zoneList) {
const elem = event.target; const zoneElement = document.createElement('div');
if(elem) { zoneElement.className = 'process-element';
zoneElement.setAttribute('zone-id', zone.id.toString());
const cardContent = document.querySelector(".card-content"); zoneElement.innerHTML = `Zone ${zone.id} : ${zone.name}`;
const service = await Services.getInstance();
const processes = await getProcesses(); service.addSubscription(zoneElement, 'click', 'goToProcessPage');
console.log("🚀 ~ Services ~ showSelectedProcess ~ processes:", processes) processDiv.appendChild(zoneElement);
const process = processes.find((process: any) => process.name === (elem as any).dataset.value); }
if (process) { if (cardContent) cardContent.appendChild(processDiv);
const processDiv = document.createElement("div"); }
processDiv.className = "process"; }
processDiv.id = process.name; }
const titleDiv = document.createElement("div");
titleDiv.className = "process-title"; function goToProcessPage(event: MouseEvent) {
titleDiv.innerHTML = `${process.name} : ${process.description}`; const target = event.target as HTMLDivElement;
processDiv.appendChild(titleDiv); const zoneId = target?.getAttribute('zone-id');
for (const zone of process.zoneList) { const processList = document.querySelectorAll('.process-element');
const zoneElement = document.createElement("div"); if (processList) {
zoneElement.className = "process-element"; for (const process of processList) {
zoneElement.setAttribute('zone-id', zone.id.toString()) process.classList.remove('selected');
zoneElement.innerHTML = `Zone ${zone.id} : ${zone.name}`; }
const service = await Services.getInstance() }
service.addSubscription(zoneElement, 'click', 'goToProcessPage') target.classList.add('selected');
processDiv.appendChild(zoneElement);
} console.log('=======================> going to process page', zoneId);
if(cardContent) cardContent.appendChild(processDiv); }
}
} async function getProcesses(): Promise<any[]> {
} const service = await Services.getInstance();
// const processes = service.getProcesses()
function goToProcessPage(event: MouseEvent) { // console.log("🚀 ~ Services ~ getProcesses ~ processes:", processes)
const target = event.target as HTMLDivElement; const process = [
const zoneId = target?.getAttribute('zone-id'); {
const processList = document.querySelectorAll('.process-element'); title: 'Messaging',
if(processList) { description: 'Messagerie chiffrée',
for(const process of processList) { html: '<div><input /></div>',
process.classList.remove('selected') css: '',
} script: '',
} zones: ['zone 1', 'zone 2'],
target.classList.add('selected') roles: {
owner: {
console.log('=======================> going to process page', zoneId) members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'],
} validation_rules: [
{
async function getProcesses(): Promise<IProcess[]> { quorum: 1.0,
const service = await Services.getInstance() fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'],
// const processes = service.getProcesses() min_sig_member: 1.0,
// console.log("🚀 ~ Services ~ getProcesses ~ processes:", processes) },
return [ ],
{ },
id: 1, },
name: "Messaging", },
description: "Encrypted messages", {
zoneList: [ title: 'Database',
{ description: 'Database chiffrée',
id: 1, html: '<div><input /></div>',
name: "General", css: '',
path: '/test' script: '',
}, zones: ['zone 1', 'zone 2'],
], roles: {
}, owner: {
{ members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'],
id: 2, validation_rules: [
name: "Storage", {
description: "Distributed storage", quorum: 1.0,
zoneList: [ fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'],
{ min_sig_member: 1.0,
id: 1, },
name: "Paris", ],
path: '/test' },
}, },
{ },
id: 2, ];
name: "Normandy", return process
path: '/test' }
},
{
id: 3,
name: "New York",
path: '/test'
},
{
id: 4,
name: "Moscow",
path: '/test'
},
],
},
];
}

View File

@ -1,85 +1,82 @@
import '../public/style/4nk.css'; import '../public/style/4nk.css';
import { initHomePage } from './pages/home/home'; import { initHomePage } from './pages/home/home';
import Services from './services/service'; import Services from './services/service';
const routes: { [key: string]: string } = { const routes: { [key: string]: string } = {
'home': '/src/pages/home/home.html', home: '/src/pages/home/home.html',
'process': '/src/pages/process/process.html', process: '/src/pages/process/process.html',
}; };
export async function navigate(path: string) { export async function navigate(path: string) {
path = path.replace(/^\//, ''); path = path.replace(/^\//, '');
if (!routes[path]) { if (!routes[path]) {
path = 'home'; path = 'home';
} }
await handleLocation(path); await handleLocation(path);
} }
async function handleLocation(path: string) { async function handleLocation(path: string) {
const routeHtml = routes[path] || routes['home']; const routeHtml = routes[path] || routes['home'];
const content = document.getElementById('containerId'); const content = document.getElementById('containerId');
if (content) { if (content) {
const html = await fetch(routeHtml).then(data => data.text()); const html = await fetch(routeHtml).then((data) => data.text());
content.innerHTML = html; content.innerHTML = html;
await new Promise(requestAnimationFrame); await new Promise(requestAnimationFrame);
if(path === "home") { if (path === 'home') {
const { initHomePage } = await import('./pages/home/home'); const { initHomePage } = await import('./pages/home/home');
initHomePage() initHomePage();
} } else if (path === 'process') {
else if (path === "process") { await import('./pages/process/process');
await import('./pages/process/process'); }
} }
} }
}
window.onpopstate = () => handleLocation('home');
window.onpopstate = () => handleLocation('home');
async function init(): Promise<boolean> {
async function init(): Promise<boolean> { let isPaired = false;
let isPaired = false; try {
try { const services = await Services.getInstance();
setTimeout(async () => {
const services = await Services.getInstance(); let device = await services.getDevice();
setTimeout( async () => { console.log('🚀 ~ setTimeout ~ device:', device);
let device = await services.getDevice()
console.log("🚀 ~ setTimeout ~ device:", device) if (!device) {
device = await services.createNewDevice();
if(!device) { } else {
device = await services.createNewDevice(); await services.restoreDevice(device);
} else { }
await services.restoreDevice(device) await services.restoreProcesses();
} await services.restoreMessages();
await services.restoreProcesses();
await services.restoreMessages(); if (services.isPaired()) {
isPaired = true;
if (services.isPaired()) { console.log('🚀 ~ setTimeout ~ isPaired:', isPaired);
isPaired = true; await navigate('process');
console.log("🚀 ~ setTimeout ~ isPaired:", isPaired) return isPaired;
await navigate('process'); } else {
return isPaired const queryString = window.location.search;
} else { const urlParams = new URLSearchParams(queryString);
const queryString = window.location.search; const pairingAddress = urlParams.get('sp_address');
const urlParams = new URLSearchParams(queryString) if (pairingAddress) {
const pairingAddress = urlParams.get('sp_address') setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000);
if(pairingAddress) { }
setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000) return isPaired;
} }
return isPaired }, 200);
} } catch (error) {
}, 200); console.error(error);
} catch (error) { return isPaired;
console.error(error); }
return isPaired return isPaired;
} }
return isPaired
(async () => {
} const isPaired = await init();
console.log('🚀 ~ handleLocation ~ isPaired:', isPaired);
(async () => { await navigate('home');
const isPaired = await init() })();
console.log("🚀 ~ handleLocation ~ isPaired:", isPaired)
await navigate('home');
})();

View File

@ -1,117 +1,117 @@
import modalHtml from '../html/login-modal.html?raw'; import modalHtml from '../html/login-modal.html?raw';
import confirmationModalHtml from '../html/confirmation-modal.html?raw'; import confirmationModalHtml from '../html/confirmation-modal.html?raw';
import modalScript from '../html/login-modal.js?raw'; import modalScript from '../html/login-modal.js?raw';
import confirmationModalScript from '../html/confirmation-modal.js?raw'; import confirmationModalScript from '../html/confirmation-modal.js?raw';
import Services from './service'; import Services from './service';
import { U32_MAX } from './service'; import { U32_MAX } from './service';
import { navigate } from '../router'; import { navigate } from '../router';
export default class Routing {
export default class Routing { private static instance: Routing;
private static instance: Routing; private sdkClient: any;
private sdkClient: any; private currentPrd: any;
private currentPrd: any; private currentOutpoint?: string;
private currentOutpoint?: string; private constructor() {}
private constructor() {} private paired_addresses: string[] = [];
private paired_addresses: string[] = [];
// Method to access the singleton instance of Services
// Method to access the singleton instance of Services public static async getInstance(): Promise<Routing> {
public static async getInstance(): Promise<Routing> { if (!Routing.instance) {
if (!Routing.instance) { Routing.instance = new Routing();
Routing.instance = new Routing(); await Routing.instance.init();
await Routing.instance.init(); }
} return Routing.instance;
return Routing.instance; }
}
public async init(): Promise<void> {
public async init(): Promise<void> { this.sdkClient = await import('../../dist/pkg/sdk_client');
this.sdkClient = await import("../../dist/pkg/sdk_client"); }
}
public openLoginModal(myAddress: string, receiverAddress: string) {
public openLoginModal(myAddress: string, receiverAddress: string) { const container = document.querySelector('.page-container');
const container = document.querySelector('.page-container'); let html = modalHtml;
let html = modalHtml html = html.replace('{{device1}}', myAddress);
html = html.replace('{{device1}}', myAddress) html = html.replace('{{device2}}', receiverAddress);
html = html.replace('{{device2}}', receiverAddress) if (container) container.innerHTML += html;
if (container) container.innerHTML += html; const modal = document.getElementById('login-modal');
const modal = document.getElementById('login-modal') if (modal) modal.style.display = 'flex';
if (modal) modal.style.display = 'flex'; const newScript = document.createElement('script');
const newScript = document.createElement('script');
newScript.setAttribute('type', 'module');
newScript.textContent = modalScript;
newScript.setAttribute('type', 'module') document.head.appendChild(newScript).parentNode?.removeChild(newScript);
newScript.textContent = modalScript; }
document.head.appendChild(newScript).parentNode?.removeChild(newScript);
} public async openConfirmationModal(pcd: any, outpointCommitment: string) {
console.log('');
public async openConfirmationModal(pcd: any, outpointCommitment: string) { let roles = JSON.parse(pcd['roles']); // ['members'][0];
console.log("") console.log(roles);
let roles = JSON.parse(pcd['roles']);// ['members'][0]; let members = roles['owner']['members'];
console.log(roles); console.log(members);
let members = roles['owner']['members']; // We take all the addresses except our own
console.log(members); const local_address = this.sdkClient.get_address();
// We take all the addresses except our own console.log('🚀 ~ Routing ~ openConfirmationModal ~ pcd:', pcd);
const local_address = this.sdkClient.get_address(); for (const address of members[0]['sp_addresses']) {
console.log("🚀 ~ Routing ~ openConfirmationModal ~ pcd:", pcd) if (address !== local_address) {
for (const address of members[0]['sp_addresses']) { this.paired_addresses.push(address);
if (address !== local_address) { this.paired_addresses.push(address) } }
} }
let html = confirmationModalHtml; let html = confirmationModalHtml;
let services = await Services.getInstance(); let services = await Services.getInstance();
html = html.replace('{{device1}}', await services.addressToEmoji(members[0]['sp_addresses'][0])); html = html.replace('{{device1}}', await services.addressToEmoji(members[0]['sp_addresses'][0]));
html = html.replace('{{device2}}', await services.addressToEmoji(members[0]['sp_addresses'][1])); html = html.replace('{{device2}}', await services.addressToEmoji(members[0]['sp_addresses'][1]));
this.currentOutpoint = outpointCommitment as string; this.currentOutpoint = outpointCommitment as string;
const container = document.querySelector('.page-container'); const container = document.querySelector('.page-container');
if (container) container.innerHTML += html; if (container) container.innerHTML += html;
const modal = document.getElementById('modal') const modal = document.getElementById('modal');
if (modal) modal.style.display = 'flex'; if (modal) modal.style.display = 'flex';
const newScript = document.createElement('script'); const newScript = document.createElement('script');
newScript.setAttribute('type', 'module') newScript.setAttribute('type', 'module');
newScript.textContent = confirmationModalScript; newScript.textContent = confirmationModalScript;
document.head.appendChild(newScript).parentNode?.removeChild(newScript); document.head.appendChild(newScript).parentNode?.removeChild(newScript);
// Add correct text // Add correct text
// Close modal when clicking outside of it // Close modal when clicking outside of it
window.onclick = (event) => { window.onclick = (event) => {
const modal = document.getElementById('modal'); const modal = document.getElementById('modal');
if (event.target === modal) { if (event.target === modal) {
this.closeConfirmationModal(); this.closeConfirmationModal();
} }
} };
} }
confirmLogin() { confirmLogin() {
console.log('=============> Confirm Login') console.log('=============> Confirm Login');
const loginTx = this.sdkClient.create_login_transaction(1) const loginTx = this.sdkClient.create_login_transaction(1);
this.sdkClient.login('LOGIN', loginTx) this.sdkClient.login('LOGIN', loginTx);
} }
async closeLoginModal() { async closeLoginModal() {
const modal = document.getElementById('login-modal') const modal = document.getElementById('login-modal');
if (modal) modal.style.display = 'none'; if (modal) modal.style.display = 'none';
} }
async confirmPairing() { async confirmPairing() {
const service = await Services.getInstance() const service = await Services.getInstance();
const modal = document.getElementById('modal') const modal = document.getElementById('modal');
// console.log("🚀 ~ Routing ~ confirm ~ prd:", prd) // console.log("🚀 ~ Routing ~ confirm ~ prd:", prd)
if (modal) modal.style.display = 'none'; if (modal) modal.style.display = 'none';
// Just make an empty commitment for now // Just make an empty commitment for now
const emptyTxid = '0'.repeat(64) const emptyTxid = '0'.repeat(64);
const commitmentOutpoint = `${emptyTxid}:${U32_MAX}`; const commitmentOutpoint = `${emptyTxid}:${U32_MAX}`;
// We take the paired device(s) from the contract // We take the paired device(s) from the contract
await this.sdkClient.pair_device(commitmentOutpoint, this.paired_addresses) await this.sdkClient.pair_device(commitmentOutpoint, this.paired_addresses);
this.paired_addresses = [] this.paired_addresses = [];
const newDevice = await service.dumpDevice(); const newDevice = await service.dumpDevice();
await service.saveDevice(newDevice); await service.saveDevice(newDevice);
navigate('process'); navigate('process');
} }
async closeConfirmationModal() { async closeConfirmationModal() {
const service = await Services.getInstance() const service = await Services.getInstance();
await service.unpairDevice() await service.unpairDevice();
const modal = document.getElementById('modal') const modal = document.getElementById('modal');
if (modal) modal.style.display = 'none'; if (modal) modal.style.display = 'none';
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,136 +1,137 @@
import { AnkFlag, CachedMessage } from "dist/pkg/sdk_client"; import { AnkFlag, CachedMessage } from 'dist/pkg/sdk_client';
import Services from "./services/service"; import Services from './services/service';
// import { AnkFlag, AnkNetworkMsg, CachedMessage } from "../dist/pkg/sdk_client"; // import { AnkFlag, AnkNetworkMsg, CachedMessage } from "../dist/pkg/sdk_client";
class WebSocketClient { class WebSocketClient {
private ws: WebSocket; private ws: WebSocket;
private messageQueue: string[] = []; private messageQueue: string[] = [];
constructor(url: string, private services: Services) { constructor(
this.ws = new WebSocket(url); url: string,
private services: Services,
if(this.ws !== null) { ) {
this.ws.onopen = async (event) => { this.ws = new WebSocket(url);
console.log('WebSocket connection established');
if (this.ws !== null) {
const amount = await services.getAmount(); this.ws.onopen = async (event) => {
console.log('WebSocket connection established');
if (amount === 0n) {
const faucetMsg = await services.createFaucetMessage(); const amount = await services.getAmount();
await services.sendFaucetMessage(faucetMsg);
} if (amount === 0n) {
while (this.messageQueue.length > 0) { const faucetMsg = await services.createFaucetMessage();
const message = this.messageQueue.shift(); await services.sendFaucetMessage(faucetMsg);
if (message) { }
this.ws.send(message); while (this.messageQueue.length > 0) {
} const message = this.messageQueue.shift();
} if (message) {
}; this.ws.send(message);
}
// Listen for messages }
this.ws.onmessage = (event) => { };
const msgData = event.data;
// Listen for messages
// console.log("Received text message: ", msgData); this.ws.onmessage = (event) => {
(async () => { const msgData = event.data;
if (typeof msgData === 'string') {
try { // console.log("Received text message: ", msgData);
const feeRate = 0.0001; (async () => {
const parsedMessage = JSON.parse(msgData) if (typeof msgData === 'string') {
// console.log("🚀 ~ WebSocketClient ~ parsedMessage:", parsedMessage) try {
const services = await Services.getInstance() const feeRate = 0.0001;
switch(parsedMessage.flag) { const parsedMessage = JSON.parse(msgData);
case 'NewTx': // console.log("🚀 ~ WebSocketClient ~ parsedMessage:", parsedMessage)
await services.parseNewTx(parsedMessage.content) const services = await Services.getInstance();
break; switch (parsedMessage.flag) {
case 'Cipher': case 'NewTx':
await services.parseCipher(parsedMessage.content) await services.parseNewTx(parsedMessage.content);
// device = await services.dumpWallet() break;
// console.log("🚀 ~ WebSocketClient ~ device:", device) case 'Cipher':
// await services.saveDevice(device) await services.parseCipher(parsedMessage.content);
break; // device = await services.dumpWallet()
} // console.log("🚀 ~ WebSocketClient ~ device:", device)
// By parsing the message, we can link it with existing cached message and return the updated version of the message // await services.saveDevice(device)
// if (res.status === 'FaucetComplete') { break;
// // we received a faucet tx, there's nothing else to do }
// window.alert(`New faucet output\n${res.commited_in}`); // By parsing the message, we can link it with existing cached message and return the updated version of the message
// } else if (res.status === 'TxWaitingCipher') { // if (res.status === 'FaucetComplete') {
// // we received a tx but we don't have the cipher // // we received a faucet tx, there's nothing else to do
// console.debug(`received notification in output ${res.commited_in}, waiting for cipher message`); // window.alert(`New faucet output\n${res.commited_in}`);
// } else if (res.status === 'CipherWaitingTx') { // } else if (res.status === 'TxWaitingCipher') {
// // we received a cipher but we don't have the key // // we received a tx but we don't have the cipher
// console.debug(`received a cipher`); // console.debug(`received notification in output ${res.commited_in}, waiting for cipher message`);
// } else if (res.status === 'SentWaitingConfirmation') { // } else if (res.status === 'CipherWaitingTx') {
// // We are sender and we're waiting for the challenge that will confirm recipient got the transaction and the message // // we received a cipher but we don't have the key
// } else if (res.status === 'MustSpendConfirmation') { // console.debug(`received a cipher`);
// // we received a challenge for a notification we made // } else if (res.status === 'SentWaitingConfirmation') {
// // that means we can stop rebroadcasting the tx and we must spend the challenge to confirm // // We are sender and we're waiting for the challenge that will confirm recipient got the transaction and the message
// window.alert(`Spending ${res.confirmed_by} to prove our identity`); // } else if (res.status === 'MustSpendConfirmation') {
// console.debug(`sending confirm message to ${res.recipient}`); // // we received a challenge for a notification we made
// } else if (res.status === 'ReceivedMustConfirm') { // // that means we can stop rebroadcasting the tx and we must spend the challenge to confirm
// // we found a notification and decrypted the cipher // window.alert(`Spending ${res.confirmed_by} to prove our identity`);
// window.alert(`Received message from ${res.sender}\n${res.plaintext}`); // console.debug(`sending confirm message to ${res.recipient}`);
// // we must spend the commited_in output to sender // } else if (res.status === 'ReceivedMustConfirm') {
// } else if (res.status === 'Complete') { // // we found a notification and decrypted the cipher
// window.alert(`Received confirmation that ${res.sender} is the author of message ${res.plaintext}`) // window.alert(`Received message from ${res.sender}\n${res.plaintext}`);
// } else { // // we must spend the commited_in output to sender
// console.debug('Received an unimplemented valid message'); // } else if (res.status === 'Complete') {
// } // window.alert(`Received confirmation that ${res.sender} is the author of message ${res.plaintext}`)
} catch (error) { // } else {
console.error('Received an invalid message:', error); // console.debug('Received an unimplemented valid message');
} // }
} else { } catch (error) {
console.error('Received a non-string message'); console.error('Received an invalid message:', error);
} }
})(); } else {
}; console.error('Received a non-string message');
}
// Listen for possible errors })();
this.ws.onerror = (event) => { };
console.error('WebSocket error:', event);
}; // Listen for possible errors
this.ws.onerror = (event) => {
// Listen for when the connection is closed console.error('WebSocket error:', event);
this.ws.onclose = (event) => { };
console.log('WebSocket is closed now.');
} // Listen for when the connection is closed
} this.ws.onclose = (event) => {
console.log('WebSocket is closed now.');
} };
}
// Method to send messages }
public async sendMessage(flag: AnkFlag, message: string): Promise<void> {
if (this.ws.readyState === WebSocket.OPEN) { // Method to send messages
const networkMessage = { public async sendMessage(flag: AnkFlag, message: string): Promise<void> {
'flag': flag, if (this.ws.readyState === WebSocket.OPEN) {
'content': message const networkMessage = {
} flag: flag,
// if(flag === 'Cipher') { content: message,
// const services = await Services.getInstance(); };
// services.parseCipher(JSON.stringify(networkMessage)) // if(flag === 'Cipher') {
// } // const services = await Services.getInstance();
console.log("Sending message:", JSON.stringify(networkMessage)); // services.parseCipher(JSON.stringify(networkMessage))
this.ws.send(JSON.stringify(networkMessage)); // }
} else { console.log('Sending message:', JSON.stringify(networkMessage));
console.error('WebSocket is not open. ReadyState:', this.ws.readyState); this.ws.send(JSON.stringify(networkMessage));
this.messageQueue.push(message); } else {
} console.error('WebSocket is not open. ReadyState:', this.ws.readyState);
} this.messageQueue.push(message);
}
public getUrl(): string { }
return this.ws.url;
} public getUrl(): string {
return this.ws.url;
public sendNormalMessage(message: string) { }
this.ws.send(message);
console.log("Sending message:", JSON.stringify(message)); public sendNormalMessage(message: string) {
this.ws.send(message);
} console.log('Sending message:', JSON.stringify(message));
}
// Method to close the WebSocket connection
public close(): void { // Method to close the WebSocket connection
this.ws.close(); public close(): void {
} this.ws.close();
} }
}
export { WebSocketClient };
export { WebSocketClient };