197 lines
6.2 KiB
TypeScript
197 lines
6.2 KiB
TypeScript
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<string, RoleDefinition> = {};
|
|
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<string, string | fileBlob> = {};
|
|
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;
|
|
}
|
|
}
|
|
};
|
|
}
|