Модуль wiki: дерево страниц, страница с Markdown (react-markdown, remark-gfm, без сырого HTML), поиск, форма привязки корня, ход синхронизации в боковой панели, скачивание вложений, поле «Корень вики» в окне нового проекта. Сид копии вики и e2e. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
5.3 KiB
Python
68 lines
5.3 KiB
Python
"""Заполнить зеркало тестового хаба фикстурой доски и записать токены рядом с базой (для e2e и npm run dev).
|
||
Пишет в базу напрямую (mirror.apply_state, set_note), до запуска serve: гонки с первым запросом нет.
|
||
Дополнения только для тестового хаба (описание, комментарии, команды) — из seed-extras.json рядом со скриптом."""
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
from jira_hub.core import db, paths, settings
|
||
from jira_hub.modules.jira import mirror
|
||
from jira_hub.modules.wiki import paths as wiki_paths, search as wiki_search, sync as wiki_sync
|
||
|
||
snap = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
||
extras_path = Path(__file__).with_name("seed-extras.json")
|
||
extras = json.loads(extras_path.read_text(encoding="utf-8")) if extras_path.exists() else {}
|
||
extra_issues = extras.get("issues", {})
|
||
conn = db.connect(paths.db_path())
|
||
settings.ensure_defaults(conn)
|
||
|
||
def own_labels(i):
|
||
# свои задачи (не соседи) принадлежат проекту AWPCA: метка нужна для разреза GET /board?project=AWPCA
|
||
labels = list(i.get("labels") or [])
|
||
return labels if i["neighbor"] or "AWPCA" in labels else ["AWPCA", *labels]
|
||
|
||
|
||
issues = [{k: v for k, v in i.items() if k not in ("fact_status", "work_kind", "neighbor")} | {"id": i["key"]}
|
||
| {"labels": own_labels(i)} | extra_issues.get(i["key"], {}) for i in snap["issues"]]
|
||
links = [{"source_key": l["source"], "target_key": l["target"], "link_type": l["link_type"]} for l in snap["links"]]
|
||
mirror.apply_state(conn, issues, links, neighbor_keys=[i["key"] for i in snap["issues"] if i["neighbor"]])
|
||
for i in snap["issues"]:
|
||
note = {k: i[k] for k in ("fact_status", "work_kind") if i.get(k)}
|
||
if note:
|
||
mirror.set_note(conn, i["key"], note, "seed")
|
||
if extras.get("commands"): # завершённые команды по задачам — для раздела «Команды моста» карточки
|
||
with db.transaction(conn):
|
||
batch = conn.execute("INSERT INTO batch(title, author, created_at) VALUES ('Тестовые команды', 'seed', ?)",
|
||
(db.now(),)).lastrowid
|
||
for seq, c in enumerate(extras["commands"], 1):
|
||
conn.execute("INSERT INTO command(batch_id, seq, type, params, status, finished_at, error) "
|
||
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||
(batch, seq, c["type"], json.dumps(c["params"], ensure_ascii=False), c["status"], db.now(),
|
||
c.get("error")))
|
||
# копия вики проекта AWPCA для e2e (тексты синтетические): корень DOC-9001 и две страницы, у одной вложение.
|
||
# Собирается тем же build_copy, что и настоящая синхронизация, — без команд и без агента
|
||
WIKI_PAGES = [
|
||
{"code": "DOC-9001", "title": "Тестовая вики", "parent_code": None, "orderno": 1, "url": "https://eva.test/DOC-9001",
|
||
"markdown": "Корневая страница тестовой вики.\n\n[Модель данных](page:DOC-9002)\n", "attachments": []},
|
||
{"code": "DOC-9002", "title": "Модель данных", "parent_code": "DOC-9001", "orderno": 1, "url": "https://eva.test/DOC-9002",
|
||
"markdown": "# Таблицы\n\n| Поле | Смысл |\n|---|---|\n| id | ключ |\n\nСогласование схемы проводится раз в квартал.\n",
|
||
"attachments": []},
|
||
{"code": "DOC-9003", "title": "Регламент согласования", "parent_code": "DOC-9001", "orderno": 2, "url": "https://eva.test/DOC-9003",
|
||
"markdown": "Порядок согласования описан в файле.\n\n[📎 схема.txt](attachment:@0)\n\n[К модели](page:DOC-9002)\n",
|
||
"attachments": [{"url": "https://eva.test/files/schema.txt", "name": "схема.txt"}]},
|
||
]
|
||
conn.execute("INSERT OR REPLACE INTO wiki_project(label, root_code, root_title, synced_at, pages_count) VALUES ('AWPCA', 'DOC-9001', 'Тестовая вики', ?, ?)",
|
||
(db.now(), len(WIKI_PAGES)))
|
||
att_id = conn.execute("INSERT INTO wiki_attachment(label, page_code, url, name) VALUES ('AWPCA', 'DOC-9003', ?, 'схема.txt')",
|
||
("https://eva.test/files/schema.txt",)).lastrowid
|
||
wiki_rows = wiki_sync.build_copy(WIKI_PAGES, [p["code"] for p in WIKI_PAGES], wiki_paths.project_dir(conn, "AWPCA"),
|
||
{("DOC-9003", "https://eva.test/files/schema.txt"): att_id})
|
||
for r in wiki_rows:
|
||
conn.execute("INSERT INTO wiki_page(label, code, eva_id, title, parent_code, orderno, depth, path, url, size, synced_at) "
|
||
"VALUES ('AWPCA', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||
(r["code"], r["eva_id"], r["title"], r["parent_code"], r["orderno"], r["depth"], r["path"], r["url"], r["size"], r["synced_at"]))
|
||
wiki_search.replace(conn, "AWPCA", [(r["code"], r["title"], r["markdown"]) for r in wiki_rows])
|
||
(paths.home() / "tokens.json").write_text(json.dumps(settings.tokens(conn)), encoding="utf-8")
|
||
conn.close()
|
||
print("зеркало:", len(issues), "задач,", len(links), "связей; токены —", paths.home() / "tokens.json")
|