issue-flow 0.7.5 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/web/public/app.css +87 -0
- package/web/public/app.js +80 -0
- package/web/public/index.html +11 -0
package/package.json
CHANGED
package/web/public/app.css
CHANGED
|
@@ -234,6 +234,93 @@ select {
|
|
|
234
234
|
margin: 0 0 4px;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
/* ---- Resumo da issue ---- */
|
|
238
|
+
|
|
239
|
+
.issue-summary-title {
|
|
240
|
+
margin: 0 0 8px;
|
|
241
|
+
font-weight: 600;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.issue-summary-meta {
|
|
245
|
+
display: flex;
|
|
246
|
+
flex-wrap: wrap;
|
|
247
|
+
align-items: center;
|
|
248
|
+
gap: 10px;
|
|
249
|
+
margin-bottom: 8px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.badge-row {
|
|
253
|
+
display: flex;
|
|
254
|
+
flex-wrap: wrap;
|
|
255
|
+
gap: 6px;
|
|
256
|
+
margin-bottom: 8px;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.label-badge {
|
|
260
|
+
background: var(--idle-bg);
|
|
261
|
+
color: var(--fg);
|
|
262
|
+
text-transform: none;
|
|
263
|
+
font-weight: 500;
|
|
264
|
+
letter-spacing: normal;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.state-open {
|
|
268
|
+
background: var(--run-bg);
|
|
269
|
+
color: var(--run);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.state-closed {
|
|
273
|
+
background: var(--ok-bg);
|
|
274
|
+
color: var(--ok);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.state-unknown {
|
|
278
|
+
background: var(--idle-bg);
|
|
279
|
+
color: var(--muted);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.issue-description {
|
|
283
|
+
margin: 0;
|
|
284
|
+
white-space: pre-wrap;
|
|
285
|
+
word-break: break-word;
|
|
286
|
+
max-height: 220px;
|
|
287
|
+
overflow-y: auto;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* ---- User stories: status e dependências ---- */
|
|
291
|
+
|
|
292
|
+
.story-meta {
|
|
293
|
+
display: flex;
|
|
294
|
+
flex-wrap: wrap;
|
|
295
|
+
align-items: center;
|
|
296
|
+
gap: 8px;
|
|
297
|
+
margin-top: 4px;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.story-status-backlog {
|
|
301
|
+
background: var(--idle-bg);
|
|
302
|
+
color: var(--muted);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.story-status-in_progress {
|
|
306
|
+
background: var(--run-bg);
|
|
307
|
+
color: var(--run);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.story-status-in_review {
|
|
311
|
+
background: var(--warn-bg);
|
|
312
|
+
color: var(--warn);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.story-status-done {
|
|
316
|
+
background: var(--ok-bg);
|
|
317
|
+
color: var(--ok);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.story-deps {
|
|
321
|
+
font-size: 0.84rem;
|
|
322
|
+
}
|
|
323
|
+
|
|
237
324
|
/* ---- Progresso ---- */
|
|
238
325
|
|
|
239
326
|
.progress-row {
|
package/web/public/app.js
CHANGED
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
failed: '✗',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
const STORY_STATUS_LABELS = {
|
|
29
|
+
backlog: 'backlog',
|
|
30
|
+
in_progress: 'em andamento',
|
|
31
|
+
in_review: 'em revisão',
|
|
32
|
+
done: 'concluída',
|
|
33
|
+
};
|
|
34
|
+
|
|
28
35
|
const els = {
|
|
29
36
|
banner: document.getElementById('banner-disconnected'),
|
|
30
37
|
issueLink: document.getElementById('issue-link'),
|
|
@@ -35,6 +42,8 @@
|
|
|
35
42
|
refreshSelect: document.getElementById('refresh-select'),
|
|
36
43
|
alerts: document.getElementById('alerts'),
|
|
37
44
|
alertsBody: document.getElementById('alerts-body'),
|
|
45
|
+
issueSummary: document.getElementById('issue-summary'),
|
|
46
|
+
repository: document.getElementById('repository'),
|
|
38
47
|
progressBar: document.getElementById('progress-bar'),
|
|
39
48
|
progressPercent: document.getElementById('progress-percent'),
|
|
40
49
|
progressCounters: document.getElementById('progress-counters'),
|
|
@@ -266,6 +275,8 @@
|
|
|
266
275
|
if (!snapshot) return;
|
|
267
276
|
renderHeader(snapshot);
|
|
268
277
|
renderAlerts(snapshot);
|
|
278
|
+
renderIssueSummary(snapshot);
|
|
279
|
+
renderRepository(snapshot);
|
|
269
280
|
renderProgress(snapshot);
|
|
270
281
|
renderNow(snapshot);
|
|
271
282
|
renderPhases(snapshot);
|
|
@@ -341,6 +352,61 @@
|
|
|
341
352
|
}
|
|
342
353
|
}
|
|
343
354
|
|
|
355
|
+
// snapshot.issue vem sempre como objeto (schema não o torna nulável); só os
|
|
356
|
+
// campos individuais podem ser null/undefined — session.json antigo, issue
|
|
357
|
+
// local sem remote, etc. Cada leitura abaixo trata isso individualmente.
|
|
358
|
+
function renderIssueSummary(snapshot) {
|
|
359
|
+
clear(els.issueSummary);
|
|
360
|
+
const issue = snapshot.issue || {};
|
|
361
|
+
|
|
362
|
+
const heading = el('p', 'issue-summary-title');
|
|
363
|
+
heading.appendChild(
|
|
364
|
+
el('span', 'mono', issue.number !== null && issue.number !== undefined ? '#' + issue.number : '—'),
|
|
365
|
+
);
|
|
366
|
+
heading.appendChild(document.createTextNode(' ' + (issue.title || 'Sem título')));
|
|
367
|
+
els.issueSummary.appendChild(heading);
|
|
368
|
+
|
|
369
|
+
const meta = el('div', 'issue-summary-meta');
|
|
370
|
+
const state = issue.state || null;
|
|
371
|
+
const stateClass = state === 'open' ? 'state-open' : state === 'closed' ? 'state-closed' : 'state-unknown';
|
|
372
|
+
meta.appendChild(el('span', 'badge ' + stateClass, state || 'estado desconhecido'));
|
|
373
|
+
meta.appendChild(el('span', 'muted', 'Prioridade: Não definida'));
|
|
374
|
+
els.issueSummary.appendChild(meta);
|
|
375
|
+
|
|
376
|
+
const labels = issue.labels || [];
|
|
377
|
+
if (labels.length > 0) {
|
|
378
|
+
const labelRow = el('div', 'badge-row');
|
|
379
|
+
for (const label of labels) {
|
|
380
|
+
labelRow.appendChild(el('span', 'badge label-badge', label));
|
|
381
|
+
}
|
|
382
|
+
els.issueSummary.appendChild(labelRow);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
els.issueSummary.appendChild(el('p', 'issue-description', issue.description || 'Sem descrição.'));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function metaRow(grid, label, value, className) {
|
|
389
|
+
grid.appendChild(el('dt', null, label));
|
|
390
|
+
const dd = el('dd', className, value);
|
|
391
|
+
grid.appendChild(dd);
|
|
392
|
+
return dd;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// snapshot.repository é coletado de forma tolerante a falhas (sem remote,
|
|
396
|
+
// sem commits, git ausente): cada campo pode ser null independentemente dos
|
|
397
|
+
// demais, nunca o objeto inteiro.
|
|
398
|
+
function renderRepository(snapshot) {
|
|
399
|
+
clear(els.repository);
|
|
400
|
+
const repo = snapshot.repository || {};
|
|
401
|
+
const grid = el('dl', 'now-grid');
|
|
402
|
+
metaRow(grid, 'Repositório', repo.name || '—');
|
|
403
|
+
metaRow(grid, 'Branch', repo.branch || '—', 'mono');
|
|
404
|
+
metaRow(grid, 'Commit', repo.headCommit || '—', 'mono');
|
|
405
|
+
const rootDd = metaRow(grid, 'Diretório', repo.root || '—', 'mono');
|
|
406
|
+
if (repo.root) rootDd.title = repo.root;
|
|
407
|
+
els.repository.appendChild(grid);
|
|
408
|
+
}
|
|
409
|
+
|
|
344
410
|
function renderProgress(snapshot) {
|
|
345
411
|
const progress = snapshot.progress;
|
|
346
412
|
els.progressBar.value = progress.percent;
|
|
@@ -452,6 +518,20 @@
|
|
|
452
518
|
title.appendChild(el('span', 'story-id', story.id));
|
|
453
519
|
title.appendChild(document.createTextNode(story.title));
|
|
454
520
|
main.appendChild(title);
|
|
521
|
+
|
|
522
|
+
// status/dependencies vêm com default no schema (backlog/[]), mas
|
|
523
|
+
// session.json gravado antes de #29 pode chegar sem eles.
|
|
524
|
+
const storyStatus = story.status !== null && story.status !== undefined ? story.status : 'backlog';
|
|
525
|
+
const meta = el('div', 'story-meta');
|
|
526
|
+
meta.appendChild(
|
|
527
|
+
el('span', 'badge story-status-' + storyStatus, STORY_STATUS_LABELS[storyStatus] || storyStatus),
|
|
528
|
+
);
|
|
529
|
+
const dependencies = story.dependencies || [];
|
|
530
|
+
if (dependencies.length > 0) {
|
|
531
|
+
meta.appendChild(el('span', 'muted story-deps', 'depende de: ' + dependencies.join(', ')));
|
|
532
|
+
}
|
|
533
|
+
main.appendChild(meta);
|
|
534
|
+
|
|
455
535
|
item.appendChild(main);
|
|
456
536
|
const duration = metric(story.durationSeconds);
|
|
457
537
|
const side = itemSideText([
|
package/web/public/index.html
CHANGED
|
@@ -41,6 +41,17 @@
|
|
|
41
41
|
<div id="alerts-body"></div>
|
|
42
42
|
</section>
|
|
43
43
|
|
|
44
|
+
<div class="columns">
|
|
45
|
+
<section class="card">
|
|
46
|
+
<h2>Resumo da issue</h2>
|
|
47
|
+
<div id="issue-summary"></div>
|
|
48
|
+
</section>
|
|
49
|
+
<section class="card">
|
|
50
|
+
<h2>Repositório</h2>
|
|
51
|
+
<div id="repository"></div>
|
|
52
|
+
</section>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
44
55
|
<section class="card" aria-live="polite">
|
|
45
56
|
<h2>Progresso</h2>
|
|
46
57
|
<div class="progress-row">
|