Improve Activity panel + task tracking rules
- Activity loads from tasks.json dynamically - Added task tracking workflow in AGENTS.md - Notes UI improvements - Renamed recipe with date prefix
This commit is contained in:
@@ -292,6 +292,64 @@
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
|
||||
.tag-filter-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.tag-filter-header svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--text-muted);
|
||||
transition: transform var(--transition-fast);
|
||||
}
|
||||
|
||||
.tag-filter.collapsed .tag-filter-header svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.tag-pills-more {
|
||||
display: none;
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
|
||||
.tag-pills-more.expanded {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
/* More tags toggle button - same style as pills */
|
||||
.tag-pill.more-toggle {
|
||||
background: rgba(100, 116, 139, 0.2);
|
||||
border-color: rgba(100, 116, 139, 0.4);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.tag-pill.more-toggle:hover {
|
||||
background: rgba(100, 116, 139, 0.3);
|
||||
}
|
||||
.tag-pill.more-toggle.expanded {
|
||||
background: rgba(100, 116, 139, 0.4);
|
||||
}
|
||||
|
||||
/* Dimmed pills - tags not in visible notes */
|
||||
.tag-pill.dimmed {
|
||||
opacity: 0.35;
|
||||
}
|
||||
.tag-pill.dimmed:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.filter-count {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-muted);
|
||||
margin-left: var(--space-1);
|
||||
}
|
||||
|
||||
.tag-filter-label {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-muted);
|
||||
@@ -335,6 +393,44 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Category pills (📁) - teal */
|
||||
.tag-pill.category {
|
||||
background: rgba(20, 184, 166, 0.2);
|
||||
border-color: rgba(20, 184, 166, 0.5);
|
||||
color: #14b8a6;
|
||||
}
|
||||
.tag-pill.category:hover {
|
||||
background: rgba(20, 184, 166, 0.3);
|
||||
}
|
||||
.tag-pill.category.active {
|
||||
background: #14b8a6;
|
||||
border-color: #14b8a6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Domain pills (@) - purple */
|
||||
.tag-pill.domain {
|
||||
background: rgba(139, 92, 246, 0.2);
|
||||
border-color: rgba(139, 92, 246, 0.5);
|
||||
color: #8b5cf6;
|
||||
}
|
||||
.tag-pill.domain:hover {
|
||||
background: rgba(139, 92, 246, 0.3);
|
||||
}
|
||||
.tag-pill.domain.active {
|
||||
background: #8b5cf6;
|
||||
border-color: #8b5cf6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Light mode adjustments */
|
||||
[data-theme="light"] .tag-pill.category {
|
||||
color: #0d9488;
|
||||
}
|
||||
[data-theme="light"] .tag-pill.domain {
|
||||
color: #7c3aed;
|
||||
}
|
||||
|
||||
.tag-pill-count {
|
||||
font-size: var(--text-xs);
|
||||
opacity: 0.7;
|
||||
@@ -426,8 +522,8 @@
|
||||
</div>
|
||||
|
||||
<div class="tag-filter">
|
||||
<span class="tag-filter-label">Filtrează după tags:</span>
|
||||
<div class="tag-pills" id="tagPills"></div>
|
||||
<div class="tag-pills" id="mainPills"></div>
|
||||
<div class="tag-pills-more" id="tagPills"></div>
|
||||
</div>
|
||||
|
||||
<div id="notesContainer">
|
||||
@@ -482,6 +578,7 @@
|
||||
|
||||
const notesCache = {};
|
||||
let notesIndex = [];
|
||||
let lastFilteredNotes = null;
|
||||
const notesBasePath = "notes-data/";
|
||||
const indexPath = notesBasePath + "index.json";
|
||||
|
||||
@@ -499,37 +596,107 @@
|
||||
}
|
||||
let selectedTags = new Set();
|
||||
|
||||
// Extract all tags with counts
|
||||
// Extract all tags with counts (including domains and categories)
|
||||
function getAllTags() {
|
||||
const tagCounts = {};
|
||||
notesIndex.forEach(note => {
|
||||
// Category tags (📁youtube, 📁retete)
|
||||
if (note.category) {
|
||||
const catTag = '📁' + note.category;
|
||||
tagCounts[catTag] = (tagCounts[catTag] || 0) + 1;
|
||||
}
|
||||
// Domain tags (@work, @health, etc.)
|
||||
if (note.domains) {
|
||||
note.domains.forEach(domain => {
|
||||
const domainTag = '@' + domain;
|
||||
tagCounts[domainTag] = (tagCounts[domainTag] || 0) + 1;
|
||||
});
|
||||
}
|
||||
// Regular tags
|
||||
note.tags.forEach(tag => {
|
||||
tagCounts[tag] = (tagCounts[tag] || 0) + 1;
|
||||
});
|
||||
});
|
||||
// Sort by count descending
|
||||
// Sort: categories first (📁), then domains (@), then by count
|
||||
return Object.entries(tagCounts)
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.sort((a, b) => {
|
||||
const aIsCat = a[0].startsWith('📁');
|
||||
const bIsCat = b[0].startsWith('📁');
|
||||
const aIsDomain = a[0].startsWith('@');
|
||||
const bIsDomain = b[0].startsWith('@');
|
||||
if (aIsCat && !bIsCat) return -1;
|
||||
if (!aIsCat && bIsCat) return 1;
|
||||
if (aIsDomain && !bIsDomain) return -1;
|
||||
if (!aIsDomain && bIsDomain) return 1;
|
||||
return b[1] - a[1];
|
||||
})
|
||||
.map(([tag, count]) => ({ tag, count }));
|
||||
}
|
||||
|
||||
// Render tag pills
|
||||
function renderTagPills() {
|
||||
const container = document.getElementById('tagPills');
|
||||
function renderTagPills(visibleNotes = null) {
|
||||
const mainContainer = document.getElementById('mainPills');
|
||||
const moreContainer = document.getElementById('tagPills');
|
||||
const tags = getAllTags();
|
||||
|
||||
let html = tags.map(({ tag, count }) => `
|
||||
<span class="tag-pill ${selectedTags.has(tag) ? 'active' : ''}"
|
||||
onclick="toggleTag('${tag}')">
|
||||
${tag} <span class="tag-pill-count">(${count})</span>
|
||||
</span>
|
||||
`).join('');
|
||||
// Calculate which tags appear in visible notes
|
||||
const visibleTags = new Set();
|
||||
if (visibleNotes && visibleNotes.length > 0) {
|
||||
visibleNotes.forEach(note => {
|
||||
note.tags.forEach(t => visibleTags.add(t));
|
||||
(note.domains || []).forEach(d => visibleTags.add('@' + d));
|
||||
if (note.category) visibleTags.add('📁' + note.category);
|
||||
});
|
||||
}
|
||||
const hasFilter = visibleNotes !== null;
|
||||
|
||||
if (selectedTags.size > 0) {
|
||||
html += `<button class="clear-filters" onclick="clearTagFilters()">✕ Clear</button>`;
|
||||
// Separate: categories + domains vs regular tags
|
||||
const mainTags = tags.filter(({tag}) => tag.startsWith('📁') || tag.startsWith('@'));
|
||||
const moreTags = tags.filter(({tag}) => !tag.startsWith('📁') && !tag.startsWith('@'));
|
||||
|
||||
// Check if more section is expanded
|
||||
const isExpanded = moreContainer.classList.contains('expanded');
|
||||
const activeMoreCount = [...selectedTags].filter(t => !t.startsWith('📁') && !t.startsWith('@')).length;
|
||||
|
||||
// Render main pills (categories + domains)
|
||||
let mainHtml = mainTags.map(({ tag, count }) => {
|
||||
let pillClass = 'tag-pill';
|
||||
if (tag.startsWith('📁')) pillClass += ' category';
|
||||
else if (tag.startsWith('@')) pillClass += ' domain';
|
||||
if (selectedTags.has(tag)) pillClass += ' active';
|
||||
// Dim tags not in visible notes (unless it's already selected)
|
||||
if (hasFilter && !visibleTags.has(tag) && !selectedTags.has(tag)) pillClass += ' dimmed';
|
||||
return `<span class="${pillClass}" onclick="toggleTag('${tag}')">
|
||||
${tag} <span class="tag-pill-count">(${count})</span>
|
||||
</span>`;
|
||||
}).join('');
|
||||
|
||||
// Add "more tags" toggle button inline
|
||||
if (moreTags.length > 0) {
|
||||
const visibleMoreCount = moreTags.filter(({tag}) => visibleTags.has(tag)).length;
|
||||
const moreLabel = activeMoreCount > 0
|
||||
? `+${moreTags.length} tags (${activeMoreCount} active)`
|
||||
: (hasFilter && visibleMoreCount > 0 ? `+${visibleMoreCount}/${moreTags.length} tags` : `+${moreTags.length} tags`);
|
||||
mainHtml += `<span class="tag-pill more-toggle ${isExpanded ? 'expanded' : ''}" onclick="toggleMoreTags()">
|
||||
${isExpanded ? '−' : '+'} ${moreLabel}
|
||||
</span>`;
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
if (selectedTags.size > 0) {
|
||||
mainHtml += `<button class="clear-filters" onclick="clearTagFilters()">✕ Clear</button>`;
|
||||
}
|
||||
mainContainer.innerHTML = mainHtml;
|
||||
|
||||
// Render more pills (regular tags)
|
||||
const moreHtml = moreTags.map(({ tag, count }) => {
|
||||
let pillClass = 'tag-pill';
|
||||
if (selectedTags.has(tag)) pillClass += ' active';
|
||||
if (hasFilter && !visibleTags.has(tag) && !selectedTags.has(tag)) pillClass += ' dimmed';
|
||||
return `<span class="${pillClass}" onclick="toggleTag('${tag}')">
|
||||
${tag} <span class="tag-pill-count">(${count})</span>
|
||||
</span>`;
|
||||
}).join('');
|
||||
moreContainer.innerHTML = moreHtml;
|
||||
}
|
||||
|
||||
// Toggle tag selection
|
||||
@@ -550,17 +717,29 @@
|
||||
filterNotes();
|
||||
}
|
||||
|
||||
// Toggle more tags section
|
||||
function toggleMoreTags() {
|
||||
const moreContainer = document.getElementById('tagPills');
|
||||
moreContainer.classList.toggle('expanded');
|
||||
renderTagPills(lastFilteredNotes);
|
||||
}
|
||||
|
||||
// Filter notes by search and tags
|
||||
function filterNotes() {
|
||||
const query = document.getElementById('searchInput').value.toLowerCase().trim();
|
||||
|
||||
let filtered = notesIndex;
|
||||
|
||||
// Filter by selected tags (AND logic)
|
||||
// Filter by selected tags (AND logic) - includes categories and domains
|
||||
if (selectedTags.size > 0) {
|
||||
filtered = filtered.filter(note =>
|
||||
[...selectedTags].every(tag => note.tags.includes(tag))
|
||||
);
|
||||
filtered = filtered.filter(note => {
|
||||
const allNoteTags = [
|
||||
...note.tags,
|
||||
...(note.domains || []).map(d => '@' + d),
|
||||
note.category ? '📁' + note.category : null
|
||||
].filter(Boolean);
|
||||
return [...selectedTags].every(tag => allNoteTags.includes(tag));
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by search query
|
||||
@@ -574,6 +753,12 @@
|
||||
}
|
||||
|
||||
renderNotesAccordion(filtered);
|
||||
|
||||
// Save filtered notes for tag pills
|
||||
lastFilteredNotes = filtered;
|
||||
|
||||
// Update tag pills to show which tags are in visible notes
|
||||
renderTagPills(filtered);
|
||||
}
|
||||
|
||||
// Group notes by date category
|
||||
|
||||
Reference in New Issue
Block a user