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