71 lines
2.5 KiB
JavaScript
71 lines
2.5 KiB
JavaScript
// Icon sets management panel — list, upload, delete custom icon sets.
|
|
import { el, mount, clear } from '../dom.js';
|
|
import { api } from '../api.js';
|
|
|
|
export function iconSetsPanel() {
|
|
const root = el('div', { class: 'icon-sets-panel' });
|
|
|
|
async function refresh() {
|
|
clear(root);
|
|
let list = [];
|
|
try { list = await api.get('/api/icon-sets'); } catch {
|
|
root.appendChild(el('div', { class: 'muted' }, 'unavailable'));
|
|
return;
|
|
}
|
|
for (const s of list) {
|
|
const grid = el('div', { class: 'ip-grid' },
|
|
s.icons.map(f =>
|
|
el('div', { class: 'ip-icon' },
|
|
el('img', { src: `/api/icon-sets/${s.set}/${f}`, title: f })
|
|
)
|
|
)
|
|
);
|
|
const head = el('div', { class: 'isp-hd' },
|
|
el('b', {}, s.set),
|
|
el('span', { class: 'muted' }, ` ${s.icons.length}`)
|
|
);
|
|
if (!s.readonly) {
|
|
const del = el('button', { class: 'ghost' }, 'Delete');
|
|
del.addEventListener('click', async () => {
|
|
await api.del('/api/icon-sets/' + s.set);
|
|
refresh();
|
|
});
|
|
head.appendChild(del);
|
|
}
|
|
root.appendChild(el('div', { class: 'isp-set' }, head, grid));
|
|
}
|
|
root.appendChild(uploadForm(refresh));
|
|
}
|
|
|
|
refresh();
|
|
return root;
|
|
}
|
|
|
|
function uploadForm(onDone) {
|
|
const setI = el('input', { class: 'dv-edit-name', placeholder: 'new set name (a-z0-9-)' });
|
|
const fileI = el('input', { type: 'file', accept: '.svg,.png,.jpg,.jpeg,.zip', multiple: true });
|
|
const urlI = el('input', { class: 'dv-edit-name', placeholder: 'or ingest from URL (image or .zip)' });
|
|
const err = el('span', { class: 'muted', style: { fontSize: '11px' } }, '');
|
|
const up = el('button', { class: 'dv-add' }, 'Upload');
|
|
|
|
up.addEventListener('click', async () => {
|
|
const set = setI.value.trim().toLowerCase();
|
|
if (!/^[a-z0-9-]+$/.test(set)) { err.textContent = 'set name: a-z 0-9 - only'; return; }
|
|
if (!fileI.files.length && !urlI.value.trim()) { err.textContent = 'pick files or a URL'; return; }
|
|
const fd = new FormData();
|
|
for (const f of fileI.files) fd.append('files', f);
|
|
if (urlI.value.trim()) fd.append('url', urlI.value.trim());
|
|
up.textContent = 'Uploading…'; up.disabled = true;
|
|
try {
|
|
await api.postForm('/api/icon-sets/' + set, fd);
|
|
onDone();
|
|
} catch {
|
|
err.textContent = 'upload failed';
|
|
up.textContent = 'Upload';
|
|
up.disabled = false;
|
|
}
|
|
});
|
|
|
|
return el('div', { class: 'isp-upload' }, setI, fileI, urlI, up, err);
|
|
}
|