added a shortcut to open the loging app

This commit is contained in:
Pierre committed 2026-10-04 14:06:31 +02:00
1 parent 5614ad049d
commit f57e23d76a
7 files changed
+31 -5

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ By default, it reads the existing AppDaemon text logs from the workspace:
- `logs/error.log`
- `logs/virtualsensors.log`
The explorer groups lines by the app name in the standard AppDaemon log format. It provides INFO/WARNING/ERROR counts, expandable app histories, relative timestamps, sorting by latest activity or app name, text/time/level filters, live updates, and raw-log navigation. Duplicate error lines found in multiple files are merged. The log reader handles file rotation, truncation, multiline exceptions, UTF-8, and legacy Windows-1252 bytes.
The explorer groups lines by the app name in the standard AppDaemon log format. It provides INFO/WARNING/ERROR counts, expandable app histories, links to app definitions, relative timestamps, sorting by latest activity or app name, text/time/level filters, live updates, and raw-log navigation. Duplicate error lines found in multiple files are merged. The log reader handles file rotation, truncation, multiline exceptions, UTF-8, and legacy Windows-1252 bytes.
**AD Logs** turns red when the loaded logs contain an ERROR or CRITICAL entry. **Clear logs** empties the configured log files and clears the current explorer history.
+1
View File
@@ -13,3 +13,4 @@
summary{display:grid;grid-template-columns:auto minmax(0,1fr) repeat(3,max-content);align-items:center;column-gap:10px;row-gap:5px}
summary .last-log{grid-column:1/-1;min-width:0}
.rows{max-height:min(45vh,420px);overflow-y:auto;scrollbar-gutter:stable;overflow-anchor:none}
.app-label{flex-direction:row;align-items:center;gap:6px}.app-label .name{min-width:0}.app-link{color:var(--accent);font-size:13px;line-height:1;text-decoration:none;white-space:nowrap}.app-link:hover{text-decoration:underline}.app-link:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
+9
View File
@@ -161,6 +161,15 @@
const last = lastLogs.get(app);
let preview;
label.append(node('span', app, 'name'));
const appLink = node('a', '↗', 'app-link');
appLink.href = '#';
appLink.title = `Open ${app} definition`;
appLink.setAttribute('aria-label', `Open ${app} definition`);
appLink.onclick = event => {
event.preventDefault(); event.stopPropagation();
vscode.postMessage({ type: 'app', app });
};
label.append(appLink);
if (last) {
const line = node('span', undefined, `last-log log-message level-${normalLevel(last)}`);
const age = node('span', shortTimeSince(last.time), 'last-age');
+6 -4
View File
@@ -444,10 +444,12 @@ export async function activate(context: vscode.ExtensionContext) {
editor.revealRange(new vscode.Range(pos, pos), vscode.TextEditorRevealType.InCenter);
}),
vscode.commands.registerCommand('appdaemon.goToApp', async () => {
const apps = await findAllApps();
vscode.commands.registerCommand('appdaemon.goToApp', async (requestedName?: string) => {
const apps = (await findAllApps()).filter(app => !requestedName || app.appName === requestedName);
if (apps.length === 0) {
vscode.window.showWarningMessage('AppDaemon: No app definitions found in workspace');
vscode.window.showWarningMessage(requestedName
? `AppDaemon: No definition found for ${requestedName}`
: 'AppDaemon: No app definitions found in workspace');
return;
}
@@ -459,7 +461,7 @@ export async function activate(context: vscode.ExtensionContext) {
app
}));
const picked = await vscode.window.showQuickPick(items, {
const picked = apps.length === 1 && requestedName ? items[0] : await vscode.window.showQuickPick(items, {
placeHolder: 'Go to AppDaemon app…',
matchOnDescription: true,
matchOnDetail: false
+3
View File
@@ -58,6 +58,9 @@ export class LogExplorer implements vscode.Disposable {
this.messageListener?.dispose();
this.messageListener = webview.onDidReceiveMessage(async message => {
if (message.type === 'ready') { this.publish(); }
if (message.type === 'app' && typeof message.app === 'string') {
await vscode.commands.executeCommand('appdaemon.goToApp', message.app);
}
if (message.type === 'open' && typeof message.id === 'string') {
const entry = this.entries.get(message.id);
if (!entry?.file) { return; }
+11
View File
@@ -51,6 +51,17 @@ test('selects individual logs and entire initialization groups',()=>{
const input=d.getElementById('search'),paste=new dom.window.KeyboardEvent('keydown',{key:'v',ctrlKey:true,bubbles:true,cancelable:true});input.dispatchEvent(paste);assert.equal(paste.defaultPrevented,false);
assert.deepEqual(errors,[]);dom.window.close();
});
test('app link opens its YAML definition without expanding the log group',async()=>{
const {dom,d,sent}=setup();
const app=d.querySelector('[data-app="alpha"]'),link=app.querySelector('.app-link');
assert.equal(link.getAttribute('aria-label'),'Open alpha definition');
link.click();
await new Promise(resolve=>setTimeout(resolve,0));
assert.equal(sent.at(-1).type,'app');assert.equal(sent.at(-1).app,'alpha');
assert.equal(app.open,false);
dom.window.close();
});
test('retains selected text during live updates and leaves Ctrl+C to the browser',async()=>{
const {dom,d,entries,errors,send}=setup();const alpha=d.querySelector('[data-app="alpha"]');alpha.open=true;alpha.dispatchEvent(new dom.window.Event('toggle'));
const text=alpha.querySelector('.row-message'),range=d.createRange();range.selectNodeContents(text);dom.window.getSelection().addRange(range);
Binary file not shown.