feat(console): simplify workspace and add filtered resource pagination
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
const ui = { after: '', next: '', selected: '', detail: null, loading: false, busy: false, pending: null, rotating: null, result: null, saved: true, mode: 'CREATE', helpCredential: '' };
|
||||
const escape = value => String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
const time = value => value ? new Date(value).toLocaleString('zh-CN', { hour12: false }) : '长期有效';
|
||||
let tokenRequest = 0, tokenTarget = null;
|
||||
let tokenRequest = 0, tokenTarget = null, selectionSequence = 0;
|
||||
const resourceMessages = {
|
||||
'resource is retired; history remains available':'资源已退役,历史仍可查询。',
|
||||
'queue has unfinished tasks, including tasks needing review':'队列还有未完成或待核查任务,请先结清。',
|
||||
@@ -27,6 +27,8 @@
|
||||
return value.data;
|
||||
}
|
||||
const queueMemory = new Map();
|
||||
function filterApplications() { const term=$('access-search').value.trim().toLocaleLowerCase(); const items=[...document.querySelectorAll('#access-list [data-access-id]')]; items.forEach(item=>{item.hidden=!!term&&!item.textContent.toLocaleLowerCase().includes(term);}); $('access-search-empty').hidden=!term||items.some(item=>!item.hidden); }
|
||||
$('access-search').addEventListener('input',filterApplications);
|
||||
function rememberedQueue(namespace) { try { return localStorage.getItem(`orbit.access.queue.${namespace}`) || queueMemory.get(namespace) || ''; } catch { return queueMemory.get(namespace) || ''; } }
|
||||
function rememberQueue() { const value = $('access-queue').value; queueMemory.set(ui.selected, value); try { localStorage.setItem(`orbit.access.queue.${ui.selected}`, value); } catch {} renderConfig(); }
|
||||
function config(token = '••••••••', queue = $('access-queue').value, namespace = ui.selected) {
|
||||
@@ -42,16 +44,21 @@
|
||||
try {
|
||||
const page = await api(ui.after ? `?after=${encodeURIComponent(ui.after)}` : ''); ui.next = page.next || ''; $('access-next').disabled = !ui.next;
|
||||
$('access-list').innerHTML = page.items.length ? page.items.map(entry => `<button class="access-item ${entry.namespace_id === ui.selected ? 'selected' : ''}" data-access-id="${escape(entry.namespace_id)}"><span class="access-avatar">${escape(entry.application.slice(0, 1).toUpperCase())}</span><span><strong>${escape(entry.application)}</strong><small>${escape(entry.environment)} / ${escape(entry.namespace)} · ${entry.enabled ? '已启用' : '已停用'}</small></span></button>`).join('') : '<p class="panel-description">还没有接入应用,点击右上角新建。</p>';
|
||||
filterApplications();
|
||||
if (!ui.selected && page.items.length) await select(page.items[0].namespace_id);
|
||||
else if (ui.selected && !$('access-dialog').open && !$('access-token-dialog').open) await select(ui.selected);
|
||||
} catch (error) { $('access-error').textContent = message(error); }
|
||||
finally { ui.loading = false; }
|
||||
}
|
||||
async function select(namespace) {
|
||||
if (namespace !== ui.selected) { retirement = null; $('access-retire-form').hidden = true; }
|
||||
const requested = namespace; ui.selected = namespace;
|
||||
if (namespace !== ui.selected) {
|
||||
retirement = null; $('access-retire-form').hidden = true;
|
||||
$('access-detail').hidden = true; $('access-empty').hidden = false;
|
||||
$('access-empty').textContent = '正在读取应用配置…';
|
||||
}
|
||||
const requested = namespace, ticket = ++selectionSequence; ui.selected = namespace;
|
||||
try {
|
||||
const detail = await api(`/${encodeURIComponent(namespace)}`); if (ui.selected !== requested) return; ui.detail = detail;
|
||||
const detail = await api(`/${encodeURIComponent(namespace)}`); if (ui.selected !== requested || ticket !== selectionSequence) return; ui.detail = detail;
|
||||
$('access-empty').hidden = true; $('access-detail').hidden = false;
|
||||
$('access-title').textContent = detail.entry.application; $('access-status').textContent = detail.entry.enabled ? '已启用' : '已停用';
|
||||
$('access-app-id').textContent = detail.entry.application_id; $('access-ns-id').textContent = namespace; $('access-scope').textContent = `${detail.entry.environment} / ${detail.entry.namespace}`;
|
||||
@@ -79,13 +86,18 @@
|
||||
<div class="access-token-summary"><div><strong>接入配置 · 当前 Token</strong><span>${c.revoked_at ? '凭据已撤销' : c.token_stored ? '•••••••••••••••• · 已加密保管' : '历史凭据 · 导入当前 Token 后可随时查看'}</span></div></div>
|
||||
<div class="access-form-actions"><button type="button" class="primary-button compact" data-access-token="${escape(c.id)}" ${c.revoked_at ? 'disabled' : ''}>${c.token_stored ? '查看接入信息' : '导入当前 Token'}</button><button type="button" class="secondary-button compact" data-access-copy-config="${escape(c.id)}" ${c.revoked_at || !c.token_stored ? 'disabled' : ''}>复制接入配置 ↗</button></div>
|
||||
${rotationHelp}
|
||||
<div class="access-form-actions"><button class="text-button" data-access-expiry="${escape(c.id)}" ${c.revoked_at ? 'disabled' : ''}>调整有效期</button>${c.previous_valid_until && !c.revoked_at ? `<button class="text-button" data-access-finalize="${escape(c.id)}">结束过渡,停用旧 Token</button>` : ''}</div>
|
||||
<div class="access-permissions">${groups.map(a => `<span>${escape(a)}</span>`).join('')}</div><details class="access-permission-details"><summary>查看具体权限</summary><p>${c.permissions.actions.map(escape).join(' · ')}<br>授权队列:${escape(c.permissions.queues.join(', '))}</p></details>
|
||||
<details class="credential-controls"><summary>凭据管理与权限</summary><div class="access-form-actions"><button class="text-button" data-access-expiry="${escape(c.id)}" ${c.revoked_at ? 'disabled' : ''}>调整有效期</button>${c.previous_valid_until && !c.revoked_at ? `<button class="text-button" data-access-finalize="${escape(c.id)}">结束过渡,停用旧 Token</button>` : ''}</div>
|
||||
<div class="access-permissions">${groups.map(a => `<span>${escape(a)}</span>`).join('')}</div><details class="access-permission-details"><summary>查看具体权限</summary><p>${c.permissions.actions.map(escape).join(' · ')}<br>授权队列:${escape(c.permissions.queues.join(', '))}</p></details></details>
|
||||
</section>`;
|
||||
}).join('') || '<p class="panel-description">该环境暂无凭据。</p>';
|
||||
if ($('access-help-dialog').open) renderCredentialHelp();
|
||||
document.querySelectorAll('[data-access-id]').forEach(el => el.classList.toggle('selected', el.dataset.accessId === namespace)); renderConfig();
|
||||
} catch (error) { $('access-error').textContent = message(error); }
|
||||
} catch (error) {
|
||||
if (ticket !== selectionSequence) return;
|
||||
$('access-error').textContent = message(error);
|
||||
$('access-detail').hidden = true; $('access-empty').hidden = false;
|
||||
$('access-empty').textContent = '应用配置读取失败,请刷新重试。';
|
||||
}
|
||||
}
|
||||
function renderConfig() { const q = ui.detail?.queues.find(q => q.id === $('access-queue').value); $('access-queue-note').textContent = !q ? '请明确选择接入队列,避免复制到错误的目标。' : `当前目标:${q.name} · ${q.paused ? '已暂停,任务暂不执行' : '可用'}。选择只影响复制配置,不修改服务端路由。`; $('access-retire-queue').disabled = !q || !!q.retired_at; try { $('access-config').textContent = config(); } catch (error) { $('access-config').textContent = error.message; } }
|
||||
function closeToken() {
|
||||
|
||||
Reference in New Issue
Block a user