Commented all files in /src/pages/account

This commit is contained in:
NicolasCantu 2025-11-04 23:02:39 +01:00
parent f78ed88cb1
commit dddbe04a2d
8 changed files with 1999 additions and 1999 deletions

View File

@ -1,20 +1,20 @@
import { SignatureComponent } from './pages/signature/signature-component'; import { SignatureComponent } from './pages/signature/signature-component';
import { SignatureElement } from './pages/signature/signature'; import { SignatureElement } from './pages/signature/signature';
/*import { ChatComponent } from './pages/chat/chat-component'; // import { ChatComponent } from './pages/chat/chat-component';
import { ChatElement } from './pages/chat/chat';*/ // import { ChatElement } from './pages/chat/chat';
import { AccountComponent } from './pages/account/account-component'; // import { AccountComponent } from './pages/account/account-component';
import { AccountElement } from './pages/account/account'; // import { AccountElement } from './pages/account/account';
export { SignatureComponent, SignatureElement, AccountComponent, AccountElement }; export { SignatureComponent, SignatureElement };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'signature-component': SignatureComponent; 'signature-component': SignatureComponent;
'signature-element': SignatureElement; 'signature-element': SignatureElement;
/*'chat-component': ChatComponent; // 'chat-component': ChatComponent;
'chat-element': ChatElement;*/ // 'chat-element': ChatElement;
'account-component': AccountComponent; // 'account-component': AccountComponent;
'account-element': AccountElement; // 'account-element': AccountElement;
} }
} }
@ -25,6 +25,6 @@ if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) {
customElements.define('signature-element', SignatureElement); customElements.define('signature-element', SignatureElement);
/*customElements.define('chat-component', ChatComponent); /*customElements.define('chat-component', ChatComponent);
customElements.define('chat-element', ChatElement);*/ customElements.define('chat-element', ChatElement);*/
customElements.define('account-component', AccountComponent); // customElements.define('account-component', AccountComponent);
customElements.define('account-element', AccountElement); // customElements.define('account-element', AccountElement);
} }

View File

@ -1,62 +1,62 @@
import { AccountElement } from './account'; // import { AccountElement } from './account';
import accountCss from '../../../public/style/account.css?raw'; // import accountCss from '../../../style/account.css?raw';
import Services from '../../services/service.js'; // import Services from '../../services/service.js';
class AccountComponent extends HTMLElement { // class AccountComponent extends HTMLElement {
_callback: any; // _callback: any;
accountElement: AccountElement | null = null; // accountElement: AccountElement | null = null;
constructor() { // constructor() {
super(); // super();
console.log('INIT'); // console.log('INIT');
this.attachShadow({ mode: 'open' }); // this.attachShadow({ mode: 'open' });
this.accountElement = this.shadowRoot?.querySelector('account-element') || null; // this.accountElement = this.shadowRoot?.querySelector('account-element') || null;
} // }
connectedCallback() { // connectedCallback() {
console.log('CALLBACKs'); // console.log('CALLBACKs');
this.render(); // this.render();
this.fetchData(); // this.fetchData();
if (!customElements.get('account-element')) { // if (!customElements.get('account-element')) {
customElements.define('account-element', AccountElement); // customElements.define('account-element', AccountElement);
} // }
} // }
async fetchData() { // async fetchData() {
if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) { // if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) {
const data = await (window as any).myService?.getProcesses(); // const data = await (window as any).myService?.getProcesses();
} else { // } else {
const service = await Services.getInstance(); // const service = await Services.getInstance();
const data = await service.getProcesses(); // const data = await service.getProcesses();
} // }
} // }
set callback(fn) { // set callback(fn) {
if (typeof fn === 'function') { // if (typeof fn === 'function') {
this._callback = fn; // this._callback = fn;
} else { // } else {
console.error('Callback is not a function'); // console.error('Callback is not a function');
} // }
} // }
get callback() { // get callback() {
return this._callback; // return this._callback;
} // }
render() { // render() {
if (this.shadowRoot && !this.shadowRoot.querySelector('account-element')) { // if (this.shadowRoot && !this.shadowRoot.querySelector('account-element')) {
const style = document.createElement('style'); // const style = document.createElement('style');
style.textContent = accountCss; // style.textContent = accountCss;
const accountElement = document.createElement('account-element'); // const accountElement = document.createElement('account-element');
this.shadowRoot.appendChild(style); // this.shadowRoot.appendChild(style);
this.shadowRoot.appendChild(accountElement); // this.shadowRoot.appendChild(accountElement);
} // }
} // }
} // }
export { AccountComponent }; // export { AccountComponent };
customElements.define('account-component', AccountComponent); // customElements.define('account-component', AccountComponent);

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!-- <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>Account</title> <title>Account</title>
@ -7,4 +7,4 @@
<account-component></account-component> <account-component></account-component>
<script type="module" src="./account.ts"></script> <script type="module" src="./account.ts"></script>
</body> </body>
</html> </html> -->

File diff suppressed because it is too large Load Diff

View File

