Updated the process and process-element page
This commit is contained in:
parent
465a4a3c18
commit
614569f5aa
@ -1,12 +1,12 @@
|
||||
import processHtml from './process-element.html?raw';
|
||||
import processScript from './process-element.ts?raw';
|
||||
import processCss from '../../4nk.css?raw';
|
||||
import { initProcessElement } from './process-element';
|
||||
// src/pages/process-element/process-component.ts
|
||||
|
||||
export class ProcessListComponent extends HTMLElement {
|
||||
import processHtml from './process-element.html?raw';
|
||||
import processCss from '../../4nk.css?raw';
|
||||
import { initProcessElement } from './process-element'; // On importe la vraie fonction
|
||||
|
||||
// 1. Nom de classe corrigé (plus logique)
|
||||
export class ProcessElementComponent extends HTMLElement {
|
||||
_callback: any;
|
||||
id: string = '';
|
||||
zone: string = '';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@ -14,38 +14,61 @@ export class ProcessListComponent extends HTMLElement {
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
console.log('CALLBACK PROCESS LIST PAGE');
|
||||
this.render();
|
||||
setTimeout(() => {
|
||||
initProcessElement(this.id, this.zone);
|
||||
}, 500);
|
||||
}
|
||||
console.log('[ProcessElementComponent] 1. Composant connecté.');
|
||||
|
||||
// 2. Lire les attributs passés par le routeur (router.ts)
|
||||
const processId = this.getAttribute('process-id');
|
||||
const stateId = this.getAttribute('state-id');
|
||||
|
||||
set callback(fn) {
|
||||
if (typeof fn === 'function') {
|
||||
this._callback = fn;
|
||||
} else {
|
||||
console.error('Callback is not a function');
|
||||
if (!processId || !stateId) {
|
||||
console.error("💥 ProcessElementComponent a été créé sans 'process-id' ou 'state-id'.");
|
||||
this.renderError("Erreur: ID de processus ou d'état manquant.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Afficher le HTML/CSS du squelette
|
||||
this.render();
|
||||
|
||||
// 4. Appeler la logique (init) en lui passant le shadowRoot et les IDs
|
||||
try {
|
||||
if (this.shadowRoot) {
|
||||
console.log(`[ProcessElementComponent] 2. Appel de initProcessElement pour ${processId}_${stateId}`);
|
||||
initProcessElement(this.shadowRoot, processId, stateId);
|
||||
} else {
|
||||
console.error("[ProcessElementComponent] 💥 ShadowRoot est nul.");
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[ProcessElementComponent] 💥 Échec de l'initProcessElement():", e);
|
||||
}
|
||||
}
|
||||
|
||||
get callback() {
|
||||
return this._callback;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.shadowRoot)
|
||||
if (this.shadowRoot) {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
${processCss}
|
||||
</style>${processHtml}
|
||||
<script type="module">
|
||||
${processScript}
|
||||
</scipt>
|
||||
<style>${processCss}</style>
|
||||
${processHtml}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
renderError(message: string) {
|
||||
if (this.shadowRoot) {
|
||||
this.shadowRoot.innerHTML = `<style>${processCss}</style>
|
||||
<div class="title-container"><h1>Erreur</h1></div>
|
||||
<div class="process-container"><p>${message}</p></div>`;
|
||||
}
|
||||
}
|
||||
|
||||
// ... (Tes callbacks) ...
|
||||
set callback(fn) {
|
||||
if (typeof fn === 'function') { this._callback = fn; }
|
||||
else { console.error('Callback is not a function'); }
|
||||
}
|
||||
get callback() { return this._callback; }
|
||||
}
|
||||
|
||||
// 6. Utilisation du bon nom de classe
|
||||
if (!customElements.get('process-4nk-component')) {
|
||||
customElements.define('process-4nk-component', ProcessListComponent);
|
||||
}
|
||||
console.log('[ProcessElementComponent] Définition de <process-4nk-component>.');
|
||||
customElements.define('process-4nk-component', ProcessElementComponent);
|
||||
}
|
||||
@ -1,50 +1,111 @@
|
||||
// src/pages/process-element/process-element.ts
|
||||
|
||||
import { interpolate } from '../../utils/html.utils';
|
||||
import Services from '../../services/service';
|
||||
import { Process } from 'pkg/sdk_client';
|
||||
import { getCorrectDOM } from '~/utils/document.utils';
|
||||
import { Process, ProcessState } from 'pkg/sdk_client';
|
||||
// 1. Plus besoin de 'getCorrectDOM'
|
||||
|
||||
let currentPageStyle: HTMLStyleElement | null = null;
|
||||
/**
|
||||
* Fonction d'initialisation, appelée par process-component.ts
|
||||
* Reçoit le shadowRoot et les IDs.
|
||||
*/
|
||||
export async function initProcessElement(container: ShadowRoot, processId: string, stateId: string) {
|
||||
console.log(`[process-element.ts] 3. init() appelé pour ${processId}_${stateId}`);
|
||||
|
||||
const services = await Services.getInstance();
|
||||
|
||||
export async function initProcessElement(id: string, zone: string) {
|
||||
const processes = await getProcesses();
|
||||
const container = getCorrectDOM('process-4nk-component');
|
||||
// const currentProcess = processes.find((process) => process[0] === id)[1];
|
||||
// const currentProcess = {title: 'Hello', html: '', css: ''};
|
||||
// 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);
|
||||
// }
|
||||
// 2. Récupérer les éléments du DOM *dans* le shadowRoot (container)
|
||||
const titleH1 = container.querySelector('h1');
|
||||
const processContainer = container.querySelector('.process-container');
|
||||
|
||||
if (!titleH1 || !processContainer) {
|
||||
console.error("[process-element.ts] 💥 Le HTML de base (h1 ou .process-container) est introuvable !");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Récupérer les données
|
||||
const process = await services.getProcess(processId);
|
||||
if (!process) {
|
||||
console.error(`[process-element.ts] 💥 Processus ${processId} non trouvé !`);
|
||||
titleH1.innerText = "Erreur";
|
||||
processContainer.innerHTML = `<p>Le processus ${processId} n'a pas pu être chargé.</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
const state = services.getStateFromId(process, stateId);
|
||||
if (!state) {
|
||||
console.error(`[process-element.ts] 💥 État ${stateId} non trouvé dans le processus ${processId} !`);
|
||||
titleH1.innerText = "Erreur";
|
||||
processContainer.innerHTML = `<p>L'état ${stateId} n'a pas pu être chargé.</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[process-element.ts] ✅ Processus et État chargés.");
|
||||
|
||||
// 4. Mettre à jour le titre
|
||||
const processName = services.getProcessName(process) || "Processus";
|
||||
titleH1.innerHTML = interpolate(titleH1.innerHTML, { processTitle: processName });
|
||||
|
||||
// 5. Logique de rendu de l'élément (À COMPLÉTER PAR TES SOINS)
|
||||
// C'est là que tu dois construire le HTML pour cet état spécifique
|
||||
// Par exemple, déchiffrer les attributs et les afficher.
|
||||
processContainer.innerHTML = `
|
||||
<div class="card" style="margin: 1rem; padding: 1rem;">
|
||||
<h3>État: ${stateId.substring(0, 10)}...</h3>
|
||||
<p>Commit: ${state.commited_in}</p>
|
||||
<div id="attributes-list">
|
||||
<p><em>Chargement des attributs...</em></p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 6. Tenter de déchiffrer les données de cet état
|
||||
await decryptAndDisplayAttributes(services, container, processId, state);
|
||||
}
|
||||
|
||||
async function loadPage(data?: any) {
|
||||
const content = document.getElementById('containerId');
|
||||
if (content && data) {
|
||||
if (data) {
|
||||
content.innerHTML = interpolate(content.innerHTML, data);
|
||||
/**
|
||||
* Helper (exemple) pour déchiffrer et afficher les données dans le conteneur
|
||||
*/
|
||||
async function decryptAndDisplayAttributes(services: Services, container: ShadowRoot, processId: string, state: ProcessState) {
|
||||
const attributesList = container.querySelector('#attributes-list');
|
||||
if (!attributesList) return;
|
||||
|
||||
console.log(`[process-element.ts] 🔐 Déchiffrement des attributs pour l'état ${state.state_id}...`);
|
||||
attributesList.innerHTML = ''; // Vide le message "Chargement..."
|
||||
let hasPrivateData = false;
|
||||
|
||||
// Affiche les données publiques
|
||||
if (state.public_data) {
|
||||
for (const [key, value] of Object.entries(state.public_data)) {
|
||||
const el = document.createElement('div');
|
||||
el.className = 'attribute-pair public';
|
||||
el.innerHTML = `<strong>${key} (public):</strong> ${JSON.stringify(services.decodeValue(value))}`;
|
||||
attributesList.appendChild(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function injectCss(cssContent: string) {
|
||||
removeCss(); // Ensure that the previous CSS is removed
|
||||
|
||||
currentPageStyle = document.createElement('style');
|
||||
currentPageStyle.type = 'text/css';
|
||||
currentPageStyle.appendChild(document.createTextNode(cssContent));
|
||||
document.head.appendChild(currentPageStyle);
|
||||
}
|
||||
|
||||
function removeCss() {
|
||||
if (currentPageStyle) {
|
||||
document.head.removeChild(currentPageStyle);
|
||||
currentPageStyle = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getProcesses(): Promise<Record<string, Process>> {
|
||||
const service = await Services.getInstance();
|
||||
const processes = await service.getProcesses();
|
||||
return processes;
|
||||
}
|
||||
// Affiche les données privées
|
||||
for (const attribute of Object.keys(state.pcd_commitment)) {
|
||||
if (attribute === 'roles' || (state.public_data && state.public_data[attribute])) {
|
||||
continue; // Skip les données publiques (déjà fait) et les rôles
|
||||
}
|
||||
|
||||
const decryptedValue = await services.decryptAttribute(processId, state, attribute);
|
||||
|
||||
const el = document.createElement('div');
|
||||
el.className = 'attribute-pair private';
|
||||
|
||||
if (decryptedValue) {
|
||||
hasPrivateData = true;
|
||||
el.innerHTML = `<strong>${attribute} (privé):</strong> ${JSON.stringify(decryptedValue)}`;
|
||||
} else {
|
||||
el.innerHTML = `<strong>${attribute} (privé):</strong> <span style="color: red;">[Déchiffrement impossible / Clé manquante]</span>`;
|
||||
}
|
||||
attributesList.appendChild(el);
|
||||
}
|
||||
|
||||
if (!hasPrivateData && !(state.public_data && Object.keys(state.public_data).length > 0)) {
|
||||
console.log("[process-element.ts] ℹ️ Aucun attribut (public ou privé) trouvé pour cet état.");
|
||||
attributesList.innerHTML = '<p>Cet état ne contient aucun attribut visible.</p>';
|
||||
}
|
||||
}
|
||||
@ -1,49 +1,40 @@
|
||||
// import processHtml from './process.html?raw';
|
||||
// import processScript from './process.ts?raw';
|
||||
// import processCss from '../../4nk.css?raw';
|
||||
// import { init } from './process';
|
||||
// src/pages/process/process-list-component.ts
|
||||
|
||||
// export class ProcessListComponent extends HTMLElement {
|
||||
// _callback: any;
|
||||
// constructor() {
|
||||
// super();
|
||||
// this.attachShadow({ mode: 'open' });
|
||||
// }
|
||||
import processHtml from './process.html?raw';
|
||||
import processCss from '../../4nk.css?raw';
|
||||
import { init } from './process';
|
||||
|
||||
// connectedCallback() {
|
||||
// console.log('CALLBACK PROCESS LIST PAGE');
|
||||
// this.render();
|
||||
// setTimeout(() => {
|
||||
// init();
|
||||
// }, 500);
|
||||
// }
|
||||
export class ProcessListComponent extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
// set callback(fn) {
|
||||
// if (typeof fn === 'function') {
|
||||
// this._callback = fn;
|
||||
// } else {
|
||||
// console.error('Callback is not a function');
|
||||
// }
|
||||
// }
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
|
||||
// get callback() {
|
||||
// return this._callback;
|
||||
// }
|
||||
try {
|
||||
if (this.shadowRoot) {
|
||||
init(this.shadowRoot);
|
||||
} else {
|
||||
console.error('[ProcessListComponent] 💥 ShadowRoot est nul.');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[ProcessListComponent] 💥 Échec de l'init():", e);
|
||||
}
|
||||
}
|
||||
|
||||
// render() {
|
||||
// if (this.shadowRoot)
|
||||
// this.shadowRoot.innerHTML = `
|
||||
// <style>
|
||||
// ${processCss}
|
||||
// </style>${processHtml}
|
||||
// <script type="module">
|
||||
// ${processScript}
|
||||
// </scipt>
|
||||
|
||||
// `;
|
||||
// }
|
||||
// }
|
||||
render() {
|
||||
if (this.shadowRoot) {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>${processCss}</style>
|
||||
${processHtml}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// if (!customElements.get('process-list-4nk-component')) {
|
||||
// customElements.define('process-list-4nk-component', ProcessListComponent);
|
||||
// }
|
||||
}
|
||||
|
||||
if (!customElements.get('process-list-4nk-component')) {
|
||||
customElements.define('process-list-4nk-component', ProcessListComponent);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<!-- <div class="title-container">
|
||||
<div class="title-container">
|
||||
<h1>Process Selection</h1>
|
||||
</div>
|
||||
|
||||
@ -7,13 +7,17 @@
|
||||
<div class="process-card-description">
|
||||
<div class="input-container">
|
||||
<select multiple data-multi-select-plugin id="autocomplete" placeholder="Filter processes..." class="select-field"></select>
|
||||
|
||||
<label for="autocomplete" class="input-label">Filter processes :</label>
|
||||
|
||||
<div class="selected-processes"></div>
|
||||
</div>
|
||||
|
||||
<div class="process-card-content"></div>
|
||||
</div>
|
||||
|
||||
<div class="process-card-action">
|
||||
<a class="btn" onclick="goToProcessPage()">OK</a>
|
||||
<a class="btn" id="go-to-process-btn">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
@ -1,520 +1,486 @@
|
||||
// import { addSubscription } from '../../utils/subscription.utils';
|
||||
// import Services from '../../services/service';
|
||||
// import { getCorrectDOM } from '~/utils/html.utils';
|
||||
// import { Process } from 'pkg/sdk_client';
|
||||
// import chatStyle from '../../../public/style/chat.css?inline';
|
||||
// import { Database } from '../../services/database.service';
|
||||
// src/pages/process/process.ts
|
||||
|
||||
// // Initialize function, create initial tokens with itens that are already selected by the user
|
||||
// export async function init() {
|
||||
|
||||
// const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
|
||||
// const element = container.querySelector('select') as HTMLSelectElement;
|
||||
// // Create div that wroaps all the elements inside (select, elements selected, search div) to put select inside
|
||||
// const wrapper = document.createElement('div');
|
||||
// if (wrapper) addSubscription(wrapper, 'click', clickOnWrapper);
|
||||
// wrapper.classList.add('multi-select-component');
|
||||
// wrapper.classList.add('input-field');
|
||||
import { addSubscription } from '../../utils/subscription.utils';
|
||||
import Services from '../../services/service';
|
||||
import { Process, ProcessState, UserDiff } from 'pkg/sdk_client';
|
||||
|
||||
// // Create elements of search
|
||||
// const search_div = document.createElement('div');
|
||||
// search_div.classList.add('search-container');
|
||||
// const input = document.createElement('input');
|
||||
// input.classList.add('selected-input');
|
||||
// input.setAttribute('autocomplete', 'off');
|
||||
// input.setAttribute('tabindex', '0');
|
||||
// if (input) {
|
||||
// addSubscription(input, 'keyup', inputChange);
|
||||
// addSubscription(input, 'keydown', deletePressed);
|
||||
// addSubscription(input, 'click', openOptions);
|
||||
// }
|
||||
// On garde une référence aux éléments du DOM pour ne pas les chercher partout
|
||||
let shadowContainer: ShadowRoot;
|
||||
let services: Services;
|
||||
let wrapper: HTMLElement;
|
||||
let select: HTMLSelectElement;
|
||||
let inputSearch: HTMLInputElement;
|
||||
let autocompleteList: HTMLUListElement;
|
||||
let selectedProcessesContainer: HTMLElement;
|
||||
let processCardContent: HTMLElement;
|
||||
let okButton: HTMLElement;
|
||||
|
||||
// const dropdown_icon = document.createElement('a');
|
||||
// dropdown_icon.classList.add('dropdown-icon');
|
||||
/**
|
||||
* Fonction d'initialisation principale, appelée par le composant.
|
||||
*/
|
||||
export async function init(container: ShadowRoot) {
|
||||
console.log('[process.ts] 1. init() appelé.');
|
||||
|
||||
// if (dropdown_icon) addSubscription(dropdown_icon, 'click', clickDropdown);
|
||||
// const autocomplete_list = document.createElement('ul');
|
||||
// autocomplete_list.classList.add('autocomplete-list');
|
||||
// search_div.appendChild(input);
|
||||
// search_div.appendChild(autocomplete_list);
|
||||
// search_div.appendChild(dropdown_icon);
|
||||
// Stocke les références globales
|
||||
shadowContainer = container;
|
||||
services = await Services.getInstance();
|
||||
|
||||
// // set the wrapper as child (instead of the element)
|
||||
// element.parentNode?.replaceChild(wrapper, element);
|
||||
// // set element as child of wrapper
|
||||
// wrapper.appendChild(element);
|
||||
// wrapper.appendChild(search_div);
|
||||
const element = container.querySelector('select') as HTMLSelectElement;
|
||||
if (!element) {
|
||||
console.error("[process.ts] 💥 Échec de l'init: <select> introuvable dans process.html !");
|
||||
return;
|
||||
}
|
||||
|
||||
// addPlaceholder(wrapper);
|
||||
// }
|
||||
console.log('[process.ts] 2. <select> trouvé. Construction du DOM du multi-select...');
|
||||
|
||||
// function removePlaceholder(wrapper: HTMLElement) {
|
||||
// const input_search = wrapper.querySelector('.selected-input');
|
||||
// input_search?.removeAttribute('placeholder');
|
||||
// }
|
||||
// --- 1. Logique de Création du DOM (Ton code original, mais au bon endroit) ---
|
||||
const newWrapper = document.createElement('div');
|
||||
if (newWrapper) addSubscription(newWrapper, 'click', clickOnWrapper);
|
||||
newWrapper.classList.add('multi-select-component');
|
||||
newWrapper.classList.add('input-field');
|
||||
|
||||
// function addPlaceholder(wrapper: HTMLElement) {
|
||||
// const input_search = wrapper.querySelector('.selected-input');
|
||||
// const tokens = wrapper.querySelectorAll('.selected-wrapper');
|
||||
// if (!tokens.length && !(document.activeElement === input_search)) input_search?.setAttribute('placeholder', '---------');
|
||||
// }
|
||||
const search_div = document.createElement('div');
|
||||
search_div.classList.add('search-container');
|
||||
|
||||
// // Listener of user search
|
||||
// function inputChange(e: Event) {
|
||||
// const target = e.target as HTMLInputElement;
|
||||
// const wrapper = target?.parentNode?.parentNode;
|
||||
// const select = wrapper?.querySelector('select') as HTMLSelectElement;
|
||||
// const dropdown = wrapper?.querySelector('.dropdown-icon');
|
||||
const newInput = document.createElement('input');
|
||||
newInput.classList.add('selected-input');
|
||||
newInput.setAttribute('autocomplete', 'off');
|
||||
newInput.setAttribute('tabindex', '0');
|
||||
|
||||
// const input_val = target?.value;
|
||||
const dropdown_icon = document.createElement('a');
|
||||
dropdown_icon.classList.add('dropdown-icon');
|
||||
|
||||
// if (input_val) {
|
||||
// dropdown?.classList.add('active');
|
||||
// populateAutocompleteList(select, input_val.trim());
|
||||
// } else {
|
||||
// dropdown?.classList.remove('active');
|
||||
// const event = new Event('click');
|
||||
// dropdown?.dispatchEvent(event);
|
||||
// }
|
||||
// }
|
||||
const newAutocompleteList = document.createElement('ul');
|
||||
newAutocompleteList.classList.add('autocomplete-list');
|
||||
|
||||
// // Listen for clicks on the wrapper, if click happens focus on the input
|
||||
// function clickOnWrapper(e: Event) {
|
||||
// const wrapper = e.target as HTMLElement;
|
||||
// if (wrapper.tagName == 'DIV') {
|
||||
// const input_search = wrapper.querySelector('.selected-input');
|
||||
// const dropdown = wrapper.querySelector('.dropdown-icon');
|
||||
// if (!dropdown?.classList.contains('active')) {
|
||||
// const event = new Event('click');
|
||||
// dropdown?.dispatchEvent(event);
|
||||
// }
|
||||
// (input_search as HTMLInputElement)?.focus();
|
||||
// removePlaceholder(wrapper);
|
||||
// }
|
||||
// }
|
||||
search_div.appendChild(newInput);
|
||||
search_div.appendChild(newAutocompleteList);
|
||||
search_div.appendChild(dropdown_icon);
|
||||
|
||||
// function openOptions(e: Event) {
|
||||
// const input_search = e.target as HTMLElement;
|
||||
// const wrapper = input_search?.parentElement?.parentElement;
|
||||
// const dropdown = wrapper?.querySelector('.dropdown-icon');
|
||||
// if (!dropdown?.classList.contains('active')) {
|
||||
// const event = new Event('click');
|
||||
// dropdown?.dispatchEvent(event);
|
||||
// }
|
||||
// e.stopPropagation();
|
||||
// }
|
||||
// Remplace le <select> original par le 'wrapper'
|
||||
element.parentNode?.replaceChild(newWrapper, element);
|
||||
// Ajoute le <select> (caché) et la 'search_div' (visible) dans le wrapper
|
||||
newWrapper.appendChild(element);
|
||||
newWrapper.appendChild(search_div);
|
||||
console.log('[process.ts] 3. DOM du multi-select construit.');
|
||||
|
||||
// // Function that create a token inside of a wrapper with the given value
|
||||
// function createToken(wrapper: HTMLElement, value: any) {
|
||||
// const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
|
||||
// const search = wrapper.querySelector('.search-container');
|
||||
// const inputInderline = container.querySelector('.selected-processes');
|
||||
// // Create token wrapper
|
||||
// const token = document.createElement('div');
|
||||
// token.classList.add('selected-wrapper');
|
||||
// const token_span = document.createElement('span');
|
||||
// token_span.classList.add('selected-label');
|
||||
// token_span.innerText = value;
|
||||
// const close = document.createElement('a');
|
||||
// close.classList.add('selected-close');
|
||||
// close.setAttribute('tabindex', '-1');
|
||||
// close.setAttribute('data-option', value);
|
||||
// close.setAttribute('data-hits', '0');
|
||||
// close.innerText = 'x';
|
||||
// if (close) addSubscription(close, 'click', removeToken);
|
||||
// token.appendChild(token_span);
|
||||
// token.appendChild(close);
|
||||
// inputInderline?.appendChild(token);
|
||||
// }
|
||||
// --- 2. Sélection des éléments (Maintenant qu'ils existent) ---
|
||||
// Note: On utilise 'newWrapper' comme base pour être plus rapide
|
||||
wrapper = newWrapper;
|
||||
select = wrapper.querySelector('select') as HTMLSelectElement;
|
||||
inputSearch = wrapper.querySelector('.selected-input') as HTMLInputElement;
|
||||
autocompleteList = wrapper.querySelector('.autocomplete-list') as HTMLUListElement;
|
||||
|
||||
// // Listen for clicks in the dropdown option
|
||||
// function clickDropdown(e: Event) {
|
||||
// const dropdown = e.target as HTMLElement;
|
||||
// const wrapper = dropdown?.parentNode?.parentNode;
|
||||
// const input_search = wrapper?.querySelector('.selected-input') as HTMLInputElement;
|
||||
// const select = wrapper?.querySelector('select') as HTMLSelectElement;
|
||||
// dropdown.classList.toggle('active');
|
||||
// Ces éléments sont en dehors du wrapper, on utilise le 'shadowContainer'
|
||||
selectedProcessesContainer = shadowContainer.querySelector('.selected-processes') as HTMLElement;
|
||||
processCardContent = shadowContainer.querySelector('.process-card-content') as HTMLElement;
|
||||
okButton = shadowContainer.querySelector('#go-to-process-btn') as HTMLElement;
|
||||
|
||||
// if (dropdown.classList.contains('active')) {
|
||||
// removePlaceholder(wrapper as HTMLElement);
|
||||
// input_search?.focus();
|
||||
if (!wrapper || !select || !inputSearch || !autocompleteList || !okButton || !selectedProcessesContainer || !processCardContent) {
|
||||
console.error("[process.ts] 💥 Échec de l'init: Un ou plusieurs éléments DOM sont introuvables après la construction.", {
|
||||
wrapper,
|
||||
select,
|
||||
inputSearch,
|
||||
autocompleteList,
|
||||
okButton,
|
||||
selectedProcessesContainer,
|
||||
processCardContent,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!input_search?.value) {
|
||||
// populateAutocompleteList(select, '', true);
|
||||
// } else {
|
||||
// populateAutocompleteList(select, input_search.value);
|
||||
// }
|
||||
// } else {
|
||||
// clearAutocompleteList(select);
|
||||
// addPlaceholder(wrapper as HTMLElement);
|
||||
// }
|
||||
// }
|
||||
// --- 3. Attachement des Écouteurs ---
|
||||
addSubscription(inputSearch, 'keyup', inputChange);
|
||||
addSubscription(inputSearch, 'keydown', deletePressed);
|
||||
addSubscription(inputSearch, 'click', openOptions);
|
||||
addSubscription(dropdown_icon, 'click', clickDropdown);
|
||||
addSubscription(okButton, 'click', goToProcessPage);
|
||||
|
||||
// // Clears the results of the autocomplete list
|
||||
// function clearAutocompleteList(select: HTMLSelectElement) {
|
||||
// const wrapper = select.parentNode;
|
||||
// Gère le clic en dehors du composant
|
||||
addSubscription(document, 'click', (event: Event) => {
|
||||
const isClickInside = wrapper.contains(event.target as Node);
|
||||
if (!isClickInside) {
|
||||
closeAutocomplete();
|
||||
}
|
||||
});
|
||||
|
||||
// const autocomplete_list = wrapper?.querySelector('.autocomplete-list');
|
||||
// if (autocomplete_list) autocomplete_list.innerHTML = '';
|
||||
// }
|
||||
// --- 4. Initialisation de l'état ---
|
||||
addPlaceholder();
|
||||
|
||||
// async function populateAutocompleteList(select: HTMLSelectElement, query: string, dropdown = false) {
|
||||
// const { autocomplete_options } = getOptions(select);
|
||||
// Peuple la liste une première fois (elle sera vide, c'est OK)
|
||||
console.log('[process.ts] 4. Peuplement initial (probablement vide)...');
|
||||
await populateAutocompleteList('');
|
||||
|
||||
// let options_to_show = [];
|
||||
// S'abonne à l'événement de mise à jour du service
|
||||
console.log('[process.ts] 5. 🎧 Abonnement à l\'événement "processes-updated"');
|
||||
addSubscription(document, 'processes-updated', async () => {
|
||||
console.log('[process.ts] 🔔 Événement "processes-updated" reçu ! Re-population de la liste...');
|
||||
await populateAutocompleteList(inputSearch.value);
|
||||
});
|
||||
|
||||
// const service = await Services.getInstance();
|
||||
// const mineArray: string[] = await service.getMyProcesses();
|
||||
// const allProcesses = await service.getProcesses();
|
||||
// const allArray: string[] = Object.keys(allProcesses).filter(x => !mineArray.includes(x));
|
||||
console.log('[process.ts] 6. init() terminée. Le composant est prêt.');
|
||||
}
|
||||
|
||||
// const wrapper = select.parentNode;
|
||||
// const input_search = wrapper?.querySelector('.search-container');
|
||||
// const autocomplete_list = wrapper?.querySelector('.autocomplete-list');
|
||||
// if (autocomplete_list) autocomplete_list.innerHTML = '';
|
||||
// ==========================================
|
||||
// Fonctions de l'Autocomplete Multi-Select
|
||||
// (Toutes les fonctions ci-dessous sont des "helpers" pour init)
|
||||
// ==========================================
|
||||
|
||||
// const addProcessToList = (processId:string, isMine: boolean) => {
|
||||
// const li = document.createElement('li');
|
||||
// li.innerText = processId;
|
||||
// li.setAttribute("data-value", processId);
|
||||
function removePlaceholder() {
|
||||
inputSearch?.removeAttribute('placeholder');
|
||||
}
|
||||
|
||||
// if (isMine) {
|
||||
// li.classList.add("my-process");
|
||||
// li.style.cssText = `color: var(--accent-color)`;
|
||||
// }
|
||||
function addPlaceholder() {
|
||||
if (!selectedProcessesContainer) return; // Sécurité
|
||||
const tokens = selectedProcessesContainer.querySelectorAll('.selected-wrapper');
|
||||
|
||||
// if (li) addSubscription(li, 'click', selectOption);
|
||||
// autocomplete_list?.appendChild(li);
|
||||
// };
|
||||
if (!tokens?.length && document.activeElement !== inputSearch) {
|
||||
inputSearch?.setAttribute('placeholder', 'Filtrer les processus...');
|
||||
}
|
||||
}
|
||||
|
||||
// mineArray.forEach(processId => addProcessToList(processId, true));
|
||||
// allArray.forEach(processId => addProcessToList(processId, false));
|
||||
|
||||
// if (mineArray.length === 0 && allArray.length === 0) {
|
||||
// const li = document.createElement('li');
|
||||
// li.classList.add('not-cursor');
|
||||
// li.innerText = 'No options found';
|
||||
// autocomplete_list?.appendChild(li);
|
||||
// }
|
||||
// }
|
||||
function inputChange(e: Event) {
|
||||
const input_val = (e.target as HTMLInputElement).value;
|
||||
const dropdown = wrapper.querySelector('.dropdown-icon');
|
||||
|
||||
// // Listener to autocomplete results when clicked set the selected property in the select option
|
||||
// function selectOption(e: any) {
|
||||
// console.log('🎯 Click event:', e);
|
||||
// console.log('🎯 Target value:', e.target.dataset.value);
|
||||
|
||||
// const wrapper = e.target.parentNode.parentNode.parentNode;
|
||||
// const select = wrapper.querySelector('select');
|
||||
// const input_search = wrapper.querySelector('.selected-input');
|
||||
// const option = wrapper.querySelector(`select option[value="${e.target.dataset.value}"]`);
|
||||
|
||||
// console.log('🎯 Selected option:', option);
|
||||
// console.log('🎯 Process ID:', option?.getAttribute('data-process-id'));
|
||||
if (input_val) {
|
||||
dropdown?.classList.add('active');
|
||||
populateAutocompleteList(input_val.trim());
|
||||
} else {
|
||||
dropdown?.classList.remove('active');
|
||||
dropdown?.dispatchEvent(new Event('click'));
|
||||
}
|
||||
}
|
||||
|
||||
// if (e.target.dataset.value.includes('messaging')) {
|
||||
// const messagingNumber = parseInt(e.target.dataset.value.split(' ')[1]);
|
||||
// const processId = select.getAttribute(`data-messaging-id-${messagingNumber}`);
|
||||
|
||||
// console.log('🚀 Dispatching newMessagingProcess event:', {
|
||||
// processId,
|
||||
// processName: `Messaging Process ${processId}`
|
||||
// });
|
||||
function clickOnWrapper(e: Event) {
|
||||
// Ouvre la liste si on clique dans la zone vide du wrapper
|
||||
if (e.target === wrapper || e.target === selectedProcessesContainer) {
|
||||
openAutocomplete();
|
||||
}
|
||||
}
|
||||
|
||||
// // Dispatch l'événement avant la navigation
|
||||
// document.dispatchEvent(new CustomEvent('newMessagingProcess', {
|
||||
// detail: {
|
||||
// processId: processId,
|
||||
// processName: `Messaging Process ${processId}`
|
||||
// }
|
||||
// }));
|
||||
|
||||
// // Navigation vers le chat
|
||||
// const navigateEvent = new CustomEvent('navigate', {
|
||||
// detail: {
|
||||
// page: 'chat',
|
||||
// processId: processId || ''
|
||||
// }
|
||||
// });
|
||||
// document.dispatchEvent(navigateEvent);
|
||||
// return;
|
||||
// }
|
||||
// option.setAttribute('selected', '');
|
||||
// createToken(wrapper, e.target.dataset.value);
|
||||
// if (input_search.value) {
|
||||
// input_search.value = '';
|
||||
// }
|
||||
function openOptions(e: Event) {
|
||||
const dropdown = wrapper.querySelector('.dropdown-icon');
|
||||
if (!dropdown?.classList.contains('active')) {
|
||||
dropdown?.dispatchEvent(new Event('click'));
|
||||
}
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// showSelectedProcess(e.target.dataset.value);
|
||||
function createToken(processId: string, name: string) {
|
||||
const token = document.createElement('div');
|
||||
token.classList.add('selected-wrapper');
|
||||
token.setAttribute('data-process-id', processId); // Stocke l'ID
|
||||
|
||||
// input_search.focus();
|
||||
const tokenSpan = document.createElement('span');
|
||||
tokenSpan.classList.add('selected-label');
|
||||
tokenSpan.innerText = name; // Affiche le nom
|
||||
|
||||
// e.target.remove();
|
||||
// const autocomplete_list = wrapper.querySelector('.autocomplete-list');
|
||||
const close = document.createElement('a');
|
||||
close.classList.add('selected-close');
|
||||
close.innerText = 'x';
|
||||
close.setAttribute('data-process-id', processId); // Utilise l'ID pour la suppression
|
||||
addSubscription(close, 'click', removeToken);
|
||||
|
||||
// if (!autocomplete_list.children.length) {
|
||||
// const li = document.createElement('li');
|
||||
// li.classList.add('not-cursor');
|
||||
// li.innerText = 'No options found';
|
||||
// autocomplete_list.appendChild(li);
|
||||
// }
|
||||
token.appendChild(tokenSpan);
|
||||
token.appendChild(close);
|
||||
selectedProcessesContainer.appendChild(token);
|
||||
removePlaceholder();
|
||||
}
|
||||
|
||||
// const event = new Event('keyup');
|
||||
// input_search.dispatchEvent(event);
|
||||
// e.stopPropagation();
|
||||
// }
|
||||
function clickDropdown(e: Event) {
|
||||
const dropdown = e.currentTarget as HTMLElement;
|
||||
dropdown.classList.toggle('active');
|
||||
|
||||
// // function that returns a list with the autcomplete list of matches
|
||||
// function autocomplete(query: string, options: any) {
|
||||
// // No query passed, just return entire list
|
||||
// if (!query) {
|
||||
// return options;
|
||||
// }
|
||||
// let options_return = [];
|
||||
if (dropdown.classList.contains('active')) {
|
||||
openAutocomplete();
|
||||
} else {
|
||||
closeAutocomplete();
|
||||
}
|
||||
}
|
||||
|
||||
// for (let i = 0; i < options.length; i++) {
|
||||
// if (query.toLowerCase() === options[i].slice(0, query.length).toLowerCase()) {
|
||||
// options_return.push(options[i]);
|
||||
// }
|
||||
// }
|
||||
// return options_return;
|
||||
// }
|
||||
function openAutocomplete() {
|
||||
if (!wrapper || !inputSearch) return;
|
||||
const dropdown = wrapper.querySelector('.dropdown-icon');
|
||||
dropdown?.classList.add('active');
|
||||
removePlaceholder();
|
||||
inputSearch.focus();
|
||||
populateAutocompleteList(inputSearch.value);
|
||||
}
|
||||
|
||||
// // Returns the options that are selected by the user and the ones that are not
|
||||
// function getOptions(select: HTMLSelectElement) {
|
||||
// // Select all the options available
|
||||
// const all_options = Array.from(select.querySelectorAll('option')).map((el) => el.value);
|
||||
function closeAutocomplete() {
|
||||
if (!wrapper || !autocompleteList) return;
|
||||
const dropdown = wrapper.querySelector('.dropdown-icon');
|
||||
dropdown?.classList.remove('active');
|
||||
autocompleteList.innerHTML = '';
|
||||
addPlaceholder();
|
||||
}
|
||||
|
||||
// // Get the options that are selected from the user
|
||||
// const options_selected = Array.from(select.querySelectorAll('option:checked')).map((el: any) => el.value);
|
||||
function clearAutocompleteList() {
|
||||
if (autocompleteList) autocompleteList.innerHTML = '';
|
||||
}
|
||||
|
||||
// // Create an autocomplete options array with the options that are not selected by the user
|
||||
// const autocomplete_options: any[] = [];
|
||||
// all_options.forEach((option) => {
|
||||
// if (!options_selected.includes(option)) {
|
||||
// autocomplete_options.push(option);
|
||||
// }
|
||||
// });
|
||||
async function populateAutocompleteList(query: string) {
|
||||
if (!autocompleteList || !select) return; // Sécurité
|
||||
|
||||
// autocomplete_options.sort();
|
||||
autocompleteList.innerHTML = ''; // Vide la liste visible
|
||||
select.innerHTML = ''; // Vide le select caché
|
||||
|
||||
// return {
|
||||
// options_selected,
|
||||
// autocomplete_options,
|
||||
// };
|
||||
// }
|
||||
const mineArray: string[] = (await services.getMyProcesses()) ?? [];
|
||||
const allProcesses = await services.getProcesses();
|
||||
const allArray: string[] = Object.keys(allProcesses).filter((x) => !mineArray.includes(x));
|
||||
|
||||
// // Listener for when the user wants to remove a given token.
|
||||
// function removeToken(e: Event) {
|
||||
// // Get the value to remove
|
||||
// const target = e.target as HTMLSelectElement;
|
||||
// const value_to_remove = target.dataset.option;
|
||||
// const wrapper = target.parentNode?.parentNode?.parentNode;
|
||||
// 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}"]`);
|
||||
// option_to_unselect?.removeAttribute('selected');
|
||||
// // Remove token attribute
|
||||
// (target.parentNode as any)?.remove();
|
||||
// dropdown?.classList.remove('active');
|
||||
// const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
|
||||
const processIdsToShow = [...mineArray, ...allArray];
|
||||
let itemsFound = 0;
|
||||
|
||||
// const process = container.querySelector('#' + target.dataset.option);
|
||||
// process?.remove();
|
||||
// }
|
||||
for (const processId of processIdsToShow) {
|
||||
const process = allProcesses[processId];
|
||||
if (!process) continue;
|
||||
|
||||
// // Listen for 2 sequence of hits on the delete key, if this happens delete the last token if exist
|
||||
// function deletePressed(e: Event) {
|
||||
// const input_search = e.target as HTMLInputElement;
|
||||
// const wrapper = input_search?.parentNode?.parentNode;
|
||||
// const key = (e as KeyboardEvent).keyCode || (e as KeyboardEvent).charCode;
|
||||
// const tokens = wrapper?.querySelectorAll('.selected-wrapper');
|
||||
const name = services.getProcessName(process) || processId;
|
||||
|
||||
// if (tokens?.length) {
|
||||
// const last_token_x = tokens[tokens.length - 1].querySelector('a');
|
||||
// let hits = +(last_token_x?.dataset?.hits || 0);
|
||||
// Filtre
|
||||
if (query && !name.toLowerCase().includes(query.toLowerCase()) && !processId.includes(query)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (key == 8 || key == 46) {
|
||||
// if (!input_search.value) {
|
||||
// if (hits > 1) {
|
||||
// // Trigger delete event
|
||||
// const event = new Event('click');
|
||||
// last_token_x?.dispatchEvent(event);
|
||||
// } else {
|
||||
// if (last_token_x?.dataset.hits) last_token_x.dataset.hits = '2';
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if (last_token_x?.dataset.hits) last_token_x.dataset.hits = '0';
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
itemsFound++;
|
||||
|
||||
// // Dismiss on outside click
|
||||
// addSubscription(document, 'click', () => {
|
||||
// // get select that has the options available
|
||||
// const select = document.querySelectorAll('[data-multi-select-plugin]');
|
||||
// for (let i = 0; i < select.length; i++) {
|
||||
// if (event) {
|
||||
// var isClickInside = select[i].parentElement?.parentElement?.contains(event.target as Node);
|
||||
// 1. Crée l'élément VISIBLE (<li>)
|
||||
const li = document.createElement('li');
|
||||
li.innerText = name;
|
||||
li.setAttribute('data-value', processId); // L'ID est le 'data-value'
|
||||
if (mineArray.includes(processId)) {
|
||||
li.classList.add('my-process');
|
||||
li.style.cssText = `color: var(--accent-color)`;
|
||||
}
|
||||
addSubscription(li, 'click', selectOption);
|
||||
autocompleteList.appendChild(li);
|
||||
|
||||
// if (!isClickInside) {
|
||||
// const wrapper = select[i].parentElement?.parentElement;
|
||||
// const dropdown = wrapper?.querySelector('.dropdown-icon');
|
||||
// const autocomplete_list = wrapper?.querySelector('.autocomplete-list');
|
||||
// //the click was outside the specifiedElement, do something
|
||||
// dropdown?.classList.remove('active');
|
||||
// if (autocomplete_list) autocomplete_list.innerHTML = '';
|
||||
// addPlaceholder(wrapper as HTMLElement);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// 2. Crée l'élément CACHÉ (<option>)
|
||||
const option = document.createElement('option');
|
||||
option.value = processId; // 'value' correspond au 'data-value'
|
||||
option.text = name;
|
||||
option.setAttribute('data-process-id', processId);
|
||||
select.appendChild(option);
|
||||
}
|
||||
|
||||
// async function showSelectedProcess(elem: MouseEvent) {
|
||||
// const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
|
||||
if (itemsFound === 0) {
|
||||
const li = document.createElement('li');
|
||||
li.classList.add('not-cursor');
|
||||
li.innerText = 'No options found';
|
||||
autocompleteList.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
// if (elem) {
|
||||
// const cardContent = container.querySelector('.process-card-content');
|
||||
function selectOption(e: any) {
|
||||
console.log('🎯 Click event:', e);
|
||||
const selectedLi = e.currentTarget as HTMLLIElement; // Utilise currentTarget
|
||||
const clickedValue = selectedLi.dataset.value;
|
||||
console.log('🎯 Clicked value (depuis le <li>):', clickedValue);
|
||||
|
||||
// const processes = await getProcesses();
|
||||
// const process = processes.find((process: any) => process[1].title === elem);
|
||||
// if (process) {
|
||||
// const processDiv = document.createElement('div');
|
||||
// processDiv.className = 'process';
|
||||
// processDiv.id = process[0];
|
||||
// const titleDiv = document.createElement('div');
|
||||
// titleDiv.className = 'process-title';
|
||||
// titleDiv.innerHTML = `${process[1].title} : ${process[1].description}`;
|
||||
// processDiv.appendChild(titleDiv);
|
||||
// for (const zone of process.zones) {
|
||||
// const zoneElement = document.createElement('div');
|
||||
// zoneElement.className = 'process-element';
|
||||
// const zoneId = process[1].title + '-' + zone.id;
|
||||
// zoneElement.setAttribute('zone-id', zoneId);
|
||||
// zoneElement.setAttribute('process-title', process[1].title);
|
||||
// zoneElement.setAttribute('process-id', `${process[0]}_${zone.id}`);
|
||||
// zoneElement.innerHTML = `${zone.title}: ${zone.description}`;
|
||||
// addSubscription(zoneElement, 'click', select);
|
||||
// processDiv.appendChild(zoneElement);
|
||||
// }
|
||||
// if (cardContent) cardContent.appendChild(processDiv);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (!clickedValue) {
|
||||
console.error("💥 Clic sur un élément sans 'data-value'.");
|
||||
return;
|
||||
}
|
||||
|
||||
// function select(event: Event) {
|
||||
// const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
|
||||
// const target = event.target as HTMLElement;
|
||||
// const oldSelectedProcess = container.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 processIdValue = clickedValue; // C'est déjà le bon ID
|
||||
|
||||
// function goToProcessPage() {
|
||||
// const container = getCorrectDOM('process-list-4nk-component') as HTMLElement;
|
||||
// --- Gestion 'messaging' ---
|
||||
if (clickedValue.includes('messaging')) {
|
||||
// ... (ta logique 'messaging' reste ici) ...
|
||||
// Note: cette logique est probablement cassée si 'messaging' n'est pas un processId
|
||||
return;
|
||||
}
|
||||
|
||||
// const target = container.querySelector('.selected-process-zone');
|
||||
// console.log('🚀 ~ goToProcessPage ~ event:', target);
|
||||
// if (target) {
|
||||
// const process = target?.getAttribute('process-id');
|
||||
// --- 🚨 CORRECTION DU CRASH ---
|
||||
const option = select?.querySelector(`option[value="${processIdValue}"]`) as HTMLOptionElement;
|
||||
|
||||
// console.log('=======================> going to process page', process);
|
||||
// // navigate('process-element/' + process);
|
||||
// document.querySelector('process-list-4nk-component')?.dispatchEvent(
|
||||
// new CustomEvent('processSelected', {
|
||||
// detail: {
|
||||
// process: process,
|
||||
// },
|
||||
// }),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
if (!option) {
|
||||
console.error(`💥 BUG: Impossible de trouver l'option avec la valeur "${processIdValue}"`);
|
||||
return;
|
||||
}
|
||||
|
||||
// (window as any).goToProcessPage = goToProcessPage;
|
||||
option.setAttribute('selected', 'true');
|
||||
option.selected = true;
|
||||
|
||||
// async function createMessagingProcess(): Promise<void> {
|
||||
// console.log('Creating messaging process');
|
||||
// const service = await Services.getInstance();
|
||||
// const otherMembers = [
|
||||
// {
|
||||
// sp_addresses: [
|
||||
// "tsp1qqd7snxfh44am8f7a3x36znkh4v0dcagcgakfux488ghsg0tny7degq4gd9q4n4us0cyp82643f2p4jgcmtwknadqwl3waf9zrynl6n7lug5tg73a",
|
||||
// "tsp1qqvd8pak9fyz55rxqj90wxazqzwupf2egderc96cn84h3l84z8an9vql85scudrmwvsnltfuy9ungg7pxnhys2ft5wnf2gyr3n4ukvezygswesjuc"
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// sp_addresses: [
|
||||
// "tsp1qqgl5vawdey6wnnn2sfydcejsr06uzwsjlfa6p6yr8u4mkqwezsnvyqlazuqmxhxd8crk5eq3wfvdwv4k3tn68mkj2nj72jj39d2ngauu4unfx0q7",
|
||||
// "tsp1qqthmj56gj8vvkjzwhcmswftlrf6ye7ukpks2wra92jkehqzrvx7m2q570q5vv6zj6dnxvussx2h8arvrcfwz9sp5hpdzrfugmmzz90pmnganxk28"
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// sp_addresses: [
|
||||
// "tsp1qqwjtxr9jye7d40qxrsmd6h02egdwel6mfnujxzskgxvxphfya4e6qqjq4tsdmfdmtnmccz08ut24q8y58qqh4lwl3w8pvh86shlmavrt0u3smhv2",
|
||||
// "tsp1qqwn7tf8q2jhmfh8757xze53vg2zc6x5u6f26h3wyty9mklvcy0wnvqhhr4zppm5uyyte4y86kljvh8r0tsmkmszqqwa3ecf2lxcs7q07d56p8sz5"
|
||||
// ]
|
||||
// }
|
||||
// ];
|
||||
// await service.checkConnections(otherMembers);
|
||||
// const relayAddress = service.getAllRelays().pop();
|
||||
// if (!relayAddress) {
|
||||
// throw new Error('Empty relay address list');
|
||||
// }
|
||||
// const feeRate = 1;
|
||||
// setTimeout(async () => {
|
||||
// const createProcessReturn = await service.createMessagingProcess(otherMembers, relayAddress.spAddress, feeRate);
|
||||
// const updatedProcess = createProcessReturn.updated_process.current_process;
|
||||
// if (!updatedProcess) {
|
||||
// console.error('Failed to retrieved new messaging process');
|
||||
// return;
|
||||
// }
|
||||
// const processId = updatedProcess.states[0].commited_in;
|
||||
// const stateId = updatedProcess.states[0].state_id;
|
||||
// await service.handleApiReturn(createProcessReturn);
|
||||
// const createPrdReturn = await service.createPrdUpdate(processId, stateId);
|
||||
// await service.handleApiReturn(createPrdReturn);
|
||||
// const approveChangeReturn = await service.approveChange(processId, stateId);
|
||||
// await service.handleApiReturn(approveChangeReturn);
|
||||
// }, 500)
|
||||
// }
|
||||
createToken(processIdValue, option.text); // Passe l'ID et le nom
|
||||
if (inputSearch.value) {
|
||||
inputSearch.value = '';
|
||||
}
|
||||
|
||||
// async function getDescription(processId: string, process: Process): Promise<string | null> {
|
||||
// const service = await Services.getInstance();
|
||||
// // Get the `commited_in` value of the last state and remove it from the array
|
||||
// const currentCommitedIn = process.states.pop()?.commited_in;
|
||||
showSelectedProcess(processIdValue);
|
||||
|
||||
// if (currentCommitedIn === undefined) {
|
||||
// return null; // No states available
|
||||
// }
|
||||
inputSearch.focus();
|
||||
|
||||
// // Find the last state where `commited_in` is different
|
||||
// let lastDifferentState = process.states.findLast(
|
||||
// state => state.commited_in !== currentCommitedIn
|
||||
// );
|
||||
selectedLi.remove(); // Supprime le <li> de la liste des suggestions
|
||||
|
||||
// if (!lastDifferentState) {
|
||||
// // It means that we only have one state that is not commited yet, that can happen with process we just created
|
||||
// // let's assume that the right description is in the last concurrent state and not handle the (arguably rare) case where we have multiple concurrent states on a creation
|
||||
// lastDifferentState = process.states.pop();
|
||||
// }
|
||||
if (!autocompleteList?.children.length) {
|
||||
const li = document.createElement('li');
|
||||
li.classList.add('not-cursor');
|
||||
li.innerText = 'No options found';
|
||||
autocompleteList.appendChild(li);
|
||||
}
|
||||
|
||||
// // Take the description out of the state, if any
|
||||
// const description = lastDifferentState!.pcd_commitment['description'];
|
||||
// if (description) {
|
||||
// const userDiff = await service.getDiffByValue(description);
|
||||
// if (userDiff) {
|
||||
// console.log("Successfully retrieved userDiff:", userDiff);
|
||||
// return userDiff.new_value;
|
||||
// } else {
|
||||
// console.log("Failed to retrieve a non-null userDiff.");
|
||||
// }
|
||||
// }
|
||||
inputSearch.dispatchEvent(new Event('keyup'));
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
// return null;
|
||||
// }
|
||||
function removeToken(e: Event) {
|
||||
e.stopPropagation();
|
||||
|
||||
const closeButton = e.currentTarget as HTMLElement;
|
||||
const processId = closeButton.dataset.processId;
|
||||
|
||||
if (!processId) return;
|
||||
|
||||
// 1. Supprime le "token" visuel
|
||||
const token = shadowContainer.querySelector(`.selected-wrapper[data-process-id="${processId}"]`);
|
||||
token?.remove();
|
||||
|
||||
// 2. Désélectionne l'option dans le <select> caché
|
||||
const option = select?.querySelector(`option[value="${processId}"]`) as HTMLOptionElement;
|
||||
if (option) {
|
||||
option.removeAttribute('selected');
|
||||
option.selected = false;
|
||||
}
|
||||
|
||||
// 3. Vide le panneau de détails
|
||||
if (processCardContent) processCardContent.innerHTML = '';
|
||||
|
||||
// 4. Recharge la liste d'autocomplétion (pour y remettre l'option)
|
||||
populateAutocompleteList(inputSearch.value);
|
||||
addPlaceholder();
|
||||
}
|
||||
|
||||
function deletePressed(e: Event) {
|
||||
const key = (e as KeyboardEvent).keyCode || (e as KeyboardEvent).charCode;
|
||||
|
||||
if (!selectedProcessesContainer) return;
|
||||
const tokens = selectedProcessesContainer.querySelectorAll('.selected-wrapper');
|
||||
|
||||
if (tokens?.length) {
|
||||
const last_token_x = tokens[tokens.length - 1].querySelector('a');
|
||||
let hits = +(last_token_x?.dataset?.hits || 0);
|
||||
|
||||
if (key == 8 || key == 46) {
|
||||
// Backspace ou Suppr
|
||||
if (!inputSearch.value) {
|
||||
if (hits > 1) {
|
||||
last_token_x?.dispatchEvent(new Event('click'));
|
||||
} else {
|
||||
if (last_token_x?.dataset.hits) last_token_x.dataset.hits = '2';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (last_token_x?.dataset.hits) last_token_x.dataset.hits = '0';
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// Fonctions de Logique (Affichage)
|
||||
// ==========================================
|
||||
|
||||
async function showSelectedProcess(processIdValue: string) {
|
||||
const processId = processIdValue;
|
||||
// const processId = processIdValue.split(':')[0];
|
||||
|
||||
if (!processId || !processCardContent) return;
|
||||
|
||||
console.log(`[process.ts] 🔍 Affichage des détails pour: ${processId}`);
|
||||
processCardContent.innerHTML = ''; // Nettoie
|
||||
|
||||
const process = await services.getProcess(processId);
|
||||
if (process) {
|
||||
const processDiv = document.createElement('div');
|
||||
processDiv.className = 'process';
|
||||
processDiv.id = processId;
|
||||
|
||||
const titleDiv = document.createElement('div');
|
||||
titleDiv.className = 'process-title';
|
||||
const processName = services.getProcessName(process) || 'Processus sans nom';
|
||||
const description = await getDescription(process);
|
||||
titleDiv.innerHTML = `${processName} : ${description || 'Pas de description'}`;
|
||||
processDiv.appendChild(titleDiv);
|
||||
|
||||
const uncommittedStates = services.getUncommitedStates(process);
|
||||
if (uncommittedStates.length > 0) {
|
||||
for (const state of uncommittedStates) {
|
||||
const zoneElement = document.createElement('div');
|
||||
zoneElement.className = 'process-element';
|
||||
const zoneId = `${processId}_${state.state_id}`;
|
||||
zoneElement.setAttribute('zone-id', zoneId);
|
||||
zoneElement.setAttribute('process-id', zoneId);
|
||||
zoneElement.innerHTML = `État (non "commité"): ${state.state_id.substring(0, 10)}...`;
|
||||
addSubscription(zoneElement, 'click', selectState);
|
||||
processDiv.appendChild(zoneElement);
|
||||
}
|
||||
} else {
|
||||
const noStateSpan = document.createElement('span');
|
||||
noStateSpan.innerText = "Ce processus n'a pas d'état en attente.";
|
||||
processDiv.appendChild(noStateSpan);
|
||||
}
|
||||
processCardContent.appendChild(processDiv);
|
||||
} else {
|
||||
console.error(`[process.ts] 💥 Processus ${processId} non trouvé.`);
|
||||
processCardContent.innerHTML = '<span>Erreur: Processus non trouvé.</span>';
|
||||
}
|
||||
}
|
||||
|
||||
async function getProcesses(): Promise<[string, Process][]> {
|
||||
const processes = await services.getProcesses();
|
||||
const res = Object.entries(processes);
|
||||
return res;
|
||||
}
|
||||
|
||||
function selectState(event: Event) {
|
||||
const target = event.currentTarget as HTMLElement;
|
||||
const oldSelectedProcess = shadowContainer.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('[process.ts] 🎯 État sélectionné:', name);
|
||||
}
|
||||
|
||||
function goToProcessPage() {
|
||||
const target = shadowContainer.querySelector('.selected-process-zone');
|
||||
console.log('[process.ts] 🚀 Clic sur "OK". État sélectionné:', target);
|
||||
|
||||
if (target) {
|
||||
const process = target?.getAttribute('process-id');
|
||||
console.log('=======================> Navigation vers process-element', process);
|
||||
|
||||
// Dispatch l'événement 'navigate' que 'router.ts' écoute
|
||||
document.dispatchEvent(
|
||||
new CustomEvent('navigate', {
|
||||
detail: {
|
||||
page: `process-element/${process}`,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true, // Permet à l'événement de sortir du Shadow DOM
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
console.warn('[process.ts] ⚠️ Clic sur "OK" mais aucun état n\'est sélectionné.');
|
||||
}
|
||||
}
|
||||
|
||||
async function getDescription(process: Process): Promise<string | null> {
|
||||
const lastDifferentState = services.getLastCommitedState(process);
|
||||
if (!lastDifferentState) return null;
|
||||
|
||||
const descriptionHash = lastDifferentState!.pcd_commitment['description'];
|
||||
if (descriptionHash) {
|
||||
const userDiff = await services.getDiffByValue(descriptionHash);
|
||||
if (userDiff) {
|
||||
return userDiff.value_commitment; // Utilise le bon champ
|
||||
} else {
|
||||
console.warn(`[process.ts] Impossible de trouver le 'diff' pour la description (hash: ${descriptionHash})`);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user