summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/plans/2026-05-03-article-list-metadata.md200
1 files changed, 200 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-05-03-article-list-metadata.md b/docs/superpowers/plans/2026-05-03-article-list-metadata.md
new file mode 100644
index 0000000..a9b97aa
--- /dev/null
+++ b/docs/superpowers/plans/2026-05-03-article-list-metadata.md
@@ -0,0 +1,200 @@
+# Article List Metadata Display Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Show type, tags, categories, and date for each article row in the articles list (both IT and EN tabs).
+
+**Architecture:** Extend `ArticleItem` to render a two-line item: line 1 = slug + translation badge (existing), line 2 = metadata fields extracted from `article.frontmatter`. Use `\n` in item text and `setSizeHint` for row height. No new files needed.
+
+**Tech Stack:** PyQt6 QListWidgetItem, existing Article.frontmatter dict.
+
+---
+
+### Task 1: Add metadata helpers to Article model
+
+**Files:**
+- Modify: `core/models.py`
+- Test: `tests/test_models.py`
+
+- [ ] **Step 1: Write failing tests**
+
+Add to `tests/test_models.py`:
+
+```python
+def test_article_draft_property():
+ fm = {"draft": True, "type": "Tech", "tags": ["linux"], "categories": ["DIY"], "date": "2024-01-15T10:00:00+00:00"}
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter=fm, has_translation=False, translation_path=None)
+ assert a.draft is True
+
+def test_article_meta_type():
+ fm = {"type": "Tech"}
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter=fm, has_translation=False, translation_path=None)
+ assert a.meta_type == "Tech"
+
+def test_article_meta_type_missing():
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter={}, has_translation=False, translation_path=None)
+ assert a.meta_type == ""
+
+def test_article_meta_tags():
+ fm = {"tags": ["linux", "python"]}
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter=fm, has_translation=False, translation_path=None)
+ assert a.meta_tags == "linux, python"
+
+def test_article_meta_tags_empty():
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter={}, has_translation=False, translation_path=None)
+ assert a.meta_tags == ""
+
+def test_article_meta_categories():
+ fm = {"categories": ["DIY", "Tech"]}
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter=fm, has_translation=False, translation_path=None)
+ assert a.meta_categories == "DIY, Tech"
+
+def test_article_meta_date():
+ fm = {"date": "2024-01-15T10:00:00+00:00"}
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter=fm, has_translation=False, translation_path=None)
+ assert a.meta_date == "2024-01-15"
+
+def test_article_meta_date_missing():
+ a = Article(slug="test", lang="it", path=Path("/tmp/test"), frontmatter={}, has_translation=False, translation_path=None)
+ assert a.meta_date == ""
+```
+
+- [ ] **Step 2: Run tests to confirm they fail**
+
+```bash
+pytest tests/test_models.py -v
+```
+
+Expected: FAIL — `Article` has no `meta_type`, `meta_tags`, `meta_categories`, `meta_date` attributes.
+
+- [ ] **Step 3: Implement properties in Article**
+
+In `core/models.py`, add four properties after the existing `draft` property:
+
+```python
+@property
+def meta_type(self) -> str:
+ return str(self.frontmatter.get("type", ""))
+
+@property
+def meta_tags(self) -> str:
+ tags = self.frontmatter.get("tags", [])
+ if isinstance(tags, list):
+ return ", ".join(str(t) for t in tags)
+ return str(tags) if tags else ""
+
+@property
+def meta_categories(self) -> str:
+ cats = self.frontmatter.get("categories", [])
+ if isinstance(cats, list):
+ return ", ".join(str(c) for c in cats)
+ return str(cats) if cats else ""
+
+@property
+def meta_date(self) -> str:
+ raw = self.frontmatter.get("date", "")
+ if not raw:
+ return ""
+ return str(raw)[:10] # ISO date → "YYYY-MM-DD"
+```
+
+- [ ] **Step 4: Run tests to confirm they pass**
+
+```bash
+pytest tests/test_models.py -v
+```
+
+Expected: all pass.
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add core/models.py tests/test_models.py
+git commit -m "feat: add meta_type, meta_tags, meta_categories, meta_date properties to Article"
+```
+
+---
+
+### Task 2: Render metadata in ArticleItem
+
+**Files:**
+- Modify: `ui/articles_view.py`
+
+No automated tests for UI — verify manually.
+
+- [ ] **Step 1: Update ArticleItem to render two-line text**
+
+In `ui/articles_view.py`, replace the `ArticleItem.__init__` method. The first line keeps slug + translation badge (and `[DRAFT]` prefix). The second line shows metadata fields, omitting empty ones.
+
+Replace the existing `ArticleItem` class (lines 10-26) with:
+
+```python
+class ArticleItem(QListWidgetItem):
+ def __init__(self, article: Article):
+ super().__init__()
+ self.article = article
+ if article.has_translation:
+ badge = f"🇬🇧 ✓" if article.lang == "it" else "🇮🇹 ✓"
+ else:
+ badge = f"🇬🇧 ✗" if article.lang == "it" else "🇮🇹 ✗"
+ line1 = f"{article.slug} [{badge}]"
+ if article.draft:
+ line1 = f"[DRAFT] {line1}"
+
+ parts = []
+ if article.meta_type:
+ parts.append(article.meta_type)
+ if article.meta_date:
+ parts.append(article.meta_date)
+ if article.meta_tags:
+ parts.append(f"#{article.meta_tags.replace(', ', ' #')}")
+ if article.meta_categories:
+ parts.append(f"[{article.meta_categories}]")
+ line2 = " ".join(parts) if parts else ""
+
+ text = f"{line1}\n{line2}" if line2 else line1
+ self.setText(text)
+ self.setSizeHint(QSize(0, 42) if line2 else QSize(0, 26))
+
+ if article.draft:
+ self.setForeground(QColor("#f59e0b"))
+ elif not article.has_translation:
+ self.setForeground(QColor("#ff6b6b"))
+```
+
+Also add `QSize` to the imports at the top of the file:
+
+```python
+from PyQt6.QtCore import Qt, pyqtSignal, QSize
+```
+
+- [ ] **Step 2: Run the app and verify visually**
+
+```bash
+python main.py
+```
+
+Check:
+- Each article row shows two lines: slug + badge on line 1, metadata on line 2
+- Articles with no metadata (missing type/date/tags/categories) show single line
+- Draft articles: amber color on both lines
+- Missing-translation articles: red color
+- Tags rendered as `#tag1 #tag2`
+- Categories rendered as `[Cat1, Cat2]`
+- Date rendered as `YYYY-MM-DD`
+- Row height accommodates two lines without clipping
+
+- [ ] **Step 3: Run full test suite**
+
+```bash
+pytest tests/ -v
+```
+
+Expected: all 22+ tests pass (UI change has no tests, but existing tests must not break).
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add ui/articles_view.py
+git commit -m "feat: show type, date, tags, categories in article list rows"
+```