Skip to content

Commit 541e98f

Browse files
author
abrusco
committed
feat: polish standalone UI and bump to v0.9.3
1 parent 04fac83 commit 541e98f

4 files changed

Lines changed: 781 additions & 489 deletions

File tree

docs/app.js

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ const elements = {
175175
selectedFile: document.querySelector('#selectedFile'),
176176
selectedTitle: document.querySelector('#selectedTitle'),
177177
metaObject: document.querySelector('#metaObject'),
178+
nodeName: document.querySelector('#nodeName'),
179+
roleName: document.querySelector('#roleName'),
178180
organization: document.querySelector('#organization'),
179181
date: document.querySelector('#date'),
180182
duration: document.querySelector('#duration'),
@@ -719,13 +721,16 @@ function highlightSql(sql) {
719721
'NVL', 'TO_DATE', 'TRUNC', 'REGEXP_SUBSTR', 'SYSDATE', 'COUNT', 'SUM',
720722
'MIN', 'MAX', 'AVG', 'SUBSTR', 'DECODE', 'COALESCE', 'TO_CHAR', 'TO_NUMBER'
721723
]);
722-
const tokenPattern = /(--[^\n]*|'(?:''|[^'])*'|\b\d+(?:\.\d+)?\b|\b[A-Za-z_][A-Za-z0-9_$#]*\b|<>|<=|>=|:=|[=+\-*/(),.;])/g;
724+
const tokenPattern = /(--[^\n]*|"(?:""|[^"])*"|'(?:''|[^'])*'|\b\d+(?:\.\d+)?\b|\b[A-Za-z_][A-Za-z0-9_$#]*\b|<>|<=|>=|:=|[=+\-*/(),.;])/g;
723725