@ -1,321 +1,321 @@
import { ProcessState } from '../../../pkg/sdk_client'; // import { ProcessState } from '../../../pkg/sdk_client';
import Services from '../../services/service'; // import Services from '../../services/service';
interface State { // interface State {
file: File | null; // file: File | null;
fileHash: string | null; // fileHash: string | null;
certificate: ProcessState | null; // certificate: ProcessState | null;
commitmentHashes: string[]; // commitmentHashes: string[];
} // }
export interface Vin { // export interface Vin {
txid: string; // The txid of the previous transaction (being spent) // txid: string; // The txid of the previous transaction (being spent)
vout: number; // The output index in the previous tx // vout: number; // The output index in the previous tx
prevout: { // prevout: {
scriptpubkey: string; // scriptpubkey: string;
scriptpubkey_asm: string; // scriptpubkey_asm: string;
scriptpubkey_type: string; // scriptpubkey_type: string;
scriptpubkey_address: string; // scriptpubkey_address: string;
value: number; // value: number;
}; // };
scriptsig: string; // scriptsig: string;
scriptsig_asm: string; // scriptsig_asm: string;
witness: string[]; // witness: string[];
is_coinbase: boolean; // is_coinbase: boolean;
sequence: number; // sequence: number;
} // }
export interface TransactionInfo { // export interface TransactionInfo {
txid: string; // txid: string;
version: number; // version: number;
locktime: number; // locktime: number;
vin: Vin[]; // vin: Vin[];
vout: any[]; // vout: any[];
size: number; // size: number;
weight: number; // weight: number;
fee: number; // fee: number;
status: { // status: {
confirmed: boolean; // confirmed: boolean;
block_height: number; // block_height: number;
block_hash: string; // block_hash: string;
block_time: number; // block_time: number;
}; // };
} // }
export function getDocumentValidation(container: HTMLElement) { // export function getDocumentValidation(container: HTMLElement) {
const state: State = { // const state: State = {
file: null, // file: null,
fileHash: null, // fileHash: null,
certificate: null, // certificate: null,
commitmentHashes: [] // commitmentHashes: []
} // }
container.innerHTML = ''; // container.innerHTML = '';
container.style.cssText = ` // container.style.cssText = `
display: flex; // display: flex;
flex-direction: column; // flex-direction: column;
justify-content: center; // justify-content: center;
align-items: center; // align-items: center;
min-height: 100vh; // min-height: 100vh;
gap: 2rem; // gap: 2rem;
`; // `;
function createDropButton( // function createDropButton(
label: string, // label: string,
onDrop: (file: File, updateVisuals: (file: File) => void) => void, // onDrop: (file: File, updateVisuals: (file: File) => void) => void,
accept: string = '*/*' // accept: string = '*/*'
): HTMLElement { // ): HTMLElement {
const wrapper = document.createElement('div'); // const wrapper = document.createElement('div');
wrapper.style.cssText = ` // wrapper.style.cssText = `
width: 200px; // width: 200px;
height: 100px; // height: 100px;
border: 2px dashed #888; // border: 2px dashed #888;
border-radius: 8px; // border-radius: 8px;
display: flex; // display: flex;
flex-direction: column; // flex-direction: column;
align-items: center; // align-items: center;
justify-content: center; // justify-content: center;
cursor: pointer; // cursor: pointer;
font-weight: bold; // font-weight: bold;
background: #f8f8f8; // background: #f8f8f8;
text-align: center; // text-align: center;
padding: 0.5rem; // padding: 0.5rem;
box-sizing: border-box; // box-sizing: border-box;
`; // `;
const title = document.createElement('div'); // const title = document.createElement('div');
title.textContent = label; // title.textContent = label;
const filename = document.createElement('div'); // const filename = document.createElement('div');
filename.style.cssText = ` // filename.style.cssText = `
font-size: 0.85rem; // font-size: 0.85rem;
margin-top: 0.5rem; // margin-top: 0.5rem;
color: #444; // color: #444;
word-break: break-word; // word-break: break-word;
text-align: center; // text-align: center;
`; // `;
wrapper.appendChild(title); // wrapper.appendChild(title);
wrapper.appendChild(filename); // wrapper.appendChild(filename);
const updateVisuals = (file: File) => { // const updateVisuals = (file: File) => {
wrapper.style.borderColor = 'green'; // wrapper.style.borderColor = 'green';
wrapper.style.background = '#e6ffed'; // wrapper.style.background = '#e6ffed';
filename.textContent = file.name; // filename.textContent = file.name;
}; // };
// === Hidden file input === // // === Hidden file input ===
const fileInput = document.createElement('input'); // const fileInput = document.createElement('input');
fileInput.type = 'file'; // fileInput.type = 'file';
fileInput.accept = accept; // fileInput.accept = accept;
fileInput.style.display = 'none'; // fileInput.style.display = 'none';
document.body.appendChild(fileInput); // document.body.appendChild(fileInput);
fileInput.onchange = () => { // fileInput.onchange = () => {
const file = fileInput.files?.[0]; // const file = fileInput.files?.[0];
if (file) { // if (file) {
onDrop(file, updateVisuals); // onDrop(file, updateVisuals);
fileInput.value = ''; // reset so same file can be re-selected // fileInput.value = ''; // reset so same file can be re-selected
} // }
}; // };
// === Handle drag-and-drop === // // === Handle drag-and-drop ===
wrapper.ondragover = e => { // wrapper.ondragover = e => {
e.preventDefault(); // e.preventDefault();
wrapper.style.background = '#e0e0e0'; // wrapper.style.background = '#e0e0e0';
}; // };
wrapper.ondragleave = () => { // wrapper.ondragleave = () => {
wrapper.style.background = '#f8f8f8'; // wrapper.style.background = '#f8f8f8';
}; // };
wrapper.ondrop = e => { // wrapper.ondrop = e => {
e.preventDefault(); // e.preventDefault();
wrapper.style.background = '#f8f8f8'; // wrapper.style.background = '#f8f8f8';
const file = e.dataTransfer?.files?.[0]; // const file = e.dataTransfer?.files?.[0];
if (file) { // if (file) {
onDrop(file, updateVisuals); // onDrop(file, updateVisuals);
} // }
}; // };
// === Handle click to open file manager === // // === Handle click to open file manager ===
wrapper.onclick = () => { // wrapper.onclick = () => {
fileInput.click(); // fileInput.click();
}; // };
return wrapper; // return wrapper;
} // }
const fileDropButton = createDropButton('Drop file', async (file, updateVisuals) => { // const fileDropButton = createDropButton('Drop file', async (file, updateVisuals) => {
try { // try {
state.file = file; // state.file = file;
updateVisuals(file); // updateVisuals(file);
console.log('Loaded file:', state.file); // console.log('Loaded file:', state.file);
checkReady(); // checkReady();
} catch (err) { // } catch (err) {
alert('Failed to drop the file.'); // alert('Failed to drop the file.');
console.error(err); // console.error(err);
} // }
}); // });
const certDropButton = createDropButton('Drop certificate', async (file, updateVisuals) => { // const certDropButton = createDropButton('Drop certificate', async (file, updateVisuals) => {
try { // try {
const text = await file.text(); // const text = await file.text();
const json = JSON.parse(text); // const json = JSON.parse(text);
if ( // if (
typeof json === 'object' && // typeof json === 'object' &&
json !== null && // json !== null &&
typeof json.pcd_commitment === 'object' && // typeof json.pcd_commitment === 'object' &&
typeof json.state_id === 'string' // typeof json.state_id === 'string'
) { // ) {
state.certificate = json as ProcessState; // state.certificate = json as ProcessState;
state.commitmentHashes = Object.values(json.pcd_commitment).map((h: string) => // state.commitmentHashes = Object.values(json.pcd_commitment).map((h: string) =>
h.toLowerCase() // h.toLowerCase()
); // );
updateVisuals(file); // updateVisuals(file);
console.log('Loaded certificate, extracted hashes:', state.commitmentHashes); // console.log('Loaded certificate, extracted hashes:', state.commitmentHashes);
checkReady(); // checkReady();
} else { // } else {
alert('Invalid certificate structure.'); // alert('Invalid certificate structure.');
} // }
} catch (err) { // } catch (err) {
alert('Failed to parse certificate JSON.'); // alert('Failed to parse certificate JSON.');
console.error(err); // console.error(err);
} // }
}); // });
const buttonRow = document.createElement('div'); // const buttonRow = document.createElement('div');
buttonRow.style.display = 'flex'; // buttonRow.style.display = 'flex';
buttonRow.style.gap = '2rem'; // buttonRow.style.gap = '2rem';
buttonRow.appendChild(fileDropButton); // buttonRow.appendChild(fileDropButton);
buttonRow.appendChild(certDropButton); // buttonRow.appendChild(certDropButton);
container.appendChild(buttonRow); // container.appendChild(buttonRow);
async function checkReady() { // async function checkReady() {
if (state.file && state.certificate && state.commitmentHashes.length > 0) { // if (state.file && state.certificate && state.commitmentHashes.length > 0) {
// We take the commited_in and all pcd_commitment keys to reconstruct all the possible hash // // We take the commited_in and all pcd_commitment keys to reconstruct all the possible hash
const fileBlob = { // const fileBlob = {
type: state.file.type, // type: state.file.type,
data: new Uint8Array(await state.file.arrayBuffer()) // data: new Uint8Array(await state.file.arrayBuffer())
}; // };
const service = await Services.getInstance(); // const service = await Services.getInstance();
const commitedIn = state.certificate.commited_in; // const commitedIn = state.certificate.commited_in;
if (!commitedIn) return; // if (!commitedIn) return;
const [prevTxid, prevTxVout] = commitedIn.split(':'); // const [prevTxid, prevTxVout] = commitedIn.split(':');
const processId = state.certificate.process_id; // const processId = state.certificate.process_id;
const stateId = state.certificate.state_id; // const stateId = state.certificate.state_id;
const process = await service.getProcess(processId); // const process = await service.getProcess(processId);
if (!process) return; // if (!process) return;
// Get the transaction that comes right after the commited_in // // Get the transaction that comes right after the commited_in
const nextState = service.getNextStateAfterId(process, stateId); // const nextState = service.getNextStateAfterId(process, stateId);
if (!nextState) { // if (!nextState) {
alert(`❌ Validation failed: No next state, is the state you're trying to validate commited?`); // alert(`❌ Validation failed: No next state, is the state you're trying to validate commited?`);
return; // return;
} // }
const [outspentTxId, _] = nextState.commited_in.split(':'); // const [outspentTxId, _] = nextState.commited_in.split(':');
console.log(outspentTxId); // console.log(outspentTxId);
// Check that the commitment transaction exists, and that it commits to the state id // // Check that the commitment transaction exists, and that it commits to the state id
const txInfo = await fetchTransaction(outspentTxId); // const txInfo = await fetchTransaction(outspentTxId);
if (!txInfo) { // if (!txInfo) {
console.error(`Validation error: Can't fetch new state commitment transaction`); // console.error(`Validation error: Can't fetch new state commitment transaction`);
alert(`❌ Validation failed: invalid or non existent commited_in for state ${stateId}.`); // alert(`❌ Validation failed: invalid or non existent commited_in for state ${stateId}.`);
return; // return;
} // }
// We must check that this transaction indeed spend the commited_in we have in the certificate // // We must check that this transaction indeed spend the commited_in we have in the certificate
let found = false; // let found = false;
for (const vin of txInfo.vin) { // for (const vin of txInfo.vin) {
if (vin.txid === prevTxid) { // if (vin.txid === prevTxid) {
found = true; // found = true;
break; // break;
} // }
} // }
if (!found) { // if (!found) {
console.error(`Validation error: new state doesn't spend previous state commitment transaction`); // console.error(`Validation error: new state doesn't spend previous state commitment transaction`);
alert('❌ Validation failed: Unconsistent commitment transactions history.'); // alert('❌ Validation failed: Unconsistent commitment transactions history.');
return; // return;
} // }
// set found back to false for next check // // set found back to false for next check
found = false; // found = false;
// is the state_id commited in the transaction? // // is the state_id commited in the transaction?
for (const vout of txInfo.vout) { // for (const vout of txInfo.vout) {
console.log(vout); // console.log(vout);
if (vout.scriptpubkey_type && vout.scriptpubkey_type === 'op_return') { // if (vout.scriptpubkey_type && vout.scriptpubkey_type === 'op_return') {
found = true; // found = true;
} else { // } else {
continue; // continue;
} // }
if (vout.scriptpubkey_asm) { // if (vout.scriptpubkey_asm) {
const hash = extractHexFromScriptAsm(vout.scriptpubkey_asm); // const hash = extractHexFromScriptAsm(vout.scriptpubkey_asm);
if (hash) { // if (hash) {
if (hash !== stateId) { // if (hash !== stateId) {
console.error(`Validation error: expected stateId ${stateId}, got ${hash}`); // console.error(`Validation error: expected stateId ${stateId}, got ${hash}`);
alert('❌ Validation failed: Transaction does not commit to that state.'); // alert('❌ Validation failed: Transaction does not commit to that state.');
return; // return;
} // }
} // }
} // }
} // }
if (!found) { // if (!found) {
alert('❌ Validation failed: Transaction does not contain data.'); // alert('❌ Validation failed: Transaction does not contain data.');
return; // return;
} // }
// set found back to false for next check // // set found back to false for next check
found = false; // found = false;
for (const label of Object.keys(state.certificate.pcd_commitment)) { // for (const label of Object.keys(state.certificate.pcd_commitment)) {
// Compute the hash for this label // // Compute the hash for this label
console.log(`Computing hash with label ${label}`) // console.log(`Computing hash with label ${label}`)
const fileHex = service.getHashForFile(commitedIn, label, fileBlob); // const fileHex = service.getHashForFile(commitedIn, label, fileBlob);
console.log(`Found hash ${fileHex}`); // console.log(`Found hash ${fileHex}`);
found = state.commitmentHashes.includes(fileHex); // found = state.commitmentHashes.includes(fileHex);
if (found) break; // if (found) break;
} // }
if (found) { // if (found) {
alert('✅ Validation successful: file hash found in pcd_commitment.'); // alert('✅ Validation successful: file hash found in pcd_commitment.');
} else { // } else {
alert('❌ Validation failed: file hash NOT found in pcd_commitment.'); // alert('❌ Validation failed: file hash NOT found in pcd_commitment.');
} // }
} // }
} // }
async function fetchTransaction(txid: string): Promise<TransactionInfo> { // async function fetchTransaction(txid: string): Promise<TransactionInfo> {
const url = `https://mempool.4nkweb.com/api/tx/${txid}`; // const url = `https://mempool.4nkweb.com/api/tx/${txid}`;
const response = await fetch(url); // const response = await fetch(url);
if (!response.ok) { // if (!response.ok) {
throw new Error(`Failed to fetch outspend status: ${response.statusText}`); // throw new Error(`Failed to fetch outspend status: ${response.statusText}`);
} // }
const outspend: TransactionInfo = await response.json(); // const outspend: TransactionInfo = await response.json();
return outspend; // return outspend;
} // }
function extractHexFromScriptAsm(scriptAsm: string): string | null { // function extractHexFromScriptAsm(scriptAsm: string): string | null {
const parts = scriptAsm.trim().split(/\s+/); // const parts = scriptAsm.trim().split(/\s+/);
const last = parts[parts.length - 1]; // const last = parts[parts.length - 1];
// Basic validation: must be 64-char hex (32 bytes) // // Basic validation: must be 64-char hex (32 bytes)
if (/^[0-9a-fA-F]{64}$/.test(last)) { // if (/^[0-9a-fA-F]{64}$/.test(last)) {
return last.toLowerCase(); // return last.toLowerCase();
} // }
return null; // return null;
} // }
} // }

