From: Danilo M. Date: Sun, 3 May 2026 08:40:54 +0000 (+0200) Subject: feat: new article stub creation with Typora open X-Git-Tag: v1.0~13 X-Git-Url: https://git.danix.xyz/?a=commitdiff_plain;h=5ac2f470c18a9eda17c1f2f8489c07e2eed2cd04;p=publisher.git feat: new article stub creation with Typora open --- diff --git a/ui/main_window.py b/ui/main_window.py index 01e4cf2..001b03a 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -80,7 +80,7 @@ class MainWindow(QMainWindow): self._page_detail = self._stack.count() - 1 # Remaining placeholders - for name in ["new_article", "taxonomy", "media", "translations", "git", "hugo"]: + for name in ["taxonomy", "media", "translations", "git", "hugo"]: w = QLabel(f"[{name}]") w.setAlignment(Qt.AlignmentFlag.AlignCenter) self._stack.addWidget(w) @@ -134,7 +134,10 @@ class MainWindow(QMainWindow): no_trans_row.addWidget(self._badge_no_trans) layout.addLayout(no_trans_row) - btn("➕ Nuovo articolo", "_page_new_article") + b_new = SidebarButton("➕ Nuovo articolo") + b_new.clicked.connect(self._do_new_article) + layout.addWidget(b_new) + self._btn_group.append(b_new) btn("🏷 Tassonomia", "_page_taxonomy") btn("🖼 Media", "_page_media") @@ -178,6 +181,13 @@ class MainWindow(QMainWindow): if dlg.exec(): self._detail_view.set_article(article) + def _do_new_article(self): + from ui.new_article_dialog import NewArticleDialog + dlg = NewArticleDialog(Path(self.config.blog_repo), self) + if dlg.exec() and dlg.created_path: + self._refresh_articles() + subprocess.Popen([self.config.typora_bin, str(dlg.created_path)]) + def _do_translate(self, article: Article): pass # implemented in Task 15 diff --git a/ui/new_article_dialog.py b/ui/new_article_dialog.py new file mode 100644 index 0000000..0e0b4f5 --- /dev/null +++ b/ui/new_article_dialog.py @@ -0,0 +1,93 @@ +from __future__ import annotations +from datetime import date +from pathlib import Path +from PyQt6.QtWidgets import ( + QDialog, QVBoxLayout, QFormLayout, QHBoxLayout, + QLineEdit, QComboBox, QLabel, QPushButton, QMessageBox, +) +from core.models import ARTICLE_TYPES + +STUB_TEMPLATE = """\ ++++ +title = "{title}" +date = {date} +type = "{type}" +draft = true +excerpt = "" +tags = [] +categories = [] ++++ + +TODO: scrivi il contenuto qui. +""" + +class NewArticleDialog(QDialog): + def __init__(self, blog_root: Path, parent=None): + super().__init__(parent) + self.setWindowTitle("Nuovo articolo") + self.setMinimumWidth(400) + self._blog_root = blog_root + self._created_path: Path | None = None + self._build_ui() + + @property + def created_path(self) -> Path | None: + return self._created_path + + def _build_ui(self): + layout = QVBoxLayout(self) + form = QFormLayout() + + self._slug = QLineEdit() + self._slug.setPlaceholderText("mio-articolo-2026") + form.addRow("Slug:", self._slug) + + self._title = QLineEdit() + self._title.setPlaceholderText("Il mio articolo") + form.addRow("Titolo:", self._title) + + self._lang = QComboBox() + self._lang.addItems(["it", "en"]) + form.addRow("Lingua:", self._lang) + + self._type = QComboBox() + self._type.addItems(ARTICLE_TYPES) + form.addRow("Tipo:", self._type) + + layout.addLayout(form) + + btns = QHBoxLayout() + create_btn = QPushButton("Crea") + create_btn.clicked.connect(self._create) + cancel_btn = QPushButton("Annulla") + cancel_btn.clicked.connect(self.reject) + btns.addStretch() + btns.addWidget(cancel_btn) + btns.addWidget(create_btn) + layout.addLayout(btns) + + def _create(self): + slug = self._slug.text().strip() + title = self._title.text().strip() + lang = self._lang.currentText() + article_type = self._type.currentText() + + if not slug or not title: + QMessageBox.warning(self, "Errore", "Slug e titolo sono obbligatori.") + return + + target = self._blog_root / "content" / lang / "articles" / slug + if target.exists(): + QMessageBox.warning(self, "Errore", f"Esiste già: {target}") + return + + target.mkdir(parents=True) + index_md = target / "index.md" + index_md.write_text(STUB_TEMPLATE.format( + title=title, + date=date.today().isoformat(), + type=article_type, + ), encoding="utf-8") + + self._created_path = index_md + self.accept()