@cccarv82/freya 2.3.1 → 2.3.3

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.
Files changed (2) hide show
  1. package/cli/web-ui.js +57 -2
  2. package/package.json +1 -1
package/cli/web-ui.js CHANGED
@@ -663,6 +663,7 @@
663
663
  const items = Array.isArray(state.projects) ? state.projects : [];
664
664
  const filtered = items.filter((p) => {
665
665
  const hay = [p.client, p.program, p.stream, p.project, p.slug, (p.tags||[]).join(' ')].join(' ').toLowerCase();
666
+ if (kind !== 'all' && String(i.kind||'') !== kind) return false;
666
667
  return !filter || hay.includes(filter);
667
668
  });
668
669
  el.innerHTML = '';
@@ -703,17 +704,32 @@
703
704
  if (!el) return;
704
705
  const filter = String(($('timelineFilter') && $('timelineFilter').value) || '').toLowerCase();
705
706
  const items = Array.isArray(state.timeline) ? state.timeline : [];
707
+ const kind = state.timelineKind || 'all';
706
708
  const filtered = items.filter((i) => {
707
709
  const hay = [i.kind, i.title, i.content, (i.tags || []).join(' ')].join(' ').toLowerCase();
708
710
  return !filter || hay.includes(filter);
709
711
  });
710
712
  el.innerHTML = '';
713
+ let currentDate = null;
711
714
  for (const it of filtered) {
715
+ if (it.date && it.date !== currentDate) {
716
+ currentDate = it.date;
717
+ const head = document.createElement('div');
718
+ head.className = 'help';
719
+ head.style.fontWeight = '800';
720
+ head.style.marginTop = '6px';
721
+ head.textContent = currentDate;
722
+ el.appendChild(head);
723
+ }
712
724
  const card = document.createElement('div');
713
725
  card.className = 'reportCard';
714
726
  card.innerHTML = '<div class="reportHead">'
715
727
  + '<div><div class="reportTitle">' + escapeHtml(it.title || 'Evento') + '</div>'
716
728
  + '<div class="reportMeta">' + escapeHtml(it.date || '') + ' · ' + escapeHtml(it.kind || '') + '</div></div>'
729
+ + '<div class="reportActions">'
730
+ + '<span class="pill info">' + escapeHtml(it.kind || '') + '</span>'
731
+ + (it.slug ? ('<span class="pill">' + escapeHtml(it.slug) + '</span>') : '')
732
+ + '</div>'
717
733
  + '</div>'
718
734
  + '<div class="help" style="margin-top:8px">' + escapeHtml(it.content || '') + '</div>';
719
735
  el.appendChild(card);
@@ -726,6 +742,11 @@
726
742
  }
727
743
  }
728
744
 
745
+ function setTimelineKind(kind) {
746
+ state.timelineKind = kind;
747
+ renderTimeline();
748
+ }
749
+
729
750
  async function refreshTimeline() {
730
751
  try {
731
752
  const r = await api('/api/timeline', { dir: dirOrDefault() });
@@ -743,7 +764,32 @@
743
764
  const el = $('incidentsBox');
744
765
  if (el) {
745
766
  const md = r.markdown || '';
746
- el.innerHTML = md ? renderMarkdown(md) : '<div class="help">Nenhum incidente registrado.</div>';
767
+ if (!md) { el.innerHTML = '<div class="help">Nenhum incidente registrado.</div>'; return; }
768
+ const lines = md.split(/\n/);
769
+ const cards = [];
770
+ let current = null;
771
+ for (const line of lines) {
772
+ if (line.startsWith('- **')) {
773
+ if (current) cards.push(current);
774
+ current = { title: line.replace('- **', '').replace('**', '').trim(), body: [] };
775
+ } else if (current && line.trim().startsWith('- ')) {
776
+ current.body.push(line.trim().replace(/^- /, ''));
777
+ }
778
+ }
779
+ if (current) cards.push(current);
780
+ el.innerHTML = '';
781
+ if (!cards.length) { el.innerHTML = renderMarkdown(md); return; }
782
+ for (const c of cards) {
783
+ const card = document.createElement('div');
784
+ card.className = 'reportCard';
785
+ const dateLine = c.body.find((b)=> b.toLowerCase().includes('data'));
786
+ const impactLine = c.body.find((b)=> b.toLowerCase().includes('descricao') || b.toLowerCase().includes('impacto'));
787
+ card.innerHTML = '<div class="reportTitle">' + escapeHtml(c.title) + '</div>'
788
+ + (dateLine ? ('<div class="reportMeta">' + escapeHtml(dateLine) + '</div>') : '')
789
+ + (impactLine ? ('<div class="help" style="margin-top:4px">' + escapeHtml(impactLine) + '</div>') : '')
790
+ + c.body.filter((b)=> b!==dateLine && b!==impactLine).map((b) => '<div class="help" style="margin-top:4px">' + escapeHtml(b) + '</div>').join('');
791
+ el.appendChild(card);
792
+ }
747
793
  }
748
794
  } catch {
749
795
  const el = $('incidentsBox');
@@ -751,13 +797,20 @@
751
797
  }
752
798
  }
753
799
 
800
+ function setHeatmapSort(sort) {
801
+ state.heatmapSort = sort;
802
+ refreshHeatmap();
803
+ }
804
+
754
805
  async function refreshHeatmap() {
755
806
  try {
756
807
  const r = await api('/api/tasks/heatmap', { dir: dirOrDefault() });
757
808
  const el = $('heatmapGrid');
758
809
  if (!el) return;
759
810
  el.innerHTML = '';
760
- const items = r.items || [];
811
+ let items = r.items || [];
812
+ const sort = state.heatmapSort || 'pending';
813
+ items = items.slice().sort((a,b)=> (b[sort]||0) - (a[sort]||0));
761
814
  for (const it of items) {
762
815
  const row = document.createElement('div');
763
816
  row.className = 'rep';
@@ -1540,6 +1593,8 @@
1540
1593
  window.refreshTimeline = refreshTimeline;
1541
1594
  window.refreshIncidents = refreshIncidents;
1542
1595
  window.refreshHeatmap = refreshHeatmap;
1596
+ window.setHeatmapSort = setHeatmapSort;
1597
+ window.setTimelineKind = setTimelineKind;
1543
1598
  window.refreshBlockersInsights = refreshBlockersInsights;
1544
1599
  window.refreshHealthChecklist = refreshHealthChecklist;
1545
1600
  window.copyOut = copyOut;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cccarv82/freya",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "Personal AI Assistant with local-first persistence",
5
5
  "scripts": {
6
6
  "health": "node scripts/validate-data.js && node scripts/validate-structure.js",