View File

@ -1,196 +1,196 @@
import { ValidationRule, RoleDefinition } from '../../../pkg/sdk_client'; // import { ValidationRule, RoleDefinition } from '../../../pkg/sdk_client';
import { showValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal'; // import { showValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal';
export function createKeyValueSection(title: string, id: string, isRoleSection = false) { // export function createKeyValueSection(title: string, id: string, isRoleSection = false) {
const section = document.createElement('div'); // const section = document.createElement('div');
section.id = id; // section.id = id;
section.style.cssText = 'margin-bottom: 2rem; background: #fff; padding: 1rem; border-radius: 0.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1);'; // section.style.cssText = 'margin-bottom: 2rem; background: #fff; padding: 1rem; border-radius: 0.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1);';
const titleEl = document.createElement('h2'); // const titleEl = document.createElement('h2');
titleEl.textContent = title; // titleEl.textContent = title;
titleEl.style.cssText = 'font-size: 1.25rem; font-weight: bold; margin-bottom: 1rem;'; // titleEl.style.cssText = 'font-size: 1.25rem; font-weight: bold; margin-bottom: 1rem;';
section.appendChild(titleEl); // section.appendChild(titleEl);
const rowContainer = document.createElement('div'); // const rowContainer = document.createElement('div');
section.appendChild(rowContainer); // section.appendChild(rowContainer);
const addBtn = document.createElement('button'); // const addBtn = document.createElement('button');
addBtn.textContent = '+ Add Row'; // addBtn.textContent = '+ Add Row';
addBtn.style.cssText = ` // addBtn.style.cssText = `
margin-top: 1rem; // margin-top: 1rem;
padding: 0.5rem 1rem; // padding: 0.5rem 1rem;
border: 1px solid #888; // border: 1px solid #888;
border-radius: 0.375rem; // border-radius: 0.375rem;
background-color: #f9f9f9; // background-color: #f9f9f9;
cursor: pointer; // cursor: pointer;
`; // `;
section.appendChild(addBtn); // section.appendChild(addBtn);
const roleRowStates: { // const roleRowStates: {
roleNameInput: HTMLInputElement; // roleNameInput: HTMLInputElement;
membersInput: HTMLInputElement; // membersInput: HTMLInputElement;
storagesInput: HTMLInputElement; // storagesInput: HTMLInputElement;
validationRules: ValidationRule[]; // validationRules: ValidationRule[];
}[] = []; // }[] = [];
type fileBlob = { // type fileBlob = {
type: string, // type: string,
data: Uint8Array // data: Uint8Array
}; // };
const nonRoleRowStates: { // const nonRoleRowStates: {
keyInput: HTMLInputElement, // keyInput: HTMLInputElement,
valueInput: HTMLInputElement, // valueInput: HTMLInputElement,
fileInput: HTMLInputElement, // fileInput: HTMLInputElement,
fileBlob: fileBlob | null // fileBlob: fileBlob | null
}[] = []; // }[] = [];
const inputStyle = 'flex: 1; height: 2.5rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem;'; // const inputStyle = 'flex: 1; height: 2.5rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem;';
const createRow = () => { // const createRow = () => {
const row = document.createElement('div'); // const row = document.createElement('div');
row.style.cssText = 'display: flex; gap: 1rem; margin-bottom: 0.5rem; align-items: center;'; // row.style.cssText = 'display: flex; gap: 1rem; margin-bottom: 0.5rem; align-items: center;';
const deleteBtn = document.createElement('button'); // const deleteBtn = document.createElement('button');
deleteBtn.textContent = '🗑️'; // deleteBtn.textContent = '🗑️';
deleteBtn.style.cssText = 'background: none; border: none; font-size: 1.2rem; cursor: pointer;'; // deleteBtn.style.cssText = 'background: none; border: none; font-size: 1.2rem; cursor: pointer;';
deleteBtn.onclick = () => { // deleteBtn.onclick = () => {
row.remove(); // row.remove();
updateDeleteButtons(); // updateDeleteButtons();
}; // };
if (isRoleSection) { // if (isRoleSection) {
const roleName = document.createElement('input'); // const roleName = document.createElement('input');
const members = document.createElement('input'); // const members = document.createElement('input');
const storages = document.createElement('input'); // const storages = document.createElement('input');
roleName.placeholder = 'Role name'; // roleName.placeholder = 'Role name';
members.placeholder = 'members'; // members.placeholder = 'members';
storages.placeholder = 'storages'; // storages.placeholder = 'storages';
[roleName, members, storages].forEach(input => { // [roleName, members, storages].forEach(input => {
input.type = 'text'; // input.type = 'text';
input.style.cssText = inputStyle; // input.style.cssText = inputStyle;
}); // });
const ruleButton = document.createElement('button'); // const ruleButton = document.createElement('button');
ruleButton.textContent = 'Add Validation Rule'; // ruleButton.textContent = 'Add Validation Rule';
ruleButton.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;'; // ruleButton.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;';
const rules: ValidationRule[] = []; // const rules: ValidationRule[] = [];
ruleButton.onclick = () => { // ruleButton.onclick = () => {
showValidationRuleModal(rule => { // showValidationRuleModal(rule => {
rules.push(rule); // rules.push(rule);
ruleButton.textContent = `Rules (${rules.length})`; // ruleButton.textContent = `Rules (${rules.length})`;
}); // });
}; // };
row.appendChild(roleName); // row.appendChild(roleName);
row.appendChild(members); // row.appendChild(members);
row.appendChild(storages); // row.appendChild(storages);
row.appendChild(ruleButton); // row.appendChild(ruleButton);
row.appendChild(deleteBtn); // row.appendChild(deleteBtn);
roleRowStates.push({ roleNameInput: roleName, membersInput: members, storagesInput: storages, validationRules: rules }); // roleRowStates.push({ roleNameInput: roleName, membersInput: members, storagesInput: storages, validationRules: rules });
} else { // } else {
const fileInput = document.createElement('input'); // const fileInput = document.createElement('input');
fileInput.type = 'file'; // fileInput.type = 'file';
fileInput.style.display = 'none'; // fileInput.style.display = 'none';
fileInput.onchange = async () => { // fileInput.onchange = async () => {
const file = fileInput.files?.[0]; // const file = fileInput.files?.[0];
if (!file) return; // if (!file) return;
const buffer = await file.arrayBuffer(); // const buffer = await file.arrayBuffer();
const uint8 = new Uint8Array(buffer); // const uint8 = new Uint8Array(buffer);
rowState.fileBlob = { // rowState.fileBlob = {
type: file.type, // type: file.type,
data: uint8, // data: uint8,
}; // };
valueInput.value = `📄 ${file.name}`; // valueInput.value = `📄 ${file.name}`;
valueInput.disabled = true; // valueInput.disabled = true;
attachBtn.textContent = `📎 ${file.name}`; // attachBtn.textContent = `📎 ${file.name}`;
}; // };
const attachBtn = document.createElement('button'); // const attachBtn = document.createElement('button');
attachBtn.textContent = '📎 Attach'; // attachBtn.textContent = '📎 Attach';
attachBtn.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;'; // attachBtn.style.cssText = 'padding: 0.3rem 0.75rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;';
attachBtn.onclick = () => fileInput.click(); // attachBtn.onclick = () => fileInput.click();
const keyInput = document.createElement('input'); // const keyInput = document.createElement('input');
const valueInput = document.createElement('input'); // const valueInput = document.createElement('input');
const rowState = { // const rowState = {
keyInput, // keyInput,
valueInput, // valueInput,
fileInput, // fileInput,
fileBlob: null as fileBlob | null // fileBlob: null as fileBlob | null
}; // };
nonRoleRowStates.push(rowState); // nonRoleRowStates.push(rowState);
keyInput.placeholder = 'Key'; // keyInput.placeholder = 'Key';
valueInput.placeholder = 'Value'; // valueInput.placeholder = 'Value';
[keyInput, valueInput].forEach(input => { // [keyInput, valueInput].forEach(input => {
input.type = 'text'; // input.type = 'text';
input.style.cssText = inputStyle; // input.style.cssText = inputStyle;
}); // });
row.appendChild(keyInput); // row.appendChild(keyInput);
row.appendChild(valueInput); // row.appendChild(valueInput);
row.appendChild(attachBtn); // row.appendChild(attachBtn);
row.appendChild(fileInput); // row.appendChild(fileInput);
row.appendChild(deleteBtn); // row.appendChild(deleteBtn);
} // }
rowContainer.appendChild(row); // rowContainer.appendChild(row);
updateDeleteButtons(); // updateDeleteButtons();
}; // };
const updateDeleteButtons = () => { // const updateDeleteButtons = () => {
const rows = Array.from(rowContainer.children); // const rows = Array.from(rowContainer.children);
rows.forEach(row => { // rows.forEach(row => {
const btn = row.querySelector('button:last-child') as HTMLButtonElement; // const btn = row.querySelector('button:last-child') as HTMLButtonElement;
if (rows.length === 1) { // if (rows.length === 1) {
btn.disabled = true; // btn.disabled = true;
btn.style.visibility = 'hidden'; // btn.style.visibility = 'hidden';
} else { // } else {
btn.disabled = false; // btn.disabled = false;
btn.style.visibility = 'visible'; // btn.style.visibility = 'visible';
} // }
}); // });
}; // };
createRow(); // createRow();
addBtn.addEventListener('click', createRow); // addBtn.addEventListener('click', createRow);
return { // return {
element: section, // element: section,
getData: () => { // getData: () => {
if (isRoleSection) { // if (isRoleSection) {
const data: Record<string, RoleDefinition> = {}; // const data: Record<string, RoleDefinition> = {};
for (const row of roleRowStates) { // for (const row of roleRowStates) {
const key = row.roleNameInput.value.trim(); // const key = row.roleNameInput.value.trim();
if (!key) continue; // if (!key) continue;
data[key] = { // data[key] = {
members: row.membersInput.value.split(',').map(x => x.trim()).filter(Boolean), // members: row.membersInput.value.split(',').map(x => x.trim()).filter(Boolean),
storages: row.storagesInput.value.split(',').map(x => x.trim()).filter(Boolean), // storages: row.storagesInput.value.split(',').map(x => x.trim()).filter(Boolean),
validation_rules: row.validationRules // validation_rules: row.validationRules
}; // };
} // }
return data; // return data;
} else { // } else {
const data: Record<string, string | fileBlob> = {}; // const data: Record<string, string | fileBlob> = {};
for (const row of nonRoleRowStates) { // for (const row of nonRoleRowStates) {
const key = row.keyInput.value.trim(); // const key = row.keyInput.value.trim();
if (!key) continue; // if (!key) continue;
if (row.fileBlob) { // if (row.fileBlob) {
data[key] = row.fileBlob; // data[key] = row.fileBlob;
} else { // } else {
data[key] = row.valueInput.value.trim(); // data[key] = row.valueInput.value.trim();
} // }
} // }
return data; // return data;
} // }
} // }
}; // };
} // }

View File

@ -1,91 +1,91 @@
import { createKeyValueSection } from './key-value-section'; // import { createKeyValueSection } from './key-value-section';
import { loadValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal'; // import { loadValidationRuleModal } from '../../components/validation-rule-modal/validation-rule-modal';
import Services from '../../services/service'; // import Services from '../../services/service';
import { RoleDefinition } from '../../../pkg/sdk_client'; // import { RoleDefinition } from '../../../pkg/sdk_client';
export async function getProcessCreation(container: HTMLElement) { // export async function getProcessCreation(container: HTMLElement) {
await loadValidationRuleModal(); // await loadValidationRuleModal();
container.style.display = 'block'; // container.style.display = 'block';
container.innerHTML = `<div class="parameter-header">Process Creation</div>`; // container.innerHTML = `<div class="parameter-header">Process Creation</div>`;
const privateSec = createKeyValueSection('Private Data', 'private-section'); // const privateSec = createKeyValueSection('Private Data', 'private-section');
const publicSec = createKeyValueSection('Public Data', 'public-section'); // const publicSec = createKeyValueSection('Public Data', 'public-section');
const rolesSec = createKeyValueSection('Roles', 'roles-section', true); // const rolesSec = createKeyValueSection('Roles', 'roles-section', true);
container.appendChild(privateSec.element); // container.appendChild(privateSec.element);
container.appendChild(publicSec.element); // container.appendChild(publicSec.element);
container.appendChild(rolesSec.element); // container.appendChild(rolesSec.element);
const btn = document.createElement('button'); // const btn = document.createElement('button');
btn.textContent = 'Create Process'; // btn.textContent = 'Create Process';
btn.style.cssText = ` // btn.style.cssText = `
display: block; // display: block;
margin: 2rem auto 0; // margin: 2rem auto 0;
padding: 0.75rem 2rem; // padding: 0.75rem 2rem;
font-size: 1rem; // font-size: 1rem;
font-weight: bold; // font-weight: bold;
background-color: #4f46e5; // background-color: #4f46e5;
color: white; // color: white;
border: none; // border: none;
border-radius: 0.5rem; // border-radius: 0.5rem;
cursor: pointer; // cursor: pointer;
`; // `;
btn.onclick = async () => { // btn.onclick = async () => {
const privateData = privateSec.getData(); // const privateData = privateSec.getData();
const publicData = publicSec.getData(); // const publicData = publicSec.getData();
const roles = rolesSec.getData() as Record<string, RoleDefinition>; // const roles = rolesSec.getData() as Record<string, RoleDefinition>;
console.log('Private:', privateData); // console.log('Private:', privateData);
console.log('Public:', publicData); // console.log('Public:', publicData);
console.log('Roles:', roles); // console.log('Roles:', roles);
const service = await Services.getInstance(); // const service = await Services.getInstance();
const createProcessResult = await service.createProcess(privateData, publicData, roles); // const createProcessResult = await service.createProcess(privateData, publicData, roles);
const processId = createProcessResult.updated_process!.process_id; // const processId = createProcessResult.updated_process!.process_id;
const stateId = createProcessResult.updated_process!.current_process.states[0].state_id; // const stateId = createProcessResult.updated_process!.current_process.states[0].state_id;
await service.handleApiReturn(createProcessResult); // await service.handleApiReturn(createProcessResult);
// Now we want to validate the update and register the first state of our new process // // Now we want to validate the update and register the first state of our new process
const updateProcessResult = await service.createPrdUpdate(processId, stateId); // const updateProcessResult = await service.createPrdUpdate(processId, stateId);
await service.handleApiReturn(createProcessResult); // await service.handleApiReturn(createProcessResult);
const approveChangeResult = await service.approveChange(processId, stateId); // const approveChangeResult = await service.approveChange(processId, stateId);
await service.handleApiReturn(approveChangeResult); // await service.handleApiReturn(approveChangeResult);
if (approveChangeResult) { // if (approveChangeResult) {
const process = await service.getProcess(processId); // const process = await service.getProcess(processId);
let newState = service.getStateFromId(process, stateId); // let newState = service.getStateFromId(process, stateId);
if (!newState) return; // if (!newState) return;
for (const label of Object.keys(newState.keys)) { // for (const label of Object.keys(newState.keys)) {
const hash = newState.pcd_commitment[label]; // const hash = newState.pcd_commitment[label];
const encryptedData = await service.getBlobFromDb(hash); // const encryptedData = await service.getBlobFromDb(hash);
const filename = `${label}-${hash.slice(0,8)}.bin`; // const filename = `${label}-${hash.slice(0,8)}.bin`;
const blob = new Blob([encryptedData], { type: "application/octet-stream" }); // const blob = new Blob([encryptedData], { type: "application/octet-stream" });
const link = document.createElement("a"); // const link = document.createElement("a");
link.href = URL.createObjectURL(blob); // link.href = URL.createObjectURL(blob);
link.download = filename; // link.download = filename;
link.click(); // link.click();
setTimeout(() => URL.revokeObjectURL(link.href), 1000); // setTimeout(() => URL.revokeObjectURL(link.href), 1000);
} // }
await service.generateProcessPdf(processId, newState); // await service.generateProcessPdf(processId, newState);
// Add processId to the state we export // // Add processId to the state we export
newState['process_id'] = processId; // newState['process_id'] = processId;
const blob = new Blob([JSON.stringify(newState, null, 2)], { type: 'application/json' }); // const blob = new Blob([JSON.stringify(newState, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob); // const url = URL.createObjectURL(blob);
const a = document.createElement('a'); // const a = document.createElement('a');
a.href = url; // a.href = url;
a.download = `process_${processId}_${stateId}.json`; // a.download = `process_${processId}_${stateId}.json`;
a.click(); // a.click();
URL.revokeObjectURL(url); // Clean up // URL.revokeObjectURL(url); // Clean up
} // }
}; // };
container.appendChild(btn); // container.appendChild(btn);
} // }

View File

@ -1,66 +1,66 @@
export function createProcessTab(container: HTMLElement, processes: { name: string, publicData: Record<string, any> }[]): HTMLElement { // export function createProcessTab(container: HTMLElement, processes: { name: string, publicData: Record<string, any> }[]): HTMLElement {
container.id = 'process-tab'; // container.id = 'process-tab';
container.style.display = 'block'; // container.style.display = 'block';
container.style.cssText = 'padding: 1.5rem;'; // container.style.cssText = 'padding: 1.5rem;';
const title = document.createElement('h2'); // const title = document.createElement('h2');
title.textContent = 'Processes'; // title.textContent = 'Processes';
title.style.cssText = 'font-size: 1.5rem; font-weight: bold; margin-bottom: 1rem;'; // title.style.cssText = 'font-size: 1.5rem; font-weight: bold; margin-bottom: 1rem;';
container.appendChild(title); // container.appendChild(title);
processes.forEach(proc => { // processes.forEach(proc => {
const card = document.createElement('div'); // const card = document.createElement('div');
card.style.cssText = 'margin-bottom: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 0.5rem; background: #fff;'; // card.style.cssText = 'margin-bottom: 1rem; padding: 1rem; border: 1px solid #ddd; border-radius: 0.5rem; background: #fff;';
const nameEl = document.createElement('h3'); // const nameEl = document.createElement('h3');
nameEl.textContent = proc.name; // nameEl.textContent = proc.name;
nameEl.style.cssText = 'font-size: 1.2rem; font-weight: bold; margin-bottom: 0.5rem;'; // nameEl.style.cssText = 'font-size: 1.2rem; font-weight: bold; margin-bottom: 0.5rem;';
card.appendChild(nameEl); // card.appendChild(nameEl);
const dataList = document.createElement('div'); // const dataList = document.createElement('div');
for (const [key, value] of Object.entries(proc.publicData)) { // for (const [key, value] of Object.entries(proc.publicData)) {
const item = document.createElement('div'); // const item = document.createElement('div');
item.style.cssText = 'margin-bottom: 0.5rem;'; // item.style.cssText = 'margin-bottom: 0.5rem;';
const label = document.createElement('strong'); // const label = document.createElement('strong');
label.textContent = key + ': '; // label.textContent = key + ': ';
item.appendChild(label); // item.appendChild(label);
// Let's trim the quotes // // Let's trim the quotes
const trimmed = value.replace(/^'|'$/g, ''); // const trimmed = value.replace(/^'|'$/g, '');
let parsed; // let parsed;
try { // try {
parsed = JSON.parse(trimmed); // parsed = JSON.parse(trimmed);
} catch (_) { // } catch (_) {
parsed = trimmed; // parsed = trimmed;
} // }
if (parsed && typeof parsed === 'object') { // if (parsed && typeof parsed === 'object') {
const saveBtn = document.createElement('button'); // const saveBtn = document.createElement('button');
saveBtn.textContent = '💾 Save as JSON'; // saveBtn.textContent = '💾 Save as JSON';
saveBtn.style.cssText = 'margin-left: 0.5rem; padding: 0.25rem 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;'; // saveBtn.style.cssText = 'margin-left: 0.5rem; padding: 0.25rem 0.5rem; border: 1px solid #ccc; border-radius: 0.375rem; background: #f0f0f0; cursor: pointer;';
saveBtn.onclick = () => { // saveBtn.onclick = () => {
const blob = new Blob([JSON.stringify(parsed, null, 2)], { type: 'application/json' }); // const blob = new Blob([JSON.stringify(parsed, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob); // const url = URL.createObjectURL(blob);
const a = document.createElement('a'); // const a = document.createElement('a');
a.href = url; // a.href = url;
a.download = `${proc.name}_${key}.json`; // a.download = `${proc.name}_${key}.json`;
a.click(); // a.click();
URL.revokeObjectURL(url); // URL.revokeObjectURL(url);
}; // };
item.appendChild(saveBtn); // item.appendChild(saveBtn);
} else { // } else {
const span = document.createElement('span'); // const span = document.createElement('span');
span.textContent = String(parsed); // span.textContent = String(parsed);
item.appendChild(span); // item.appendChild(span);
} // }
dataList.appendChild(item); // dataList.appendChild(item);
} // }
card.appendChild(dataList); // card.appendChild(dataList);
container.appendChild(card); // container.appendChild(card);
}); // });
return container; // return container;
} // }