Polish official plugin workbench UI
This commit is contained in:
parent
0e079e8290
commit
d6b8ab17f1
|
|
@ -26,6 +26,27 @@
|
||||||
'browser.capture.file',
|
'browser.capture.file',
|
||||||
'browser.capture.converted'
|
'browser.capture.converted'
|
||||||
];
|
];
|
||||||
|
var EVENT_LABELS = {
|
||||||
|
'workspace.selected': 'Workspace selected',
|
||||||
|
'case.selected': 'Workspace selected',
|
||||||
|
'file.opened': 'File opened',
|
||||||
|
'file.changed': 'File changed',
|
||||||
|
'note.saved': 'Note edited',
|
||||||
|
'action.started': 'Work session detected',
|
||||||
|
'browser.capture.received': 'Browser capture received',
|
||||||
|
'browser.capture.page': 'Page captured',
|
||||||
|
'browser.capture.selection': 'Selection captured',
|
||||||
|
'browser.capture.link': 'Link captured',
|
||||||
|
'browser.capture.file': 'File captured',
|
||||||
|
'browser.capture.converted': 'Capture converted'
|
||||||
|
};
|
||||||
|
var LOW_VALUE_EVENT_TYPES = {
|
||||||
|
'workspace.selected': true,
|
||||||
|
'case.selected': true,
|
||||||
|
'file.selected': true,
|
||||||
|
'file.opened': true,
|
||||||
|
'note.opened': true
|
||||||
|
};
|
||||||
|
|
||||||
function injectStyles() {
|
function injectStyles() {
|
||||||
if (document.getElementById('activity-style-injected')) return;
|
if (document.getElementById('activity-style-injected')) return;
|
||||||
|
|
@ -36,33 +57,36 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.activity-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:#e0e0e0;background:#0d0d1a}',
|
'.activity-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:var(--vt-color-text-primary,#f4f7fb);background:var(--vt-color-background,#101020)}',
|
||||||
'.activity-toolbar{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid #16213e;background:#12122a;flex-shrink:0;flex-wrap:wrap}',
|
'.activity-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.5rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface-muted,#111629);flex-shrink:0;flex-wrap:wrap}',
|
||||||
'.activity-title{font-size:.84rem;font-weight:600;color:#e0e0e0}',
|
'.activity-title{font-size:.84rem;font-weight:600;color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.activity-count{font-size:.72rem;color:#8b8ba8}',
|
'.activity-count{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.activity-spacer{flex:1}',
|
'.activity-spacer{flex:1}',
|
||||||
'.activity-btn{font-size:.78rem;padding:.32rem .65rem;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ccc;cursor:pointer}',
|
'.activity-btn{font-size:.78rem;padding:.32rem .65rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer}',
|
||||||
'.activity-btn:hover{background:#2a2a4e;border-color:#4ecca3}',
|
'.activity-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.activity-btn:disabled{opacity:.45;cursor:default}',
|
'.activity-btn:disabled{opacity:.45;cursor:default}',
|
||||||
'.activity-btn.danger{border-color:#633;color:#ff9a9a}',
|
'.activity-btn.danger{border-color:rgba(233,69,96,.42);color:#ff9a9a}',
|
||||||
'.activity-status{font-size:.72rem;color:#8b8ba8;white-space:nowrap}',
|
'.activity-status{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);white-space:nowrap}',
|
||||||
'.activity-status.error{color:#e74c3c}',
|
'.activity-status.error{display:inline-flex;border:1px solid rgba(233,69,96,.45);border-radius:var(--vt-radius-sm,4px);background:var(--vt-color-danger-muted,rgba(233,69,96,.14));color:#ffc6ce;padding:.18rem .4rem}',
|
||||||
'.activity-suggestions{border-bottom:1px solid rgba(22,33,62,.65);background:#111126;padding:.55rem .75rem;display:grid;gap:.5rem}',
|
'.activity-suggestions{border-bottom:1px solid rgba(32,43,70,.72);background:var(--vt-color-surface-muted,#111629);padding:.65rem .75rem;display:grid;gap:.5rem}',
|
||||||
'.activity-suggestions-title{font-size:.76rem;font-weight:600;color:#8b8ba8;text-transform:uppercase;letter-spacing:.04em}',
|
'.activity-suggestions-title{font-size:.76rem;font-weight:600;color:var(--vt-color-text-muted,#7f8aa3);text-transform:uppercase;letter-spacing:.04em}',
|
||||||
'.activity-suggestion{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.65rem;align-items:start;padding:.55rem .65rem;border:1px solid rgba(78,204,163,.25);border-radius:4px;background:#14142c}',
|
'.activity-suggestion{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.65rem;align-items:start;padding:.65rem .75rem;border:1px solid var(--vt-color-border,#202b46);border-radius:var(--vt-radius-lg,8px);background:var(--vt-color-surface,#15152c)}',
|
||||||
'.activity-suggestion-title{font-size:.84rem;color:#e0e0e0;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.activity-suggestion-title{font-size:.84rem;color:var(--vt-color-text-primary,#f4f7fb);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.activity-suggestion-summary{margin-top:.22rem;font-size:.76rem;color:#aaa;line-height:1.4;white-space:pre-wrap;overflow-wrap:anywhere}',
|
'.activity-suggestion-summary{margin-top:.22rem;font-size:.76rem;color:var(--vt-color-text-secondary,#b7c0d4);line-height:1.4;white-space:pre-wrap;overflow-wrap:anywhere}',
|
||||||
'.activity-suggestion-minutes{font-size:.76rem;color:#4ecca3;white-space:nowrap}',
|
'.activity-suggestion-minutes{font-size:.76rem;color:var(--vt-color-accent,#4ecca3);white-space:nowrap}',
|
||||||
'.activity-list{flex:1;min-height:0;overflow:auto;background:#101020}',
|
'.activity-list{flex:1;min-height:0;overflow:auto;background:var(--vt-color-background,#101020)}',
|
||||||
'.activity-empty{height:100%;display:flex;align-items:center;justify-content:center;color:#666;font-size:.86rem;padding:2rem;text-align:center}',
|
'.activity-empty{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;color:var(--vt-color-text-muted,#7f8aa3);font-size:.86rem;padding:2rem;text-align:center}',
|
||||||
'.activity-row{display:grid;grid-template-columns:9.5rem minmax(0,1fr);gap:.75rem;padding:.72rem .85rem;border-bottom:1px solid rgba(22,33,62,.6)}',
|
'.activity-empty-title{color:var(--vt-color-text-secondary,#b7c0d4);font-weight:650}',
|
||||||
'.activity-time{font-size:.72rem;color:#777;white-space:nowrap}',
|
'.activity-row{display:grid;grid-template-columns:9.5rem minmax(0,1fr);gap:.75rem;padding:.72rem .85rem;border-bottom:1px solid rgba(32,43,70,.72)}',
|
||||||
|
'.activity-row:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
|
'.activity-time{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);white-space:nowrap}',
|
||||||
'.activity-main{min-width:0}',
|
'.activity-main{min-width:0}',
|
||||||
'.activity-row-head{display:flex;align-items:center;gap:.45rem;min-width:0}',
|
'.activity-row-head{display:flex;align-items:center;gap:.45rem;min-width:0}',
|
||||||
'.activity-type{font-size:.68rem;color:#4ecca3;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0}',
|
'.activity-type{font-size:.68rem;color:var(--vt-color-accent,#4ecca3);text-transform:uppercase;letter-spacing:.04em;flex-shrink:0}',
|
||||||
'.activity-title-text{font-size:.86rem;color:#e0e0e0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.activity-title-text{font-size:.86rem;color:var(--vt-color-text-primary,#f4f7fb);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.activity-summary{margin-top:.25rem;font-size:.78rem;line-height:1.4;color:#aaa;white-space:pre-wrap;overflow-wrap:anywhere}',
|
'.activity-summary{margin-top:.25rem;font-size:.78rem;line-height:1.4;color:var(--vt-color-text-secondary,#b7c0d4);white-space:pre-wrap;overflow-wrap:anywhere}',
|
||||||
'.activity-source{margin-top:.25rem;font-size:.72rem;color:#777}',
|
'.activity-source{margin-top:.25rem;font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
|
'.activity-details{margin-top:.25rem;font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}.activity-details summary{cursor:pointer}',
|
||||||
'@media(max-width:760px){.activity-row,.activity-suggestion{grid-template-columns:1fr;gap:.25rem}.activity-toolbar{align-items:stretch}.activity-status{width:100%}}'
|
'@media(max-width:760px){.activity-row,.activity-suggestion{grid-template-columns:1fr;gap:.25rem}.activity-toolbar{align-items:stretch}.activity-status{width:100%}}'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
|
|
@ -178,6 +202,11 @@
|
||||||
}).slice(0, MAX_EVENTS);
|
}).slice(0, MAX_EVENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isMeaningfulActivity(activity) {
|
||||||
|
var type = text(activity && activity.type).toLowerCase();
|
||||||
|
return !LOW_VALUE_EVENT_TYPES[type];
|
||||||
|
}
|
||||||
|
|
||||||
function eventTimeMs(activity) {
|
function eventTimeMs(activity) {
|
||||||
var value = activity && (activity.occurredAt || activity.receivedAt);
|
var value = activity && (activity.occurredAt || activity.receivedAt);
|
||||||
var date = value ? new Date(value) : null;
|
var date = value ? new Date(value) : null;
|
||||||
|
|
@ -209,7 +238,28 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function eventLabel(activity) {
|
function eventLabel(activity) {
|
||||||
return text(activity && (activity.title || activity.summary || activity.type || activity.activityId)).trim();
|
return humanEventTitle(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
function humanEventType(type) {
|
||||||
|
return EVENT_LABELS[text(type).toLowerCase()] || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function humanEventTitle(activity) {
|
||||||
|
var explicit = text(activity && activity.title).trim();
|
||||||
|
var type = text(activity && activity.type).trim();
|
||||||
|
if (explicit && explicit.toLowerCase() !== type.toLowerCase()) return explicit;
|
||||||
|
return humanEventType(type) || text(activity && (activity.summary || activity.activityId)).trim() || 'Activity event';
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventKind(activity) {
|
||||||
|
var type = text(activity && activity.type).toLowerCase();
|
||||||
|
if (type.indexOf('browser.capture') === 0) return 'Capture';
|
||||||
|
if (type.indexOf('file.') === 0) return 'File';
|
||||||
|
if (type.indexOf('note.') === 0) return 'Note';
|
||||||
|
if (type.indexOf('workspace') !== -1 || type.indexOf('case.') === 0) return 'Workspace';
|
||||||
|
if (type.indexOf('action.') === 0) return 'Work';
|
||||||
|
return 'Activity';
|
||||||
}
|
}
|
||||||
|
|
||||||
function summarizeEvents(groupEvents) {
|
function summarizeEvents(groupEvents) {
|
||||||
|
|
@ -226,7 +276,7 @@
|
||||||
function buildWorklogSuggestions(activityList, workspaceFilter) {
|
function buildWorklogSuggestions(activityList, workspaceFilter) {
|
||||||
var filter = cleanWorkspace(workspaceFilter);
|
var filter = cleanWorkspace(workspaceFilter);
|
||||||
var groups = {};
|
var groups = {};
|
||||||
sortEvents(activityList || []).forEach(function (activity) {
|
sortEvents(activityList || []).filter(isMeaningfulActivity).forEach(function (activity) {
|
||||||
var workspace = suggestionWorkspace(activity);
|
var workspace = suggestionWorkspace(activity);
|
||||||
if (filter && workspace !== filter) return;
|
if (filter && workspace !== filter) return;
|
||||||
var day = eventDay(activity);
|
var day = eventDay(activity);
|
||||||
|
|
@ -271,7 +321,7 @@
|
||||||
globalEventKeys(settings).forEach(function (key) {
|
globalEventKeys(settings).forEach(function (key) {
|
||||||
all = all.concat(normalizeStoredEvents(settings[key], key));
|
all = all.concat(normalizeStoredEvents(settings[key], key));
|
||||||
});
|
});
|
||||||
return sortEvents(all);
|
return sortEvents(all).filter(isMeaningfulActivity);
|
||||||
}
|
}
|
||||||
var workspaceKey = WORKSPACE_PREFIX + encodeKey(workspace);
|
var workspaceKey = WORKSPACE_PREFIX + encodeKey(workspace);
|
||||||
var scopedEvents = normalizeStoredEvents(settings[workspaceKey], workspaceKey);
|
var scopedEvents = normalizeStoredEvents(settings[workspaceKey], workspaceKey);
|
||||||
|
|
@ -281,7 +331,7 @@
|
||||||
var legacyEvents = normalizeStoredEvents(settings[LEGACY_KEY], LEGACY_KEY).filter(function (item) {
|
var legacyEvents = normalizeStoredEvents(settings[LEGACY_KEY], LEGACY_KEY).filter(function (item) {
|
||||||
return item.workspaceRootPath === workspace;
|
return item.workspaceRootPath === workspace;
|
||||||
});
|
});
|
||||||
return sortEvents(scopedEvents.concat(globalEvents, legacyEvents));
|
return sortEvents(scopedEvents.concat(globalEvents, legacyEvents)).filter(isMeaningfulActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(value) {
|
function formatDate(value) {
|
||||||
|
|
@ -378,7 +428,10 @@
|
||||||
function renderList() {
|
function renderList() {
|
||||||
listEl.innerHTML = '';
|
listEl.innerHTML = '';
|
||||||
if (events.length === 0) {
|
if (events.length === 0) {
|
||||||
listEl.appendChild(el('div', { className: 'activity-empty', textContent: 'No activity events yet.' }));
|
listEl.appendChild(el('div', { className: 'activity-empty' }, [
|
||||||
|
el('div', { className: 'activity-empty-title', textContent: 'No activity events yet' }),
|
||||||
|
el('div', { textContent: 'File changes, browser captures, and conversions will appear here.' })
|
||||||
|
]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
events.forEach(function (activity) {
|
events.forEach(function (activity) {
|
||||||
|
|
@ -389,11 +442,14 @@
|
||||||
el('div', { className: 'activity-time', textContent: formatDate(activity.occurredAt) || '-' }),
|
el('div', { className: 'activity-time', textContent: formatDate(activity.occurredAt) || '-' }),
|
||||||
el('div', { className: 'activity-main' }, [
|
el('div', { className: 'activity-main' }, [
|
||||||
el('div', { className: 'activity-row-head' }, [
|
el('div', { className: 'activity-row-head' }, [
|
||||||
el('span', { className: 'activity-type', textContent: activity.type }),
|
el('span', { className: 'activity-type', textContent: eventKind(activity) }),
|
||||||
el('span', { className: 'activity-title-text', textContent: activity.title || 'Activity event' })
|
el('span', { className: 'activity-title-text', textContent: humanEventTitle(activity) })
|
||||||
]),
|
]),
|
||||||
activity.summary ? el('div', { className: 'activity-summary', textContent: activity.summary }) : null,
|
activity.summary ? el('div', { className: 'activity-summary', textContent: activity.summary }) : null,
|
||||||
activity.sourcePluginId ? el('div', { className: 'activity-source', textContent: activity.sourcePluginId }) : null
|
el('details', { className: 'activity-details' }, [
|
||||||
|
el('summary', {}, ['Details']),
|
||||||
|
el('div', { className: 'activity-source', textContent: 'Event: ' + activity.type + (activity.sourcePluginId ? ' · Source: ' + activity.sourcePluginId : '') })
|
||||||
|
])
|
||||||
])
|
])
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -22,35 +22,35 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.browser-inbox-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:#e0e0e0;background:#0d0d1a}',
|
'.browser-inbox-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:var(--vt-color-text-primary,#f4f7fb);background:var(--vt-color-background,#101020)}',
|
||||||
'.browser-inbox-toolbar{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid #16213e;background:#12122a;flex-shrink:0;flex-wrap:wrap}',
|
'.browser-inbox-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.5rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface-muted,#111629);flex-shrink:0;flex-wrap:wrap}',
|
||||||
'.browser-inbox-title{font-size:.82rem;font-weight:600;color:#e0e0e0}',
|
'.browser-inbox-title{font-size:.82rem;font-weight:600;color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.browser-inbox-count{font-size:.72rem;color:#8b8ba8}',
|
'.browser-inbox-count{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.browser-inbox-spacer{flex:1}',
|
'.browser-inbox-spacer{flex:1}',
|
||||||
'.browser-inbox-btn{font-size:.78rem;padding:.32rem .65rem;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ccc;cursor:pointer}',
|
'.browser-inbox-btn{font-size:.78rem;padding:.32rem .65rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer}',
|
||||||
'.browser-inbox-btn:hover{background:#2a2a4e;border-color:#4ecca3}',
|
'.browser-inbox-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.browser-inbox-btn:disabled{opacity:.45;cursor:default}',
|
'.browser-inbox-btn:disabled{opacity:.45;cursor:default}',
|
||||||
'.browser-inbox-btn.danger{border-color:#633;color:#ff9a9a}',
|
'.browser-inbox-btn.danger{border-color:rgba(233,69,96,.42);color:#ff9a9a;background:var(--vt-color-danger-muted,rgba(233,69,96,.14))}',
|
||||||
'.browser-inbox-status{font-size:.72rem;color:#8b8ba8;white-space:nowrap}',
|
'.browser-inbox-status{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);white-space:nowrap}',
|
||||||
'.browser-inbox-status.error{color:#e74c3c}',
|
'.browser-inbox-status.error{display:inline-flex;border:1px solid rgba(233,69,96,.45);border-radius:var(--vt-radius-sm,4px);background:var(--vt-color-danger-muted,rgba(233,69,96,.14));color:#ffc6ce;padding:.18rem .4rem}',
|
||||||
'.browser-inbox-body{display:grid;grid-template-columns:minmax(260px,360px) minmax(0,1fr);flex:1;min-height:0}',
|
'.browser-inbox-body{display:grid;grid-template-columns:minmax(260px,360px) minmax(0,1fr);flex:1;min-height:0}',
|
||||||
'.browser-inbox-list{min-height:0;overflow:auto;border-right:1px solid #16213e;background:#101020}',
|
'.browser-inbox-list{min-height:0;overflow:auto;border-right:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface-muted,#111629)}',
|
||||||
'.browser-inbox-empty{height:100%;display:flex;align-items:center;justify-content:center;color:#666;font-size:.86rem;padding:2rem;text-align:center}',
|
'.browser-inbox-empty{height:100%;display:flex;align-items:center;justify-content:center;color:var(--vt-color-text-muted,#7f8aa3);font-size:.86rem;padding:2rem;text-align:center;line-height:1.45}',
|
||||||
'.browser-inbox-row{display:flex;flex-direction:column;gap:.22rem;padding:.65rem .75rem;border-bottom:1px solid rgba(22,33,62,.6);cursor:pointer}',
|
'.browser-inbox-row{display:flex;flex-direction:column;gap:.22rem;padding:.65rem .75rem;border-bottom:1px solid rgba(32,43,70,.72);cursor:pointer}',
|
||||||
'.browser-inbox-row:hover{background:#17172d}',
|
'.browser-inbox-row:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
'.browser-inbox-row.selected{background:#1a2a3a}',
|
'.browser-inbox-row.selected{background:var(--vt-color-surface-selected,rgba(78,204,163,.14));box-shadow:inset 2px 0 0 var(--vt-color-accent,#4ecca3)}',
|
||||||
'.browser-inbox-row-head{display:flex;align-items:center;gap:.45rem;min-width:0}',
|
'.browser-inbox-row-head{display:flex;align-items:center;gap:.45rem;min-width:0}',
|
||||||
'.browser-inbox-kind{font-size:.68rem;color:#4ecca3;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0}',
|
'.browser-inbox-kind{font-size:.68rem;color:var(--vt-color-accent,#4ecca3);text-transform:uppercase;letter-spacing:.04em;flex-shrink:0}',
|
||||||
'.browser-inbox-row-title{font-size:.86rem;color:#e0e0e0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.browser-inbox-row-title{font-size:.86rem;color:var(--vt-color-text-primary,#f4f7fb);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.browser-inbox-row-url{font-size:.72rem;color:#8b8ba8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.browser-inbox-row-url{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.browser-inbox-row-text{font-size:.76rem;color:#aaa;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}',
|
'.browser-inbox-row-text{font-size:.76rem;color:var(--vt-color-text-secondary,#b7c0d4);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}',
|
||||||
'.browser-inbox-detail{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:auto;padding:1rem;gap:.75rem}',
|
'.browser-inbox-detail{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:auto;padding:1rem;gap:.75rem}',
|
||||||
'.browser-inbox-detail-empty{margin:auto;color:#666;font-size:.86rem}',
|
'.browser-inbox-detail-empty{margin:auto;color:var(--vt-color-text-muted,#7f8aa3);font-size:.86rem}',
|
||||||
'.browser-inbox-detail-title{font-size:1rem;font-weight:600;color:#f0f0f0;word-break:break-word}',
|
'.browser-inbox-detail-title{font-size:1rem;font-weight:600;color:var(--vt-color-text-primary,#f4f7fb);word-break:break-word}',
|
||||||
'.browser-inbox-meta{display:grid;grid-template-columns:7rem minmax(0,1fr);gap:.35rem .75rem;font-size:.78rem}',
|
'.browser-inbox-meta{display:grid;grid-template-columns:7rem minmax(0,1fr);gap:.35rem .75rem;font-size:.78rem}',
|
||||||
'.browser-inbox-meta-label{color:#777}',
|
'.browser-inbox-meta-label{color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.browser-inbox-meta-value{color:#ccc;min-width:0;overflow-wrap:anywhere}',
|
'.browser-inbox-meta-value{color:var(--vt-color-text-secondary,#b7c0d4);min-width:0;overflow-wrap:anywhere}',
|
||||||
'.browser-inbox-text{border:1px solid #24304f;background:#101020;border-radius:6px;padding:.75rem;font-size:.85rem;line-height:1.5;color:#ddd;white-space:pre-wrap;overflow-wrap:anywhere}',
|
'.browser-inbox-text{border:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface,#15152c);border-radius:var(--vt-radius-lg,8px);padding:.75rem;font-size:.85rem;line-height:1.5;color:var(--vt-color-text-primary,#f4f7fb);white-space:pre-wrap;overflow-wrap:anywhere}',
|
||||||
'.browser-inbox-detail-actions{display:flex;gap:.5rem;flex-wrap:wrap}',
|
'.browser-inbox-detail-actions{display:flex;gap:.5rem;flex-wrap:wrap}',
|
||||||
'@media(max-width:760px){.browser-inbox-body{grid-template-columns:1fr}.browser-inbox-list{border-right:0;border-bottom:1px solid #16213e;max-height:45vh}.browser-inbox-meta{grid-template-columns:1fr}}'
|
'@media(max-width:760px){.browser-inbox-body{grid-template-columns:1fr}.browser-inbox-list{border-right:0;border-bottom:1px solid #16213e;max-height:45vh}.browser-inbox-meta{grid-template-columns:1fr}}'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
|
||||||
|
|
@ -15,56 +15,63 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.files-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:#e0e0e0;background:#0d0d1a;outline:none}',
|
'.files-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:var(--vt-color-text-primary,#f4f7fb);background:var(--vt-color-background,#101020);outline:none}',
|
||||||
'.files-toolbar{display:flex;align-items:center;gap:.45rem;padding:.5rem .75rem;border-bottom:1px solid #16213e;flex-shrink:0;background:#12122a;flex-wrap:wrap}',
|
'.files-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.5rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46);flex-shrink:0;background:var(--vt-color-surface-muted,#111629);flex-wrap:wrap}',
|
||||||
'.files-toolbar-btn,.files-row-btn{display:inline-flex;align-items:center;justify-content:center;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ccc;cursor:pointer;line-height:1}',
|
'.files-toolbar-group{display:inline-flex;align-items:center;gap:.25rem;padding-right:.5rem;border-right:1px solid var(--vt-color-border,#202b46)}',
|
||||||
|
'.files-toolbar-group:last-child{border-right:0;padding-right:0}',
|
||||||
|
'.files-toolbar-spacer{flex:1}',
|
||||||
|
'.files-toolbar-btn,.files-row-btn{display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer;line-height:1}',
|
||||||
'.files-toolbar-btn{width:2rem;height:2rem;padding:0}',
|
'.files-toolbar-btn{width:2rem;height:2rem;padding:0}',
|
||||||
'.files-row-btn{width:1.75rem;height:1.75rem;padding:0}',
|
'.files-row-btn{width:1.75rem;height:1.75rem;padding:0}',
|
||||||
|
'.files-panel .files-toolbar-btn{width:auto;min-width:4.5rem;padding:0 .65rem}',
|
||||||
'.files-toolbar-btn svg,.files-row-btn svg{width:16px;height:16px;display:block;fill:currentColor}',
|
'.files-toolbar-btn svg,.files-row-btn svg{width:16px;height:16px;display:block;fill:currentColor}',
|
||||||
'.files-toolbar-btn:hover,.files-row-btn:hover{background:#2a2a4e;border-color:#4ecca3}',
|
'.files-toolbar-btn:hover,.files-row-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.files-toolbar-btn:disabled,.files-row-btn:disabled{opacity:.45;cursor:default;border-color:#333}',
|
'.files-toolbar-btn:focus-visible,.files-row-btn:focus-visible{outline:0;box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.files-breadcrumb{display:flex;align-items:center;gap:.25rem;font-size:.8rem;color:#8b8ba8;min-width:160px;flex:1;overflow:hidden}',
|
'.files-toolbar-btn:disabled,.files-row-btn:disabled{opacity:.45;cursor:default;border-color:var(--vt-color-border,#202b46)}',
|
||||||
'.files-breadcrumb-item{color:#4ecca3;cursor:pointer;padding:.1rem .3rem;border-radius:3px;white-space:nowrap}',
|
'.files-toolbar-btn.danger,.files-row-btn.danger{color:#ff9aaa;border-color:rgba(233,69,96,.42)}',
|
||||||
'.files-breadcrumb-item:hover{background:#1a2a3a}',
|
'.files-breadcrumb{display:flex;align-items:center;gap:.25rem;font-size:.8rem;color:var(--vt-color-text-muted,#7f8aa3);min-width:160px;flex:1;overflow:hidden}',
|
||||||
'.files-breadcrumb-current{color:#ddd;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
'.files-breadcrumb-item{color:var(--vt-color-accent,#4ecca3);cursor:pointer;padding:.1rem .3rem;border-radius:var(--vt-radius-sm,4px);white-space:nowrap}',
|
||||||
'.files-breadcrumb-sep{color:#555}',
|
'.files-breadcrumb-item:hover{background:var(--vt-color-accent-muted,rgba(78,204,163,.14))}',
|
||||||
'.files-filter,.files-sort,.files-create-input,.files-rename-input{font-size:.78rem;padding:.32rem .5rem;border:1px solid #333;border-radius:4px;background:#0d0d1a;color:#e0e0e0;outline:none}',
|
'.files-breadcrumb-current{color:var(--vt-color-text-primary,#f4f7fb);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
||||||
|
'.files-breadcrumb-sep{color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
|
'.files-filter,.files-sort,.files-create-input,.files-rename-input{font-size:.78rem;padding:.32rem .5rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-primary,#f4f7fb);outline:none}',
|
||||||
'.files-filter{width:11rem}',
|
'.files-filter{width:11rem}',
|
||||||
'.files-sort{width:9.5rem;appearance:none;background-color:#0d0d1a;background-image:linear-gradient(45deg,transparent 50%,#8b8ba8 50%),linear-gradient(135deg,#8b8ba8 50%,transparent 50%);background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:1.6rem}',
|
'.files-sort{width:9.5rem;appearance:none;background-color:#0f1424;background-image:linear-gradient(45deg,transparent 50%,#8b8ba8 50%),linear-gradient(135deg,#8b8ba8 50%,transparent 50%);background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:1.6rem}',
|
||||||
'.files-filter:focus,.files-sort:focus,.files-create-input:focus,.files-rename-input:focus{border-color:#4ecca3}',
|
'.files-filter:focus,.files-sort:focus,.files-create-input:focus,.files-rename-input:focus{border-color:var(--vt-color-accent,#4ecca3);box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.files-list{flex:1;overflow:auto;min-height:0}',
|
'.files-list{flex:1;overflow:auto;min-height:0}',
|
||||||
'.files-header,.files-item{display:grid;grid-template-columns:minmax(160px,1fr) 90px 90px 150px 220px;align-items:center;gap:.5rem;padding:.38rem .75rem;border-bottom:1px solid rgba(22,33,62,.55)}',
|
'.files-header,.files-item{display:grid;grid-template-columns:minmax(160px,1fr) 90px 90px 150px 220px;align-items:center;gap:.5rem;padding:.38rem .75rem;border-bottom:1px solid rgba(22,33,62,.55)}',
|
||||||
'.files-header{position:sticky;top:0;background:#101028;color:#8b8ba8;font-size:.7rem;text-transform:uppercase;letter-spacing:.04em;z-index:1}',
|
'.files-header{position:sticky;top:0;background:var(--vt-color-surface-muted,#111629);color:var(--vt-color-text-muted,#7f8aa3);font-size:.7rem;text-transform:uppercase;letter-spacing:.04em;z-index:1}',
|
||||||
'.files-item{font-size:.84rem;cursor:pointer}',
|
'.files-item{font-size:.84rem;cursor:pointer}',
|
||||||
'.files-item:hover{background:#17172d}',
|
'.files-item:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
'.files-item.selected{background:#1a2a3a}',
|
'.files-item.selected{background:var(--vt-color-surface-selected,rgba(78,204,163,.14));box-shadow:inset 2px 0 0 var(--vt-color-accent,#4ecca3)}',
|
||||||
'.files-namecell{display:flex;align-items:center;gap:.55rem;min-width:0}',
|
'.files-namecell{display:flex;align-items:center;gap:.55rem;min-width:0}',
|
||||||
'.files-item-icon{width:1.25rem;height:1.25rem;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:#8b8ba8}',
|
'.files-item-icon{width:1.25rem;height:1.25rem;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.files-item-icon svg{display:block;width:16px;height:16px}',
|
'.files-item-icon svg{display:block;width:16px;height:16px}',
|
||||||
'.files-item-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.files-item-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.files-item-meta{font-size:.74rem;color:#777;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
'.files-item-meta{font-size:.74rem;color:var(--vt-color-text-muted,#7f8aa3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
||||||
'.files-row-actions{display:flex;align-items:center;justify-content:flex-end;gap:.35rem;white-space:nowrap}',
|
'.files-row-actions{display:flex;align-items:center;justify-content:flex-end;gap:.35rem;white-space:nowrap;opacity:.28;transition:opacity .12s ease}',
|
||||||
'.files-empty,.files-loading{flex:1;display:flex;align-items:center;justify-content:center;color:#666;font-size:.9rem;padding:2rem}',
|
'.files-item:hover .files-row-actions,.files-item.selected .files-row-actions{opacity:1}',
|
||||||
|
'.files-empty,.files-loading{flex:1;display:flex;align-items:center;justify-content:center;color:var(--vt-color-text-muted,#7f8aa3);font-size:.9rem;padding:2rem}',
|
||||||
'.files-empty{flex-direction:column;gap:.75rem;text-align:center}',
|
'.files-empty{flex-direction:column;gap:.75rem;text-align:center}',
|
||||||
'.files-empty-title{color:#8b8ba8}',
|
'.files-empty-title{color:var(--vt-color-text-secondary,#b7c0d4);font-weight:650}',
|
||||||
'.files-empty-actions{display:flex;align-items:center;justify-content:center;gap:.5rem;flex-wrap:wrap}',
|
'.files-empty-actions{display:flex;align-items:center;justify-content:center;gap:.5rem;flex-wrap:wrap}',
|
||||||
'.files-empty-btn{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;min-height:2rem;padding:.35rem .6rem;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ccc;cursor:pointer;font-size:.78rem}',
|
'.files-empty-btn{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;min-height:2rem;padding:.35rem .6rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer;font-size:.78rem}',
|
||||||
'.files-empty-btn:hover{background:#2a2a4e;border-color:#4ecca3}',
|
'.files-empty-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3)}',
|
||||||
'.files-empty-btn svg{width:15px;height:15px;display:block;fill:currentColor}',
|
'.files-empty-btn svg{width:15px;height:15px;display:block;fill:currentColor}',
|
||||||
'.files-error{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#e74c3c;gap:.5rem;padding:1rem}',
|
'.files-error{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--vt-color-danger,#e94560);gap:.5rem;padding:1rem}',
|
||||||
'.files-error-msg{font-size:.85rem;color:#aaa;max-width:420px;text-align:center}',
|
'.files-error-msg{font-size:.85rem;color:var(--vt-color-text-secondary,#b7c0d4);max-width:420px;text-align:center}',
|
||||||
'.files-panel{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-top:1px solid #16213e;flex-shrink:0;background:#12122a}',
|
'.files-panel{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-top:1px solid var(--vt-color-border,#202b46);flex-shrink:0;background:var(--vt-color-surface-muted,#111629)}',
|
||||||
'.files-field-stack{display:flex;flex:1;min-width:160px;flex-direction:column;gap:.25rem}',
|
'.files-field-stack{display:flex;flex:1;min-width:160px;flex-direction:column;gap:.25rem}',
|
||||||
'.files-panel-error{display:none;color:#ff8a8a;font-size:.72rem;line-height:1.2}',
|
'.files-panel-error{display:none;color:#ff9aaa;font-size:.72rem;line-height:1.2}',
|
||||||
'.files-create-input,.files-rename-input{flex:1;min-width:160px}',
|
'.files-create-input,.files-rename-input{flex:1;min-width:160px}',
|
||||||
'@media(max-width:760px){.files-header,.files-item{grid-template-columns:minmax(130px,1fr) 70px 0 0 150px}.files-header span:nth-child(3),.files-header span:nth-child(4),.files-item-meta.hide-narrow{display:none}.files-toolbar{align-items:stretch}.files-filter,.files-sort{width:100%}}',
|
'@media(max-width:760px){.files-header,.files-item{grid-template-columns:minmax(130px,1fr) 70px 0 0 150px}.files-header span:nth-child(3),.files-header span:nth-child(4),.files-item-meta.hide-narrow{display:none}.files-toolbar{align-items:stretch}.files-filter,.files-sort{width:100%}}',
|
||||||
'.files-ctx-menu{position:fixed;z-index:9999;min-width:180px;background:#1a1a2e;border:1px solid #333;border-radius:6px;padding:6px 0;box-shadow:0 8px 24px rgba(0,0,0,.5);font-size:.84rem;color:#e0e0e0;user-select:none}',
|
'.files-ctx-menu{position:fixed;z-index:9999;min-width:180px;background:var(--vt-color-surface,#15152c);border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);padding:6px 0;box-shadow:var(--vt-elevation-menu,0 14px 32px rgba(0,0,0,.42));font-size:.84rem;color:var(--vt-color-text-primary,#f4f7fb);user-select:none}',
|
||||||
'.files-ctx-menu-item{padding:6px 16px;cursor:pointer;white-space:nowrap;display:flex;align-items:center;gap:.5rem}',
|
'.files-ctx-menu-item{padding:6px 16px;cursor:pointer;white-space:nowrap;display:flex;align-items:center;gap:.5rem}',
|
||||||
'.files-ctx-menu-item svg{width:14px;height:14px;fill:currentColor;opacity:.9}',
|
'.files-ctx-menu-item svg{width:14px;height:14px;fill:currentColor;opacity:.9}',
|
||||||
'.files-ctx-menu-item:hover{background:#2a2a4e}',
|
'.files-ctx-menu-item:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
'.files-ctx-menu-item.danger{color:#e74c3c}',
|
'.files-ctx-menu-item.danger{color:#ff9aaa}',
|
||||||
'.files-ctx-menu-item.danger:hover{background:#2a2a4e;color:#ff6b6b}',
|
'.files-ctx-menu-item.danger:hover{background:var(--vt-color-danger-muted,rgba(233,69,96,.14));color:#ffc6ce}',
|
||||||
'.files-ctx-menu-sep{height:1px;background:#333;margin:4px 8px}',
|
'.files-ctx-menu-sep{height:1px;background:var(--vt-color-border,#202b46);margin:4px 8px}',
|
||||||
'.files-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:center;justify-content:center}',
|
'.files-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:center;justify-content:center}',
|
||||||
'.files-modal{width:400px;max-width:90vw;padding:24px;background:#1a1a2e;border:1px solid #333;border-radius:12px;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;box-shadow:0 12px 40px rgba(0,0,0,.5)}',
|
'.files-modal{width:400px;max-width:90vw;padding:24px;background:#1a1a2e;border:1px solid #333;border-radius:12px;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;box-shadow:0 12px 40px rgba(0,0,0,.5)}',
|
||||||
'.files-modal-title{font-size:.95rem;line-height:1.5;margin-bottom:20px;word-wrap:break-word}',
|
'.files-modal-title{font-size:.95rem;line-height:1.5;margin-bottom:20px;word-wrap:break-word}',
|
||||||
|
|
@ -407,8 +414,16 @@
|
||||||
el('option', { value: 'modified-desc' }, ['Modified']),
|
el('option', { value: 'modified-desc' }, ['Modified']),
|
||||||
el('option', { value: 'size-desc' }, ['Size'])
|
el('option', { value: 'size-desc' }, ['Size'])
|
||||||
]);
|
]);
|
||||||
|
trashBtn.classList.add('danger');
|
||||||
toolbar.appendChild(breadcrumb);
|
toolbar.appendChild(breadcrumb);
|
||||||
[backBtn, forwardBtn, upBtn, refreshBtn, newFolderBtn, newMdBtn, newTextBtn, openBtn, renameBtn, trashBtn, trashViewBtn, cutBtn, copyBtn, pasteBtn, filterInput, sortSelect].forEach(function (node) { toolbar.appendChild(node); });
|
[
|
||||||
|
el('div', { className: 'files-toolbar-group', 'aria-label': 'Navigation' }, [backBtn, forwardBtn, upBtn, refreshBtn]),
|
||||||
|
el('div', { className: 'files-toolbar-group', 'aria-label': 'Create' }, [newFolderBtn, newMdBtn, newTextBtn]),
|
||||||
|
el('div', { className: 'files-toolbar-group', 'aria-label': 'Selection actions' }, [openBtn, renameBtn, trashBtn]),
|
||||||
|
el('div', { className: 'files-toolbar-group', 'aria-label': 'Clipboard and trash' }, [trashViewBtn, cutBtn, copyBtn, pasteBtn]),
|
||||||
|
el('span', { className: 'files-toolbar-spacer' }),
|
||||||
|
el('div', { className: 'files-toolbar-group', 'aria-label': 'Filter and sort' }, [filterInput, sortSelect])
|
||||||
|
].forEach(function (node) { toolbar.appendChild(node); });
|
||||||
containerEl.appendChild(toolbar);
|
containerEl.appendChild(toolbar);
|
||||||
|
|
||||||
var listContainer = el('div', { className: 'files-list', 'data-files-list': '' });
|
var listContainer = el('div', { className: 'files-list', 'data-files-list': '' });
|
||||||
|
|
@ -647,7 +662,9 @@
|
||||||
'data-file-path': entry.relativePath,
|
'data-file-path': entry.relativePath,
|
||||||
draggable: 'true',
|
draggable: 'true',
|
||||||
tabindex: '0',
|
tabindex: '0',
|
||||||
onClick: function (e) { selectEntry(entry, e); },
|
onClick: function (e) {
|
||||||
|
selectEntry(entry, e);
|
||||||
|
},
|
||||||
onDblclick: function () { openEntry(entry); },
|
onDblclick: function () { openEntry(entry); },
|
||||||
onDragstart: function (e) {
|
onDragstart: function (e) {
|
||||||
var paths = [];
|
var paths = [];
|
||||||
|
|
@ -676,7 +693,7 @@
|
||||||
el('div', { className: 'files-row-actions' }, [
|
el('div', { className: 'files-row-actions' }, [
|
||||||
iconButton('row-open', 'Open', 'open', function (event) { event.stopPropagation(); openEntry(entry); }, 'files-row-btn'),
|
iconButton('row-open', 'Open', 'open', function (event) { event.stopPropagation(); openEntry(entry); }, 'files-row-btn'),
|
||||||
iconButton('row-rename', 'Rename', 'rename', function (event) { event.stopPropagation(); beginRename(entry); }, 'files-row-btn'),
|
iconButton('row-rename', 'Rename', 'rename', function (event) { event.stopPropagation(); beginRename(entry); }, 'files-row-btn'),
|
||||||
iconButton('row-trash', 'Move to trash', 'trash', function (event) { event.stopPropagation(); trashEntry(entry); }, 'files-row-btn')
|
iconButton('row-trash', 'Move to trash', 'trash', function (event) { event.stopPropagation(); trashEntry(entry); }, 'files-row-btn danger')
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
listContainer.appendChild(row);
|
listContainer.appendChild(row);
|
||||||
|
|
|
||||||
|
|
@ -20,30 +20,47 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.journal-root{display:flex;flex-direction:column;height:100%;min-height:0;background:#0d0d1a;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif}',
|
'.journal-root{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--vt-color-background,#101020);color:var(--vt-color-text-primary,#f4f7fb);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif}',
|
||||||
'.journal-toolbar{display:flex;align-items:center;gap:.5rem;padding:.55rem .75rem;border-bottom:1px solid #16213e;background:#12122a;flex-shrink:0;flex-wrap:wrap}',
|
'.journal-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.55rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface-muted,#111629);flex-shrink:0;flex-wrap:wrap}',
|
||||||
'.journal-title{font-size:.86rem;font-weight:600}',
|
'.journal-title{font-size:.86rem;font-weight:600}',
|
||||||
'.journal-count{font-size:.72rem;color:#8b8ba8}',
|
'.journal-count{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.journal-spacer{flex:1}',
|
'.journal-spacer{flex:1}',
|
||||||
'.journal-btn{font-size:.78rem;padding:.36rem .65rem;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ddd;cursor:pointer}',
|
'.journal-btn{font-size:.78rem;padding:.36rem .65rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:.35rem}',
|
||||||
'.journal-btn:hover{border-color:#4ecca3;background:#2a2a4e}',
|
'.journal-btn svg{width:14px;height:14px;display:block;fill:currentColor}',
|
||||||
|
'.journal-btn:hover{border-color:var(--vt-color-accent,#4ecca3);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.journal-btn:disabled{opacity:.45;cursor:default}',
|
'.journal-btn:disabled{opacity:.45;cursor:default}',
|
||||||
'.journal-status{font-size:.72rem;color:#8b8ba8}',
|
'.journal-status{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.journal-status.error{color:#e74c3c}',
|
'.journal-status.error{display:inline-flex;border:1px solid rgba(233,69,96,.45);border-radius:var(--vt-radius-sm,4px);background:var(--vt-color-danger-muted,rgba(233,69,96,.14));color:#ffc6ce;padding:.18rem .4rem}',
|
||||||
'.journal-form{display:grid;grid-template-columns:8rem minmax(10rem,1fr) 7rem auto auto;gap:.45rem;padding:.65rem .75rem;border-bottom:1px solid rgba(22,33,62,.65);background:#101020;align-items:center}',
|
'.journal-input{font-size:.8rem;padding:.38rem .5rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-primary,#f4f7fb);min-width:0;font-family:inherit}',
|
||||||
'.journal-input{font-size:.8rem;padding:.38rem .5rem;border:1px solid #333;border-radius:4px;background:#0d0d1a;color:#e0e0e0;min-width:0}',
|
'.journal-input.textarea{min-height:7rem;resize:vertical;line-height:1.4}',
|
||||||
'.journal-input:focus{outline:none;border-color:#4ecca3}',
|
'.journal-input:focus{outline:none;border-color:var(--vt-color-accent,#4ecca3);box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.journal-billable{display:flex;align-items:center;gap:.25rem;font-size:.74rem;color:#aaa;white-space:nowrap}',
|
'.journal-billable{display:flex;align-items:center;gap:.25rem;font-size:.74rem;color:var(--vt-color-text-secondary,#b7c0d4);white-space:nowrap}',
|
||||||
'.journal-list{flex:1;min-height:0;overflow:auto;background:#101020}',
|
'.journal-list{flex:1;min-height:0;overflow:auto;background:var(--vt-color-background,#101020)}',
|
||||||
'.journal-empty{height:100%;display:flex;align-items:center;justify-content:center;color:#666;font-size:.86rem;padding:2rem;text-align:center}',
|
'.journal-empty{height:100%;display:flex;align-items:center;justify-content:center;color:var(--vt-color-text-muted,#7f8aa3);font-size:.86rem;padding:2rem;text-align:center}',
|
||||||
'.journal-row{display:grid;grid-template-columns:8rem minmax(0,1fr) auto;gap:.7rem;padding:.75rem .85rem;border-bottom:1px solid rgba(22,33,62,.6)}',
|
'.journal-row{display:grid;grid-template-columns:8rem minmax(0,1fr) auto auto;gap:.7rem;margin:.5rem .75rem 0;padding:.75rem .85rem;border:1px solid var(--vt-color-border,#202b46);border-radius:var(--vt-radius-lg,8px);background:var(--vt-color-surface,#15152c);align-items:start}',
|
||||||
'.journal-date{font-size:.75rem;color:#8b8ba8;white-space:nowrap}',
|
'.journal-row:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
|
'.journal-date{font-size:.75rem;color:var(--vt-color-text-muted,#7f8aa3);white-space:nowrap}',
|
||||||
'.journal-main{min-width:0}',
|
'.journal-main{min-width:0}',
|
||||||
'.journal-entry-title{font-size:.88rem;color:#e0e0e0;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.journal-entry-title{font-size:.88rem;color:var(--vt-color-text-primary,#f4f7fb);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.journal-summary{margin-top:.25rem;font-size:.78rem;line-height:1.4;color:#aaa;white-space:pre-wrap;overflow-wrap:anywhere}',
|
'.journal-summary{margin-top:.25rem;font-size:.78rem;line-height:1.4;color:var(--vt-color-text-secondary,#b7c0d4);white-space:pre-wrap;overflow-wrap:anywhere}',
|
||||||
'.journal-meta{margin-top:.25rem;font-size:.72rem;color:#777}',
|
'.journal-meta{margin-top:.25rem;font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.journal-minutes{font-size:.78rem;color:#4ecca3;white-space:nowrap}',
|
'.journal-minutes{font-size:.78rem;color:var(--vt-color-accent,#4ecca3);white-space:nowrap}',
|
||||||
'@media(max-width:820px){.journal-form,.journal-row{grid-template-columns:1fr}.journal-btn{width:100%}.journal-toolbar{align-items:stretch}.journal-status{width:100%}}'
|
'.journal-row-actions{display:flex;gap:.25rem}',
|
||||||
|
'.journal-icon-btn{width:1.65rem;height:1.65rem;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--vt-color-border,#202b46);border-radius:var(--vt-radius-sm,4px);background:transparent;color:var(--vt-color-text-muted,#7f8aa3);cursor:pointer;padding:0}',
|
||||||
|
'.journal-icon-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3);color:var(--vt-color-accent,#4ecca3)}',
|
||||||
|
'.journal-icon-btn.danger:hover{border-color:rgba(233,69,96,.65);color:var(--vt-color-danger,#e94560)}',
|
||||||
|
'.journal-icon-btn svg{width:14px;height:14px;display:block;fill:currentColor}',
|
||||||
|
'.journal-modal-host[hidden]{display:none}',
|
||||||
|
'.journal-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.58);z-index:10000;display:flex;align-items:center;justify-content:center;padding:1rem}',
|
||||||
|
'.journal-modal{width:520px;max-width:96vw;display:grid;gap:.75rem;padding:1rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-lg,8px);background:var(--vt-color-surface,#15152c);box-shadow:0 18px 44px rgba(0,0,0,.38)}',
|
||||||
|
'.journal-modal-title{font-size:.95rem;font-weight:650;color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
|
'.journal-modal-grid{display:grid;grid-template-columns:1fr 8rem;gap:.6rem}',
|
||||||
|
'.journal-field{display:grid;gap:.3rem;font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
|
'.journal-field.wide{grid-column:1/-1}',
|
||||||
|
'.journal-modal-actions{display:flex;justify-content:flex-end;gap:.5rem}',
|
||||||
|
'.journal-btn.primary{background:var(--vt-color-accent,#4ecca3);border-color:var(--vt-color-accent,#4ecca3);color:#101827}',
|
||||||
|
'.journal-btn.ghost{background:transparent}',
|
||||||
|
'@media(max-width:820px){.journal-row{grid-template-columns:1fr}.journal-btn{width:100%}.journal-toolbar{align-items:stretch}.journal-status{width:100%}.journal-modal-grid{grid-template-columns:1fr}}'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
function el(tag, attrs, children) {
|
function el(tag, attrs, children) {
|
||||||
|
|
@ -52,6 +69,7 @@
|
||||||
Object.keys(attrs).forEach(function (key) {
|
Object.keys(attrs).forEach(function (key) {
|
||||||
if (attrs[key] == null) return;
|
if (attrs[key] == null) return;
|
||||||
if (key === 'className') elem.className = attrs[key];
|
if (key === 'className') elem.className = attrs[key];
|
||||||
|
else if (key === 'innerHTML') elem.innerHTML = attrs[key];
|
||||||
else if (key === 'textContent') elem.textContent = attrs[key];
|
else if (key === 'textContent') elem.textContent = attrs[key];
|
||||||
else if (key.slice(0, 2) === 'on') elem.addEventListener(key.slice(2).toLowerCase(), attrs[key]);
|
else if (key.slice(0, 2) === 'on') elem.addEventListener(key.slice(2).toLowerCase(), attrs[key]);
|
||||||
else elem.setAttribute(key, attrs[key]);
|
else elem.setAttribute(key, attrs[key]);
|
||||||
|
|
@ -166,6 +184,16 @@
|
||||||
return 'journal:' + cleanWorkspace(workspaceRoot || 'Global') + ':' + text(date) + ':' + encodeKey(title).slice(0, 48) + ':' + Date.now();
|
return 'journal:' + cleanWorkspace(workspaceRoot || 'Global') + ':' + text(date) + ':' + encodeKey(title).slice(0, 48) + ':' + Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ICONS = {
|
||||||
|
add: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z',
|
||||||
|
edit: 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z',
|
||||||
|
trash: 'M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM8 9h8v10H8V9zm7.5-5-1-1h-5l-1 1H5v2h14V4z'
|
||||||
|
};
|
||||||
|
|
||||||
|
function iconSvg(name) {
|
||||||
|
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="' + (ICONS[name] || ICONS.edit) + '" fill="currentColor"/></svg>';
|
||||||
|
}
|
||||||
|
|
||||||
function JournalView() {}
|
function JournalView() {}
|
||||||
|
|
||||||
JournalView.mount = function (containerEl, props, api) {
|
JournalView.mount = function (containerEl, props, api) {
|
||||||
|
|
@ -178,6 +206,7 @@
|
||||||
var entries = [];
|
var entries = [];
|
||||||
var statusText = 'Loading journal...';
|
var statusText = 'Loading journal...';
|
||||||
var statusClass = '';
|
var statusClass = '';
|
||||||
|
var modalHost = el('div', { className: 'journal-modal-host', hidden: 'hidden' });
|
||||||
|
|
||||||
var toolbar = el('div', { className: 'journal-toolbar' });
|
var toolbar = el('div', { className: 'journal-toolbar' });
|
||||||
var titleEl = el('span', { className: 'journal-title', textContent: scope.mode === 'global' ? 'Journal' : 'Journal · ' + scope.label });
|
var titleEl = el('span', { className: 'journal-title', textContent: scope.mode === 'global' ? 'Journal' : 'Journal · ' + scope.label });
|
||||||
|
|
@ -189,35 +218,23 @@
|
||||||
textContent: 'Import Activity',
|
textContent: 'Import Activity',
|
||||||
onClick: importActivity
|
onClick: importActivity
|
||||||
});
|
});
|
||||||
|
var addBtn = el('button', {
|
||||||
|
className: 'journal-btn primary',
|
||||||
|
'data-journal-action': 'add',
|
||||||
|
innerHTML: iconSvg('add') + '<span>Add</span>',
|
||||||
|
onClick: function () { showEntryModal(); }
|
||||||
|
});
|
||||||
toolbar.appendChild(titleEl);
|
toolbar.appendChild(titleEl);
|
||||||
toolbar.appendChild(countEl);
|
toolbar.appendChild(countEl);
|
||||||
toolbar.appendChild(el('span', { className: 'journal-spacer' }));
|
toolbar.appendChild(el('span', { className: 'journal-spacer' }));
|
||||||
toolbar.appendChild(statusEl);
|
toolbar.appendChild(statusEl);
|
||||||
|
toolbar.appendChild(addBtn);
|
||||||
toolbar.appendChild(importBtn);
|
toolbar.appendChild(importBtn);
|
||||||
|
|
||||||
var dateInput = el('input', { className: 'journal-input', type: 'date', value: today(), 'data-journal-input': 'date' });
|
|
||||||
var titleInput = el('input', { className: 'journal-input', type: 'text', placeholder: 'Work item', 'data-journal-input': 'title' });
|
|
||||||
var summaryInput = el('input', { className: 'journal-input', type: 'text', placeholder: 'Summary', 'data-journal-input': 'summary' });
|
|
||||||
var minutesInput = el('input', { className: 'journal-input', type: 'number', min: '0', step: '15', value: '30', 'data-journal-input': 'minutes' });
|
|
||||||
var billableInput = el('input', { type: 'checkbox', 'data-journal-input': 'billable' });
|
|
||||||
var addBtn = el('button', {
|
|
||||||
className: 'journal-btn',
|
|
||||||
'data-journal-action': 'add',
|
|
||||||
textContent: 'Add',
|
|
||||||
onClick: addManualEntry
|
|
||||||
});
|
|
||||||
var formEl = el('div', { className: 'journal-form' }, [
|
|
||||||
dateInput,
|
|
||||||
titleInput,
|
|
||||||
summaryInput,
|
|
||||||
minutesInput,
|
|
||||||
el('label', { className: 'journal-billable' }, [billableInput, 'Billable']),
|
|
||||||
addBtn
|
|
||||||
]);
|
|
||||||
var listEl = el('div', { className: 'journal-list' });
|
var listEl = el('div', { className: 'journal-list' });
|
||||||
containerEl.appendChild(toolbar);
|
containerEl.appendChild(toolbar);
|
||||||
if (scope.mode === 'workspace') containerEl.appendChild(formEl);
|
|
||||||
containerEl.appendChild(listEl);
|
containerEl.appendChild(listEl);
|
||||||
|
containerEl.appendChild(modalHost);
|
||||||
|
|
||||||
function persist() {
|
function persist() {
|
||||||
if (scope.mode !== 'workspace') return Promise.resolve();
|
if (scope.mode !== 'workspace') return Promise.resolve();
|
||||||
|
|
@ -254,9 +271,59 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addManualEntry() {
|
function closeEntryModal() {
|
||||||
|
modalHost.innerHTML = '';
|
||||||
|
modalHost.setAttribute('hidden', 'hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEntryModal(existingEntry) {
|
||||||
if (scope.mode !== 'workspace') return;
|
if (scope.mode !== 'workspace') return;
|
||||||
var title = text(titleInput.value).trim();
|
var editing = !!existingEntry;
|
||||||
|
var dateInput = el('input', { className: 'journal-input', type: 'date', value: editing ? existingEntry.date : today(), 'data-journal-input': 'date' });
|
||||||
|
var titleInput = el('input', { className: 'journal-input', type: 'text', placeholder: 'Work item', value: editing ? existingEntry.title : '', 'data-journal-input': 'title' });
|
||||||
|
var summaryInput = el('textarea', { className: 'journal-input textarea', placeholder: 'Summary', 'data-journal-input': 'summary' });
|
||||||
|
summaryInput.value = editing ? existingEntry.summary : '';
|
||||||
|
var minutesInput = el('input', { className: 'journal-input', type: 'number', min: '0', step: '15', value: editing ? existingEntry.minutes : '30', 'data-journal-input': 'minutes' });
|
||||||
|
var billableInput = el('input', { type: 'checkbox', 'data-journal-input': 'billable' });
|
||||||
|
billableInput.checked = editing ? existingEntry.billable === true : false;
|
||||||
|
|
||||||
|
function saveEntry() {
|
||||||
|
addOrUpdateEntry(existingEntry, {
|
||||||
|
date: dateInput.value || today(),
|
||||||
|
title: titleInput.value,
|
||||||
|
summary: summaryInput.value,
|
||||||
|
minutes: minutesInput.value,
|
||||||
|
billable: billableInput.checked === true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
modalHost.innerHTML = '';
|
||||||
|
if (typeof modalHost.removeAttribute === 'function') modalHost.removeAttribute('hidden');
|
||||||
|
else delete modalHost.attributes.hidden;
|
||||||
|
modalHost.appendChild(el('div', { className: 'journal-modal-overlay', onClick: function (event) {
|
||||||
|
if (event.target === event.currentTarget) closeEntryModal();
|
||||||
|
} }, [
|
||||||
|
el('div', { className: 'journal-modal' }, [
|
||||||
|
el('div', { className: 'journal-modal-title', textContent: editing ? 'Edit journal entry' : 'Add journal entry' }),
|
||||||
|
el('div', { className: 'journal-modal-grid' }, [
|
||||||
|
el('label', { className: 'journal-field' }, ['Date', dateInput]),
|
||||||
|
el('label', { className: 'journal-field' }, ['Minutes', minutesInput]),
|
||||||
|
el('label', { className: 'journal-field wide' }, ['Title', titleInput]),
|
||||||
|
el('label', { className: 'journal-field wide' }, ['Summary', summaryInput]),
|
||||||
|
el('label', { className: 'journal-billable' }, [billableInput, 'Billable'])
|
||||||
|
]),
|
||||||
|
el('div', { className: 'journal-modal-actions' }, [
|
||||||
|
el('button', { className: 'journal-btn ghost', type: 'button', textContent: 'Cancel', onClick: closeEntryModal }),
|
||||||
|
el('button', { className: 'journal-btn primary', type: 'button', 'data-journal-action': 'save-entry', textContent: editing ? 'Save changes' : 'Add entry', onClick: saveEntry })
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]));
|
||||||
|
titleInput.focus && titleInput.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOrUpdateEntry(existingEntry, formValue) {
|
||||||
|
if (scope.mode !== 'workspace') return;
|
||||||
|
var title = text(formValue && formValue.title).trim();
|
||||||
if (!title) {
|
if (!title) {
|
||||||
statusText = 'Title is required';
|
statusText = 'Title is required';
|
||||||
statusClass = 'error';
|
statusClass = 'error';
|
||||||
|
|
@ -264,18 +331,34 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var entry = normalizeEntry({
|
var entry = normalizeEntry({
|
||||||
entryId: entryId(scope.workspaceRoot, dateInput.value || today(), title),
|
entryId: existingEntry ? existingEntry.entryId : entryId(scope.workspaceRoot, formValue.date || today(), title),
|
||||||
workspaceRootPath: scope.workspaceRoot,
|
workspaceRootPath: scope.workspaceRoot,
|
||||||
date: dateInput.value || today(),
|
date: formValue.date || today(),
|
||||||
title: title,
|
title: title,
|
||||||
summary: summaryInput.value,
|
summary: formValue.summary,
|
||||||
minutes: Number(minutesInput.value || 0),
|
minutes: Number(formValue.minutes || 0),
|
||||||
billable: billableInput.checked === true
|
billable: formValue.billable === true,
|
||||||
|
sourceSuggestionId: existingEntry ? existingEntry.sourceSuggestionId : '',
|
||||||
|
eventIds: existingEntry ? existingEntry.eventIds : []
|
||||||
}, scope.key);
|
}, scope.key);
|
||||||
entries = sortEntries([entry].concat(entries));
|
if (existingEntry) {
|
||||||
titleInput.value = '';
|
entries = entries.map(function (item) {
|
||||||
summaryInput.value = '';
|
return item.entryId === existingEntry.entryId ? entry : item;
|
||||||
statusText = 'Entry added';
|
});
|
||||||
|
} else {
|
||||||
|
entries = [entry].concat(entries);
|
||||||
|
}
|
||||||
|
entries = sortEntries(entries);
|
||||||
|
closeEntryModal();
|
||||||
|
statusText = existingEntry ? 'Entry updated' : 'Entry added';
|
||||||
|
statusClass = '';
|
||||||
|
persist().then(render);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteEntry(entry) {
|
||||||
|
if (scope.mode !== 'workspace' || !entry) return;
|
||||||
|
entries = entries.filter(function (item) { return item.entryId !== entry.entryId; });
|
||||||
|
statusText = 'Entry deleted';
|
||||||
statusClass = '';
|
statusClass = '';
|
||||||
persist().then(render);
|
persist().then(render);
|
||||||
}
|
}
|
||||||
|
|
@ -352,7 +435,11 @@
|
||||||
entry.summary ? el('div', { className: 'journal-summary', textContent: entry.summary }) : null,
|
entry.summary ? el('div', { className: 'journal-summary', textContent: entry.summary }) : null,
|
||||||
el('div', { className: 'journal-meta', textContent: entry.workspaceRootPath + (entry.billable ? ' · billable' : ' · non-billable') })
|
el('div', { className: 'journal-meta', textContent: entry.workspaceRootPath + (entry.billable ? ' · billable' : ' · non-billable') })
|
||||||
]),
|
]),
|
||||||
el('div', { className: 'journal-minutes', textContent: entry.minutes + ' min' })
|
el('div', { className: 'journal-minutes', textContent: entry.minutes + ' min' }),
|
||||||
|
scope.mode === 'workspace' ? el('div', { className: 'journal-row-actions' }, [
|
||||||
|
el('button', { className: 'journal-icon-btn', type: 'button', title: 'Edit', 'aria-label': 'Edit', 'data-journal-action': 'edit', innerHTML: iconSvg('edit'), onClick: function () { showEntryModal(entry); } }),
|
||||||
|
el('button', { className: 'journal-icon-btn danger', type: 'button', title: 'Delete', 'aria-label': 'Delete', 'data-journal-action': 'delete', innerHTML: iconSvg('trash'), onClick: function () { deleteEntry(entry); } })
|
||||||
|
]) : null
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -361,6 +448,7 @@
|
||||||
countEl.textContent = entries.length + ' entr' + (entries.length === 1 ? 'y' : 'ies');
|
countEl.textContent = entries.length + ' entr' + (entries.length === 1 ? 'y' : 'ies');
|
||||||
statusEl.textContent = statusText;
|
statusEl.textContent = statusText;
|
||||||
statusEl.className = 'journal-status' + (statusClass ? ' ' + statusClass : '');
|
statusEl.className = 'journal-status' + (statusClass ? ' ' + statusClass : '');
|
||||||
|
addBtn.disabled = scope.mode !== 'workspace';
|
||||||
importBtn.disabled = scope.mode !== 'workspace' || importBtn.disabled;
|
importBtn.disabled = scope.mode !== 'workspace' || importBtn.disabled;
|
||||||
renderList();
|
renderList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,35 +15,38 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.notes-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:#e0e0e0;background:#0d0d1a;outline:none}',
|
'.notes-root{display:flex;flex-direction:column;height:100%;min-height:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;color:var(--vt-color-text-primary,#f4f7fb);background:var(--vt-color-background,#101020);outline:none}',
|
||||||
'.notes-toolbar{display:flex;align-items:center;gap:.45rem;padding:.5rem .75rem;border-bottom:1px solid #16213e;flex-shrink:0;background:#12122a;flex-wrap:wrap}',
|
'.notes-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.5rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46);flex-shrink:0;background:var(--vt-color-surface-muted,#111629);flex-wrap:wrap}',
|
||||||
'.notes-btn{font-size:.78rem;padding:.32rem .65rem;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ccc;cursor:pointer;display:inline-flex;align-items:center;gap:.35rem}',
|
'.notes-btn{font-size:.78rem;padding:.36rem .7rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer;display:inline-flex;align-items:center;gap:.35rem}',
|
||||||
'.notes-btn:hover{background:#2a2a4e;border-color:#4ecca3}',
|
'.notes-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
|
'.notes-btn:focus-visible{outline:0;box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.notes-btn:disabled{opacity:.45;cursor:default}',
|
'.notes-btn:disabled{opacity:.45;cursor:default}',
|
||||||
'.notes-btn.primary{background:#1a3a2a;border-color:#4ecca3;color:#4ecca3}',
|
'.notes-btn.primary{background:var(--vt-color-accent,#4ecca3);border-color:var(--vt-color-accent,#4ecca3);color:#101827}',
|
||||||
'.notes-btn.primary:hover{background:#2a4a3a}',
|
'.notes-btn.primary:hover{background:#63d9b3;color:#101827}',
|
||||||
'.notes-filter,.notes-sort{font-size:.78rem;padding:.32rem .5rem;border:1px solid #333;border-radius:4px;background:#0d0d1a;color:#e0e0e0;outline:none}',
|
'.notes-filter,.notes-sort{font-size:.78rem;padding:.32rem .5rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-primary,#f4f7fb);outline:none}',
|
||||||
'.notes-filter{width:11rem}',
|
'.notes-filter{width:11rem}',
|
||||||
'.notes-sort{width:8rem;appearance:none;background-color:#0d0d1a;background-image:linear-gradient(45deg,transparent 50%,#8b8ba8 50%),linear-gradient(135deg,#8b8ba8 50%,transparent 50%);background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:1.6rem}',
|
'.notes-sort{width:8rem;appearance:none;background-color:#0f1424;background-image:linear-gradient(45deg,transparent 50%,#8b8ba8 50%),linear-gradient(135deg,#8b8ba8 50%,transparent 50%);background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:1.6rem}',
|
||||||
'.notes-filter:focus,.notes-sort:focus{border-color:#4ecca3}',
|
'.notes-filter:focus,.notes-sort:focus{border-color:var(--vt-color-accent,#4ecca3);box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.notes-list{flex:1;overflow:auto;min-height:0}',
|
'.notes-list{flex:1;overflow:auto;min-height:0}',
|
||||||
'.notes-item{display:flex;align-items:center;gap:.5rem;padding:.45rem .75rem;border-bottom:1px solid rgba(22,33,62,.55);cursor:pointer;font-size:.85rem}',
|
'.notes-item{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid rgba(32,43,70,.72);cursor:pointer;font-size:.85rem}',
|
||||||
'.notes-item:hover{background:#17172d}',
|
'.notes-item:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
'.notes-item.selected{background:#1a2a3a}',
|
'.notes-item.selected{background:var(--vt-color-surface-selected,rgba(78,204,163,.14));box-shadow:inset 2px 0 0 var(--vt-color-accent,#4ecca3)}',
|
||||||
'.notes-item-icon{width:1.25rem;height:1.25rem;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:#8b8ba8}',
|
'.notes-item-icon{width:1.25rem;height:1.25rem;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.notes-item-icon svg{width:16px;height:16px;display:block;fill:currentColor}',
|
'.notes-item-icon svg{width:16px;height:16px;display:block;fill:currentColor}',
|
||||||
'.notes-item-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.notes-item-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.notes-item-actions{display:flex;gap:.25rem;opacity:0;transition:opacity .15s}',
|
'.notes-item-actions{display:flex;gap:.25rem;opacity:.78;transition:opacity .15s}',
|
||||||
'.notes-item:hover .notes-item-actions{opacity:1}',
|
'.notes-item:hover .notes-item-actions{opacity:1}',
|
||||||
'.notes-item-btn{width:1.5rem;height:1.5rem;display:inline-flex;align-items:center;justify-content:center;border:1px solid #333;border-radius:3px;background:transparent;color:#888;cursor:pointer;padding:0;font-size:.7rem}',
|
'.notes-item-btn{width:1.65rem;height:1.65rem;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--vt-color-border,#202b46);border-radius:var(--vt-radius-sm,4px);background:transparent;color:var(--vt-color-text-muted,#7f8aa3);cursor:pointer;padding:0;font-size:.7rem}',
|
||||||
'.notes-item-btn:hover{background:#2a2a4e;border-color:#4ecca3;color:#4ecca3}',
|
'.notes-item-btn:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-accent,#4ecca3);color:var(--vt-color-accent,#4ecca3)}',
|
||||||
'.notes-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#666;font-size:.85rem;padding:2rem;gap:.5rem}',
|
'.notes-item-btn:focus-visible{outline:0;box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.notes-empty-hint{font-size:.75rem;color:#555}',
|
'.notes-item-btn svg{width:14px;height:14px;display:block;fill:currentColor}',
|
||||||
'.notes-error{flex:1;display:flex;align-items:center;justify-content:center;color:#e74c3c;padding:1rem;font-size:.85rem}',
|
'.notes-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--vt-color-text-muted,#7f8aa3);font-size:.85rem;padding:2rem;gap:.5rem;text-align:center}',
|
||||||
'.notes-panel{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-top:1px solid #16213e;flex-shrink:0;background:#12122a}',
|
'.notes-empty-hint{font-size:.75rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.notes-input{flex:1;font-size:.78rem;padding:.32rem .5rem;border:1px solid #333;border-radius:4px;background:#0d0d1a;color:#e0e0e0;outline:none;min-width:120px}',
|
'.notes-error{flex:1;display:flex;align-items:center;justify-content:center;color:var(--vt-color-danger,#e94560);padding:1rem;font-size:.85rem}',
|
||||||
'.notes-input:focus{border-color:#4ecca3}',
|
'.notes-panel{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-top:1px solid var(--vt-color-border,#202b46);flex-shrink:0;background:var(--vt-color-surface-muted,#111629)}',
|
||||||
'.notes-title-bar{padding:.4rem .75rem;font-size:.72rem;color:#8b8ba8;background:#101028;border-bottom:1px solid #16213e;text-transform:uppercase;letter-spacing:.04em}',
|
'.notes-input{flex:1;font-size:.78rem;padding:.32rem .5rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-primary,#f4f7fb);outline:none;min-width:120px}',
|
||||||
|
'.notes-input:focus{border-color:var(--vt-color-accent,#4ecca3);box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
|
'.notes-title-bar{padding:.4rem .75rem;font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);background:var(--vt-color-surface-muted,#111629);border-bottom:1px solid var(--vt-color-border,#202b46);text-transform:uppercase;letter-spacing:.04em}',
|
||||||
'.notes-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:center;justify-content:center}',
|
'.notes-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:center;justify-content:center}',
|
||||||
'.notes-modal{width:380px;max-width:90vw;padding:20px;background:#1a1a2e;border:1px solid #333;border-radius:10px;color:#e0e0e0;font-family:inherit;box-shadow:0 12px 40px rgba(0,0,0,.5)}',
|
'.notes-modal{width:380px;max-width:90vw;padding:20px;background:#1a1a2e;border:1px solid #333;border-radius:10px;color:#e0e0e0;font-family:inherit;box-shadow:0 12px 40px rgba(0,0,0,.5)}',
|
||||||
'.notes-modal-title{font-size:.9rem;font-weight:600;margin-bottom:12px}',
|
'.notes-modal-title{font-size:.9rem;font-weight:600;margin-bottom:12px}',
|
||||||
|
|
@ -259,7 +262,7 @@
|
||||||
// ─── UI Elements ────────────────────────────────────────
|
// ─── UI Elements ────────────────────────────────────────
|
||||||
|
|
||||||
var toolbar = el('div', { className: 'notes-toolbar' });
|
var toolbar = el('div', { className: 'notes-toolbar' });
|
||||||
var createBtn = el('button', { className: 'notes-btn', 'data-action': 'create', innerHTML: iconSvg('add') + ' New Note' });
|
var createBtn = el('button', { className: 'notes-btn primary', 'data-action': 'create', innerHTML: iconSvg('add') + ' New Note' });
|
||||||
var filterInput = el('input', { className: 'notes-filter', 'data-notes-filter': '', placeholder: 'Filter notes' });
|
var filterInput = el('input', { className: 'notes-filter', 'data-notes-filter': '', placeholder: 'Filter notes' });
|
||||||
var sortSelect = el('select', { className: 'notes-sort', 'data-notes-sort': '' }, [
|
var sortSelect = el('select', { className: 'notes-sort', 'data-notes-sort': '' }, [
|
||||||
el('option', { value: 'title-asc' }, ['A-Z']),
|
el('option', { value: 'title-asc' }, ['A-Z']),
|
||||||
|
|
@ -402,12 +405,15 @@
|
||||||
el('button', {
|
el('button', {
|
||||||
className: 'notes-item-btn',
|
className: 'notes-item-btn',
|
||||||
title: 'Open',
|
title: 'Open',
|
||||||
|
'aria-label': 'Open',
|
||||||
|
'data-note-action': 'open',
|
||||||
innerHTML: iconSvg('open'),
|
innerHTML: iconSvg('open'),
|
||||||
onClick: function (e) { e.stopPropagation(); openNote(note); }
|
onClick: function (e) { e.stopPropagation(); openNote(note); }
|
||||||
}),
|
}),
|
||||||
el('button', {
|
el('button', {
|
||||||
className: 'notes-item-btn',
|
className: 'notes-item-btn',
|
||||||
title: 'Rename',
|
title: 'Rename',
|
||||||
|
'aria-label': 'Rename',
|
||||||
'data-note-action': 'rename',
|
'data-note-action': 'rename',
|
||||||
innerHTML: iconSvg('rename'),
|
innerHTML: iconSvg('rename'),
|
||||||
onClick: function (e) { e.stopPropagation(); beginRename(note); }
|
onClick: function (e) { e.stopPropagation(); beginRename(note); }
|
||||||
|
|
@ -415,6 +421,7 @@
|
||||||
el('button', {
|
el('button', {
|
||||||
className: 'notes-item-btn',
|
className: 'notes-item-btn',
|
||||||
title: 'Move to Trash',
|
title: 'Move to Trash',
|
||||||
|
'aria-label': 'Move to Trash',
|
||||||
'data-note-action': 'trash',
|
'data-note-action': 'trash',
|
||||||
innerHTML: iconSvg('trash'),
|
innerHTML: iconSvg('trash'),
|
||||||
onClick: function (e) { e.stopPropagation(); confirmTrashNote(note); }
|
onClick: function (e) { e.stopPropagation(); confirmTrashNote(note); }
|
||||||
|
|
|
||||||
|
|
@ -28,23 +28,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.search-root{height:100%;min-height:0;display:flex;flex-direction:column;background:#0d0d1a;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif}',
|
'.search-root{height:100%;min-height:0;display:flex;flex-direction:column;background:var(--vt-color-background,#101020);color:var(--vt-color-text-primary,#f4f7fb);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif}',
|
||||||
'.search-toolbar{display:flex;align-items:center;gap:.5rem;padding:.55rem .75rem;border-bottom:1px solid #16213e;background:#12122a;flex-shrink:0;flex-wrap:wrap}',
|
'.search-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.55rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface-muted,#111629);flex-shrink:0;flex-wrap:wrap}',
|
||||||
'.search-input{flex:1;min-width:180px;font-size:.86rem;padding:.42rem .55rem;border:1px solid #333;border-radius:4px;background:#0d0d1a;color:#e0e0e0;outline:none}',
|
'.search-input{flex:1;min-width:180px;font-size:.86rem;padding:.42rem .55rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-primary,#f4f7fb);outline:none}',
|
||||||
'.search-input:focus{border-color:#4ecca3}',
|
'.search-input:focus{border-color:var(--vt-color-accent,#4ecca3);box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.search-btn{font-size:.8rem;padding:.42rem .7rem;border:1px solid #333;border-radius:4px;background:#1a1a2e;color:#ddd;cursor:pointer}',
|
'.search-btn{font-size:.8rem;min-height:2rem;padding:.42rem .7rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);cursor:pointer}',
|
||||||
'.search-btn:hover{border-color:#4ecca3;background:#2a2a4e}',
|
'.search-btn:hover{border-color:var(--vt-color-accent,#4ecca3);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.search-btn:disabled{opacity:.45;cursor:default}',
|
'.search-btn:disabled{opacity:.45;cursor:default}',
|
||||||
'.search-scope{font-size:.72rem;color:#8b8ba8;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:18rem}',
|
'.search-scope{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:18rem}',
|
||||||
'.search-status{font-size:.78rem;color:#8b8ba8;padding:.45rem .75rem;border-bottom:1px solid rgba(22,33,62,.55);flex-shrink:0}',
|
'.search-status{font-size:.78rem;color:var(--vt-color-text-muted,#7f8aa3);padding:.45rem .75rem;border-bottom:1px solid rgba(32,43,70,.72);flex-shrink:0}',
|
||||||
'.search-status.error{color:#e74c3c}',
|
'.search-status.error{color:var(--vt-color-danger,#e94560)}',
|
||||||
|
'.search-alert{margin:.65rem .75rem 0;border:1px solid rgba(233,69,96,.45);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-danger-muted,rgba(233,69,96,.14));color:#ffc6ce;padding:.55rem .65rem;font-size:.78rem}',
|
||||||
|
'.search-alert[hidden]{display:none}',
|
||||||
|
'.search-alert summary{cursor:pointer;color:#fff}',
|
||||||
'.search-results{flex:1;min-height:0;overflow:auto}',
|
'.search-results{flex:1;min-height:0;overflow:auto}',
|
||||||
'.search-empty{height:100%;display:flex;align-items:center;justify-content:center;color:#666;font-size:.9rem;padding:2rem;text-align:center}',
|
'.search-empty{height:100%;display:flex;align-items:center;justify-content:center;color:var(--vt-color-text-muted,#7f8aa3);font-size:.9rem;padding:2rem;text-align:center}',
|
||||||
'.search-result{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.5rem;padding:.7rem .85rem;border-bottom:1px solid rgba(22,33,62,.55)}',
|
'.search-result{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.75rem;align-items:center;margin:.5rem .75rem 0;padding:.7rem .8rem;border:1px solid var(--vt-color-border,#202b46);border-radius:var(--vt-radius-lg,8px);background:var(--vt-color-surface,#15152c)}',
|
||||||
'.search-result:hover{background:#17172d}',
|
'.search-result:hover{background:var(--vt-color-surface-hover,#1b2440)}',
|
||||||
'.search-path{font-size:.84rem;color:#4ecca3;word-break:break-word}',
|
'.search-result-head{display:flex;align-items:center;gap:.5rem;min-width:0}',
|
||||||
'.search-snippet{margin-top:.25rem;font-size:.8rem;line-height:1.45;color:#cfcfe0;white-space:pre-wrap;overflow-wrap:anywhere}',
|
'.search-type{display:inline-flex;align-items:center;min-height:1.25rem;padding:.1rem .4rem;border:1px solid rgba(78,204,163,.4);border-radius:var(--vt-radius-sm,4px);background:var(--vt-color-accent-muted,rgba(78,204,163,.14));color:var(--vt-color-accent,#4ecca3);font-size:.68rem;font-weight:650;text-transform:uppercase;letter-spacing:.03em}',
|
||||||
'.search-meta{margin-top:.28rem;font-size:.72rem;color:#777}',
|
'.search-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.86rem;color:var(--vt-color-text-primary,#f4f7fb);font-weight:650}',
|
||||||
|
'.search-path{margin-top:.2rem;font-size:.76rem;color:var(--vt-color-text-muted,#7f8aa3);word-break:break-word}',
|
||||||
|
'.search-snippet{margin-top:.25rem;font-size:.8rem;line-height:1.45;color:var(--vt-color-text-secondary,#b7c0d4);white-space:pre-wrap;overflow-wrap:anywhere}',
|
||||||
|
'.search-meta{margin-top:.28rem;font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
|
'.search-open-btn{align-self:center;white-space:nowrap;min-width:4.5rem;padding:.35rem .65rem}',
|
||||||
'@media(max-width:700px){.search-result{grid-template-columns:1fr}.search-toolbar{align-items:stretch}.search-btn{width:100%}.search-scope{max-width:none}}'
|
'@media(max-width:700px){.search-result{grid-template-columns:1fr}.search-toolbar{align-items:stretch}.search-btn{width:100%}.search-scope{max-width:none}}'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
|
|
@ -54,7 +61,9 @@
|
||||||
Object.keys(attrs).forEach(function (k) {
|
Object.keys(attrs).forEach(function (k) {
|
||||||
if (attrs[k] == null) return;
|
if (attrs[k] == null) return;
|
||||||
if (k === 'className') elem.className = attrs[k];
|
if (k === 'className') elem.className = attrs[k];
|
||||||
else if (k === 'style' && typeof attrs[k] === 'object') Object.assign(elem.style, attrs[k]);
|
else if (k === 'style' && typeof attrs[k] === 'object') {
|
||||||
|
if (elem.style) Object.assign(elem.style, attrs[k]);
|
||||||
|
}
|
||||||
else if (k.slice(0, 2) === 'on') elem.addEventListener(k.slice(2).toLowerCase(), attrs[k]);
|
else if (k.slice(0, 2) === 'on') elem.addEventListener(k.slice(2).toLowerCase(), attrs[k]);
|
||||||
else if (k === 'textContent') elem.textContent = attrs[k];
|
else if (k === 'textContent') elem.textContent = attrs[k];
|
||||||
else if (k === 'innerHTML') elem.innerHTML = attrs[k];
|
else if (k === 'innerHTML') elem.innerHTML = attrs[k];
|
||||||
|
|
@ -74,6 +83,20 @@
|
||||||
return String(path || '').split('/').filter(Boolean).join('/');
|
return String(path || '').split('/').filter(Boolean).join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function baseName(path) {
|
||||||
|
path = cleanPath(path);
|
||||||
|
var parts = path.split('/');
|
||||||
|
return parts[parts.length - 1] || path || 'Untitled';
|
||||||
|
}
|
||||||
|
|
||||||
|
function resultTypeLabel(result) {
|
||||||
|
var type = String(result && result.type || 'result').toLowerCase();
|
||||||
|
if (type === 'folder') return 'Folder';
|
||||||
|
if (type === 'file') return 'File';
|
||||||
|
if (type === 'external') return 'Plugin';
|
||||||
|
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
function extension(entry) {
|
function extension(entry) {
|
||||||
var explicit = String((entry && entry.extension) || '').replace(/^\./, '').toLowerCase();
|
var explicit = String((entry && entry.extension) || '').replace(/^\./, '').toLowerCase();
|
||||||
if (explicit) return explicit;
|
if (explicit) return explicit;
|
||||||
|
|
@ -281,7 +304,7 @@
|
||||||
mount: function (containerEl, props, api) {
|
mount: function (containerEl, props, api) {
|
||||||
injectStyles();
|
injectStyles();
|
||||||
var rootPath = cleanPath(props && (props.workspaceRootPath || props.workspaceName));
|
var rootPath = cleanPath(props && (props.workspaceRootPath || props.workspaceName));
|
||||||
var state = { query: '', searching: false, results: [], status: 'Enter at least 2 characters.', error: '' };
|
var state = { query: '', searching: false, results: [], status: 'Enter at least 2 characters.', error: '', providerErrors: [] };
|
||||||
var searchTimer = null;
|
var searchTimer = null;
|
||||||
var searchSeq = 0;
|
var searchSeq = 0;
|
||||||
var index = null;
|
var index = null;
|
||||||
|
|
@ -290,6 +313,7 @@
|
||||||
var input = null;
|
var input = null;
|
||||||
var button = null;
|
var button = null;
|
||||||
var statusEl = null;
|
var statusEl = null;
|
||||||
|
var alertEl = null;
|
||||||
var resultsEl = null;
|
var resultsEl = null;
|
||||||
|
|
||||||
function ensureLayout() {
|
function ensureLayout() {
|
||||||
|
|
@ -322,6 +346,8 @@
|
||||||
|
|
||||||
statusEl = el('div', { className: 'search-status' });
|
statusEl = el('div', { className: 'search-status' });
|
||||||
containerEl.appendChild(statusEl);
|
containerEl.appendChild(statusEl);
|
||||||
|
alertEl = el('div', { className: 'search-alert', hidden: 'hidden' });
|
||||||
|
containerEl.appendChild(alertEl);
|
||||||
resultsEl = el('div', { className: 'search-results' });
|
resultsEl = el('div', { className: 'search-results' });
|
||||||
containerEl.appendChild(resultsEl);
|
containerEl.appendChild(resultsEl);
|
||||||
}
|
}
|
||||||
|
|
@ -335,6 +361,16 @@
|
||||||
button.disabled = !!state.searching;
|
button.disabled = !!state.searching;
|
||||||
statusEl.className = 'search-status' + (state.error ? ' error' : '');
|
statusEl.className = 'search-status' + (state.error ? ' error' : '');
|
||||||
statusEl.textContent = state.error || state.status;
|
statusEl.textContent = state.error || state.status;
|
||||||
|
alertEl.innerHTML = '';
|
||||||
|
if (state.providerErrors && state.providerErrors.length) {
|
||||||
|
if (typeof alertEl.removeAttribute === 'function') alertEl.removeAttribute('hidden');
|
||||||
|
alertEl.appendChild(el('details', {}, [
|
||||||
|
el('summary', {}, ['Some plugin search providers did not respond']),
|
||||||
|
el('div', {}, [state.providerErrors.join('; ')])
|
||||||
|
]));
|
||||||
|
} else if (typeof alertEl.setAttribute === 'function') {
|
||||||
|
alertEl.setAttribute('hidden', 'hidden');
|
||||||
|
}
|
||||||
resultsEl.innerHTML = '';
|
resultsEl.innerHTML = '';
|
||||||
if (!state.results.length) {
|
if (!state.results.length) {
|
||||||
resultsEl.appendChild(el('div', { className: 'search-empty' }, [state.searching ? 'Searching...' : 'No results']));
|
resultsEl.appendChild(el('div', { className: 'search-empty' }, [state.searching ? 'Searching...' : 'No results']));
|
||||||
|
|
@ -343,6 +379,10 @@
|
||||||
state.results.forEach(function (result) {
|
state.results.forEach(function (result) {
|
||||||
resultsEl.appendChild(el('div', { className: 'search-result' }, [
|
resultsEl.appendChild(el('div', { className: 'search-result' }, [
|
||||||
el('div', {}, [
|
el('div', {}, [
|
||||||
|
el('div', { className: 'search-result-head' }, [
|
||||||
|
el('span', { className: 'search-type' }, [resultTypeLabel(result)]),
|
||||||
|
el('span', { className: 'search-title', title: result.path }, [baseName(result.path)])
|
||||||
|
]),
|
||||||
el('div', { className: 'search-path' }, [result.path]),
|
el('div', { className: 'search-path' }, [result.path]),
|
||||||
el('div', { className: 'search-snippet' }, [result.snippet]),
|
el('div', { className: 'search-snippet' }, [result.snippet]),
|
||||||
el('div', { className: 'search-meta' }, [
|
el('div', { className: 'search-meta' }, [
|
||||||
|
|
@ -350,7 +390,7 @@
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
result.openable ? el('button', {
|
result.openable ? el('button', {
|
||||||
className: 'search-btn',
|
className: 'search-btn search-open-btn',
|
||||||
textContent: 'Open',
|
textContent: 'Open',
|
||||||
'data-search-open': result.path,
|
'data-search-open': result.path,
|
||||||
onClick: function () {
|
onClick: function () {
|
||||||
|
|
@ -377,6 +417,7 @@
|
||||||
state.results = [];
|
state.results = [];
|
||||||
state.status = 'Enter at least 2 characters.';
|
state.status = 'Enter at least 2 characters.';
|
||||||
state.error = '';
|
state.error = '';
|
||||||
|
state.providerErrors = [];
|
||||||
render();
|
render();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -393,11 +434,13 @@
|
||||||
state.results = [];
|
state.results = [];
|
||||||
state.status = 'Enter at least 2 characters.';
|
state.status = 'Enter at least 2 characters.';
|
||||||
state.error = '';
|
state.error = '';
|
||||||
|
state.providerErrors = [];
|
||||||
render();
|
render();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.searching = true;
|
state.searching = true;
|
||||||
state.error = '';
|
state.error = '';
|
||||||
|
state.providerErrors = [];
|
||||||
state.status = 'Searching...';
|
state.status = 'Searching...';
|
||||||
var seq = searchSeq + 1;
|
var seq = searchSeq + 1;
|
||||||
searchSeq = seq;
|
searchSeq = seq;
|
||||||
|
|
@ -409,13 +452,12 @@
|
||||||
if (seq !== searchSeq) return;
|
if (seq !== searchSeq) return;
|
||||||
state.results = results.concat(external.results);
|
state.results = results.concat(external.results);
|
||||||
state.status = state.results.length + ' result' + (state.results.length === 1 ? '' : 's');
|
state.status = state.results.length + ' result' + (state.results.length === 1 ? '' : 's');
|
||||||
if (external.errors.length) {
|
state.providerErrors = external.errors;
|
||||||
state.status += ' - ' + external.errors.join('; ');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (seq !== searchSeq) return;
|
if (seq !== searchSeq) return;
|
||||||
state.results = [];
|
state.results = [];
|
||||||
state.error = err && err.message ? err.message : String(err);
|
state.error = err && err.message ? err.message : String(err);
|
||||||
|
state.providerErrors = [];
|
||||||
} finally {
|
} finally {
|
||||||
if (seq !== searchSeq) return;
|
if (seq !== searchSeq) return;
|
||||||
state.searching = false;
|
state.searching = false;
|
||||||
|
|
|
||||||
|
|
@ -19,42 +19,44 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var STYLES = [
|
var STYLES = [
|
||||||
'.secrets-root{display:grid;grid-template-columns:minmax(17rem,20rem) minmax(0,1fr);height:100%;min-height:0;background:#0d0f14;color:#e6edf3;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif}',
|
'.secrets-root{display:grid;grid-template-columns:minmax(17rem,20rem) minmax(0,1fr);height:100%;min-height:0;background:var(--vt-color-background,#101020);color:var(--vt-color-text-primary,#f4f7fb);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif}',
|
||||||
'.secrets-panel{min-height:0;overflow:auto;border-right:1px solid #252b36;background:#11151d}',
|
'.secrets-panel{min-height:0;overflow:auto;border-right:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface-muted,#111629)}',
|
||||||
'.secrets-main{min-width:0;min-height:0;overflow:auto;padding:1rem;background:#0d0f14}',
|
'.secrets-main{min-width:0;min-height:0;overflow:auto;padding:1rem;background:var(--vt-color-background,#101020)}',
|
||||||
'.secrets-toolbar{display:flex;align-items:center;gap:.5rem;padding:.65rem .75rem;border-bottom:1px solid #252b36}',
|
'.secrets-toolbar{display:flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.65rem .75rem;border-bottom:1px solid var(--vt-color-border,#202b46)}',
|
||||||
'.secrets-title{font-weight:600;font-size:.88rem}',
|
'.secrets-title{font-weight:600;font-size:.88rem}',
|
||||||
'.secrets-count{color:#8b949e;font-size:.76rem}',
|
'.secrets-count{color:var(--vt-color-text-muted,#7f8aa3);font-size:.76rem}',
|
||||||
'.secrets-spacer{flex:1}',
|
'.secrets-spacer{flex:1}',
|
||||||
'.secrets-btn{height:2rem;padding:0 .65rem;border:1px solid #303844;border-radius:4px;background:#1b222d;color:#d8dee9;font:inherit;font-size:.78rem;cursor:pointer}',
|
'.secrets-btn{height:2rem;padding:0 .65rem;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-md,6px);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-secondary,#b7c0d4);font:inherit;font-size:.78rem;cursor:pointer}',
|
||||||
'.secrets-btn:hover{border-color:#56b6c2;background:#222b38}',
|
'.secrets-btn:hover{border-color:var(--vt-color-accent,#4ecca3);background:var(--vt-color-surface-hover,#1b2440);color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.secrets-btn.primary{background:#176b5f;border-color:#248879;color:white}',
|
'.secrets-btn.primary{background:var(--vt-color-accent,#4ecca3);border-color:var(--vt-color-accent,#4ecca3);color:#101827}',
|
||||||
|
'.secrets-btn.danger{border-color:rgba(233,69,96,.5);color:#ff9aaa;background:var(--vt-color-danger-muted,rgba(233,69,96,.14))}',
|
||||||
'.secrets-btn:disabled{opacity:.45;cursor:default}',
|
'.secrets-btn:disabled{opacity:.45;cursor:default}',
|
||||||
'.secrets-group{padding:.6rem .55rem .25rem;color:#8b949e;font-size:.72rem;text-transform:uppercase;letter-spacing:.04em}',
|
'.secrets-group{padding:.6rem .55rem .25rem;color:var(--vt-color-text-muted,#7f8aa3);font-size:.72rem;text-transform:uppercase;letter-spacing:.04em}',
|
||||||
'.secrets-list{display:grid;gap:.25rem;padding:.2rem .45rem .75rem}',
|
'.secrets-list{display:grid;gap:.25rem;padding:.2rem .45rem .75rem}',
|
||||||
'.secrets-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.45rem;align-items:center;text-align:left;border:1px solid transparent;border-radius:5px;background:transparent;color:#d8dee9;padding:.5rem .55rem;cursor:pointer}',
|
'.secrets-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.45rem;align-items:center;text-align:left;border:1px solid transparent;border-radius:var(--vt-radius-md,6px);background:transparent;color:var(--vt-color-text-secondary,#b7c0d4);padding:.5rem .55rem;cursor:pointer}',
|
||||||
'.secrets-item:hover{background:#171d27;border-color:#293241}',
|
'.secrets-item:hover{background:var(--vt-color-surface-hover,#1b2440);border-color:var(--vt-color-border,#202b46)}',
|
||||||
'.secrets-item.active{background:#18232f;border-color:#56b6c2}',
|
'.secrets-item.active{background:var(--vt-color-surface-selected,rgba(78,204,163,.14));border-color:rgba(78,204,163,.45);box-shadow:inset 2px 0 0 var(--vt-color-accent,#4ecca3)}',
|
||||||
'.secrets-item-title{font-size:.82rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.secrets-item-title{font-size:.82rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.secrets-item-meta{font-size:.72rem;color:#8b949e;margin-top:.12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
'.secrets-item-meta{font-size:.72rem;color:var(--vt-color-text-muted,#7f8aa3);margin-top:.12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
||||||
'.secrets-empty{padding:1.5rem;color:#8b949e;font-size:.84rem;text-align:center}',
|
'.secrets-empty{padding:1.5rem;color:var(--vt-color-text-muted,#7f8aa3);font-size:.84rem;text-align:center}',
|
||||||
'.secrets-card{max-width:46rem;display:grid;gap:.8rem}',
|
'.secrets-card{max-width:46rem;display:grid;gap:.8rem}',
|
||||||
'.secrets-card h2{font-size:1rem;margin:0;color:#f0f6fc}',
|
'.secrets-card h2{font-size:1rem;margin:0;color:var(--vt-color-text-primary,#f4f7fb)}',
|
||||||
'.secrets-form{display:grid;gap:.65rem;border:1px solid #252b36;border-radius:6px;padding:.9rem;background:#11151d}',
|
'.secrets-form{display:grid;gap:.65rem;border:1px solid var(--vt-color-border,#202b46);border-radius:var(--vt-radius-lg,8px);padding:.9rem;background:var(--vt-color-surface,#15152c)}',
|
||||||
'.secrets-row{display:grid;grid-template-columns:8rem minmax(0,1fr);gap:.65rem;align-items:center}',
|
'.secrets-row{display:grid;grid-template-columns:8rem minmax(0,1fr);gap:.65rem;align-items:center}',
|
||||||
'.secrets-label{font-size:.78rem;color:#8b949e}',
|
'.secrets-label{font-size:.78rem;color:var(--vt-color-text-muted,#7f8aa3)}',
|
||||||
'.secrets-input,.secrets-textarea,.secrets-select{width:100%;box-sizing:border-box;border:1px solid #303844;border-radius:4px;background:#0d1117;color:#e6edf3;font:inherit;font-size:.84rem;padding:.45rem .55rem;outline:none}',
|
'.secrets-input,.secrets-textarea,.secrets-select{width:100%;box-sizing:border-box;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-primary,#f4f7fb);font:inherit;font-size:.84rem;padding:.45rem .55rem;outline:none}',
|
||||||
'.secrets-select{appearance:none;background-color:#0d1117;background-image:linear-gradient(45deg,transparent 50%,#8b949e 50%),linear-gradient(135deg,#8b949e 50%,transparent 50%);background-position:calc(100% - 16px) 50%,calc(100% - 11px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:2rem}',
|
'.secrets-select{appearance:none;background-color:#0d1117;background-image:linear-gradient(45deg,transparent 50%,#8b949e 50%),linear-gradient(135deg,#8b949e 50%,transparent 50%);background-position:calc(100% - 16px) 50%,calc(100% - 11px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:2rem}',
|
||||||
'.secrets-textarea{min-height:6rem;resize:vertical;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}',
|
'.secrets-textarea{min-height:6rem;resize:vertical;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}',
|
||||||
'.secrets-input:focus,.secrets-textarea:focus,.secrets-select:focus{border-color:#56b6c2}',
|
'.secrets-input:focus,.secrets-textarea:focus,.secrets-select:focus{border-color:var(--vt-color-accent,#4ecca3);box-shadow:var(--vt-focus-ring,0 0 0 2px rgba(78,204,163,.34))}',
|
||||||
'.secrets-actions{display:flex;gap:.5rem;flex-wrap:wrap}',
|
'.secrets-actions{display:flex;gap:.5rem;flex-wrap:wrap}',
|
||||||
'.secrets-status{font-size:.78rem;color:#8b949e;min-height:1rem}',
|
'.secrets-status{font-size:.78rem;color:var(--vt-color-text-muted,#7f8aa3);min-height:1rem}',
|
||||||
'.secrets-status.error{color:#ff8f8f}',
|
'.secrets-status.error{color:#ffc6ce}',
|
||||||
'.secrets-secret-value{white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid #303844;background:#0d1117;border-radius:4px;padding:.7rem;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:.82rem}',
|
'.secrets-secret-value{white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--vt-color-border-strong,#2c456a);background:#0f1424;border-radius:var(--vt-radius-sm,4px);padding:.7rem;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:.82rem}',
|
||||||
'.secrets-table{width:100%;border-collapse:collapse;border:1px solid #252b36;background:#11151d;border-radius:6px;overflow:hidden}',
|
'.secrets-hidden-value{display:inline-flex;align-items:center;min-height:2rem;width:100%;border:1px solid var(--vt-color-border-strong,#2c456a);border-radius:var(--vt-radius-sm,4px);background:#0f1424;color:var(--vt-color-text-muted,#7f8aa3);padding:.35rem .55rem;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;letter-spacing:.08em}',
|
||||||
'.secrets-table th,.secrets-table td{border-bottom:1px solid #252b36;padding:.55rem .65rem;text-align:left;vertical-align:top;font-size:.84rem}',
|
'.secrets-table{width:100%;border-collapse:collapse;border:1px solid var(--vt-color-border,#202b46);background:var(--vt-color-surface,#15152c);border-radius:var(--vt-radius-lg,8px);overflow:hidden}',
|
||||||
'.secrets-table th{width:9rem;color:#8b949e;font-weight:500;background:#151a23}',
|
'.secrets-table th,.secrets-table td{border-bottom:1px solid var(--vt-color-border,#202b46);padding:.55rem .65rem;text-align:left;vertical-align:top;font-size:.84rem}',
|
||||||
'.secrets-table td{color:#e6edf3;overflow-wrap:anywhere}',
|
'.secrets-table th{width:9rem;color:var(--vt-color-text-muted,#7f8aa3);font-weight:500;background:var(--vt-color-surface-muted,#111629)}',
|
||||||
|
'.secrets-table td{color:var(--vt-color-text-primary,#f4f7fb);overflow-wrap:anywhere}',
|
||||||
'.secrets-table tr:last-child th,.secrets-table tr:last-child td{border-bottom:0}',
|
'.secrets-table tr:last-child th,.secrets-table tr:last-child td{border-bottom:0}',
|
||||||
'@media(max-width:780px){.secrets-root{grid-template-columns:1fr}.secrets-panel{border-right:0;border-bottom:1px solid #252b36;max-height:45vh}.secrets-row{grid-template-columns:1fr}}'
|
'@media(max-width:780px){.secrets-root{grid-template-columns:1fr}.secrets-panel{border-right:0;border-bottom:1px solid #252b36;max-height:45vh}.secrets-row{grid-template-columns:1fr}}'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
@ -262,7 +264,7 @@
|
||||||
fieldRow('Group', scopeLabel(selectedRecord)),
|
fieldRow('Group', scopeLabel(selectedRecord)),
|
||||||
fieldRow('ID', selectedRecord.id),
|
fieldRow('ID', selectedRecord.id),
|
||||||
fieldRow('Username', selectedRecord.username || ''),
|
fieldRow('Username', selectedRecord.username || ''),
|
||||||
fieldRow('Password', selectedValue ? selectedValue : 'Value hidden'),
|
fieldRow('Password', selectedValue ? selectedValue : '••••••••••••', selectedValue ? '' : 'secrets-hidden-value'),
|
||||||
fieldRow('Updated', selectedRecord.updatedAt || '')
|
fieldRow('Updated', selectedRecord.updatedAt || '')
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
@ -280,7 +282,7 @@
|
||||||
onClick: function () { showEditSecret(); }
|
onClick: function () { showEditSecret(); }
|
||||||
}, ['Edit']),
|
}, ['Edit']),
|
||||||
el('button', {
|
el('button', {
|
||||||
className: 'secrets-btn',
|
className: 'secrets-btn danger',
|
||||||
type: 'button',
|
type: 'button',
|
||||||
'data-secret-delete': selectedRecord.id,
|
'data-secret-delete': selectedRecord.id,
|
||||||
onClick: function () { deleteSecret(selectedRecord.id); }
|
onClick: function () { deleteSecret(selectedRecord.id); }
|
||||||
|
|
@ -290,10 +292,10 @@
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fieldRow(label, value) {
|
function fieldRow(label, value, valueClass) {
|
||||||
return el('tr', {}, [
|
return el('tr', {}, [
|
||||||
el('th', {}, [label]),
|
el('th', {}, [label]),
|
||||||
el('td', {}, [value || ''])
|
el('td', {}, [valueClass ? el('span', { className: valueClass }, [value || '']) : (value || '')])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -344,10 +344,18 @@ async function mountWithApi(api, props = { workspaceNode: { name: 'Project' }, w
|
||||||
summary: 'Notes/Case.md',
|
summary: 'Notes/Case.md',
|
||||||
occurredAt: '2026-06-27T01:00:00Z',
|
occurredAt: '2026-06-27T01:00:00Z',
|
||||||
sourcePluginId: 'verstak.notes',
|
sourcePluginId: 'verstak.notes',
|
||||||
|
}, {
|
||||||
|
activityId: 'persisted-open-1',
|
||||||
|
type: 'file.opened',
|
||||||
|
title: 'Selected file',
|
||||||
|
summary: 'Project/Notes/Case.md',
|
||||||
|
occurredAt: '2026-06-27T01:05:00Z',
|
||||||
|
sourcePluginId: 'verstak.files',
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
const persisted = await mountWithApi(persistedApi);
|
const persisted = await mountWithApi(persistedApi);
|
||||||
if (!persisted.container.textContent.includes('Saved note')) throw new Error('persisted activity was not rendered');
|
if (!persisted.container.textContent.includes('Saved note')) throw new Error('persisted activity was not rendered');
|
||||||
|
if (persisted.container.textContent.includes('Selected file')) throw new Error('low-value file activity should not be rendered');
|
||||||
|
|
||||||
const legacyApi = makeApi({
|
const legacyApi = makeApi({
|
||||||
events: [
|
events: [
|
||||||
|
|
|
||||||
|
|
@ -200,17 +200,31 @@ function byData(container, attr, value) {
|
||||||
const { component, container } = await mountWithApi(api);
|
const { component, container } = await mountWithApi(api);
|
||||||
const projectKey = 'worklog:workspace:Project';
|
const projectKey = 'worklog:workspace:Project';
|
||||||
|
|
||||||
|
byData(container, 'data-journal-action', 'add').click();
|
||||||
|
await flush();
|
||||||
byData(container, 'data-journal-input', 'date').value = '2026-06-27';
|
byData(container, 'data-journal-input', 'date').value = '2026-06-27';
|
||||||
byData(container, 'data-journal-input', 'title').value = 'Draft brief';
|
byData(container, 'data-journal-input', 'title').value = 'Draft brief';
|
||||||
byData(container, 'data-journal-input', 'summary').value = 'Reviewed docs';
|
byData(container, 'data-journal-input', 'summary').value = 'Reviewed docs';
|
||||||
byData(container, 'data-journal-input', 'minutes').value = '45';
|
byData(container, 'data-journal-input', 'minutes').value = '45';
|
||||||
byData(container, 'data-journal-action', 'add').click();
|
byData(container, 'data-journal-action', 'save-entry').click();
|
||||||
await flush();
|
await flush();
|
||||||
|
|
||||||
if (api.storedEntries(projectKey).length !== 1) throw new Error('manual journal entry was not stored');
|
if (api.storedEntries(projectKey).length !== 1) throw new Error('manual journal entry was not stored');
|
||||||
if (!container.textContent.includes('Draft brief')) throw new Error('manual journal entry was not rendered');
|
if (!container.textContent.includes('Draft brief')) throw new Error('manual journal entry was not rendered');
|
||||||
if (!container.textContent.includes('45 min')) throw new Error('manual journal entry minutes were not rendered');
|
if (!container.textContent.includes('45 min')) throw new Error('manual journal entry minutes were not rendered');
|
||||||
|
|
||||||
|
byData(container, 'data-journal-action', 'edit').click();
|
||||||
|
await flush();
|
||||||
|
byData(container, 'data-journal-input', 'title').value = 'Draft brief updated';
|
||||||
|
byData(container, 'data-journal-input', 'summary').value = 'Reviewed docs and drafted notes';
|
||||||
|
byData(container, 'data-journal-input', 'minutes').value = '60';
|
||||||
|
byData(container, 'data-journal-action', 'save-entry').click();
|
||||||
|
await flush();
|
||||||
|
|
||||||
|
if (api.storedEntries(projectKey).length !== 1) throw new Error('editing journal entry created a duplicate');
|
||||||
|
if (api.storedEntries(projectKey)[0].title !== 'Draft brief updated') throw new Error('journal entry title was not updated');
|
||||||
|
if (!container.textContent.includes('60 min')) throw new Error('edited journal entry minutes were not rendered');
|
||||||
|
|
||||||
byData(container, 'data-journal-action', 'import-activity').click();
|
byData(container, 'data-journal-action', 'import-activity').click();
|
||||||
await flush();
|
await flush();
|
||||||
|
|
||||||
|
|
@ -223,9 +237,14 @@ function byData(container, attr, value) {
|
||||||
await flush();
|
await flush();
|
||||||
if (api.storedEntries(projectKey).length !== 2) throw new Error('duplicate activity suggestion was imported');
|
if (api.storedEntries(projectKey).length !== 2) throw new Error('duplicate activity suggestion was imported');
|
||||||
|
|
||||||
|
byData(container, 'data-journal-action', 'delete').click();
|
||||||
|
await flush();
|
||||||
|
if (api.storedEntries(projectKey).length !== 1) throw new Error('journal entry was not deleted');
|
||||||
|
|
||||||
const globalView = await mountWithApi(api, {});
|
const globalView = await mountWithApi(api, {});
|
||||||
if (!globalView.container.textContent.includes('Draft brief')) throw new Error('global journal did not aggregate manual entry');
|
if (!globalView.container.textContent.includes('Project work on 2026-06-27') && !globalView.container.textContent.includes('Draft brief updated')) {
|
||||||
if (!globalView.container.textContent.includes('Project work on 2026-06-27')) throw new Error('global journal did not aggregate imported suggestion');
|
throw new Error('global journal did not aggregate remaining entries');
|
||||||
|
}
|
||||||
|
|
||||||
component.unmount && component.unmount(container);
|
component.unmount && component.unmount(container);
|
||||||
component.unmount && component.unmount(globalView.container);
|
component.unmount && component.unmount(globalView.container);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue