From 2ad34191d2c601caa1f7a61444b0243254c17a8b Mon Sep 17 00:00:00 2001 From: AnisHADJARAB Date: Wed, 30 Oct 2024 14:02:29 +0000 Subject: [PATCH] separate header into a diff component --- index.html | 2 + public/style/4nk.css | 17 ++- src/components/header/header.html | 28 ++++ src/components/header/header.js | 60 +++++++++ src/pages/home/home.html | 28 ---- .../process-element/process-element.html | 37 +----- src/pages/process-element/process-element.ts | 28 ++-- src/pages/process/process.html | 67 +++------- src/pages/process/process.ts | 69 ++++------ src/router.ts | 72 +++++----- src/services/service.ts | 123 ++++++++++-------- 11 files changed, 269 insertions(+), 262 deletions(-) create mode 100644 src/components/header/header.html create mode 100644 src/components/header/header.js diff --git a/index.html b/index.html index e528215..648bee8 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,8 @@ 4NK Application +
+
diff --git a/public/style/4nk.css b/public/style/4nk.css index bbe2b2c..bdde9a1 100644 --- a/public/style/4nk.css +++ b/public/style/4nk.css @@ -83,7 +83,7 @@ body { background: radial-gradient(circle, white, var(--primary-color)); /* background-color: #CFD8DC; */ display: flex; - justify-content: space-between; + justify-content: flex-end; align-items: center; color: #37474F; height: 9vh; @@ -99,9 +99,10 @@ body { display: inline-block; } .notification-bell, .burger-menu { - height: 20px; - width: 20px; - margin-right: 1rem; + z-index: 3; + height: 20px; + width: 20px; + margin-right: 1rem; } .notification-badge { position: absolute; @@ -144,6 +145,14 @@ body { } .brand-logo { + height: 100%; + width: 100vw; + align-content: center; + position: relative; + display: flex; + position: absolute; + align-items: center; + justify-content: center; text-align: center; font-size: 1.5em; font-weight: bold; diff --git a/src/components/header/header.html b/src/components/header/header.html new file mode 100644 index 0000000..d9bc330 --- /dev/null +++ b/src/components/header/header.html @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/src/components/header/header.js b/src/components/header/header.js new file mode 100644 index 0000000..eb8913c --- /dev/null +++ b/src/components/header/header.js @@ -0,0 +1,60 @@ +import { currentRoute } from "../../router"; +import Services from "../../services/service"; + + +let notifications = [] + +export async function unpair() { + const service = await Services.getInstance(); + await service.unpairDevice(); + } + + window.unpair = unpair; + + function toggleMenu() { + const menu = document.getElementById('menu'); + if (menu.style.display === 'block') { + menu.style.display = 'none'; + } else { + menu.style.display = 'block'; + } + } + window.toggleMenu = toggleMenu + + async function getNotifications() { + const service = await Services.getInstance() + notifications = service.getNotifications() + console.log("πŸš€ ~ getNotifications ~ notifications:", notifications) + const badge = document.querySelector('.notification-badge') + if(badge) badge.innerHTML= notifications.length + } + function openCloseNotifications() { + const notifications = document.querySelector('.notification-board'); + console.log("πŸš€ ~ openCloseNotifications ~ notifications:", notifications) + notifications.style.display = notifications?.style.display === 'none' ? 'block' : 'none'; + } + + window.openCloseNotifications = openCloseNotifications + + + if(currentRoute === 'home') { + hideSomeFunctionnalities() + } else { + getNotifications() + } + + function hideSomeFunctionnalities() { + const bell = document.querySelector('.bell-icon') + if(bell) bell.style.display = 'none'; + const notifBadge = document.querySelector('.notification-badge') + if(notifBadge) notifBadge.style.display = 'none'; + const actions = document.querySelectorAll('.menu-content a') + console.log("πŸš€ ~ hideSomeFunctionnalities ~ actions:", actions) + for(const action of actions) { + console.log("πŸš€ ~ hideSomeFunctionnalities ~ action:", action) + if(action.innerHTML !== 'Import') { + action.style.display = 'none'; + } + } + + } \ No newline at end of file diff --git a/src/pages/home/home.html b/src/pages/home/home.html index cbd0572..a89fbf3 100644 --- a/src/pages/home/home.html +++ b/src/pages/home/home.html @@ -1,32 +1,4 @@ - -

Create Account / New Session

diff --git a/src/pages/process-element/process-element.html b/src/pages/process-element/process-element.html index f2f466e..d4589ea 100644 --- a/src/pages/process-element/process-element.html +++ b/src/pages/process-element/process-element.html @@ -1,35 +1,8 @@ - - -
-

Process {{processTitle}}

-
- -
-
+
+
diff --git a/src/pages/process-element/process-element.ts b/src/pages/process-element/process-element.ts index f891695..74dfdbd 100644 --- a/src/pages/process-element/process-element.ts +++ b/src/pages/process-element/process-element.ts @@ -1,20 +1,16 @@ -import Services from "../../services/service" - +import Services from '../../services/service'; let currentPageStyle: HTMLStyleElement | null = null; export async function initProcessElement(id: string, zone: string) { -console.log("πŸš€ ~ init ~ id:", id) -const processes = await getProcesses() -const currentProcess = processes.find(process => process[0] === id)[1] -console.log("πŸš€ ~ init ~ currentProcess:", currentProcess) -const test = await loadPage({processTitle: currentProcess.title, inputValue: 'Hello World !'}) -console.log("πŸš€ ~ initProcessElement ~ test:", currentProcess.html) -const wrapper = document.querySelector('.process-container') -if(wrapper) { - wrapper.innerHTML = interpolate(currentProcess.html, {processTitle: currentProcess.title, inputValue: 'Hello World !'}) - injectCss(currentProcess.css) -} + const processes = await getProcesses(); + const currentProcess = processes.find((process) => process[0] === id)[1]; + await loadPage({ processTitle: currentProcess.title, inputValue: 'Hello World !' }); + const wrapper = document.querySelector('.process-container'); + if (wrapper) { + wrapper.innerHTML = interpolate(currentProcess.html, { processTitle: currentProcess.title, inputValue: 'Hello World !' }); + injectCss(currentProcess.css); + } } function interpolate(template: string, data: { [key: string]: string }) { @@ -48,8 +44,6 @@ function removeCss() { async function getProcesses(): Promise { const service = await Services.getInstance(); - const processes = await service.getProcesses() - console.log("πŸš€ ~ Services ~ getProcesses ~ processes:", processes) - - return processes + const processes = await service.getProcesses(); + return processes; } diff --git a/src/pages/process/process.html b/src/pages/process/process.html index c795975..f57062c 100644 --- a/src/pages/process/process.html +++ b/src/pages/process/process.html @@ -1,49 +1,22 @@ - - -
-

Process Selection

-
- -
-
-
-
- - -
-
-
-
-
-
- OK -
-
+
+

Process Selection

+
+ +
+
+
+
+ + +
+
+
+
+
+
+ OK +
+
diff --git a/src/pages/process/process.ts b/src/pages/process/process.ts index 2cb80ed..924e7ce 100644 --- a/src/pages/process/process.ts +++ b/src/pages/process/process.ts @@ -1,14 +1,5 @@ import { navigate } from '../../router'; import Services from '../../services/service'; -import { IProcess } from '~/models/process.model'; -function toggleMenu() { - const menu = document.getElementById('menu') as HTMLDivElement; - if (menu.style.display === 'block') { - menu.style.display = 'none'; - } else { - menu.style.display = 'block'; - } -} // Initialize function, create initial tokens with itens that are already selected by the user export async function init() { @@ -40,13 +31,12 @@ export async function init() { search_div.appendChild(autocomplete_list); search_div.appendChild(dropdown_icon); - const processes = await getProcesses(); - for(let process of processes) { + for (let process of processes) { const processName = process[1].title; - const opt = new Option(processName) - opt.value = processName - element.add(opt) + const opt = new Option(processName); + opt.value = processName; + element.add(opt); } // set the wrapper as child (instead of the element) element.parentNode?.replaceChild(wrapper, element); @@ -153,7 +143,6 @@ function clickDropdown(e: Event) { dropdown.classList.toggle('active'); if (dropdown.classList.contains('active')) { - removePlaceholder(wrapper as HTMLElement); input_search?.focus(); @@ -179,7 +168,7 @@ function clearAutocompleteList(select: HTMLSelectElement) { // Populate the autocomplete list following a given query from the user function populateAutocompleteList(select: HTMLSelectElement, query: string, dropdown = false) { const { autocomplete_options } = getOptions(select); - console.log("πŸš€ ~ populateAutocompleteList ~ autocomplete_options:", autocomplete_options) + console.log('πŸš€ ~ populateAutocompleteList ~ autocomplete_options:', autocomplete_options); let options_to_show; @@ -220,12 +209,12 @@ function populateAutocompleteList(select: HTMLSelectElement, query: string, drop // Listener to autocomplete results when clicked set the selected property in the select option function selectOption(e: any) { - console.log("πŸš€ ~ selectOption ~ e:", e) + console.log('πŸš€ ~ selectOption ~ e:', e); const wrapper = e.target.parentNode.parentNode.parentNode; const input_search = wrapper.querySelector('.selected-input'); const option = wrapper.querySelector(`select option[value="${e.target.dataset.value}"]`); - console.log("πŸš€ ~ selectOption ~ option:", option) + console.log('πŸš€ ~ selectOption ~ option:', option); option.setAttribute('selected', ''); createToken(wrapper, e.target.dataset.value); if (input_search.value) { @@ -337,13 +326,6 @@ function deletePressed(e: KeyboardEvent) { return true; } -// function addOption(target, val, text) { -// const select = document.querySelector(target); -// let opt = document.createElement("option"); -// opt.value = val; -// opt.innerHTML = text; -// select.appendChild(opt); -// } // Dismiss on outside click document.addEventListener('click', () => { // get select that has the options available @@ -365,13 +347,6 @@ document.addEventListener('click', () => { } }); -export async function unpair() { - const service = await Services.getInstance(); - await service.unpairDevice(); -} - -(window as any).unpair = unpair; - async function showSelectedProcess(elem: MouseEvent) { if (elem) { const cardContent = document.querySelector('.process-card-content'); @@ -396,7 +371,7 @@ async function showSelectedProcess(elem: MouseEvent) { zoneElement.innerHTML = `${zone.title}: ${zone.description}`; const service = await Services.getInstance(); // service.addSubscription(zoneElement, 'click', 'goToProcessPage'); - zoneElement.addEventListener('click', select) + zoneElement.addEventListener('click', select); processDiv.appendChild(zoneElement); } if (cardContent) cardContent.appendChild(processDiv); @@ -406,32 +381,32 @@ async function showSelectedProcess(elem: MouseEvent) { function select(event: MouseEvent) { const target = event.target as HTMLElement; - const oldSelectedProcess = document.querySelector('.selected-process-zone') - oldSelectedProcess?.classList.remove('selected-process-zone') - if(target) { - target.classList.add('selected-process-zone') + const oldSelectedProcess = document.querySelector('.selected-process-zone'); + oldSelectedProcess?.classList.remove('selected-process-zone'); + if (target) { + target.classList.add('selected-process-zone'); } - const name = target.getAttribute('zone-id') - console.log("πŸš€ ~ select ~ name:", name) + const name = target.getAttribute('zone-id'); + console.log('πŸš€ ~ select ~ name:', name); } function goToProcessPage() { const target = document.querySelector('.selected-process-zone'); - console.log("πŸš€ ~ goToProcessPage ~ event:", target) - if(target) { + console.log('πŸš€ ~ goToProcessPage ~ event:', target); + if (target) { const process = target?.getAttribute('process-id'); console.log('=======================> going to process page', process); - navigate('process-element/' + process) + navigate('process-element/' + process); } } -(window as any).goToProcessPage = goToProcessPage +(window as any).goToProcessPage = goToProcessPage; async function getProcesses(): Promise { const service = await Services.getInstance(); - const processes = await service.getProcesses() - console.log("πŸš€ ~ Services ~ getProcesses ~ processes:", processes) - - return processes + const processes = await service.getProcesses(); + console.log('πŸš€ ~ Services ~ getProcesses ~ processes:', processes); + + return processes; } diff --git a/src/router.ts b/src/router.ts index ef90ed9..2c2014b 100644 --- a/src/router.ts +++ b/src/router.ts @@ -7,12 +7,12 @@ const routes: { [key: string]: string } = { 'process-element': '/src/pages/process-element/process-element.html', }; -export let currentRoute = '' +export let currentRoute = ''; export async function navigate(path: string) { path = path.replace(/^\//, ''); - if(path.includes('/')) { - const parsedPath = path.split('/')[0] + if (path.includes('/')) { + const parsedPath = path.split('/')[0]; if (!routes[parsedPath]) { path = 'home'; } @@ -22,10 +22,9 @@ export async function navigate(path: string) { } async function handleLocation(path: string) { - console.log("πŸš€ ~ handleLocation ~ path:", path) - const parsedPath = path.split('/') - if(path.includes('/')) { - path = parsedPath[0] + const parsedPath = path.split('/'); + if (path.includes('/')) { + path = parsedPath[0]; } const routeHtml = routes[path] || routes['home']; @@ -33,23 +32,23 @@ async function handleLocation(path: string) { if (content) { const html = await fetch(routeHtml).then((data) => data.text()); content.innerHTML = html; - await new Promise(requestAnimationFrame); + injectHeader(); if (path === 'home') { const { initHomePage } = await import('./pages/home/home'); initHomePage(); } else if (path === 'process') { const { init } = await import('./pages/process/process'); - init() - } else if(path.includes('process-element')) { + init(); + } else if (path.includes('process-element')) { const { initProcessElement } = await import('./pages/process-element/process-element'); - if(parsedPath && parsedPath.length) { - const parseProcess = parsedPath[1].split('_') - initProcessElement(parseProcess[0], parseProcess[1]) + if (parsedPath && parsedPath.length) { + const parseProcess = parsedPath[1].split('_'); + initProcessElement(parseProcess[0], parseProcess[1]); } } - currentRoute = path + currentRoute = path; } } @@ -71,20 +70,20 @@ async function init(): Promise { await services.restoreProcesses(); await services.restoreMessages(); - // if (services.isPaired()) { - // isPaired = true; - // console.log('πŸš€ ~ setTimeout ~ isPaired:', isPaired); - // await navigate('process'); - // return isPaired; - // } else { - // const queryString = window.location.search; - // const urlParams = new URLSearchParams(queryString); - // const pairingAddress = urlParams.get('sp_address'); - // if (pairingAddress) { - // setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000); - // } - // return isPaired; - // } + if (services.isPaired()) { + isPaired = true; + console.log('πŸš€ ~ setTimeout ~ isPaired:', isPaired); + await navigate('process'); + return isPaired; + } else { + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const pairingAddress = urlParams.get('sp_address'); + if (pairingAddress) { + setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000); + } + return isPaired; + } }, 200); } catch (error) { console.error(error); @@ -93,8 +92,21 @@ async function init(): Promise { return isPaired; } +async function injectHeader() { + const headerContainer = document.getElementById('header-container'); + if (headerContainer) { + const headerHtml = await fetch('/src/components/header/header.html').then((res) => res.text()); + headerContainer.innerHTML = headerHtml; + + // Dynamically load the header JS + const script = document.createElement('script'); + script.src = '/src/components/header/header.js'; + script.type = 'module'; + document.head.appendChild(script); + } +} + (async () => { const isPaired = await init(); - console.log('πŸš€ ~ handleLocation ~ isPaired:', isPaired); - await navigate('process'); + await navigate('home'); })(); diff --git a/src/services/service.ts b/src/services/service.ts index d8eb583..65b67c4 100644 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -522,7 +522,7 @@ export default class Services { console.error('Services ~ Error:', e); } - if(currentRoute === 'home') { + if (currentRoute === 'home') { this.generateQRCode(spAddress || ''); //Adress to Emoji integration this.displayEmojis(spAddress); @@ -535,7 +535,7 @@ export default class Services { try { await this.sdkClient.restore_device(device); const spAddress = this.sdkClient.get_address(); - if(currentRoute === 'home') { + if (currentRoute === 'home') { this.generateQRCode(spAddress || ''); //Adress to Emoji integration this.displayEmojis(spAddress); @@ -548,69 +548,78 @@ export default class Services { async getProcesses(): Promise { const process = [ - ['1',{ - title: 'Messaging', - description: 'Messagerie chiffrΓ©e', - html: '
', - css: '', - script: '', - zones: [{ - id: '1', - title: 'zone 1', - description: 'zone 1' - }, + [ + '1', { - id: '2', - title: 'zone 2', - description: 'zone 2' - }], - roles: { - owner: { - members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'], - validation_rules: [ - { - quorum: 1.0, - fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'], - min_sig_member: 1.0, - }, - ], + title: 'Messaging', + description: 'Messagerie chiffrΓ©e', + html: '
', + css: '', + script: '', + zones: [ + { + id: '1', + title: 'zone 1', + description: 'zone 1', + }, + { + id: '2', + title: 'zone 2', + description: 'zone 2', + }, + ], + roles: { + owner: { + members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'], + validation_rules: [ + { + quorum: 1.0, + fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'], + min_sig_member: 1.0, + }, + ], + }, }, }, - }], - ['2',{ - title: 'Database', - description: 'Database chiffrΓ©e', - html: '
', - css: '', - script: '', - zones: [{ - id: '1', - title: 'zone 1', - description: 'zone 1' - }, + ], + [ + '2', { - id: '2', - title: 'zone 2', - description: 'zone 2' - }], - roles: { - owner: { - members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'], - validation_rules: [ - { - quorum: 1.0, - fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'], - min_sig_member: 1.0, - }, - ], + title: 'Database', + description: 'Database chiffrΓ©e', + html: '
', + css: '', + script: '', + zones: [ + { + id: '1', + title: 'zone 1', + description: 'zone 1', + }, + { + id: '2', + title: 'zone 2', + description: 'zone 2', + }, + ], + roles: { + owner: { + members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'], + validation_rules: [ + { + quorum: 1.0, + fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'], + min_sig_member: 1.0, + }, + ], + }, }, }, - }], + ], ]; - return process + return process; } - private getProcessesCache(): ProcessesCache { // Regular expression to match 64-character hexadecimal strings const hexU32KeyRegex: RegExp = /^[0-9a-fA-F]{64}:\d+$/; @@ -709,7 +718,7 @@ export default class Services { } public async setProcessesInSelectElement(processList: any[]) { - console.log("πŸš€ ~ Services ~ setProcessesInSelectElement ~ processList:", processList) + console.log('πŸš€ ~ Services ~ setProcessesInSelectElement ~ processList:', processList); const select = document.querySelector('.select-field'); if (select) { for (const process of processList) {