724726
return String(sql || '').replace(tokenPattern, (token) => {
725727
const escaped = escapeHtml(token);
726728
if (token.startsWith('--')) {
727729
return `<span class="sql-comment">${escaped}</span>`;
728730
}
731+
if (token.startsWith('"')) {
732+
return `<span class="sql-identifier">${escaped}</span>`;
733+
}
729734
if (token.startsWith("'")) {
730735
return `<span class="sql-string">${escaped}</span>`;
731736
}
@@ -924,6 +929,8 @@ function renderSelectedEntry() {
924929
elements.selectedFile.textContent = 'Nenhum item selecionado';
925930
elements.selectedTitle.textContent = 'Selecione uma query';
926931
elements.metaObject.textContent = '-';
932+
elements.nodeName.textContent = '-';
933+
elements.roleName.textContent = '-';
927934
elements.organization.textContent = '-';
928935
elements.date.textContent = '-';
929936
elements.duration.textContent = '-';
@@ -939,14 +946,17 @@ function renderSelectedEntry() {
939946
elements.selectedFile.textContent = `${entry.fileName} | linha ${entry.lineNumber}`;
940947
elements.selectedTitle.textContent = entryDisplayTitle(entry);
941948
elements.metaObject.textContent = entry.meta4Object || '-';
949+
elements.nodeName.textContent = entry.node || '-';
950+
elements.roleName.textContent = entry.connection?.role || '-';
942951
elements.organization.textContent = entry.connection?.organization || '-';
943952
elements.date.textContent = formatDate(entry.connection?.date);
944953
elements.duration.textContent = entry.durationMs == null ? '-' : `${entry.durationMs} ms`;
945954
elements.rowCount.textContent = String(entry.recordCount ?? entry.rows.length);
946955
const sqlText = currentSqlText(entry);
947956
elements.sqlOutput.innerHTML = sqlText ? highlightSql(sqlText) : 'Sem SQL capturado.';
948957
updateFormatSqlButton();
949-
elements.rawOutput.textContent = (entry.rawLines || []).join('\n');
958+
const rawText = (entry.rawLines || []).join('\n');
959+
elements.rawOutput.innerHTML = rawText ? highlightSql(rawText) : '';
950960
renderTable(entry);
951961
}
952962

@@ -1228,28 +1238,37 @@ if (elements.formatSqlButton) {
12281238
});
12291239
}
12301240

1231-
elements.copyButton.addEventListener('click', async () => {
1232-
const entry = selectedEntry();
1233-
if (!entry?.sql) {
1234-
return;
1235-
}
1236-
await navigator.clipboard.writeText(currentSqlText(entry));
1237-
const original = elements.copyButton.textContent;
1238-
elements.copyButton.textContent = 'Copiado';
1239-
window.setTimeout(() => {
1240-
elements.copyButton.textContent = original;
1241-
}, 1200);
1242-
});
1241+
if (elements.copyButton) {
1242+
elements.copyButton.addEventListener('click', async () => {
1243+
const entry = selectedEntry();
1244+
if (!entry?.sql) {
1245+
return;
1246+
}
1247+
await navigator.clipboard.writeText(currentSqlText(entry));
1248+
const original = elements.copyButton.textContent;
1249+
elements.copyButton.textContent = 'Copiado';
1250+
window.setTimeout(() => {
1251+
elements.copyButton.textContent = original;
1252+
}, 1200);
1253+
});
1254+
}
12431255

1244-
elements.refreshButton.addEventListener('click', reloadLoadedFiles);
1256+
if (elements.refreshButton) {
1257+
elements.refreshButton.addEventListener('click', reloadLoadedFiles);
1258+
}
12451259

12461260
async function loadAppVersion() {
1261+
const appVersionElement = document.querySelector('#appVersion');
1262+
if (!appVersionElement) {
1263+
return;
1264+
}
1265+
12471266
try {
12481267
const response = await fetch('version.json', { cache: 'no-store' });
12491268
if (response.ok) {
12501269
const data = await response.json();
12511270
const version = data.version || '0.0.0';
1252-
document.querySelector('#appVersion').textContent = `v${version}`;
1271+
appVersionElement.textContent = `v${version}`;
12531272
return;
12541273
}
12551274
} catch (e) {
@@ -1258,7 +1277,7 @@ async function loadAppVersion() {
12581277

12591278
const meta = document.querySelector('meta[name="app-version"]');
12601279
const v = (meta && meta.getAttribute('content')) || '0.0.0';
1261-
document.querySelector('#appVersion').textContent = `v${v}`;
1280+
appVersionElement.textContent = `v${v}`;
12621281
}
12631282

12641283
initializeTheme();

docs/index.html

Lines changed: 105 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -3,151 +3,134 @@
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1">
6-
<meta name="app-version" content="0.9.2">
6+
<meta name="app-version" content="0.9.3">
77
<title>M4 Log Visualizer</title>
88
<link rel="stylesheet" href="styles.css">
99
</head>
1010
<body>
11-
<aside class="sidebar">
12-
<div class="brand">
11+
<!-- ── Top bar ─────────────────────────────────────────── -->
12+
<header class="topbar">
13+
<div class="topbar-brand">
1314
<span class="brand-mark">M4</span>
14-
<div>
15-
<div class="brand-title-row">
16-
<h1>Log Visualizer</h1>
17-
<span class="app-version" id="appVersion">v0.0.0</span>
18-
</div>
19-
<p id="logDir">Pasta padrao: C:\ProgramData\meta4\M4Temp\m4ldb</p>
20-
</div>
21-
</div>
22-
23-
<div class="file-loader" id="dropZone">
24-
<label for="fileInput">Arquivos de log</label>
25-
<input id="fileInput" type="file" accept=".txt,text/plain" multiple>
26-
<p>Pasta padrao: <strong>C:\ProgramData\meta4\M4Temp\m4ldb</strong>.</p>
27-
</div>
28-
29-
<div class="search-box">
30-
<label for="searchInput">Procurar nos logs</label>
31-
<input id="searchInput" type="search" placeholder="Objeto, SQL, valor retornado...">
15+
<span class="brand-name">Log Visualizer</span>
16+
<span class="app-version" id="appVersion">v0.0.0</span>
3217
</div>
3318

34-
<div class="filters">
35-
<button class="filter active" data-file="all">Todos</button>
36-
<button class="filter" data-file="ldbinsp0_1.txt">ldbinsp0_1</button>
37-
<button class="filter" data-file="ldbinsp0_2.txt">ldbinsp0_2</button>
38-
<button id="sortDescButton" class="icon-button sort-button active" type="button" title="Eventos mais recentes no topo" aria-label="Eventos mais recentes no topo"><span id="sortIcon" aria-hidden="true"></span></button>
19+
<div class="topbar-actions">
20+
<button id="themeButton" class="icon-button theme-toggle" type="button" title="Alternar tema" aria-label="Alternar tema"><span id="themeIcon" class="theme-icon" aria-hidden="true"></span></button>
21+
<button id="settingsButton" class="icon-button" type="button" title="Configurações" aria-label="Configurações"></button>
3922
</div>
23+
</header>
4024

41-
25+
<!-- ── App body (sidebar + viewer) ───────────────────────── -->
26+
<div class="app-body">
4227

43-
<label class="system-filter">
44-
<input id="onlyRealStmt" type="checkbox">
45-
<span>Mostrar somente SQLs fisicos.</span>
46-
</label>
28+
<aside class="sidebar">
29+
<div class="sidebar-top">
4730

48-
<div class="summary" id="summary"></div>
49-
<nav class="entry-list" id="entryList" aria-label="SQLs encontrados"></nav>
50-
</aside>
31+
<div class="file-loader" id="dropZone">
32+
<label for="fileInput">Arquivos de log</label>
33+
<input id="fileInput" type="file" accept=".txt,text/plain" multiple>
34+
<p id="logDir">C:\ProgramData\meta4\M4Temp\m4ldb</p>
35+
</div>
5136

52-
<main class="viewer">
53-
<header class="toolbar">
54-
<div>
55-
<p class="eyebrow" id="selectedFile">Nenhum item selecionado</p>
56-
<h2 id="selectedTitle">Selecione uma query</h2>
57-
</div>
58-
<div class="actions">
59-
<button id="themeButton" class="icon-button theme-toggle" type="button" title="Alternar tema" aria-label="Alternar tema"><span id="themeIcon" class="theme-icon" aria-hidden="true"></span></button>
60-
<button id="settingsButton" title="Configurações" aria-label="Configurações">Config</button>
61-
<button id="refreshButton" title="Recarregar logs">Atualizar</button>
62-
<button id="copyButton" title="Copiar SQL Oracle">Copiar SQL</button>
63-
</div>
64-
</header>
37+
<div class="search-box">
38+
<input id="searchInput" type="search" placeholder="Procurar nos logs...">
39+
</div>
6540

66-
<section class="details-grid">
67-
<div>
68-
<span>Objeto</span>
69-
<strong id="metaObject">-</strong>
70-
</div>
71-
<div>
72-
<span>Organizacao</span>
73-
<strong id="organization">-</strong>
74-
</div>
75-
<div>
76-
<span>Data</span>
77-
<strong id="date">-</strong>
78-
</div>
79-
<div>
80-
<span>Tempo</span>
81-
<strong id="duration">-</strong>
82-
</div>
83-
<div>
84-
<span>Linhas</span>
85-
<strong id="rowCount">-</strong>
86-
</div>
87-
</section>
41+
<div class="filters">
42+
<button class="filter active" data-file="all">Todos</button>
43+
<button class="filter" data-file="ldbinsp0_1.txt">ldbinsp0_1</button>
44+
<button class="filter" data-file="ldbinsp0_2.txt">ldbinsp0_2</button>
45+
<button id="sortDescButton" class="icon-button sort-button active" type="button" title="Eventos mais recentes no topo" aria-label="Eventos mais recentes no topo"><span id="sortIcon" aria-hidden="true"></span></button>
46+
</div>
8847

89-
<section class="panel sql-panel">
90-
<div class="panel-header">
91-
<h3>SQL Oracle</h3>
92-
<button id="formatSqlButton" class="panel-action" type="button" title="Formatar SQL">Formatar SQL</button>
93-
</div>
94-
<pre id="sqlOutput">Aguardando selecao...</pre>
95-
</section>
48+
<label class="system-filter">
49+
<input id="onlyRealStmt" type="checkbox">
50+
<span>Mostrar somente SQLs físicos</span>
51+
</label>
9652

97-
<section class="panel">
98-
<div class="panel-header">
99-
<h3>Resultado retornado no log</h3>
100-
<span id="tableHint"></span>
53+
<div class="summary" id="summary"></div>
10154
</div>
102-
<div class="table-wrap">
103-
<table id="resultTable"></table>
104-
</div>
105-
</section>
10655

107-
<section class="panel raw-panel">
108-
<div class="panel-header">
109-
<h3>Trecho original</h3>
56+
<nav class="entry-list" id="entryList" aria-label="SQLs encontrados"></nav>
57+
</aside>
58+
59+
<main class="viewer">
60+
<section class="viewer-meta">
61+
<p class="viewer-meta-file" id="selectedFile">Nenhum item selecionado</p>
62+
<h2 class="viewer-meta-title" id="selectedTitle">Selecione uma query</h2>
63+
<div class="status-bar">
64+
<span class="status-item status-item-primary"><span class="status-label">Objeto</span><strong id="metaObject">-</strong></span>
65+
<span class="status-item"><span class="status-label">Node</span><strong id="nodeName">-</strong></span>
66+
<span class="status-item status-item-compact"><span class="status-label">Role</span><strong id="roleName">-</strong></span>
67+
<span class="status-item"><span class="status-label">Data</span><strong id="date">-</strong></span>
68+
<span class="status-item"><span class="status-label">Tempo</span><strong id="duration">-</strong></span>
69+
<span id="organization" class="status-hidden" aria-hidden="true">-</span>
70+
<span id="rowCount" class="status-hidden" aria-hidden="true">-</span>
71+
</div>
72+
</section>
73+
74+
<div class="viewer-scroll">
75+
76+
<section class="panel sql-panel">
77+
<div class="panel-header">
78+
<h3>SQL Oracle</h3>
79+
<div class="panel-actions">
80+
<button id="copyButton" class="panel-action" type="button" title="Copiar SQL Oracle">Copiar SQL</button>
81+
<button id="formatSqlButton" class="panel-action" type="button" title="Formatar SQL">Formatar SQL</button>
82+
</div>
83+
</div>
84+
<pre id="sqlOutput">Aguardando seleção...</pre>
85+
</section>
86+
87+
<section class="panel">
88+
<div class="panel-header">
89+
<h3>Resultado retornado no log</h3>
90+
<span id="tableHint"></span>
91+
</div>
92+
<div class="table-wrap">
93+
<table id="resultTable"></table>
94+
</div>
95+
</section>
96+
97+
<section class="panel raw-panel">
98+
<div class="panel-header">
99+
<h3>Trecho original</h3>
100+
</div>
101+
<pre id="rawOutput"></pre>
102+
</section>
103+
104+
</div><!-- /viewer-scroll -->
105+
</main>
106+
107+
</div><!-- /app-body -->
108+
109+
<!-- ── Settings drawer ───────────────────────────────────── -->
110+
<aside id="settingsPanel" class="settings-panel hidden" role="dialog" aria-modal="true" aria-label="Configurações">
111+
<div class="panel-header">
112+
<h3>Configurações</h3>
113+
<button id="closeSettingsButton" class="panel-action" type="button">Fechar</button>
114+
</div>
115+
<div class="settings-content">
116+
<label for="newIgnoredObject">Adicionar objeto ignorado</label>
117+
<div class="add-row">
118+
<input id="newIgnoredObject" type="text" placeholder="Nome do objeto (ex: SSC_APPUSER)">
119+
<button id="addIgnoredButton" type="button">Adicionar</button>
110120
</div>
111-
<pre id="rawOutput"></pre>
112-
</section>
113121

114-
<section id="settingsPanel" class="panel settings-panel hidden" role="dialog" aria-modal="true" aria-label="Configurações">
115-
<div class="panel-header">
116-
<h3>Configurações</h3>
122+
<div class="ignored-list-wrap">
123+
<h4>Objetos ignorados</h4>
124+
<ul id="ignoredList" class="ignored-list"></ul>
117125
</div>
118-
<div class="settings-content">
119-
<label for="newIgnoredObject">Adicionar objeto ignorado</label>
120-
<div class="add-row">
121-
<input id="newIgnoredObject" type="text" placeholder="Nome do objeto (ex: SSC_APPUSER)">
122-
<button id="addIgnoredButton">Adicionar</button>
123-
</div>
124126

125-
<div class="ignored-list-wrap">
126-
<h4>Objetos ignorados</h4>
127-
<ul id="ignoredList" class="ignored-list"></ul>
128-
</div>
129-
130-
<div class="settings-actions">
131-
<button id="resetIgnoredButton">Resetar para padrão</button>
132-
<button id="closeSettingsButton">Fechar</button>
133-
</div>
127+
<div class="settings-actions">
128+
<button id="resetIgnoredButton" type="button">Resetar para padrão</button>
134129
</div>
135-
</section>
136-
<div id="settingsBackdrop" class="hidden" aria-hidden="true"></div>
137-
</main>
130+
</div>
131+
</aside>
132+
<div id="settingsBackdrop" class="hidden" aria-hidden="true"></div>
138133

139134
<script src="app.js"></script>
140135
</body>
141136
</html>
142-
143-
144-
145-
146-
147-
148-
149-
150-
151-
152-
153-

0 commit comments

Comments
 (0)