Реструктуризация: два глобальных раздела — Яша и Семен
Весь контент перенесён в content/yasha/ (7 подразделов). Создан content/semen/ с подразделами: changelog, kb, diary. Навигация — dropdown в навбаре, двухуровневое меню в hugo.toml. Шаблоны, сайдбар, поиск обновлены под вложенные секции.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Семен"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,7 @@
|
||||
+++
|
||||
title = "История изменений"
|
||||
date = 2026-04-26
|
||||
draft = false
|
||||
tags = []
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Дневник"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "База знаний"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Яша"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Креды"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Дневник"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Инструкции"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "База знаний"
|
||||
draft = false
|
||||
+++
|
||||
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Планы"
|
||||
draft = false
|
||||
+++
|
||||
@@ -19,33 +19,74 @@ canonifyURLs = false
|
||||
|
||||
[menu]
|
||||
[[menu.main]]
|
||||
name = "Дневник"
|
||||
url = "/diary/"
|
||||
name = "Яша"
|
||||
identifier = "yasha"
|
||||
weight = 1
|
||||
[[menu.main]]
|
||||
name = "Дневник"
|
||||
identifier = "yasha-diary"
|
||||
url = "/yasha/diary/"
|
||||
parent = "yasha"
|
||||
weight = 10
|
||||
[[menu.main]]
|
||||
name = "База знаний"
|
||||
url = "/kb/"
|
||||
weight = 2
|
||||
identifier = "yasha-kb"
|
||||
url = "/yasha/kb/"
|
||||
parent = "yasha"
|
||||
weight = 20
|
||||
[[menu.main]]
|
||||
name = "Планы"
|
||||
url = "/plans/"
|
||||
weight = 3
|
||||
[[menu.main]]
|
||||
name = "Leadera"
|
||||
url = "/leadera/"
|
||||
weight = 4
|
||||
identifier = "yasha-plans"
|
||||
url = "/yasha/plans/"
|
||||
parent = "yasha"
|
||||
weight = 30
|
||||
[[menu.main]]
|
||||
name = "Инструкции"
|
||||
url = "/guides/"
|
||||
weight = 5
|
||||
identifier = "yasha-guides"
|
||||
url = "/yasha/guides/"
|
||||
parent = "yasha"
|
||||
weight = 40
|
||||
[[menu.main]]
|
||||
name = "Креды"
|
||||
url = "/creds/"
|
||||
weight = 6
|
||||
identifier = "yasha-creds"
|
||||
url = "/yasha/creds/"
|
||||
parent = "yasha"
|
||||
weight = 50
|
||||
[[menu.main]]
|
||||
name = "Leadera"
|
||||
identifier = "yasha-leadera"
|
||||
url = "/yasha/leadera/"
|
||||
parent = "yasha"
|
||||
weight = 60
|
||||
[[menu.main]]
|
||||
name = "Личный сайт"
|
||||
url = "/personal-site/"
|
||||
weight = 7
|
||||
identifier = "yasha-personal-site"
|
||||
url = "/yasha/personal-site/"
|
||||
parent = "yasha"
|
||||
weight = 70
|
||||
|
||||
[[menu.main]]
|
||||
name = "Семен"
|
||||
identifier = "semen"
|
||||
weight = 2
|
||||
[[menu.main]]
|
||||
name = "История изменений"
|
||||
identifier = "semen-changelog"
|
||||
url = "/semen/changelog/"
|
||||
parent = "semen"
|
||||
weight = 10
|
||||
[[menu.main]]
|
||||
name = "База знаний"
|
||||
identifier = "semen-kb"
|
||||
url = "/semen/kb/"
|
||||
parent = "semen"
|
||||
weight = 20
|
||||
[[menu.main]]
|
||||
name = "Дневник"
|
||||
identifier = "semen-diary"
|
||||
url = "/semen/diary/"
|
||||
parent = "semen"
|
||||
weight = 30
|
||||
|
||||
[outputs]
|
||||
home = ["HTML", "JSON"]
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
[{"content":"Basic Authentication Username: agaltsovav Password: Magamet787! Конфигурация Nginx server { listen 8091; server_name docs.a2v.space; auth_basic \u0026#34;Restricted Access\u0026#34;; auth_basic_user_file /etc/nginx/.htpasswd; } Доступ URL: https://docs.a2v.space (через reverse proxy) Local: http://localhost:8091 (для разработки) Auth: всегда требуется Мастер-пароль для шифрования Важно: Пароль для расшифровки файлов в разделе creds/\nMaster Password: Popoloka16! Шифрование Алгоритм: AES-256-GCM Хранилище: client-side encryption Файлы шифруются при сохранении Расшифровываются при чтении ","section":"creds","tags":["docs","authentication","nginx"],"title":"docs.a2v.space Basic Auth","url":"/creds/docs-a2v-space-auth/"},{"content":"Docker Compose креды (~/Projects/eversolo-companion/docker-compose.yml) services: postgres: environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: eversolo Локальные креды (.env файл) POSTGRES_USER=postgres POSTGRES_PASSWORD=password POSTGRES_DB=eversolo Хостинг Host: localhost Port: 5433 Database: eversolo Безопасность Используйте разные пароли для production Включите SSL для удаленного подключения Регулярно делайте бэкапы ","section":"creds","tags":["eversolo","companion","postgresql","docker"],"title":"Eversolo Companion PostgreSQL","url":"/creds/eversolo-companion-postgres/"},{"content":"\nNYVK4PEGwmOHmAnGk8IAUc+lyFJtnEAvX6ZddBro/ILRWHOXBGYywgglFvQZ18BLDLb5DuA8GPAIdB/LwTHRXYO0KsmtlZQVWGEeeXlXAoEXpa5theoOQhebkW6LmiKyNGAVW2z9rK3nz6NnztYdn49LvGMjrHuR4IwCLbl/pYa96CPNRnxGDFlduFi8lMSspM0rBFi/bZhNGhzy36ViCl+aKr5P9cle0ZvM8E8av/6c5JjgDt88QFI3VYdTaTCE0+uHsXlnJN7Qgg/KH7kD\n\n\n","section":"creds","tags":["postgresql","docker-compose","leadera","database"],"title":"Mac Studio — leadera-api БД (docker-compose)","url":"/creds/leadera-db-docker/"},{"content":"\np7Iw7Y3zbj1kLBcbOXGoO27oDwF85AhxBW7saT538hxi0ogJpyFeM49GDuLHzxuyknvdNC/rx3tb4AFnGkCeHSrrCmj+VK8Zxt7ujeujVJSRuOeeUlsqkHdlmaiXl2KQknrIsqVCi3Tnn0V5qcFxvo+1Ktc+surF6bBpWrTHzWV5mLtWVfD6C6kvvP/UFldFBD6v+FQs79yfoOe/j/bUrtpt6v5VndbbBmhUAQcy1BV2rpXxO373dTcLQ6coRWkt/RFo\n\n\n","section":"creds","tags":["postgresql","docker","leadera","database"],"title":"Mac Studio — leadera-api БД (локальная)","url":"/creds/leadera-db-local/"},{"content":"\nYEI16NAJ78d3lmSa/lca8Zxczt+u6GyMUYHduX47VoFQdj0Ixozd8R6yXoB7eM+AjhCtNGkOxGlOj2s73ABOBjLEIVIhD4Z+xTyzdtah4VpyLoltYOeNYsnbIIFARdF/FBYq5COXohhXs33K5ozznrtDd/awbKMjl/sbQqjXAZ+A3ZSob6/5uU+fFKetXLR6v4ZLAYQ57iiD21ImSLSggwv+rJgK5XyPDKEPD4N5nOsiDrLgoukVBMvgJ54PqfPp2Hni+2tdKOlMnOG2npTuu4SkyALcfFar\n\n\n","section":"creds","tags":["vpn","amnezia","infrastructure"],"title":"VPN VPS","url":"/creds/vpn-vps/"},{"content":"\nIpYXLMtgCFlGQ550DZCLjq37VsnNqL08Rn03iRS7kQ7ozBZNsiZySFzDAvYh4xIHytRDy0Sz0KGUXekr0S+cNiJsmtZ8kj0Pd0JhevhxTMZF2khFvs/LFWoTL5ZwAJ34y/qfLw2gaWX90VZDu0wO+KeAQeXhrWmol/2zUlfWX1AihyYqD2vRz+h2FcjD8ubYOXG35PyX7OlV1HPXgDv5X/bFNrxzPc867UOwB4aGxY9a\n\n\n","section":"creds","tags":["vps","reg.ru","infrastructure"],"title":"VPS reg.ru","url":"/creds/vps-reg-ru/"}]
|
||||
@@ -1,317 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Diaries — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../diary/">Дневник</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../kb/">База знаний</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../diary/">Все записи</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6 class="mt-3">Теги</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/system-utils/">system-utils</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/opencode/">opencode</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/leadera/">leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/gantt/">gantt</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/canvas/">canvas</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/github/">github</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/roadmap/">roadmap</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/vikunja/">vikunja</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/tasktracker/">tasktracker</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/ollama/">ollama</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/qwen/">qwen</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/mtproxy/">mtproxy</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/infrastructure/">infrastructure</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/angular/">angular</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/go/">go</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/docker/">docker</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/eversolo/">eversolo</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/hugo/">hugo</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/docs/">docs</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/identity/">identity</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../tags/companion/">companion</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Дневник</h1>
|
||||
|
||||
<div class="diary-timeline">
|
||||
|
||||
|
||||
<div class="diary-entry">
|
||||
<div class="diary-date">31.03.2026</div>
|
||||
<h3><a href="../diary/2026-03-31/">31 марта 2026</a></h3>
|
||||
|
||||
<div class="tags">
|
||||
|
||||
<a href="../tags/system-utils/" class="tag">system-utils</a>
|
||||
|
||||
<a href="../tags/opencode/" class="tag">opencode</a>
|
||||
|
||||
<a href="../tags/leadera/" class="tag">leadera</a>
|
||||
|
||||
<a href="../tags/gantt/" class="tag">gantt</a>
|
||||
|
||||
<a href="../tags/canvas/" class="tag">canvas</a>
|
||||
|
||||
<a href="../tags/github/" class="tag">github</a>
|
||||
|
||||
<a href="../tags/roadmap/" class="tag">roadmap</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="diary-entry">
|
||||
<div class="diary-date">30.03.2026</div>
|
||||
<h3><a href="../diary/2026-03-30/">30 марта 2026</a></h3>
|
||||
|
||||
<div class="tags">
|
||||
|
||||
<a href="../tags/vikunja/" class="tag">vikunja</a>
|
||||
|
||||
<a href="../tags/leadera/" class="tag">leadera</a>
|
||||
|
||||
<a href="../tags/tasktracker/" class="tag">tasktracker</a>
|
||||
|
||||
<a href="../tags/ollama/" class="tag">ollama</a>
|
||||
|
||||
<a href="../tags/qwen/" class="tag">qwen</a>
|
||||
|
||||
<a href="../tags/mtproxy/" class="tag">mtproxy</a>
|
||||
|
||||
<a href="../tags/infrastructure/" class="tag">infrastructure</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="diary-entry">
|
||||
<div class="diary-date">29.03.2026</div>
|
||||
<h3><a href="../diary/2026-03-29/">29 марта 2026</a></h3>
|
||||
|
||||
<div class="tags">
|
||||
|
||||
<a href="../tags/angular/" class="tag">angular</a>
|
||||
|
||||
<a href="../tags/go/" class="tag">go</a>
|
||||
|
||||
<a href="../tags/docker/" class="tag">docker</a>
|
||||
|
||||
<a href="../tags/eversolo/" class="tag">eversolo</a>
|
||||
|
||||
<a href="../tags/hugo/" class="tag">hugo</a>
|
||||
|
||||
<a href="../tags/docs/" class="tag">docs</a>
|
||||
|
||||
<a href="../tags/identity/" class="tag">identity</a>
|
||||
|
||||
<a href="../tags/infrastructure/" class="tag">infrastructure</a>
|
||||
|
||||
<a href="../tags/companion/" class="tag">companion</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../js/search.js"></script>
|
||||
<script src="../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,890 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Аудит Leadera — полный отчёт — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Все инструкции</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6 class="mt-3">Теги</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/audit/">audit</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/leadera/">leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/security/">security</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/architecture/">architecture</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/websocket/">websocket</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/realtime/">realtime</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/gantt/">gantt</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/api/">api</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/frontend/">frontend</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/requirements/">requirements</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/angular/">angular</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/go/">go</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ux/">ux</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ssh/">ssh</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/tunnel/">tunnel</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/vps/">vps</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/reverse-proxy/">reverse-proxy</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/nginx/">nginx</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/devops/">devops</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/openclaw/">openclaw</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/opencode/">opencode</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/docker/">docker</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Аудит Leadera — полный отчёт</h1>
|
||||
<div class="source-path mb-3">
|
||||
<small class="text-muted">
|
||||
📁 <code id="source-path" class="user-select-all">~/Projects/docs-a2v/content/guides/leadera-audit.md</code>
|
||||
<button class="btn btn-sm btn-outline-secondary ms-1 py-0 px-1" onclick="navigator.clipboard.writeText('~/Projects/docs-a2v/content/guides\/leadera-audit.md')" title="Копировать путь">
|
||||
📋
|
||||
</button>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="tags mb-3">
|
||||
|
||||
<a href="../../tags/audit/" class="tag">audit</a>
|
||||
|
||||
<a href="../../tags/leadera/" class="tag">leadera</a>
|
||||
|
||||
<a href="../../tags/security/" class="tag">security</a>
|
||||
|
||||
<a href="../../tags/architecture/" class="tag">architecture</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<h1 id="аудит-проекта-leadera">Аудит проекта Leadera</h1>
|
||||
<p><strong>Дата:</strong> 30.03.2026<br>
|
||||
<strong>Версия:</strong> pre-production, миграции 1–5</p>
|
||||
<hr>
|
||||
<h2 id="1-обзор-проекта">1. Обзор проекта</h2>
|
||||
<p>Leadera — SaaS-система управления IT-ландшафтом с диаграммами Ганта.</p>
|
||||
<h3 id="стек">Стек</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Компонент</th>
|
||||
<th>Технологии</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Backend</td>
|
||||
<td>Go 1.21+, Gin, PostgreSQL 16, pgx/v5 + sqlx, JWT (HMAC-SHA256)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Frontend</td>
|
||||
<td>Angular 21.1, Bootstrap 5, NgBootstrap, RxJS, Signals</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Инфраструктура</td>
|
||||
<td>Docker (Colima), pm2, nginx reverse proxy, VPS reg.ru</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="доменная-модель">Доменная модель</h3>
|
||||
<pre tabindex="0"><code>User ──┬── Space (через space_members с role)
|
||||
│
|
||||
└── GanttChart (принадлежит Space)
|
||||
├── GanttSection
|
||||
└── GanttTask
|
||||
</code></pre><p><strong>Роли:</strong> admin, editor, viewer — назначаются <strong>на уровне Space</strong> через таблицу <code>space_members</code>.</p>
|
||||
<h3 id="что-реализовано-endpoints">Что реализовано (endpoints)</h3>
|
||||
<p><strong>Auth (5):</strong> register, login, refresh, change-password, logout<br>
|
||||
<strong>Spaces (9):</strong> CRUD + members CRUD<br>
|
||||
<strong>Gantt Charts (9):</strong> CRUD + archive + members (добавлен, но удалён в миграции 5)<br>
|
||||
<strong>Gantt Sections (5):</strong> CRUD + reorder<br>
|
||||
<strong>Gantt Tasks (4):</strong> CRUD</p>
|
||||
<p><strong>Итого: ~32 endpoint</strong></p>
|
||||
<hr>
|
||||
<h2 id="2-архитектура-и-качество-кода">2. Архитектура и качество кода</h2>
|
||||
<h3 id="21-backend--структура">2.1. Backend — структура</h3>
|
||||
<pre tabindex="0"><code>cmd/server/main.go — точка входа
|
||||
internal/
|
||||
domain/ — модели (User, Space, GanttChart, etc.)
|
||||
dto/ — request/response DTO (auth, space, gantt)
|
||||
handlers/ — HTTP handlers (auth, space, gantt)
|
||||
middleware/ — auth, cors, space, gantt, role, logging, recovery
|
||||
repository/ — слой доступа к данным
|
||||
service/ — бизнес-логика
|
||||
config/ — конфигурация (.env)
|
||||
utils/ — jwt, password, response, validation
|
||||
migrations/ — SQL миграции (1-5)
|
||||
</code></pre><p><strong>Оценка:</strong> ✅ Чистая layered архитектура. Разделение ответственности чёткое.</p>
|
||||
<h3 id="22-frontend--структура">2.2. Frontend — структура</h3>
|
||||
<pre tabindex="0"><code>src/app/
|
||||
core/auth/ — auth service, interceptor
|
||||
core/models/ — app.model, space.model
|
||||
core/services/ — space.service, space-storage.service
|
||||
pages/auth/ — sign-in, sign-up, reset-pw, etc.
|
||||
pages/gantt/ — компоненты, модалки, сервисы, модели
|
||||
pages/dashboards/ — spaces list, dashboard
|
||||
layouts/ — navbar, topbar, main-layout
|
||||
</code></pre><p><strong>Оценка:</strong> ✅ Стандартная Angular-структура. Signals для state management.</p>
|
||||
<h3 id="23-проблемы-кода">2.3. Проблемы кода</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Проблема</th>
|
||||
<th>Критичность</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>C1</td>
|
||||
<td><code>\r</code> в service-файлах</td>
|
||||
<td>Medium</td>
|
||||
<td>gantt_service.go, gantt_section_service.go содержат CRLF</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C2</td>
|
||||
<td><code>main.go:238</code> — мёртвый код <code>getUserHandler</code></td>
|
||||
<td>Low</td>
|
||||
<td>Неиспользуемая функция</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C3</td>
|
||||
<td>Swagger не сгенерирован</td>
|
||||
<td>Medium</td>
|
||||
<td>Аннотации есть, но <code>api/</code> директории нет</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C4</td>
|
||||
<td><code>RegisterProtectedRoutes</code> не вызывается в main.go</td>
|
||||
<td><strong>Critical</strong></td>
|
||||
<td>GET/PUT/DELETE <code>/spaces/:id</code> не зарегистрированы</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 id="3-права-доступа--главный-вопрос">3. Права доступа — главный вопрос</h2>
|
||||
<h3 id="31-текущая-реализация">3.1. Текущая реализация</h3>
|
||||
<p>Права назначаются <strong>исключительно через Space</strong>:</p>
|
||||
<ol>
|
||||
<li>Таблица <code>space_members</code> — связка user ↔ space с role (admin/editor/viewer)</li>
|
||||
<li><code>SpaceMiddleware.RequireSpace()</code> — проверяет членство и записывает <code>ContextSpaceRole</code> в context</li>
|
||||
<li><code>RoleMiddleware.RequireMinRole()</code> — проверяет иерархию ролей (admin > editor > viewer)</li>
|
||||
</ol>
|
||||
<p><strong>Диаграммы Ганта НЕ имеют собственной системы ролей.</strong> Таблица <code>gantt_chart_members</code> была создана (миграция 4) и тут же удалена (миграция 5). Все проверки доступа к диаграммам идут через space membership.</p>
|
||||
<h3 id="32-как-это-работает">3.2. Как это работает</h3>
|
||||
<pre tabindex="0"><code>Запрос → AuthMiddleware (JWT → userID)
|
||||
→ SpaceMiddleware.RequireSpace() (проверяет space_members → ContextSpaceRole)
|
||||
→ GanttMiddleware.RequireGanttChart() (проверяет chart.space_id == spaceID)
|
||||
→ RoleMiddleware.RequireMinRole("editor") (проверяет ContextSpaceRole)
|
||||
</code></pre><p><strong>Это правильно.</strong> Любой член Space с ролью editor+ может создавать/редактировать диаграммы. Viewers — только читать.</p>
|
||||
<h3 id="33--критическая-проблема-frontend-не-соответствует-backend">3.3. 🔴 Критическая проблема: Frontend не соответствует Backend</h3>
|
||||
<p><strong>Frontend <code>MembersModalComponent</code></strong> пытается управлять участниками <strong>диаграммы</strong>:</p>
|
||||
<ul>
|
||||
<li><code>ganttService.addMember(chartId, dto)</code> → <code>/api/v1/spaces/{spaceId}/gantt-charts/{chartId}/members</code></li>
|
||||
<li><code>ganttService.updateMemberRole(chartId, userId, dto)</code> → <code>.../members/{userId}</code></li>
|
||||
<li><code>ganttService.removeMember(chartId, userId)</code> → <code>.../members/{userId}</code></li>
|
||||
</ul>
|
||||
<p><strong>Backend <code>GanttHandler.RegisterRoutes()</code> НЕ регистрирует маршруты для members диаграмм.</strong> После удаления <code>gantt_chart_members</code> (миграция 5) эти endpoints не существуют.</p>
|
||||
<p><strong>Результат:</strong> модальное окно «Участники диаграммы» на фронтенде <strong>не работает</strong> — все вызовы вернут 404.</p>
|
||||
<h3 id="34--проблема-role-fallback">3.4. 🔴 Проблема: Role fallback</h3>
|
||||
<p>В <code>role_middleware.go:28-31</code>:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">role</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">GetString</span>(<span style="color:#a6e22e">ContextSpaceRole</span>)
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">role</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">""</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">role</span> = <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">GetString</span>(<span style="color:#a6e22e">ContextRole</span>) <span style="color:#75715e">// fallback на глобальную роль User</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><p>Если <code>ContextSpaceRole</code> не установлен, используется <strong>глобальная роль пользователя</strong> (из JWT). Это значит:</p>
|
||||
<ul>
|
||||
<li>Пользователь с <code>role=admin</code> в таблице <code>users</code> получит admin-доступ к <strong>любому</strong> space, даже если он не член этого space</li>
|
||||
<li>Но <code>SpaceMiddleware</code> проверяет членство раньше, так что в цепочке <code>RequireSpace() → RequireMinRole()</code> это не эксплуатируется</li>
|
||||
<li>Однако если <code>RequireMinRole()</code> используется <strong>без</strong> <code>RequireSpace()</code> — это дыра</li>
|
||||
</ul>
|
||||
<p><strong>Рекомендация:</strong> Удалить fallback на <code>ContextRole</code>. Если <code>ContextSpaceRole</code> пуст — отказывать.</p>
|
||||
<h3 id="35-рекомендации-по-правам-доступа">3.5. Рекомендации по правам доступа</h3>
|
||||
<ol>
|
||||
<li><strong>Удалить модалку участников диаграммы</strong> на фронтенде — она мертва</li>
|
||||
<li><strong>Или</strong> добавить раздел «Участники Space» с возможностью управления ролями через <code>/spaces/:space_id/members</code> (эти endpoints работают)</li>
|
||||
<li>Удалить fallback на <code>ContextRole</code> в <code>role_middleware.go</code></li>
|
||||
<li>Добавить проверку: editor не может повысить кого-то до admin (сейчас может — <code>AddMember</code> разрешает editor+ назначать любую роль)</li>
|
||||
</ol>
|
||||
<hr>
|
||||
<h2 id="4-безопасность">4. Безопасность</h2>
|
||||
<h3 id="41-критические">4.1. Критические</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Проблема</th>
|
||||
<th>Файл</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>S1</td>
|
||||
<td>JWT Secret = test</td>
|
||||
<td><code>.env</code></td>
|
||||
<td><code>JWT_SECRET=test_secret_key_change_in_production</code> — <strong>это прод-конфиг!</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S2</td>
|
||||
<td>CORS: <code>*</code></td>
|
||||
<td><code>.env</code></td>
|
||||
<td><code>CORS_ALLOWED_ORIGINS=*</code> — любой домен может обращаться к API</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S3</td>
|
||||
<td>Пароль БД в .env</td>
|
||||
<td><code>.env</code></td>
|
||||
<td><code>DB_PASSWORD=popoloka16</code> — creds в открытом виде</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S4</td>
|
||||
<td>Refresh tokens: SHA256</td>
|
||||
<td><code>utils/password.go</code></td>
|
||||
<td>SHA256 вместо bcrypt для refresh token hash — быстро брутфорсится</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="42-высокие">4.2. Высокие</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Проблема</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>S5</td>
|
||||
<td>Нет rate limiting</td>
|
||||
<td>Brute-force на <code>/auth/login</code> без ограничений</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S6</td>
|
||||
<td>Нет CSRF protection</td>
|
||||
<td>API принимает POST/PUT/DELETE без CSRF-токена</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S7</td>
|
||||
<td>Нет CSP заголовков</td>
|
||||
<td>X-Frame-Options, Content-Security-Policy не настроены</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S8</td>
|
||||
<td>JWT в localStorage</td>
|
||||
<td>XSS может украсть access + refresh tokens</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="43-средние">4.3. Средние</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Проблема</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>S9</td>
|
||||
<td>Нет password policy</td>
|
||||
<td>Минимальные требования к паролю не enforced</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S10</td>
|
||||
<td>Нет audit log</td>
|
||||
<td>Действия с spaces/charts не логируются для аудита</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>S11</td>
|
||||
<td>Нет блокировки аккаунта</td>
|
||||
<td>Неограниченные попытки входа</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 id="5-инфраструктура">5. Инфраструктура</h2>
|
||||
<h3 id="51-текущее-состояние">5.1. Текущее состояние</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Компонент</th>
|
||||
<th>Статус</th>
|
||||
<th>Примечание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Go API (pm2: leadera-api)</td>
|
||||
<td>⚠️</td>
|
||||
<td>Порт 8080, хост 0.0.0.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Angular FE (pm2: leadera-fe)</td>
|
||||
<td>⚠️</td>
|
||||
<td>Порт 4200, хост 0.0.0.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PostgreSQL (Docker)</td>
|
||||
<td>✅</td>
|
||||
<td>Порт 5432, контейнер app-leadera-db</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>VPS reverse proxy</td>
|
||||
<td>⚠️</td>
|
||||
<td>sand.a2v.space → 8082/8083, но 502 если сервисы не запущены</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SSL</td>
|
||||
<td>✅</td>
|
||||
<td>Let’s Encrypt на VPS</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="52-проблемы">5.2. Проблемы</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Проблема</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>I1</td>
|
||||
<td>Docker для БД, нативно для API</td>
|
||||
<td>Несогласованность — API и FE не в Docker</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>I2</td>
|
||||
<td>Нет health-check в pm2</td>
|
||||
<td>API может упасть без перезапуска</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>I3</td>
|
||||
<td>Нет CI/CD</td>
|
||||
<td>Ручной деплой через <code>make run</code> + pm2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>I4</td>
|
||||
<td>Нет nginx на Mac Studio</td>
|
||||
<td>FE и API торчат наружу напрямую</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 id="6-функциональная-оценка">6. Функциональная оценка</h2>
|
||||
<h3 id="61-что-работает">6.1. Что работает</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Функция</th>
|
||||
<th>Backend</th>
|
||||
<th>Frontend</th>
|
||||
<th>Статус</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Регистрация/логин</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>Работает</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JWT auth + refresh</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>Работает</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spaces CRUD</td>
|
||||
<td>⚠️</td>
|
||||
<td>✅</td>
|
||||
<td><code>RegisterProtectedRoutes</code> не вызван (C4)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Space members</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>Работает</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gantt charts CRUD</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>Работает</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gantt sections</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>Работает</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gantt tasks</td>
|
||||
<td>✅</td>
|
||||
<td>⚠️</td>
|
||||
<td>Нет UI для задач внутри диаграммы</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Архивация диаграмм</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>Работает</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Members диаграммы</td>
|
||||
<td>❌</td>
|
||||
<td>✅ (мёртвый UI)</td>
|
||||
<td>Backend endpoints не существуют</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="62-что-не-работает-или-отсутствует">6.2. Что НЕ работает или отсутствует</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Функция</th>
|
||||
<th>Статус</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Визуализация Ганта (таймлайн)</td>
|
||||
<td>❌ Нет компонента отрисовки</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Drag & Drop задач</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Real-time collaboration</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Уведомления</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Поиск</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Экспорт (PDF/Excel)</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Email verification</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password reset</td>
|
||||
<td>Backend есть, UI есть — не проверено</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="63-оценка-готовности">6.3. Оценка готовности</h3>
|
||||
<p><strong>Система на стадии каркаса.</strong> Backend API функционален для CRUD операций, но:</p>
|
||||
<ul>
|
||||
<li>Визуализация Ганта — основная фича — не реализована (нет canvas/SVG рендеринга)</li>
|
||||
<li>Управление участниками только на уровне Space</li>
|
||||
<li>Нет CI/CD, тестов, мониторинга</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="7-приоритизированный-план-исправлений">7. Приоритизированный план исправлений</h2>
|
||||
<h3 id="неделя-1--критическое-безопасность">Неделя 1 — Критическое (безопасность)</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Приоритет</th>
|
||||
<th>Задача</th>
|
||||
<th>Трудоёмкость</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>P0</td>
|
||||
<td>Заменить JWT secret на криптостойкий</td>
|
||||
<td>1 час</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P0</td>
|
||||
<td>Настроить CORS (только sand.a2v.space)</td>
|
||||
<td>1 час</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P0</td>
|
||||
<td>bcrypt для refresh tokens вместо SHA256</td>
|
||||
<td>2 часа</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P0</td>
|
||||
<td>Удалить fallback на ContextRole в role_middleware</td>
|
||||
<td>30 мин</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P0</td>
|
||||
<td>Исправить <code>RegisterProtectedRoutes</code> — зарегистрировать маршруты</td>
|
||||
<td>1 час</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P1</td>
|
||||
<td>Rate limiting на auth endpoints</td>
|
||||
<td>4 часа</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P1</td>
|
||||
<td>Editor не может назначать admin роль</td>
|
||||
<td>2 часа</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="неделя-2--архитектура-прав">Неделя 2 — Архитектура прав</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Приоритет</th>
|
||||
<th>Задача</th>
|
||||
<th>Трудоёмкость</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>P1</td>
|
||||
<td>Удалить/переписать MembersModalComponent → Space members</td>
|
||||
<td>4 часа</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P1</td>
|
||||
<td>Добавить страницу управления участниками Space</td>
|
||||
<td>8 часов</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P2</td>
|
||||
<td>HttpOnly cookies для JWT (вместо localStorage)</td>
|
||||
<td>8 часов</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P2</td>
|
||||
<td>CSRF protection</td>
|
||||
<td>4 часа</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="неделя-3--функциональность">Неделя 3 — Функциональность</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Приоритет</th>
|
||||
<th>Задача</th>
|
||||
<th>Трудоёмкость</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>P2</td>
|
||||
<td>Визуализация Ганта (canvas/d3)</td>
|
||||
<td>40+ часов</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P2</td>
|
||||
<td>Drag & Drop для задач</td>
|
||||
<td>16 часов</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P3</td>
|
||||
<td>Тесты (unit + integration)</td>
|
||||
<td>24 часа</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>P3</td>
|
||||
<td>CI/CD pipeline</td>
|
||||
<td>8 часов</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 id="8-резюме">8. Резюме</h2>
|
||||
<h3 id="ключевые-выводы">Ключевые выводы</h3>
|
||||
<ol>
|
||||
<li><strong>Права доступа</strong> — архитектурно верно: роль назначается через Space, не через диаграмму. Но фронтенд ещё не обновлён после удаления <code>gantt_chart_members</code>.</li>
|
||||
<li><strong>Безопасность</strong> — критические уязвимости в конфигурации (JWT secret, CORS, bcrypt). Требуют немедленного исправления до любого публичного деплоя.</li>
|
||||
<li><strong>Функциональность</strong> — CRUD работает, но основная ценность (визуализация Ганта) не реализована.</li>
|
||||
<li><strong>Код</strong> — чистый, хорошая архитектура, но есть мёртвый код и незарегистрированные маршруты.</li>
|
||||
</ol>
|
||||
<h3 id="общая-оценка--pre-alpha">Общая оценка: 🔴 Pre-alpha</h3>
|
||||
<p>Проект готов к внутренней демонстрации CRUD, но не готов к продакшену. Первоочередное — безопасность и исправление мёртвых endpoints.</p>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,621 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Leadera — Фильтры и реорганизация списка диаграмм Ганта — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Все инструкции</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6 class="mt-3">Теги</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/audit/">audit</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/leadera/">leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/security/">security</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/architecture/">architecture</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/websocket/">websocket</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/realtime/">realtime</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/gantt/">gantt</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/api/">api</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/frontend/">frontend</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/requirements/">requirements</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/angular/">angular</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/go/">go</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ux/">ux</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ssh/">ssh</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/tunnel/">tunnel</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/vps/">vps</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/reverse-proxy/">reverse-proxy</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/nginx/">nginx</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/devops/">devops</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/openclaw/">openclaw</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/opencode/">opencode</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/docker/">docker</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Leadera — Фильтры и реорганизация списка диаграмм Ганта</h1>
|
||||
<div class="source-path mb-3">
|
||||
<small class="text-muted">
|
||||
📁 <code id="source-path" class="user-select-all">~/Projects/docs-a2v/content/guides/leadera-gantt-filters.md</code>
|
||||
<button class="btn btn-sm btn-outline-secondary ms-1 py-0 px-1" onclick="navigator.clipboard.writeText('~/Projects/docs-a2v/content/guides\/leadera-gantt-filters.md')" title="Копировать путь">
|
||||
📋
|
||||
</button>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="tags mb-3">
|
||||
|
||||
<a href="../../tags/leadera/" class="tag">leadera</a>
|
||||
|
||||
<a href="../../tags/gantt/" class="tag">gantt</a>
|
||||
|
||||
<a href="../../tags/api/" class="tag">api</a>
|
||||
|
||||
<a href="../../tags/frontend/" class="tag">frontend</a>
|
||||
|
||||
<a href="../../tags/requirements/" class="tag">requirements</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<h1 id="фильтры-и-реорганизация-списка-диаграмм-ганта">Фильтры и реорганизация списка диаграмм Ганта</h1>
|
||||
<p><strong>Дата:</strong> 07.04.2026
|
||||
<strong>Статус:</strong> Требования
|
||||
<strong>Проект:</strong> Leadera (dev — sand.a2v.space)</p>
|
||||
<hr>
|
||||
<h2 id="1-постановка-задачи">1. Постановка задачи</h2>
|
||||
<p>Список диаграмм Ганта должен показывать <strong>все доступные пользователю диаграммы</strong> из всех пространств (spaces), с возможностью фильтрации и поиска. Сейчас список привязан к одному пространству — нужно убрать эту зависимость и добавить удобный toolbar.</p>
|
||||
<hr>
|
||||
<h2 id="2-изменения-api">2. Изменения API</h2>
|
||||
<h3 id="21-новый-endpoint-списка-диаграмм">2.1. Новый endpoint списка диаграмм</h3>
|
||||
<p><strong>Было:</strong></p>
|
||||
<pre tabindex="0"><code>GET /api/v1/spaces/{spaceId}/gantt-charts?page=1&per_page=10
|
||||
</code></pre><p><strong>Стало:</strong></p>
|
||||
<pre tabindex="0"><code>GET /api/v1/gantt-charts?page=1&per_page=10
|
||||
</code></pre><p>Пользователь видит все диаграммы из <strong>всех пространств</strong>, где он является подтверждённым участником (статус <code>accepted</code>).</p>
|
||||
<h3 id="22-параметры-фильтрации-и-поиска">2.2. Параметры фильтрации и поиска</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Параметр</th>
|
||||
<th>Тип</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>page</code></td>
|
||||
<td>int</td>
|
||||
<td>Номер страницы (default: 1)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>per_page</code></td>
|
||||
<td>int</td>
|
||||
<td>Записей на странице (default: 10)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>space_id</code></td>
|
||||
<td>UUID (optional)</td>
|
||||
<td>Фильтр по конкретному пространству</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>created_by</code></td>
|
||||
<td>UUID (optional)</td>
|
||||
<td>Фильтр по создателю диаграммы</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>search</code></td>
|
||||
<td>string (optional)</td>
|
||||
<td>Поиск по назвению и описанию (ILIKE, case-insensitive)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>sort</code></td>
|
||||
<td>string (optional)</td>
|
||||
<td>Сортировка: <code>created_at</code>, <code>updated_at</code>, <code>title</code> (default: <code>updated_at</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>order</code></td>
|
||||
<td>string (optional)</td>
|
||||
<td><code>asc</code> / <code>desc</code> (default: <code>desc</code>)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Примеры:</strong></p>
|
||||
<pre tabindex="0"><code>GET /api/v1/gantt-charts?search=миграция
|
||||
GET /api/v1/gantt-charts?space_id=0b334ded-...&created_by=a1b2c3d4-...
|
||||
GET /api/v1/gantt-charts?page=2&per_page=20&sort=title&order=asc
|
||||
</code></pre><h3 id="23-изменение-структуры-ответа">2.3. Изменение структуры ответа</h3>
|
||||
<p>Добавить поле <code>space</code> в каждую диаграмму:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"data"</span>: [
|
||||
</span></span><span style="display:flex;"><span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"id"</span>: <span style="color:#e6db74">"uuid"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"title"</span>: <span style="color:#e6db74">"Миграция backend"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"description"</span>: <span style="color:#e6db74">"..."</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"created_by"</span>: <span style="color:#e6db74">"uuid"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"created_by_name"</span>: <span style="color:#e6db74">"Антон Агальцов"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"created_at"</span>: <span style="color:#e6db74">"2026-04-01T10:00:00Z"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"updated_at"</span>: <span style="color:#e6db74">"2026-04-07T09:00:00Z"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"space"</span>: {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"id"</span>: <span style="color:#e6db74">"uuid"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"IT Ландшафт"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"color"</span>: <span style="color:#e6db74">"#c4623a"</span>
|
||||
</span></span><span style="display:flex;"><span> },
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"is_archived"</span>: <span style="color:#66d9ef">false</span>
|
||||
</span></span><span style="display:flex;"><span> }
|
||||
</span></span><span style="display:flex;"><span> ],
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"pagination"</span>: {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"page"</span>: <span style="color:#ae81ff">1</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"per_page"</span>: <span style="color:#ae81ff">10</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"total"</span>: <span style="color:#ae81ff">42</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"total_pages"</span>: <span style="color:#ae81ff">5</span>
|
||||
</span></span><span style="display:flex;"><span> }
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><h3 id="24-endpoint-для-списка-фильтров">2.4. Endpoint для списка фильтров</h3>
|
||||
<p>Вспомогательный endpoint для заполнения dropdown-фильтров:</p>
|
||||
<pre tabindex="0"><code>GET /api/v1/gantt-charts/filters
|
||||
</code></pre><p><strong>Ответ:</strong></p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"spaces"</span>: [
|
||||
</span></span><span style="display:flex;"><span> { <span style="color:#f92672">"id"</span>: <span style="color:#e6db74">"uuid"</span>, <span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"IT Ландшафт"</span>, <span style="color:#f92672">"color"</span>: <span style="color:#e6db74">"#c4623a"</span> },
|
||||
</span></span><span style="display:flex;"><span> { <span style="color:#f92672">"id"</span>: <span style="color:#e6db74">"uuid"</span>, <span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"DevOps"</span>, <span style="color:#f92672">"color"</span>: <span style="color:#e6db74">"#27ae60"</span> }
|
||||
</span></span><span style="display:flex;"><span> ],
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"creators"</span>: [
|
||||
</span></span><span style="display:flex;"><span> { <span style="color:#f92672">"id"</span>: <span style="color:#e6db74">"uuid"</span>, <span style="color:#f92672">"display_name"</span>: <span style="color:#e6db74">"Антон Агальцов"</span> },
|
||||
</span></span><span style="display:flex;"><span> { <span style="color:#f92672">"id"</span>: <span style="color:#e6db74">"uuid"</span>, <span style="color:#f92672">"display_name"</span>: <span style="color:#e6db74">"Иван Петров"</span> }
|
||||
</span></span><span style="display:flex;"><span> ]
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><p><strong>Логика <code>creators</code>:</strong> уникальные создатели всех диаграмм, доступных текущему пользователю. Получается через DISTINCT-запрос по <code>created_by</code> с JOIN на users.</p>
|
||||
<h3 id="25-backend--изменения-в-go">2.5. Backend — изменения в Go</h3>
|
||||
<p><strong>Файлы для изменения:</strong></p>
|
||||
<h4 id="internalhandlersgantt_handlergo"><code>internal/handlers/gantt_handler.go</code></h4>
|
||||
<ul>
|
||||
<li>Добавить новый handler <code>ListAllGanttCharts</code> — без привязки к space</li>
|
||||
<li>Зарегистрировать маршрут <code>GET /gantt-charts</code> (без <code>/spaces/:id/</code>)</li>
|
||||
<li>Парсить query-параметры: <code>space_id</code>, <code>created_by</code>, <code>search</code>, <code>sort</code>, <code>order</code></li>
|
||||
<li>Старый маршрут <code>GET /spaces/:id/gantt-charts</code> — оставить для обратной совместимости (или удалить, если не используется)</li>
|
||||
</ul>
|
||||
<h4 id="internalservicegantt_servicego"><code>internal/service/gantt_service.go</code></h4>
|
||||
<ul>
|
||||
<li>Новый метод <code>ListAll(ctx, userId, filters)</code> — запрашивает все spaces пользователя (через <code>space_member</code> с <code>status=accepted</code>), затем выбирает все gantt_charts из этих spaces с фильтрами</li>
|
||||
</ul>
|
||||
<h4 id="internalrepositorygantt_repositorygo"><code>internal/repository/gantt_repository.go</code></h4>
|
||||
<ul>
|
||||
<li>Новый метод с динамическим SQL:
|
||||
<ul>
|
||||
<li>Базовый JOIN: <code>gantt_charts</code> → <code>spaces</code> → <code>space_members</code></li>
|
||||
<li>WHERE: <code>space_members.user_id = $1 AND space_members.status = 'accepted'</code></li>
|
||||
<li>Опциональные фильтры: <code>AND space_id = $N</code>, <code>AND created_by = $N</code>, <code>AND (title ILIKE '%' || $N || '%' OR description ILIKE '%' || $N || '%')</code></li>
|
||||
<li>Возвращать поле <code>space</code> (id, name, color) через JOIN</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h4 id="internaldtogantt"><code>internal/dto/gantt/</code></h4>
|
||||
<ul>
|
||||
<li>Новые DTO: <code>GanttChartListFilters</code>, <code>GanttChartWithSpaceResponse</code>, <code>GanttFiltersResponse</code></li>
|
||||
</ul>
|
||||
<p><strong>SQL (пример):</strong></p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">SELECT</span> gc.<span style="color:#f92672">*</span>, s.id <span style="color:#66d9ef">as</span> space_id, s.name <span style="color:#66d9ef">as</span> space_name, s.color <span style="color:#66d9ef">as</span> space_color,
|
||||
</span></span><span style="display:flex;"><span> u.display_name <span style="color:#66d9ef">as</span> created_by_name
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span> gantt_charts gc
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">JOIN</span> spaces s <span style="color:#66d9ef">ON</span> s.id <span style="color:#f92672">=</span> gc.space_id
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">JOIN</span> space_members sm <span style="color:#66d9ef">ON</span> sm.space_id <span style="color:#f92672">=</span> s.id
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">LEFT</span> <span style="color:#66d9ef">JOIN</span> users u <span style="color:#66d9ef">ON</span> u.id <span style="color:#f92672">=</span> gc.created_by
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WHERE</span> sm.user_id <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">1</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">AND</span> sm.status <span style="color:#f92672">=</span> <span style="color:#e6db74">'accepted'</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">AND</span> (<span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">2</span>::uuid <span style="color:#66d9ef">IS</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">OR</span> gc.space_id <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">2</span>)
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">AND</span> (<span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">3</span>::uuid <span style="color:#66d9ef">IS</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">OR</span> gc.created_by <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">3</span>)
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">AND</span> (<span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">4</span>::text <span style="color:#66d9ef">IS</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">OR</span> gc.title <span style="color:#66d9ef">ILIKE</span> <span style="color:#e6db74">'%'</span> <span style="color:#f92672">||</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">4</span> <span style="color:#f92672">||</span> <span style="color:#e6db74">'%'</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">OR</span> gc.description <span style="color:#66d9ef">ILIKE</span> <span style="color:#e6db74">'%'</span> <span style="color:#f92672">||</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">4</span> <span style="color:#f92672">||</span> <span style="color:#e6db74">'%'</span>)
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">ORDER</span> <span style="color:#66d9ef">BY</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">CASE</span> <span style="color:#66d9ef">WHEN</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">5</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">'title'</span> <span style="color:#66d9ef">THEN</span> gc.title <span style="color:#66d9ef">END</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">CASE</span> <span style="color:#66d9ef">WHEN</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">5</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">'created_at'</span> <span style="color:#66d9ef">THEN</span> gc.created_at::text <span style="color:#66d9ef">END</span>,
|
||||
</span></span><span style="display:flex;"><span> gc.updated_at <span style="color:#66d9ef">DESC</span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">LIMIT</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">6</span> <span style="color:#66d9ef">OFFSET</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#ae81ff">7</span>;
|
||||
</span></span></code></pre></div><hr>
|
||||
<h2 id="3-изменения-frontend-angular">3. Изменения Frontend (Angular)</h2>
|
||||
<h3 id="31-toolbar-фильтров">3.1. Toolbar фильтров</h3>
|
||||
<p>Добавить toolbar над списком диаграмм:</p>
|
||||
<pre tabindex="0"><code>┌──────────────────────────────────────────────────────────────────┐
|
||||
│ [🔍 Поиск... ] [▼ Пространство] │
|
||||
│ [▼ Создатель] [▼ Сортировка] [Сбросить фильтры] │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
</code></pre><p><strong>Компоненты:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Строка поиска</strong> — input с debounce (300ms), поиск по назвению и описанию</li>
|
||||
<li><strong>Dropdown «Пространство»</strong> — список из <code>/gantt-charts/filters</code>, с цветовой меткой</li>
|
||||
<li><strong>Dropdown «Создатель»</strong> — список уникальных создателей</li>
|
||||
<li><strong>Dropdown «Сортировка»</strong> — по дате обновления, дате создания, названию</li>
|
||||
<li><strong>Кнопка «Сбросить»</strong> — очищает все фильтры</li>
|
||||
</ul>
|
||||
<p><strong>Состояние фильтров в URL</strong> (query params):</p>
|
||||
<pre tabindex="0"><code>/gantt?search=миграция&space_id=xxx&sort=updated_at
|
||||
</code></pre><p>Это позволяет делиться ссылкой с уже настроенными фильтрами.</p>
|
||||
<h3 id="32-карточка-диаграммы--бейдж-пространства">3.2. Карточка диаграммы — бейдж пространства</h3>
|
||||
<p>На каждой карточке добавить бейдж с названием пространства:</p>
|
||||
<pre tabindex="0"><code>┌─────────────────────────────────────┐
|
||||
│ 🟠 IT Ландшафт │ ← бейдж с цветом пространства
|
||||
│ Миграция backend │
|
||||
│ Перевод PHP→Go, этап 2 │
|
||||
│ Создал: Антон А. · 07.04.2026 │
|
||||
└─────────────────────────────────────┘
|
||||
</code></pre><h3 id="33-форма-создания-диаграммы--выбор-пространства">3.3. Форма создания диаграммы — выбор пространства</h3>
|
||||
<p>В модальном окне создания:</p>
|
||||
<ul>
|
||||
<li>Dropdown со списком пространств, где пользователь имеет роль <strong>editor</strong> или выше</li>
|
||||
<li>Валидация: если пользователь не editor ни в одном пространстве — показать сообщение «Нет доступных пространств для создания»</li>
|
||||
</ul>
|
||||
<p><strong>Запрос доступных пространств:</strong> переиспользовать существующий <code>GET /api/v1/spaces</code> с фильтрацией на клиенте по <code>role ∈ [owner, admin, editor]</code>, либо добавить параметр <code>?min_role=editor</code> на backend.</p>
|
||||
<h3 id="34-изменение-routing">3.4. Изменение routing</h3>
|
||||
<p><strong>Было:</strong></p>
|
||||
<pre tabindex="0"><code>/gantt → список гантов текущего пространства
|
||||
</code></pre><p><strong>Стало:</strong></p>
|
||||
<pre tabindex="0"><code>/gantt → список всех доступных гантов (из всех пространств)
|
||||
</code></pre><p>Убрать зависимость от <code>SpaceStorageService.getSelectedSpaceId()</code> в списке гантов.</p>
|
||||
<h3 id="35-frontend--файлы-для-изменения">3.5. Frontend — файлы для изменения</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Файл</th>
|
||||
<th>Изменение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>pages/gantt/services/gantt.service.ts</code></td>
|
||||
<td>Новый метод <code>listAll(filters)</code>, <code>getFilters()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pages/gantt/gantt.component.ts</code></td>
|
||||
<td>Подключить toolbar, парсинг URL-параметров</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pages/gantt/gantt.component.html</code></td>
|
||||
<td>Добавить toolbar, бейджи на карточках</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pages/gantt/components/gantt-card/</code></td>
|
||||
<td>Добавить бейдж пространства</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pages/gantt/components/create-chart-modal/</code></td>
|
||||
<td>Dropdown выбора пространства</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>core/models/</code></td>
|
||||
<td>Обновить модели: добавить <code>space</code> в GanttChart</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 id="4-обратная-совместимость">4. Обратная совместимость</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Endpoint</th>
|
||||
<th>Статус</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>GET /api/v1/spaces/{id}/gantt-charts</code></td>
|
||||
<td>Сохранить (для детального view внутри пространства)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>GET /api/v1/gantt-charts</code></td>
|
||||
<td><strong>Новый</strong> — глобальный список</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>GET /api/v1/gantt-charts/filters</code></td>
|
||||
<td><strong>Новый</strong> — данные для dropdown’ов</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>POST /api/v1/spaces/{id}/gantt-charts</code></td>
|
||||
<td>Сохранить (создание в контексте пространства)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Все CRUD для sections/tasks</td>
|
||||
<td>Без изменений</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<h2 id="5-критерии-приёмки">5. Критерии приёмки</h2>
|
||||
<ul>
|
||||
<li><input disabled="" type="checkbox"> Endpoint <code>GET /api/v1/gantt-charts</code> возвращает все доступные диаграммы</li>
|
||||
<li><input disabled="" type="checkbox"> Фильтр по <code>space_id</code> — показывает только диаграммы конкретного пространства</li>
|
||||
<li><input disabled="" type="checkbox"> Фильтр по <code>created_by</code> — показывает только диаграммы выбранного создателя</li>
|
||||
<li><input disabled="" type="checkbox"> Поиск <code>search</code> — ищет по title и description (case-insensitive)</li>
|
||||
<li><input disabled="" type="checkbox"> Dropdown фильтров заполняется реальными данными из <code>/filters</code></li>
|
||||
<li><input disabled="" type="checkbox"> Карточка диаграммы показывает бейдж пространства с цветом</li>
|
||||
<li><input disabled="" type="checkbox"> Форма создания предлагает только пространства с ролью ≥ editor</li>
|
||||
<li><input disabled="" type="checkbox"> Состояние фильтров сохраняется в URL (можно поделиться ссылкой)</li>
|
||||
<li><input disabled="" type="checkbox"> Старые endpoints (<code>/spaces/{id}/gantt-charts</code>) продолжают работать</li>
|
||||
<li><input disabled="" type="checkbox"> Swagger документация обновлена</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="6-порядок-реализации">6. Порядок реализации</h2>
|
||||
<ol>
|
||||
<li>Backend: DTO для новых запросов/ответов</li>
|
||||
<li>Backend: Repository — SQL-запрос с фильтрами + JOIN на spaces</li>
|
||||
<li>Backend: Service — <code>ListAll</code>, <code>GetFilters</code></li>
|
||||
<li>Backend: Handler — <code>ListAllGanttCharts</code>, <code>GetGanttFilters</code>, регистрация маршрутов</li>
|
||||
<li>Backend: Swagger — обновить документацию</li>
|
||||
<li>Frontend: Модели — обновить GanttChart, добавить Space в ответ</li>
|
||||
<li>Frontend: Service — <code>listAll()</code>, <code>getFilters()</code></li>
|
||||
<li>Frontend: Toolbar компонент — поиск + dropdown’ы</li>
|
||||
<li>Frontend: Карточка — бейдж пространства</li>
|
||||
<li>Frontend: Модальное окно создания — dropdown пространства</li>
|
||||
<li>Frontend: URL-параметры — синхронизация фильтров с router</li>
|
||||
<li>Тестирование</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,776 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Leadera: Вехи (Milestones) на диаграмме Ганта — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Все инструкции</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6 class="mt-3">Теги</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/audit/">audit</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/leadera/">leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/security/">security</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/architecture/">architecture</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/websocket/">websocket</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/realtime/">realtime</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/gantt/">gantt</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/api/">api</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/frontend/">frontend</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/requirements/">requirements</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/angular/">angular</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/go/">go</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ux/">ux</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ssh/">ssh</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/tunnel/">tunnel</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/vps/">vps</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/reverse-proxy/">reverse-proxy</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/nginx/">nginx</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/devops/">devops</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/openclaw/">openclaw</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/opencode/">opencode</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/docker/">docker</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Leadera: Вехи (Milestones) на диаграмме Ганта</h1>
|
||||
<div class="source-path mb-3">
|
||||
<small class="text-muted">
|
||||
📁 <code id="source-path" class="user-select-all">~/Projects/docs-a2v/content/guides/leadera-milestones.md</code>
|
||||
<button class="btn btn-sm btn-outline-secondary ms-1 py-0 px-1" onclick="navigator.clipboard.writeText('~/Projects/docs-a2v/content/guides\/leadera-milestones.md')" title="Копировать путь">
|
||||
📋
|
||||
</button>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="tags mb-3">
|
||||
|
||||
<a href="../../tags/leadera/" class="tag">leadera</a>
|
||||
|
||||
<a href="../../tags/gantt/" class="tag">gantt</a>
|
||||
|
||||
<a href="../../tags/angular/" class="tag">angular</a>
|
||||
|
||||
<a href="../../tags/go/" class="tag">go</a>
|
||||
|
||||
<a href="../../tags/api/" class="tag">api</a>
|
||||
|
||||
<a href="../../tags/ux/" class="tag">ux</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<h2 id="бизнес-требования">Бизнес-требования</h2>
|
||||
<h3 id="br-1-сущность-веха-milestone">BR-1: Сущность «Веха» (Milestone)</h3>
|
||||
<p>Веха — это маркер на таймлайне диаграммы Ганта, обозначающий важную дату в проекте. В отличие от задач, веха не имеет длительности и привязана к конкретной дате.</p>
|
||||
<p><strong>Поля вехи:</strong></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Поле</th>
|
||||
<th>Тип</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>id</td>
|
||||
<td>UUID</td>
|
||||
<td>Идентификатор</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>gantt_chart_id</td>
|
||||
<td>UUID</td>
|
||||
<td>Принадлежность к диаграмме (не к секции!)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>title</td>
|
||||
<td>string</td>
|
||||
<td>Название вехи (обязательное, 1–255 символов)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>date</td>
|
||||
<td>date</td>
|
||||
<td>Дата вехи (без времени, обязательная)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>color</td>
|
||||
<td>string</td>
|
||||
<td>Цвет маркера (HEX, по умолчанию <code>#dc3545</code> — красный)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>created_by</td>
|
||||
<td>UUID</td>
|
||||
<td>Кто создал (не отображается в UI, хранится для аудита)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>updated_by</td>
|
||||
<td>UUID</td>
|
||||
<td>Кто обновил (не отображается в UI)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>created_at</td>
|
||||
<td>timestamp</td>
|
||||
<td>Дата создания</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>updated_at</td>
|
||||
<td>timestamp</td>
|
||||
<td>Дата обновления</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>deleted_at</td>
|
||||
<td>timestamp</td>
|
||||
<td>Soft delete</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Права доступа:</strong> Создание, редактирование и удаление вех доступно участникам с правами выше «только чтение» (аналогично задачам).</p>
|
||||
<p><strong>Особенности:</strong></p>
|
||||
<ul>
|
||||
<li>Вех может быть несколько в проекте</li>
|
||||
<li>Несколько вех могут иметь одну и ту же дату</li>
|
||||
<li>Вехи сортируются строго по дате (по возрастанию)</li>
|
||||
<li>Вехи не привязаны к секциям — они отображаются <strong>сквозь все секции</strong></li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h3 id="br-2-управление-вехами-модальное-окно">BR-2: Управление вехами (модальное окно)</h3>
|
||||
<p><strong>Вызов:</strong> Кнопка «Вехи» рядом с кнопкой «Создать секцию» на странице диаграммы.</p>
|
||||
<p><strong>Модальное окно содержит:</strong></p>
|
||||
<ul>
|
||||
<li>Заголовок: «Вехи проекта»</li>
|
||||
<li>Список всех вех текущей диаграммы (сортировка по дате по возрастанию)</li>
|
||||
<li>Каждая веха в списке показывает: цвет (индикатор), название, дату, кнопки «Редактировать» и «Удалить»</li>
|
||||
<li>Кнопка «Добавить веху»</li>
|
||||
</ul>
|
||||
<p><strong>Форма добавления/редактирования вехи:</strong></p>
|
||||
<ul>
|
||||
<li>Название — текстовый ввод (обязательное, 1–255 символов)</li>
|
||||
<li>Дата — datepicker (обязательное)</li>
|
||||
<li>Цвет — выбор цвета (по аналогии с палитрой цветов в задачах)</li>
|
||||
<li>По умолчанию цвет = красный (<code>#dc3545</code>)</li>
|
||||
</ul>
|
||||
<p><strong>Удаление:</strong> с подтверждением (confirm dialog).</p>
|
||||
<hr>
|
||||
<h3 id="br-3-отображение-вех-на-таймлайне">BR-3: Отображение вех на таймлайне</h3>
|
||||
<p><strong>Визуальное представление:</strong></p>
|
||||
<ul>
|
||||
<li><strong>Маркер-флажок</strong> (flag marker) на шкале таймлайна</li>
|
||||
<li>От маркера вниз идёт <strong>пунктирная вертикальная линия</strong> через все секции (на всю высоту диаграммы)</li>
|
||||
<li>Цвет линии и маркера = цвет вехи</li>
|
||||
</ul>
|
||||
<p><strong>Позиционирование:</strong></p>
|
||||
<ul>
|
||||
<li>Веха ставится ровно на свою дату на шкале времени</li>
|
||||
<li>Если дата вехи выходит за рамки текущего диапазона задач — таймлайн <strong>расширяется</strong> (аналогично задачам)</li>
|
||||
<li>При изменении масштаба (days/weeks/months/quarters) позиция вехи пересчитывается</li>
|
||||
</ul>
|
||||
<p><strong>Tooltip при наведении:</strong></p>
|
||||
<ul>
|
||||
<li>При наведении на маркер/линию — показывается tooltip с названием вехи</li>
|
||||
<li>Если на одну дату приходится несколько вех — в tooltip показываются <strong>все</strong> вехи этой даты с их названиями (каждая с индикацией своего цвета)</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="технические-требования">Технические требования</h2>
|
||||
<h3 id="база-данных">База данных</h3>
|
||||
<h4 id="новая-таблица-gantt_milestones">Новая таблица: gantt_milestones</h4>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">TABLE</span> gantt_milestones (
|
||||
</span></span><span style="display:flex;"><span> id UUID <span style="color:#66d9ef">PRIMARY</span> <span style="color:#66d9ef">KEY</span> <span style="color:#66d9ef">DEFAULT</span> gen_random_uuid(),
|
||||
</span></span><span style="display:flex;"><span> gantt_chart_id UUID <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">REFERENCES</span> gantt_charts(id) <span style="color:#66d9ef">ON</span> <span style="color:#66d9ef">DELETE</span> <span style="color:#66d9ef">CASCADE</span>,
|
||||
</span></span><span style="display:flex;"><span> title VARCHAR(<span style="color:#ae81ff">255</span>) <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span>,
|
||||
</span></span><span style="display:flex;"><span> date DATE <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span>,
|
||||
</span></span><span style="display:flex;"><span> color VARCHAR(<span style="color:#ae81ff">20</span>) <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">DEFAULT</span> <span style="color:#e6db74">'#dc3545'</span>,
|
||||
</span></span><span style="display:flex;"><span> created_by UUID <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">REFERENCES</span> users(id),
|
||||
</span></span><span style="display:flex;"><span> updated_by UUID <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">REFERENCES</span> users(id),
|
||||
</span></span><span style="display:flex;"><span> created_at <span style="color:#66d9ef">TIMESTAMP</span> <span style="color:#66d9ef">WITH</span> TIME <span style="color:#66d9ef">ZONE</span> <span style="color:#66d9ef">DEFAULT</span> NOW(),
|
||||
</span></span><span style="display:flex;"><span> updated_at <span style="color:#66d9ef">TIMESTAMP</span> <span style="color:#66d9ef">WITH</span> TIME <span style="color:#66d9ef">ZONE</span> <span style="color:#66d9ef">DEFAULT</span> NOW(),
|
||||
</span></span><span style="display:flex;"><span> deleted_at <span style="color:#66d9ef">TIMESTAMP</span> <span style="color:#66d9ef">WITH</span> TIME <span style="color:#66d9ef">ZONE</span>
|
||||
</span></span><span style="display:flex;"><span>);
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">INDEX</span> idx_gantt_milestones_chart <span style="color:#66d9ef">ON</span> gantt_milestones(gantt_chart_id);
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">INDEX</span> idx_gantt_milestones_date <span style="color:#66d9ef">ON</span> gantt_milestones(date);
|
||||
</span></span></code></pre></div><hr>
|
||||
<h3 id="backend-go-api">Backend (Go API)</h3>
|
||||
<h4 id="этап-1-миграция--домен">Этап 1: Миграция + Домен</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Добавь в проект новую таблицу <code>gantt_milestones</code>.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Создай миграцию в <code>cmd/migrate/</code>:</p>
|
||||
<ul>
|
||||
<li>Новая таблица <code>gantt_milestones</code> с полями: id (UUID PK), gantt_chart_id (UUID FK → gantt_charts, ON DELETE CASCADE), title (VARCHAR 255 NOT NULL), date (DATE NOT NULL), color (VARCHAR 20 NOT NULL DEFAULT ‘#dc3545’), created_by (UUID FK → users), updated_by (UUID FK → users), created_at, updated_at, deleted_at. Индексы по gantt_chart_id и date.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>Создай доменную модель <code>GanttMilestone</code> в <code>internal/domain/gantt.go</code>:</p>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">GanttMilestone</span> <span style="color:#66d9ef">struct</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">ID</span> <span style="color:#a6e22e">UUID</span> <span style="color:#e6db74">`json:"id"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">GanttChartID</span> <span style="color:#a6e22e">UUID</span> <span style="color:#e6db74">`json:"gantt_chart_id"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Title</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"title"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Date</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span> <span style="color:#e6db74">`json:"date"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Color</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"color"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">CreatedBy</span> <span style="color:#a6e22e">UUID</span> <span style="color:#e6db74">`json:"created_by"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">UpdatedBy</span> <span style="color:#a6e22e">UUID</span> <span style="color:#e6db74">`json:"updated_by"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">CreatedAt</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span> <span style="color:#e6db74">`json:"created_at"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">UpdatedAt</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span> <span style="color:#e6db74">`json:"updated_at"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">DeletedAt</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span> <span style="color:#e6db74">`json:"deleted_at,omitempty"`</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div></blockquote>
|
||||
<h4 id="этап-2-crud-для-ganttmilestones">Этап 2: CRUD для GanttMilestones</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Реализуй полный CRUD для сущности <code>GanttMilestone</code> по аналогии с существующими handlers/services/repositories в проекте.</p>
|
||||
<p><strong>Роуты:</strong></p>
|
||||
<ul>
|
||||
<li><code>GET /api/gantt-charts/:chartId/milestones</code> — список вех диаграммы</li>
|
||||
<li><code>POST /api/gantt-charts/:chartId/milestones</code> — создать веху</li>
|
||||
<li><code>PUT /api/gantt-charts/:chartId/milestones/:milestoneId</code> — обновить веху</li>
|
||||
<li><code>DELETE /api/gantt-charts/:chartId/milestones/:milestoneId</code> — удалить веху (soft delete)</li>
|
||||
</ul>
|
||||
<p><strong>Repository:</strong> <code>internal/repository/gantt_milestone_repository.go</code></p>
|
||||
<ul>
|
||||
<li><code>GetByChartID(ctx, chartID) ([]domain.GanttMilestone, error)</code> — все неудалённые вехи диаграммы, отсортированные по date ASC</li>
|
||||
<li><code>GetByID(ctx, id) (*domain.GanttMilestone, error)</code></li>
|
||||
<li><code>Create(ctx, milestone) error</code></li>
|
||||
<li><code>Update(ctx, milestone) error</code></li>
|
||||
<li><code>Delete(ctx, id) error</code> — soft delete (set deleted_at)</li>
|
||||
<li>Все запросы — raw SQL через pgx, как в остальных репозиториях проекта</li>
|
||||
</ul>
|
||||
<p><strong>Service:</strong> <code>internal/service/gantt_milestone_service.go</code></p>
|
||||
<ul>
|
||||
<li>Валидация: title (1–255 символов), date (обязательное), color (валидный HEX, default ‘#dc3545’)</li>
|
||||
<li>Проверка прав доступа: пользователь должен иметь права выше «только чтение» в пространстве (space) диаграммы</li>
|
||||
<li>Проверка что chartId существует и не архивирован</li>
|
||||
</ul>
|
||||
<p><strong>Handler:</strong> <code>internal/handler/gantt_milestone_handler.go</code></p>
|
||||
<ul>
|
||||
<li>Swagger-аннотации для всех эндпоинтов</li>
|
||||
<li>Валидация входных данных</li>
|
||||
<li>Ошибки в формате проекта</li>
|
||||
</ul>
|
||||
<p><strong>DTO:</strong> <code>internal/dto/gantt/milestones_dto.go</code></p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">CreateGanttMilestoneRequest</span> <span style="color:#66d9ef">struct</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Title</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"title" binding:"required,min=1,max=255"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Date</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"date" binding:"required"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Color</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"color" binding:"omitempty,max=20"`</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">UpdateGanttMilestoneRequest</span> <span style="color:#66d9ef">struct</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Title</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"title" binding:"omitempty,min=1,max=255"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Date</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"date" binding:"omitempty"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Color</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"color" binding:"omitempty,max=20"`</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">GanttMilestoneResponse</span> <span style="color:#66d9ef">struct</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">ID</span> <span style="color:#a6e22e">domain</span>.<span style="color:#a6e22e">UUID</span> <span style="color:#e6db74">`json:"id"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">GanttChartID</span> <span style="color:#a6e22e">domain</span>.<span style="color:#a6e22e">UUID</span> <span style="color:#e6db74">`json:"gantt_chart_id"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Title</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"title"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Date</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"date"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Color</span> <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:"color"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">CreatedByUser</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">CreatedByUpdatedUser</span> <span style="color:#e6db74">`json:"created_by_user"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">UpdatedByUser</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">CreatedByUpdatedUser</span> <span style="color:#e6db74">`json:"updated_by_user"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">CreatedAt</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span> <span style="color:#e6db74">`json:"created_at"`</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">UpdatedAt</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Time</span> <span style="color:#e6db74">`json:"updated_at"`</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">GanttMilestonesListResponse</span> <span style="color:#66d9ef">struct</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">Milestones</span> []<span style="color:#a6e22e">GanttMilestoneResponse</span> <span style="color:#e6db74">`json:"milestones"`</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><p><strong>Регистрация роутов:</strong> Добавь группу milestone-роутов в роутер рядом с существующими роутами секций/задач. Проверка прав через существующий middleware.</p>
|
||||
</blockquote>
|
||||
<h4 id="этап-3-включение-вех-в-ответ-диаграммы">Этап 3: Включение вех в ответ диаграммы</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>При запросе данных диаграммы Ганта (полная загрузка) включай связанные вехи в ответ.</p>
|
||||
<ol>
|
||||
<li>Добавь эндпоинт или расширь существующий <code>GET /api/gantt-charts/:chartId</code> — включить поле <code>milestones</code> с массивом <code>GanttMilestoneResponse</code></li>
|
||||
<li>Вехи с <code>deleted_at IS NOT NULL</code> не возвращаются</li>
|
||||
<li>Вехи сортируются по <code>date</code> ASC</li>
|
||||
<li>Вехи загружаются вместе с данными диаграммы (tasks, sections) — один запрос при открытии Ганта</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h3 id="frontend-angular">Frontend (Angular)</h3>
|
||||
<h4 id="этап-fe-1-модели--сервис">Этап FE-1: Модели + Сервис</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Добавь в проект поддержку вех (milestones) на диаграмме Ганта.</p>
|
||||
<ol>
|
||||
<li>В <code>pages/gantt/models/</code> (или соответствующем файле моделей) добавь:</li>
|
||||
</ol>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">GanttMilestone</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">id</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">gantt_chart_id</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">title</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">date</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">color</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">created_by_user</span><span style="color:#f92672">?:</span> { <span style="color:#a6e22e">id</span>: <span style="color:#66d9ef">string</span>; <span style="color:#a6e22e">full_name</span>: <span style="color:#66d9ef">string</span> };
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">updated_by_user</span><span style="color:#f92672">?:</span> { <span style="color:#a6e22e">id</span>: <span style="color:#66d9ef">string</span>; <span style="color:#a6e22e">full_name</span>: <span style="color:#66d9ef">string</span> };
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">created_at</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">updated_at</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">GanttMilestoneCreateRequest</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">title</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">date</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">color?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">GanttMilestoneUpdateRequest</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">title?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">date?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">color?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><ol start="2">
|
||||
<li>
|
||||
<p>Добавь <code>milestones: GanttMilestone[]</code> в интерфейс/модель полной загрузки данных диаграммы</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Создай сервис <code>pages/gantt/services/gantt-milestone.service.ts</code>:</p>
|
||||
</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>Inject HttpClient</li>
|
||||
<li>Методы:
|
||||
<ul>
|
||||
<li><code>getMilestones(chartId: string): Observable<GanttMilestone[]></code></li>
|
||||
<li><code>createMilestone(chartId: string, data: GanttMilestoneCreateRequest): Observable<GanttMilestone></code></li>
|
||||
<li><code>updateMilestone(chartId: string, milestoneId: string, data: GanttMilestoneUpdateRequest): Observable<GanttMilestone></code></li>
|
||||
<li><code>deleteMilestone(chartId: string, milestoneId: string): Observable<void></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Все методы возвращают Observable с типизированными ответами (по аналогии с GanttChartService)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h4 id="этап-fe-2-модальное-окно-управления-вехами">Этап FE-2: Модальное окно управления вехами</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Создай компонент модального окна для управления вехами диаграммы Ганта.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Создай компонент <code>pages/gantt/components/milestones-modal/</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Кнопка вызова:</strong> Добавь кнопку «Вехи» рядом с кнопкой «Создать секцию» в toolbar диаграммы. По клику — открытие модального окна через ng-bootstrap NgbModal.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Модальное окно</strong> (ng-bootstrap modal):</p>
|
||||
<ul>
|
||||
<li>Заголовок: «Вехи проекта»</li>
|
||||
<li>Список вех (сортировка по date ASC):
|
||||
<ul>
|
||||
<li>Каждый элемент: цветной кружок (color), название, дата (форматированная), кнопки ✏️ (редактировать) и 🗑️ (удалить с confirm)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Кнопка «Добавить веху» внизу списка</li>
|
||||
<li>Если вех нет — сообщение «Вех пока нет. Добавьте первую!»</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Форма добавления/редактирования</strong> (inline в модальном окне):</p>
|
||||
<ul>
|
||||
<li>Название — текстовый ввод (обязательное)</li>
|
||||
<li>Дата — ng-bootstrap datepicker (обязательное)</li>
|
||||
<li>Цвет — палитра цветов (использовать тот же компонент/подход, что и для задач)</li>
|
||||
<li>По умолчанию цвет = <code>#dc3545</code> (красный)</li>
|
||||
<li>Кнопки «Сохранить» и «Отмена»</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>При сохранении — вызов соответствующего метода сервиса (create/update)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>При удалении — confirm dialog → вызов deleteMilestone</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>После любого изменения — обновить список вех и обновить данные на канвасе (через сервис/GanttStore)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Инжектировать GanttMilestoneService и NgbModal</p>
|
||||
</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<h4 id="этап-fe-3-отображение-вех-на-таймлайне-konva-canvas">Этап FE-3: Отображение вех на таймлайне (Konva canvas)</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Отобрази вехи (milestones) на canvas-диаграмме Ганта.</p>
|
||||
<p>Проект использует Konva.js для рендеринга.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>При загрузке данных диаграммы — извлечь массив <code>milestones</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Для каждой вехи нарисовать на canvas:</p>
|
||||
<ul>
|
||||
<li><strong>Маркер-флажок</strong> (flag marker) на позиции даты вехи на шкале времени
|
||||
<ul>
|
||||
<li>Стиль: маленький треугольник или флаг на верхней границе таймлайна</li>
|
||||
<li>Цвет = milestone.color</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>Пунктирная вертикальная линия</strong> от маркера вниз через все секции (на всю высоту области секций)
|
||||
<ul>
|
||||
<li>Стиль: Konva.Line, dash: [5, 5], strokeWidth: 1.5, color = milestone.color, opacity: 0.7</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Позиционирование:</strong></p>
|
||||
<ul>
|
||||
<li>Рассчитать X-позицию по дате вехи с использованием текущей шкалы времени (как для задач)</li>
|
||||
<li>Если дата вехи выходит за текущий диапазон — расширить диапазон (влияет на общую ширину таймлайна)</li>
|
||||
<li>При изменении масштаба (days/weeks/months/quarters) — пересчитать позиции всех вех</li>
|
||||
<li>При скролле — вехи скроллятся вместе с задачами</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Tooltip при наведении:</strong></p>
|
||||
<ul>
|
||||
<li>При наведении на маркер или пунктирную линию — показать Konva.Tooltip или HTML tooltip:
|
||||
<ul>
|
||||
<li>Если веха одна на эту дату — показать название</li>
|
||||
<li>Если несколько вех на одну дату — показать список: цветной кружок + название для каждой</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Z-index:</strong></p>
|
||||
<ul>
|
||||
<li>Линии вех рисуются <strong>поверх</strong> фона секций, но <strong>под</strong> задачами</li>
|
||||
<li>Маркеры-флажки — поверх всего (самый высокий z-index)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Реактивность:</strong></p>
|
||||
<ul>
|
||||
<li>При добавлении/удалении/редактировании вехи — перерисовать только вехи (без полного ре рендера задач)</li>
|
||||
<li>Подписаться на изменения массива milestones через сервис/store</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2 id="порядок-реализации">Порядок реализации</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Этап</th>
|
||||
<th>Сторона</th>
|
||||
<th>Зависимости</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Миграция + Домен</td>
|
||||
<td>Backend</td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>CRUD вех</td>
|
||||
<td>Backend</td>
|
||||
<td>Этап 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Включение вех в ответ диаграммы</td>
|
||||
<td>Backend</td>
|
||||
<td>Этап 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Модели + Сервис</td>
|
||||
<td>Frontend</td>
|
||||
<td>— (параллельно с backend)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Модальное окно управления вехами</td>
|
||||
<td>Frontend</td>
|
||||
<td>Этапы 4 + backend 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>Отображение вех на таймлайне</td>
|
||||
<td>Frontend</td>
|
||||
<td>Этапы 4 + backend 3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,839 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Leadera: Ограничения секций в диаграмме Ганта — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Все инструкции</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6 class="mt-3">Теги</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/audit/">audit</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/leadera/">leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/security/">security</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/architecture/">architecture</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/websocket/">websocket</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/realtime/">realtime</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/gantt/">gantt</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/api/">api</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/frontend/">frontend</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/requirements/">requirements</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/angular/">angular</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/go/">go</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ux/">ux</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/ssh/">ssh</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/tunnel/">tunnel</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/vps/">vps</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/reverse-proxy/">reverse-proxy</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/nginx/">nginx</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/devops/">devops</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/openclaw/">openclaw</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/opencode/">opencode</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../tags/docker/">docker</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Leadera: Ограничения секций в диаграмме Ганта</h1>
|
||||
<div class="source-path mb-3">
|
||||
<small class="text-muted">
|
||||
📁 <code id="source-path" class="user-select-all">~/Projects/docs-a2v/content/guides/leadera-section-constraints.md</code>
|
||||
<button class="btn btn-sm btn-outline-secondary ms-1 py-0 px-1" onclick="navigator.clipboard.writeText('~/Projects/docs-a2v/content/guides\/leadera-section-constraints.md')" title="Копировать путь">
|
||||
📋
|
||||
</button>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="tags mb-3">
|
||||
|
||||
<a href="../../tags/leadera/" class="tag">leadera</a>
|
||||
|
||||
<a href="../../tags/gantt/" class="tag">gantt</a>
|
||||
|
||||
<a href="../../tags/angular/" class="tag">angular</a>
|
||||
|
||||
<a href="../../tags/go/" class="tag">go</a>
|
||||
|
||||
<a href="../../tags/api/" class="tag">api</a>
|
||||
|
||||
<a href="../../tags/ux/" class="tag">ux</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<h2 id="бизнес-требования">Бизнес-требования</h2>
|
||||
<h3 id="br-1-лимит-одновременных-задач-concurrency-limit">BR-1: Лимит одновременных задач (Concurrency Limit)</h3>
|
||||
<p>У каждой секции появляется параметр <strong>max_concurrent_tasks</strong> (целое число ≥ 0, по умолчанию 0).</p>
|
||||
<p><strong>Поведение:</strong></p>
|
||||
<ul>
|
||||
<li>Если <code>max_concurrent_tasks = 3</code> — в любой данный день в этой секции не может быть больше 3 активных задач одновременно</li>
|
||||
<li>Если <code>max_concurrent_tasks = 0</code> — ограничение отключено, лимита нет</li>
|
||||
<li>Пересечение считается по дате: задача занимает дни с <code>start_date</code> по <code>end_date</code> включительно. Две задачи «пересекаются», если у них есть хотя бы один общий день</li>
|
||||
<li>Ограничение работает <strong>только в рамках одной секции</strong>. Задачи из разных секций не влияют друг на друга</li>
|
||||
</ul>
|
||||
<p><strong>Срабатывание при:</strong></p>
|
||||
<ol>
|
||||
<li>Создании задачи — если добавление нарушает лимит → Alert</li>
|
||||
<li>Перетаскивании задачи (drag) — если новая позиция нарушает лимит → Alert</li>
|
||||
<li>Растягивании задачи (resize) — если новый размер нарушает лимит → Alert</li>
|
||||
<li>Редактировании задачи (форма) — если изменённые даты нарушают лимит → Alert</li>
|
||||
</ol>
|
||||
<p><strong>Важно:</strong> Действие <strong>НЕ отменяется</strong>. Задача создаётся/перемещается в любом случае, но пользователь видит предупреждение.</p>
|
||||
<p><strong>Текст Alert:</strong> «В секции “[название секции]” на [дата/диапазон] превышен лимит одновременных задач (максимум: N)»</p>
|
||||
<hr>
|
||||
<h3 id="br-2-блоки-секций-section-blocks">BR-2: Блоки секций (Section Blocks)</h3>
|
||||
<p>У каждой секции появляется набор <strong>блоков</strong> — особый вид записей, отображаемых на таймлайне как заштрихованные области.</p>
|
||||
<p><strong>Сущность GanttSectionBlock:</strong></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Поле</th>
|
||||
<th>Тип</th>
|
||||
<th>Описание</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>id</td>
|
||||
<td>UUID</td>
|
||||
<td>Идентификатор</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>section_id</td>
|
||||
<td>UUID</td>
|
||||
<td>Принадлежность к секции</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>title</td>
|
||||
<td>string</td>
|
||||
<td>Название (например: «Отпуск», «Командировка»)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>start_date</td>
|
||||
<td>date</td>
|
||||
<td>Начало интервала (минимум 1 день)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>end_date</td>
|
||||
<td>date</td>
|
||||
<td>Конец интервала</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>block_concurrency</td>
|
||||
<td>boolean</td>
|
||||
<td>Запрещать ли пересечение обычных задач с данным блоком</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Валидация:</strong></p>
|
||||
<ul>
|
||||
<li><code>end_date</code> не может быть раньше <code>start_date</code></li>
|
||||
<li>Все поля обязательны</li>
|
||||
<li>Блок может быть в прошлом</li>
|
||||
</ul>
|
||||
<p><strong>Визуальное отображение на Ганте:</strong></p>
|
||||
<ul>
|
||||
<li>Заштрихованная область на <strong>всю высоту секции</strong> (включая все строки задач в секции)</li>
|
||||
<li>Название блока отображается <strong>поверх штриховки с подложкой</strong> (для читаемости)</li>
|
||||
</ul>
|
||||
<p><strong>Поведение block_concurrency:</strong></p>
|
||||
<ul>
|
||||
<li>Если <code>block_concurrency = true</code> — при пересечении задачи с данным блоком показывается Alert (аналогично BR-1), но задача <strong>всё равно создаётся/перемещается</strong></li>
|
||||
<li>Если <code>block_concurrency = false</code> — блок отображается визуально, но не влияет на задачи</li>
|
||||
</ul>
|
||||
<p><strong>Срабатывание при:</strong></p>
|
||||
<ol>
|
||||
<li>Создании задачи — пересекает блок с <code>block_concurrency = true</code> → Alert</li>
|
||||
<li>Перетаскивании задачи (drag) → Alert</li>
|
||||
<li>Растягивании задачи (resize) → Alert</li>
|
||||
<li>Редактировании задачи (форма) → Alert</li>
|
||||
</ol>
|
||||
<p><strong>Текст Alert:</strong> «В секции “[название секции]” задача пересекает блок “[название блока]” ([дата] — [дата])»</p>
|
||||
<hr>
|
||||
<h3 id="br-3-система-alert-ов">BR-3: Система Alert-ов</h3>
|
||||
<p>Все предупреждения (от BR-1 и BR-2) выводятся в <strong>единую область</strong> над диаграммой Ганта.</p>
|
||||
<p><strong>Поведение:</strong></p>
|
||||
<ul>
|
||||
<li>Alert-ы — Bootstrap Alert (warning), <strong>постоянные</strong></li>
|
||||
<li>Пользователь <strong>НЕ может</strong> закрыть Alert вручную</li>
|
||||
<li>Alert исчезает <strong>автоматически</strong>, когда текущая дата прошла дату конфликта (конфликт больше не актуален)</li>
|
||||
<li>Проверка конфликтов — <strong>только на фронтенде</strong> (на основе загруженных данных: задачи секции, блоки, max_concurrent_tasks)</li>
|
||||
<li>Если Alert-ов много — область <strong>сворачиваемая</strong> с счётчиком в бейдже (например: «⚠️ 3 предупреждения»)</li>
|
||||
<li>По умолчанию — развёрнуто</li>
|
||||
<li>Сворачивание/разворачивание — клик по заголовку области</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h3 id="br-4-настройки-секции">BR-4: Настройки секции</h3>
|
||||
<ul>
|
||||
<li>Настройки совмещены с <strong>существующим модальным окном редактирования секции</strong> (не отдельное окно)</li>
|
||||
</ul>
|
||||
<p><strong>Окно создания секции</strong> — добавляется:</p>
|
||||
<ul>
|
||||
<li>Поле «Макс. одновременных задач» (числовой ввод, 0 = без лимита, по умолчанию 0)</li>
|
||||
</ul>
|
||||
<p><strong>Окно редактирования секции</strong> — добавляется:</p>
|
||||
<ul>
|
||||
<li>Поле «Макс. одновременных задач» (числовой ввод, 0 = без лимита)</li>
|
||||
<li>Список блоков (таблица/список с CRUD: добавить, редактировать, удалить)
|
||||
<ul>
|
||||
<li><strong>Сортировка:</strong> по <code>start_date</code> по убыванию (будущее сверху)</li>
|
||||
<li>Каждый блок — форма: title, start_date, end_date, block_concurrency (чекбокс: «Запретить пересечение задач»)</li>
|
||||
<li>Валидация: end_date >= start_date, все поля заполнены</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h3 id="br-5-наследование">BR-5: Наследование</h3>
|
||||
<ul>
|
||||
<li>При появлении функционала копирования/дублирования диаграммы — настройки секций (лимит + блоки) наследуются</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="технические-требования">Технические требования</h2>
|
||||
<h3 id="база-данных">База данных</h3>
|
||||
<h4 id="новая-таблица-gantt_section_blocks">Новая таблица: gantt_section_blocks</h4>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">TABLE</span> gantt_section_blocks (
|
||||
</span></span><span style="display:flex;"><span> id UUID <span style="color:#66d9ef">PRIMARY</span> <span style="color:#66d9ef">KEY</span> <span style="color:#66d9ef">DEFAULT</span> gen_random_uuid(),
|
||||
</span></span><span style="display:flex;"><span> section_id UUID <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">REFERENCES</span> gantt_sections(id) <span style="color:#66d9ef">ON</span> <span style="color:#66d9ef">DELETE</span> <span style="color:#66d9ef">CASCADE</span>,
|
||||
</span></span><span style="display:flex;"><span> title VARCHAR(<span style="color:#ae81ff">255</span>) <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span>,
|
||||
</span></span><span style="display:flex;"><span> start_date DATE <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span>,
|
||||
</span></span><span style="display:flex;"><span> end_date DATE <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span>,
|
||||
</span></span><span style="display:flex;"><span> block_concurrency BOOLEAN <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">DEFAULT</span> <span style="color:#66d9ef">false</span>,
|
||||
</span></span><span style="display:flex;"><span> created_by UUID <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">REFERENCES</span> users(id),
|
||||
</span></span><span style="display:flex;"><span> updated_by UUID <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">REFERENCES</span> users(id),
|
||||
</span></span><span style="display:flex;"><span> created_at <span style="color:#66d9ef">TIMESTAMP</span> <span style="color:#66d9ef">WITH</span> TIME <span style="color:#66d9ef">ZONE</span> <span style="color:#66d9ef">DEFAULT</span> NOW(),
|
||||
</span></span><span style="display:flex;"><span> updated_at <span style="color:#66d9ef">TIMESTAMP</span> <span style="color:#66d9ef">WITH</span> TIME <span style="color:#66d9ef">ZONE</span> <span style="color:#66d9ef">DEFAULT</span> NOW(),
|
||||
</span></span><span style="display:flex;"><span> deleted_at <span style="color:#66d9ef">TIMESTAMP</span> <span style="color:#66d9ef">WITH</span> TIME <span style="color:#66d9ef">ZONE</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">CONSTRAINT</span> chk_block_dates <span style="color:#66d9ef">CHECK</span> (end_date <span style="color:#f92672">>=</span> start_date)
|
||||
</span></span><span style="display:flex;"><span>);
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">INDEX</span> idx_gantt_section_blocks_section <span style="color:#66d9ef">ON</span> gantt_section_blocks(section_id);
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">INDEX</span> idx_gantt_section_blocks_dates <span style="color:#66d9ef">ON</span> gantt_section_blocks(start_date, end_date);
|
||||
</span></span></code></pre></div><h4 id="изменение-таблицы-gantt_sections">Изменение таблицы: gantt_sections</h4>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">ALTER</span> <span style="color:#66d9ef">TABLE</span> gantt_sections <span style="color:#66d9ef">ADD</span> <span style="color:#66d9ef">COLUMN</span> max_concurrent_tasks INTEGER <span style="color:#66d9ef">NOT</span> <span style="color:#66d9ef">NULL</span> <span style="color:#66d9ef">DEFAULT</span> <span style="color:#ae81ff">0</span>;
|
||||
</span></span></code></pre></div><hr>
|
||||
<h3 id="backend-go-api">Backend (Go API)</h3>
|
||||
<h4 id="этап-1-миграция--домен">Этап 1: Миграция + Домен</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Добавь в проект новую таблицу <code>gantt_section_blocks</code> и колонку <code>max_concurrent_tasks</code> в <code>gantt_sections</code>.</p>
|
||||
<ol>
|
||||
<li>Создай миграцию в <code>cmd/migrate/</code>:
|
||||
<ul>
|
||||
<li>Новая таблица <code>gantt_section_blocks</code> с полями: id (UUID PK), section_id (UUID FK → gantt_sections, ON DELETE CASCADE), title (VARCHAR 255 NOT NULL), start_date (DATE NOT NULL), end_date (DATE NOT NULL), block_concurrency (BOOLEAN DEFAULT false), created_by (UUID FK → users), updated_by (UUID FK → users), created_at, updated_at, deleted_at. CHECK constraint: end_date >= start_date. Индексы по section_id и (start_date, end_date).</li>
|
||||
<li>ALTER TABLE gantt_sections ADD COLUMN max_concurrent_tasks INTEGER NOT NULL DEFAULT 0.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Создай доменную модель <code>GanttSectionBlock</code> в <code>internal/domain/gantt.go</code> со всеми полями таблицы.</li>
|
||||
<li>Добавь поле <code>MaxConcurrentTasks int</code> в структуру <code>GanttSection</code>.</li>
|
||||
<li>Обнови маппинг в relevant repository файлах, чтобы новое поле <code>max_concurrent_tasks</code> читалось/писалось.</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<h4 id="этап-2-crud-для-ganttsectionblocks">Этап 2: CRUD для GanttSectionBlocks</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Реализуй полный CRUD для сущности <code>GanttSectionBlock</code> по аналогии с существующими handlers/services/repositories в проекте.</p>
|
||||
<p><strong>Роуты (внутри группы секции):</strong></p>
|
||||
<ul>
|
||||
<li><code>GET /api/gantt-charts/:chartId/sections/:sectionId/blocks</code> — список блоков секции</li>
|
||||
<li><code>POST /api/gantt-charts/:chartId/sections/:sectionId/blocks</code> — создать блок</li>
|
||||
<li><code>PUT /api/gantt-charts/:chartId/sections/:sectionId/blocks/:blockId</code> — обновить блок</li>
|
||||
<li><code>DELETE /api/gantt-charts/:chartId/sections/:sectionId/blocks/:blockId</code> — удалить блок (soft delete)</li>
|
||||
</ul>
|
||||
<p><strong>Repository:</strong> <code>internal/repository/gantt_section_block_repository.go</code></p>
|
||||
<ul>
|
||||
<li><code>GetBySectionID(ctx, sectionID) ([]domain.GanttSectionBlock, error)</code></li>
|
||||
<li><code>GetByID(ctx, id) (*domain.GanttSectionBlock, error)</code></li>
|
||||
<li><code>Create(ctx, block) error</code></li>
|
||||
<li><code>Update(ctx, block) error</code></li>
|
||||
<li><code>Delete(ctx, id) error</code> — soft delete (set deleted_at)</li>
|
||||
<li>Все запросы — raw SQL через pgx, как в остальных репозиториях проекта</li>
|
||||
</ul>
|
||||
<p><strong>Service:</strong> <code>internal/service/gantt_section_block_service.go</code></p>
|
||||
<ul>
|
||||
<li>Бизнес-логика: валидация dates (end >= start), проверка прав доступа к секции</li>
|
||||
<li>Inject repository</li>
|
||||
</ul>
|
||||
<p><strong>Handler:</strong> <code>internal/handler/gantt_section_block_handler.go</code></p>
|
||||
<ul>
|
||||
<li>Swagger-аннотации для всех эндпоинтов</li>
|
||||
<li>Валидация входных данных</li>
|
||||
<li>Ошибки в формате проекта (GanttErrorResponse)</li>
|
||||
</ul>
|
||||
<p><strong>Модели запросов:</strong></p>
|
||||
<ul>
|
||||
<li>Create: title (required), start_date (required), end_date (required), block_concurrency (bool, default false)</li>
|
||||
<li>Update: title, start_date, end_date, block_concurrency — все опциональны</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h4 id="этап-3-обновление-настроек-секции">Этап 3: Обновление настроек секции</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Обнови CRUD секций (gantt_sections) для поддержки нового поля <code>max_concurrent_tasks</code>.</p>
|
||||
<ol>
|
||||
<li>Добавь <code>max_concurrent_tasks</code> в <code>GanttSectionCreateRequest</code> (опциональное, int ≥ 0, default 0)</li>
|
||||
<li>Добавь <code>max_concurrent_tasks</code> в <code>GanttSectionUpdateRequest</code> (опциональное, int ≥ 0)</li>
|
||||
<li>Обнови SQL-запросы в repository: INSERT и UPDATE должны включать <code>max_concurrent_tasks</code></li>
|
||||
<li>При GET секции (или списке секций) — возвращать <code>max_concurrent_tasks</code> в ответе</li>
|
||||
<li>Валидация: значение должно быть ≥ 0</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<h4 id="этап-4-включение-блоков-в-ответ-секций">Этап 4: Включение блоков в ответ секций</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>При запросе списка секций или одной секции включай связанные блоки в ответ.</p>
|
||||
<ol>
|
||||
<li>Обнови <code>GET /api/gantt-charts/:chartId/sections/:sectionId</code> — добавить поле <code>blocks</code> с массивом GanttSectionBlock</li>
|
||||
<li>Обнови <code>GET /api/gantt-charts/:chartId/sections</code> — добавить поле <code>blocks</code> для каждой секции</li>
|
||||
<li>Блоки с <code>deleted_at IS NOT NULL</code> не возвращаются</li>
|
||||
<li>Блоки сортируются по start_date по убыванию (будущее сверху)</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h3 id="frontend-angular">Frontend (Angular)</h3>
|
||||
<h4 id="этап-fe-1-модели--сервис">Этап FE-1: Модели + Сервис</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Добавь в проект поддержку ограничений секций Ганта.</p>
|
||||
<ol>
|
||||
<li>В <code>pages/gantt/models/gantt-chart.model.ts</code> добавь:</li>
|
||||
</ol>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">GanttSectionBlock</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">id</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">section_id</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">title</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">start_date</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">end_date</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">block_concurrency</span>: <span style="color:#66d9ef">boolean</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">created_by_user</span>: <span style="color:#66d9ef">UserInfo</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">updated_by_user</span>: <span style="color:#66d9ef">UserInfo</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">created_at</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">updated_at</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">GanttSectionBlockCreateRequest</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">title</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">start_date</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">end_date</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">block_concurrency?</span>: <span style="color:#66d9ef">boolean</span>;
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">GanttSectionBlockUpdateRequest</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">title?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">start_date?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">end_date?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">block_concurrency?</span>: <span style="color:#66d9ef">boolean</span>;
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ConflictCheck</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">has_conflicts</span>: <span style="color:#66d9ef">boolean</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">conflicts</span>: <span style="color:#66d9ef">ConflictItem</span>[];
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span><span style="display:flex;"><span>
|
||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ConflictItem</span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">type</span><span style="color:#f92672">:</span> <span style="color:#e6db74">'concurrency'</span> <span style="color:#f92672">|</span> <span style="color:#e6db74">'block'</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">section_id</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">section_title</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">block_title?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">start_date?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">end_date?</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">message</span>: <span style="color:#66d9ef">string</span>;
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">dates?</span>: <span style="color:#66d9ef">string</span>[];
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><ol start="2">
|
||||
<li>
|
||||
<p>Добавь <code>max_concurrent_tasks: number</code> в интерфейс <code>GanttSection</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Добавь <code>blocks: GanttSectionBlock[]</code> в интерфейс <code>GanttSection</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Добавь <code>max_concurrent_tasks?: number</code> в <code>GanttSectionCreateRequest</code> и <code>GanttSectionUpdateRequest</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Создай сервис <code>pages/gantt/services/gantt-section-block.service.ts</code>:</p>
|
||||
</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>Inject HttpClient</li>
|
||||
<li>Методы: getBlocks(chartId, sectionId), createBlock(chartId, sectionId, data), updateBlock(chartId, sectionId, blockId, data), deleteBlock(chartId, sectionId, blockId)</li>
|
||||
<li>Все методы возвращают Observable с типизированными ответами (по аналогии с GanttChartService)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h4 id="этап-fe-2-интеграция-в-модальные-окна-секции">Этап FE-2: Интеграция в модальные окна секции</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Интегрируй настройки ограничений в существующие модальные окна создания и редактирования секции Ганта.</p>
|
||||
<ol>
|
||||
<li>Найди существующие компоненты модальных окон секции (создание/редактирование).</li>
|
||||
</ol>
|
||||
<p><strong>Окно создания секции</strong> — добавить:</p>
|
||||
<ul>
|
||||
<li>Числовой ввод: «Максимум одновременных задач»</li>
|
||||
<li>Подсказка: «0 = без ограничений»</li>
|
||||
<li>Валидация: число ≥ 0</li>
|
||||
<li>Значение по умолчанию: 0</li>
|
||||
<li>Отправляется в <code>GanttSectionCreateRequest</code> как <code>max_concurrent_tasks</code></li>
|
||||
</ul>
|
||||
<p><strong>Окно редактирования секции</strong> — добавить:</p>
|
||||
<ul>
|
||||
<li>Числовой ввод: «Максимум одновременных задач» (аналогично созданию)</li>
|
||||
<li>Секция «Блоки (запретные интервалы)»:
|
||||
<ul>
|
||||
<li>Таблица/список существующих блоков с колонками: Название, Начало, Конец, Блокировка (чекбокс/иконка), Действия (редактировать/удалить)</li>
|
||||
<li><strong>Сортировка:</strong> по <code>start_date</code> по убыванию (будущее сверху)</li>
|
||||
<li>Кнопка «Добавить блок» — inline-форма:
|
||||
<ul>
|
||||
<li>title (текстовый ввод, обязательный)</li>
|
||||
<li>start_date (datepicker, обязательный)</li>
|
||||
<li>end_date (datepicker, обязательный)</li>
|
||||
<li>block_concurrency (чекбокс: «Запретить пересечение задач»)</li>
|
||||
<li>Валидация: end_date >= start_date, все поля заполнены</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Редактирование — inline или через ту же форму</li>
|
||||
<li>Удаление — с подтверждением</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ol start="2">
|
||||
<li>При открытии окна редактирования — загрузить текущие настройки секции + блоки</li>
|
||||
<li>При сохранении — обновить max_concurrent_tasks и сохранить изменения блоков</li>
|
||||
<li>Инжектировать GanttChartService и GanttSectionBlockService</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<h4 id="этап-fe-3-визуализация-блоков-на-ганте">Этап FE-3: Визуализация блоков на Ганте</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Отобрази блоки секций (GanttSectionBlock) на canvas-диаграмме Ганта.</p>
|
||||
<p>Проект использует Konva.js для рендеринга. Основной компонент: <code>gantt-chart-canvas</code>.</p>
|
||||
<ol>
|
||||
<li>При загрузке данных диаграммы — извлечь блоки из каждой секции</li>
|
||||
<li>В рендерере секций (canvas/timeline-renderer.ts или аналогичный) — для каждого блока:
|
||||
<ul>
|
||||
<li>Нарисовать заштрихованную область (diagonal hatch pattern) на <strong>всю высоту секции</strong> (все строки задач в этой секции)</li>
|
||||
<li>Область ограничена по горизонтали: от start_date до end_date (в пикселях по шкале времени)</li>
|
||||
<li>Цвет штриховки: полупрозрачный серый или configurable</li>
|
||||
<li>Поверх штриховки — текст с названием блока (block.title) на подложке (прямоугольник с фоном, чтобы текст читался)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Блоки рендерятся <strong>до</strong> задач (z-index ниже), чтобы задачи были поверх</li>
|
||||
<li>Блоки с <code>block_concurrency = true</code> и <code>false</code> визуально не отличаются (штриховка одинаковая)</li>
|
||||
<li>При скролле/зуме — блоки пересчитываются как обычные элементы таймлайна</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<h4 id="этап-fe-4-система-alert-ов">Этап FE-4: Система Alert-ов</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Создай компонент для отображения Alert-ов о конфликтах на диаграмме Ганта.</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Создай компонент <code>pages/gantt/components/gantt-conflict-alerts/</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Компонент размещается <strong>над</strong> canvas-диаграммой Ганта</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Входные данные: массив <code>ConflictItem[]</code> (из модели)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Визуал:</p>
|
||||
<ul>
|
||||
<li>Bootstrap Alert (warning) для каждого конфликта</li>
|
||||
<li>Каждый Alert показывает message из ConflictItem</li>
|
||||
<li><strong>Без кнопки закрытия</strong> — Alert нельзя закрыть вручную</li>
|
||||
<li>Alert исчезает автоматически, когда текущая дата прошла дату конфликта</li>
|
||||
<li>Область <strong>сворачиваемая</strong>: заголовок «⚠️ Предупреждения (N)» — клик сворачивает/разворачивает список</li>
|
||||
<li>По умолчанию — развёрнуто</li>
|
||||
<li>При 0 конфликтов — область скрыта</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>Состояние хранится в сервисе или в компоненте диаграммы:</p>
|
||||
<ul>
|
||||
<li>Добавление нового конфликта → area auto-expands</li>
|
||||
<li>Alert удаляется из массива <strong>автоматически</strong>, когда текущая дата прошла дату конфликта</li>
|
||||
<li>Проверка актуальности конфликтов — при каждой отрисовке / изменении данных</li>
|
||||
<li>Не использовать toast — Alert-ы постоянные</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<h4 id="этап-fe-5-проверка-конфликтов-при-операциях-с-задачами">Этап FE-5: Проверка конфликтов при операциях с задачами</h4>
|
||||
<p><strong>Промт для агента:</strong></p>
|
||||
<blockquote>
|
||||
<p>Интегрируй проверку конфликтов во все операции с задачами на диаграмме Ганта.</p>
|
||||
<p>Проект использует interaction-handler.ts для drag/resize и формы для создания/редактирования.</p>
|
||||
<p><strong>Важно:</strong> Проверка конфликтов — <strong>только на фронтенде</strong>, без вызова API. Используются загруженные данные секции (задачи, блоки, max_concurrent_tasks).</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Вынеси логику проверки конфликтов <code>checkConflicts()</code> в отдельный метод в gantt-canvas.service.ts:</p>
|
||||
<ul>
|
||||
<li>Принимает: section (GanttSection — содержит max_concurrent_tasks и blocks), tasks (GanttTask[] — задачи секции), task_id (nullable — исключить текущую задачу), start_date, end_date</li>
|
||||
<li>Логика:
|
||||
a. Если section.max_concurrent_tasks > 0: посчитать кол-во задач (исключая task_id), пересекающихся с [start_date, end_date] на каждый день. Если в любой день count > max_concurrent_tasks — добавить конфликт concurrency
|
||||
b. Для каждого блока секции с block_concurrency = true, пересекающегося с [start_date, end_date] — добавить конфликт block</li>
|
||||
<li>Возвращает ConflictCheck</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>После <strong>каждой</strong> успешной операции с задачей (создание, обновление, drag, resize):</p>
|
||||
<ul>
|
||||
<li>Вызвать checkConflicts с параметрами задачи</li>
|
||||
<li>Если has_conflicts = true — передать конфликты в GanttConflictAlertsComponent</li>
|
||||
<li>Alert-ы показываются, действие <strong>НЕ отменяется</strong></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>Точки интеграции:</p>
|
||||
<ul>
|
||||
<li><strong>Создание задачи</strong> (форма): после успешного POST → checkConflicts → show alerts</li>
|
||||
<li><strong>Редактирование задачи</strong> (форма): после успешного PUT → checkConflicts → show alerts</li>
|
||||
<li><strong>Drag задачи</strong> (interaction-handler.ts): после успешного обновления позиции → checkConflicts → show alerts</li>
|
||||
<li><strong>Resize задачи</strong> (interaction-handler.ts): после успешного обновления размера → checkConflicts → show alerts</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p>При переключении диаграммы или секции — очищать Alert-ы</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Alert-ы автоматически удаляются, когда текущая дата прошла дату конфликта — область скрывается, когда конфликтов не осталось</p>
|
||||
</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h2 id="порядок-реализации">Порядок реализации</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Этап</th>
|
||||
<th>Сторона</th>
|
||||
<th>Зависимости</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Миграция + Домен</td>
|
||||
<td>Backend</td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>CRUD блоков</td>
|
||||
<td>Backend</td>
|
||||
<td>Этап 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Обновление настроек секции</td>
|
||||
<td>Backend</td>
|
||||
<td>Этап 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Включение блоков в ответ секций</td>
|
||||
<td>Backend</td>
|
||||
<td>Этап 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Модели + Сервис</td>
|
||||
<td>Frontend</td>
|
||||
<td>— (можно параллельно с backend)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>Интеграция в модальные окна</td>
|
||||
<td>Frontend</td>
|
||||
<td>Этапы 5 + backend 2,3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td>Визуализация блоков на Ганте</td>
|
||||
<td>Frontend</td>
|
||||
<td>Этапы 5 + backend 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td>Система Alert-ов</td>
|
||||
<td>Frontend</td>
|
||||
<td>Этап 5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9</td>
|
||||
<td>Проверка конфликтов при операциях</td>
|
||||
<td>Frontend</td>
|
||||
<td>Этапы 5,7,8</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
+48
-74
@@ -27,33 +27,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="./semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="./semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="./personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -88,25 +102,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="./yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="./semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -124,9 +128,9 @@
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Дневник</h3>
|
||||
<p class="card-text">Записи по датам о событиях и обсуждениях.</p>
|
||||
<a href="./diary/" class="btn btn-outline-primary">Открыть</a>
|
||||
<h3 class="card-title">Яша</h3>
|
||||
<p class="card-text">Дневник, база знаний, планы, инструкции, креды, Leadera, личный сайт.</p>
|
||||
<a href="./yasha/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,39 +138,9 @@
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">База знаний</h3>
|
||||
<p class="card-text">Статьи и документация по различным темам.</p>
|
||||
<a href="./kb/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Планы</h3>
|
||||
<p class="card-text">Запланированные задачи и их статус.</p>
|
||||
<a href="./plans/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Инструкции</h3>
|
||||
<p class="card-text">Пошаговые инструкции для различных задач.</p>
|
||||
<a href="./guides/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Креды</h3>
|
||||
<p class="card-text">Зашифрованные учётные данные (требуется мастер-пароль).</p>
|
||||
<a href="./creds/" class="btn btn-outline-primary">Открыть</a>
|
||||
<h3 class="card-title">Семен</h3>
|
||||
<p class="card-text">История изменений, база знаний, дневник.</p>
|
||||
<a href="./semen/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+10
-5
@@ -38,11 +38,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
resultsList.innerHTML = results.map(result => {
|
||||
const item = result.item;
|
||||
const sectionLabels = {
|
||||
'diary': 'Дневник',
|
||||
'kb': 'База знаний',
|
||||
'plans': 'Планы',
|
||||
'guides': 'Инструкции',
|
||||
'creds': 'Креды'
|
||||
'yasha/diary': 'Яша / Дневник',
|
||||
'yasha/kb': 'Яша / База знаний',
|
||||
'yasha/plans': 'Яша / Планы',
|
||||
'yasha/guides': 'Яша / Инструкции',
|
||||
'yasha/creds': 'Яша / Креды',
|
||||
'yasha/leadera': 'Яша / Leadera',
|
||||
'yasha/personal-site': 'Яша / Личный сайт',
|
||||
'semen': 'Семен',
|
||||
'semen/diary': 'Семен / Дневник',
|
||||
'semen/kb': 'Семен / База знаний'
|
||||
};
|
||||
const label = sectionLabels[item.section] || item.section;
|
||||
return `<li>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,166 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Личный сайт (agaltsovav.ru) — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../diary/">Дневник</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../kb/">База знаний</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Личный сайт (agaltsovav.ru)</h1>
|
||||
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../personal-site/netlify-node-version/">Устаревший Node.js 16 в Netlify</a></li>
|
||||
|
||||
<li><a href="../personal-site/no-node-modules/">Отсутствуют node_modules — нужна установка</a></li>
|
||||
|
||||
<li><a href="../personal-site/binary-files-in-repo/">Бинарный файл в репозитории</a></li>
|
||||
|
||||
<li><a href="../personal-site/no-analytics/">Yandex Metrika отключена</a></li>
|
||||
|
||||
<li><a href="../personal-site/twitter-handle-mismatch/">Twitter handle не соответствует имени</a></li>
|
||||
|
||||
<li><a href="../personal-site/outdated-doks-theme/">Hugo Doks 0.5 — сильно устарел</a></li>
|
||||
|
||||
<li><a href="../personal-site/digest-stale/">Digest не обновлялся с февраля 2025</a></li>
|
||||
|
||||
<li><a href="../personal-site/copyright-outdated/">Copyright без 2026 года</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../js/search.js"></script>
|
||||
<script src="../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,161 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>История изменений — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>История изменений</h1>
|
||||
<div class="source-path mb-3">
|
||||
<small class="text-muted">
|
||||
📁 <code id="source-path" class="user-select-all">~/Projects/docs-a2v/content/semen/changelog.md</code>
|
||||
<button class="btn btn-sm btn-outline-secondary ms-1 py-0 px-1" onclick="navigator.clipboard.writeText('~/Projects/docs-a2v/content/semen\/changelog.md')" title="Копировать путь">
|
||||
📋
|
||||
</button>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,159 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Дневник — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/diary/">Все записи</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Дневник</h1>
|
||||
|
||||
<div class="diary-timeline">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,184 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Семен — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>Семен</h1>
|
||||
<p class="lead">Документация Семена.</p>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">История изменений</h3>
|
||||
<p class="card-text">Лог изменений и обновлений.</p>
|
||||
<a href="../semen/changelog/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">База знаний</h3>
|
||||
<p class="card-text">Статьи и документация по различным темам.</p>
|
||||
<a href="../semen/kb/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Дневник</h3>
|
||||
<p class="card-text">Записи по датам о событиях и обсуждениях.</p>
|
||||
<a href="../semen/diary/" class="btn btn-outline-primary">Открыть</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../js/search.js"></script>
|
||||
<script src="../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
[{"content":"","section":"semen","tags":[],"title":"История изменений","url":"/semen/changelog/"},{"content":"","section":"semen","tags":null,"title":"База знаний","url":"/semen/kb/"},{"content":"","section":"semen","tags":null,"title":"Дневник","url":"/semen/diary/"}]
|
||||
@@ -0,0 +1,159 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru-ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>База знаний — docs.a2v.space</title>
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../../css/custom.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="../../">docs.a2v.space</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain" aria-controls="navbarMain" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<form class="d-flex search-form" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Поиск..." aria-label="Search" id="search-input">
|
||||
<button class="btn btn-outline-light" type="submit">Найти</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-light d-md-none ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-expanded="false" aria-controls="sidebar">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="search-results" class="search-results" style="display: none;">
|
||||
<div class="search-results-content">
|
||||
<button type="button" class="btn-close float-end" id="close-search"></button>
|
||||
<h5>Результаты поиска</h5>
|
||||
<ul id="results-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Фильтры</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/kb/">Все статьи</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
|
||||
<main class="col-md-9 col-lg-10 main-content">
|
||||
|
||||
<div class="article-content">
|
||||
<h1>База знаний</h1>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p class="text-center mb-0">© 2026 docs.a2v.space</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
|
||||
|
||||
|
||||
<script src="../../js/search.js"></script>
|
||||
<script src="../../js/creds.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
+64
-51
@@ -2,29 +2,35 @@
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
<url>
|
||||
<loc>/leadera/</loc>
|
||||
<loc>/yasha/leadera/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/</loc>
|
||||
<loc>/yasha/personal-site/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-audit/</loc>
|
||||
<loc>/yasha/leadera/leadera-audit/</loc>
|
||||
<lastmod>2026-03-30T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-websocket-gantt/</loc>
|
||||
<loc>/yasha/leadera/leadera-websocket-gantt/</loc>
|
||||
<lastmod>2026-04-07T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-gantt-excel-export/</loc>
|
||||
<loc>/yasha/leadera/leadera-gantt-excel-export/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-gantt-filters/</loc>
|
||||
<loc>/yasha/leadera/leadera-gantt-filters/</loc>
|
||||
<lastmod>2026-04-07T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-gantt-public-access/</loc>
|
||||
<loc>/yasha/leadera/leadera-gantt-public-access/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
<lastmod>2026-04-26T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/semen/changelog/</loc>
|
||||
<lastmod>2026-04-26T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/semen/</loc>
|
||||
<lastmod>2026-04-26T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/excel/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
@@ -46,6 +52,9 @@
|
||||
</url><url>
|
||||
<loc>/tags/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/yasha/</loc>
|
||||
<lastmod>2026-04-09T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/angular/</loc>
|
||||
<lastmod>2026-04-08T00:00:00+00:00</lastmod>
|
||||
@@ -56,7 +65,7 @@
|
||||
<loc>/tags/go/</loc>
|
||||
<lastmod>2026-04-08T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-milestones/</loc>
|
||||
<loc>/yasha/leadera/leadera-milestones/</loc>
|
||||
<lastmod>2026-04-08T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/ux/</loc>
|
||||
@@ -77,10 +86,10 @@
|
||||
<loc>/tags/websocket/</loc>
|
||||
<lastmod>2026-04-07T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/leadera/leadera-section-constraints/</loc>
|
||||
<loc>/yasha/leadera/leadera-section-constraints/</loc>
|
||||
<lastmod>2026-04-06T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/diary/2026-03-31/</loc>
|
||||
<loc>/yasha/diary/2026-03-31/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/audit/</loc>
|
||||
@@ -89,13 +98,10 @@
|
||||
<loc>/tags/canvas/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/copyright-outdated/</loc>
|
||||
<loc>/yasha/personal-site/copyright-outdated/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/diary/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/digest-stale/</loc>
|
||||
<loc>/yasha/personal-site/digest-stale/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/github/</loc>
|
||||
@@ -104,7 +110,7 @@
|
||||
<loc>/tags/hugo/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/outdated-doks-theme/</loc>
|
||||
<loc>/yasha/personal-site/outdated-doks-theme/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/infrastructure/</loc>
|
||||
@@ -122,22 +128,25 @@
|
||||
<loc>/tags/system-utils/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/twitter-handle-mismatch/</loc>
|
||||
<loc>/yasha/personal-site/twitter-handle-mismatch/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/no-analytics/</loc>
|
||||
<loc>/yasha/personal-site/no-analytics/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/binary-files-in-repo/</loc>
|
||||
<loc>/yasha/personal-site/binary-files-in-repo/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/no-node-modules/</loc>
|
||||
<loc>/yasha/diary/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/personal-site/netlify-node-version/</loc>
|
||||
<loc>/yasha/personal-site/no-node-modules/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/diary/2026-03-30/</loc>
|
||||
<loc>/yasha/personal-site/netlify-node-version/</loc>
|
||||
<lastmod>2026-03-31T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/yasha/diary/2026-03-30/</loc>
|
||||
<lastmod>2026-03-30T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/mtproxy/</loc>
|
||||
@@ -158,7 +167,7 @@
|
||||
<loc>/tags/vikunja/</loc>
|
||||
<lastmod>2026-03-30T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/diary/2026-03-29/</loc>
|
||||
<loc>/yasha/diary/2026-03-29/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/amnezia/</loc>
|
||||
@@ -169,9 +178,6 @@
|
||||
</url><url>
|
||||
<loc>/tags/companion/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/database/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
@@ -188,34 +194,28 @@
|
||||
<loc>/tags/docs/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/docs-a2v-space-auth/</loc>
|
||||
<loc>/yasha/creds/docs-a2v-space-auth/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/eversolo/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/eversolo-companion-postgres/</loc>
|
||||
<loc>/yasha/creds/eversolo-companion-postgres/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/kb/eversolo-api/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/guides/</loc>
|
||||
<loc>/yasha/kb/eversolo-api/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/identity/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/kb/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/llm/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/leadera-db-docker/</loc>
|
||||
<loc>/yasha/creds/leadera-db-docker/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/leadera-db-local/</loc>
|
||||
<loc>/yasha/creds/leadera-db-local/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/music/</loc>
|
||||
@@ -226,9 +226,6 @@
|
||||
</url><url>
|
||||
<loc>/tags/openclaw/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/plans/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/postgresql/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
@@ -242,7 +239,7 @@
|
||||
<loc>/tags/ssh/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/guides/ssh-tunnels-vps/</loc>
|
||||
<loc>/yasha/guides/ssh-tunnels-vps/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/streamer/</loc>
|
||||
@@ -254,38 +251,54 @@
|
||||
<loc>/tags/vpn/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/vpn-vps/</loc>
|
||||
<loc>/yasha/creds/vpn-vps/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/tags/vps/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/creds/vps-reg-ru/</loc>
|
||||
<loc>/yasha/creds/vps-reg-ru/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/plans/eversolo-companion-phases-3-9/</loc>
|
||||
<loc>/yasha/kb/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/plans/ollama-openclaw/</loc>
|
||||
<loc>/yasha/plans/eversolo-companion-phases-3-9/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/guides/vps-reverse-proxy/</loc>
|
||||
<loc>/yasha/guides/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/guides/claw-a2v-space/</loc>
|
||||
<loc>/yasha/creds/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/guides/code-a2v-space/</loc>
|
||||
<loc>/yasha/plans/ollama-openclaw/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/guides/sand-a2v-space/</loc>
|
||||
<loc>/yasha/guides/vps-reverse-proxy/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/plans/eversolo-control/</loc>
|
||||
<loc>/yasha/plans/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/yasha/guides/claw-a2v-space/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/yasha/guides/code-a2v-space/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/yasha/guides/sand-a2v-space/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/yasha/plans/eversolo-control/</loc>
|
||||
<lastmod>2026-03-29T00:00:00+00:00</lastmod>
|
||||
</url><url>
|
||||
<loc>/categories/</loc>
|
||||
</url><url>
|
||||
<loc>/statuses/</loc>
|
||||
</url><url>
|
||||
<loc>/semen/kb/</loc>
|
||||
</url><url>
|
||||
<loc>/semen/diary/</loc>
|
||||
</url>
|
||||
</urlset>
|
||||
|
||||
+42
-38
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,7 +125,7 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../creds/vpn-vps/">VPN VPS</a></li>
|
||||
<li><a href="../../yasha/creds/vpn-vps/">VPN VPS</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<atom:link href="/tags/amnezia/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>VPN VPS</title>
|
||||
<link>/creds/vpn-vps/</link>
|
||||
<link>/yasha/creds/vpn-vps/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/vpn-vps/</guid>
|
||||
<guid>/yasha/creds/vpn-vps/</guid>
|
||||
<description>YEI16NAJ78d3lmSa/lca8Zxczt+u6GyMUYHduX47VoFQdj0Ixozd8R6yXoB7eM+AjhCtNGkOxGlOj2s73ABOBjLEIVIhD4Z+xTyzdtah4VpyLoltYOeNYsnbIIFARdF/FBYq5COXohhXs33K5ozznrtDd/awbKMjl/sbQqjXAZ+A3ZSob6/5uU+fFKetXLR6v4ZLAYQ57iiD21ImSLSggwv+rJgK5XyPDKEPD4N5nOsiDrLgoukVBMvgJ54PqfPp2Hni+2tdKOlMnOG2npTuu4SkyALcfFar</description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,15 +125,15 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../leadera/leadera-milestones/">Leadera: Вехи (Milestones) на диаграмме Ганта</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-milestones/">Leadera: Вехи (Milestones) на диаграмме Ганта</a></li>
|
||||
|
||||
<li><a href="../../leadera/leadera-section-constraints/">Leadera: Ограничения секций в диаграмме Ганта</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-section-constraints/">Leadera: Ограничения секций в диаграмме Ганта</a></li>
|
||||
|
||||
<li><a href="../../guides/sand-a2v-space/">Подключение sand.a2v.space (Leadera Project)</a></li>
|
||||
<li><a href="../../yasha/guides/sand-a2v-space/">Подключение sand.a2v.space (Leadera Project)</a></li>
|
||||
|
||||
<li><a href="../../plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
<li><a href="../../yasha/plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
|
||||
<li><a href="../../diary/2026-03-29/">29 марта 2026</a></li>
|
||||
<li><a href="../../yasha/diary/2026-03-29/">29 марта 2026</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
+47
-43
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,15 +125,15 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../leadera/leadera-milestones/">Leadera: Вехи (Milestones) на диаграмме Ганта</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-milestones/">Leadera: Вехи (Milestones) на диаграмме Ганта</a></li>
|
||||
|
||||
<li><a href="../../leadera/leadera-gantt-filters/">Leadera — Фильтры и реорганизация списка диаграмм Ганта</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-gantt-filters/">Leadera — Фильтры и реорганизация списка диаграмм Ганта</a></li>
|
||||
|
||||
<li><a href="../../leadera/leadera-section-constraints/">Leadera: Ограничения секций в диаграмме Ганта</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-section-constraints/">Leadera: Ограничения секций в диаграмме Ганта</a></li>
|
||||
|
||||
<li><a href="../../plans/eversolo-control/">Реализовать управление Eversolo из OpenClaw</a></li>
|
||||
<li><a href="../../yasha/plans/eversolo-control/">Реализовать управление Eversolo из OpenClaw</a></li>
|
||||
|
||||
<li><a href="../../kb/eversolo-api/">Eversolo T8 API</a></li>
|
||||
<li><a href="../../yasha/kb/eversolo-api/">Eversolo T8 API</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
+10
-10
@@ -10,37 +10,37 @@
|
||||
<atom:link href="/tags/api/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>Leadera — Фильтры и реорганизация списка диаграмм Ганта</title>
|
||||
<link>/leadera/leadera-gantt-filters/</link>
|
||||
<link>/yasha/leadera/leadera-gantt-filters/</link>
|
||||
<pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/leadera/leadera-gantt-filters/</guid>
|
||||
<guid>/yasha/leadera/leadera-gantt-filters/</guid>
|
||||
<description><h1 id="фильтры-и-реорганизация-списка-диаграмм-ганта">Фильтры и реорганизация списка диаграмм Ганта</h1>
<p><strong>Дата:</strong> 07.04.2026
<strong>Статус:</strong> Требования
<strong>Проект:</strong> Leadera (dev — sand.a2v.space)</p>
<hr>
<h2 id="1-постановка-задачи">1. Постановка задачи</h2>
<p>Список диаграмм Ганта должен показывать <strong>все доступные пользователю диаграммы</strong> из всех пространств (spaces), с возможностью фильтрации и поиска. Сейчас список привязан к одному пространству — нужно убрать эту зависимость и добавить удобный toolbar.</p>
<hr>
<h2 id="2-изменения-api">2. Изменения API</h2>
<h3 id="21-новый-endpoint-списка-диаграмм">2.1. Новый endpoint списка диаграмм</h3>
<p><strong>Было:</strong></p>
<pre tabindex="0"><code>GET /api/v1/spaces/{spaceId}/gantt-charts?page=1&amp;per_page=10
</code></pre><p><strong>Стало:</strong></p>
<pre tabindex="0"><code>GET /api/v1/gantt-charts?page=1&amp;per_page=10
</code></pre><p>Пользователь видит все диаграммы из <strong>всех пространств</strong>, где он является подтверждённым участником (статус <code>accepted</code>).</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Leadera: Вехи (Milestones) на диаграмме Ганта</title>
|
||||
<link>/leadera/leadera-milestones/</link>
|
||||
<link>/yasha/leadera/leadera-milestones/</link>
|
||||
<pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/leadera/leadera-milestones/</guid>
|
||||
<guid>/yasha/leadera/leadera-milestones/</guid>
|
||||
<description><h2 id="бизнес-требования">Бизнес-требования</h2>
<h3 id="br-1-сущность-веха-milestone">BR-1: Сущность «Веха» (Milestone)</h3>
<p>Веха — это маркер на таймлайне диаграммы Ганта, обозначающий важную дату в проекте. В отличие от задач, веха не имеет длительности и привязана к конкретной дате.</p>
<p><strong>Поля вехи:</strong></p>
<table>
 <thead>
 <tr>
 <th>Поле</th>
 <th>Тип</th>
 <th>Описание</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>id</td>
 <td>UUID</td>
 <td>Идентификатор</td>
 </tr>
 <tr>
 <td>gantt_chart_id</td>
 <td>UUID</td>
 <td>Принадлежность к диаграмме (не к секции!)</td>
 </tr>
 <tr>
 <td>title</td>
 <td>string</td>
 <td>Название вехи (обязательное, 1–255 символов)</td>
 </tr>
 <tr>
 <td>date</td>
 <td>date</td>
 <td>Дата вехи (без времени, обязательная)</td>
 </tr>
 <tr>
 <td>color</td>
 <td>string</td>
 <td>Цвет маркера (HEX, по умолчанию <code>#dc3545</code> — красный)</td>
 </tr>
 <tr>
 <td>created_by</td>
 <td>UUID</td>
 <td>Кто создал (не отображается в UI, хранится для аудита)</td>
 </tr>
 <tr>
 <td>updated_by</td>
 <td>UUID</td>
 <td>Кто обновил (не отображается в UI)</td>
 </tr>
 <tr>
 <td>created_at</td>
 <td>timestamp</td>
 <td>Дата создания</td>
 </tr>
 <tr>
 <td>updated_at</td>
 <td>timestamp</td>
 <td>Дата обновления</td>
 </tr>
 <tr>
 <td>deleted_at</td>
 <td>timestamp</td>
 <td>Soft delete</td>
 </tr>
 </tbody>
</table>
<p><strong>Права доступа:</strong> Создание, редактирование и удаление вех доступно участникам с правами выше «только чтение» (аналогично задачам).</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Leadera: Ограничения секций в диаграмме Ганта</title>
|
||||
<link>/leadera/leadera-section-constraints/</link>
|
||||
<link>/yasha/leadera/leadera-section-constraints/</link>
|
||||
<pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/leadera/leadera-section-constraints/</guid>
|
||||
<guid>/yasha/leadera/leadera-section-constraints/</guid>
|
||||
<description><h2 id="бизнес-требования">Бизнес-требования</h2>
<h3 id="br-1-лимит-одновременных-задач-concurrency-limit">BR-1: Лимит одновременных задач (Concurrency Limit)</h3>
<p>У каждой секции появляется параметр <strong>max_concurrent_tasks</strong> (целое число ≥ 0, по умолчанию 0).</p>
<p><strong>Поведение:</strong></p>
<ul>
<li>Если <code>max_concurrent_tasks = 3</code> — в любой данный день в этой секции не может быть больше 3 активных задач одновременно</li>
<li>Если <code>max_concurrent_tasks = 0</code> — ограничение отключено, лимита нет</li>
<li>Пересечение считается по дате: задача занимает дни с <code>start_date</code> по <code>end_date</code> включительно. Две задачи «пересекаются», если у них есть хотя бы один общий день</li>
<li>Ограничение работает <strong>только в рамках одной секции</strong>. Задачи из разных секций не влияют друг на друга</li>
</ul>
<p><strong>Срабатывание при:</strong></p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Eversolo T8 API</title>
|
||||
<link>/kb/eversolo-api/</link>
|
||||
<link>/yasha/kb/eversolo-api/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/kb/eversolo-api/</guid>
|
||||
<guid>/yasha/kb/eversolo-api/</guid>
|
||||
<description><p>Eversolo T8 — музыкальный стример.</p>
<p><strong>IP:</strong> 192.168.0.156
<strong>Порт:</strong> 9529
<strong>Авторизация:</strong> нет</p>
<p>Базовый URL: <code>http://192.168.0.156:9529</code></p>
<h2 id="воспроизведение">Воспроизведение</h2>
<table>
 <thead>
 <tr>
 <th>Действие</th>
 <th>URL</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Play/Pause</td>
 <td><code>/ZidooMusicControl/v2/playOrPause</code></td>
 </tr>
 <tr>
 <td>Следующий трек</td>
 <td><code>/ZidooMusicControl/v2/playNext</code></td>
 </tr>
 <tr>
 <td>Предыдущий трек</td>
 <td><code>/ZidooMusicControl/v2/playLast</code></td>
 </tr>
 <tr>
 <td>Перемотка (ms)</td>
 <td><code>/ZidooMusicControl/v2/seekTo?time=&lt;ms&gt;</code></td>
 </tr>
 <tr>
 <td>Воспроизвести по ID</td>
 <td><code>/ZidooMusicControl/v2/playMusic?type=4&amp;id=&lt;id&gt;</code></td>
 </tr>
 <tr>
 <td>Состояние</td>
 <td><code>/ZidooMusicControl/v2/getState</code></td>
 </tr>
 </tbody>
</table>
<h2 id="громкость">Громкость</h2>
<table>
 <thead>
 <tr>
 <th>Действие</th>
 <th>URL</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Громкость вверх</td>
 <td><code>/ZidooControlCenter/RemoteControl/sendkey?key=Key.VolumeUp</code></td>
 </tr>
 <tr>
 <td>Громкость вниз</td>
 <td><code>/ZidooControlCenter/RemoteControl/sendkey?key=Key.VolumeDown</code></td>
 </tr>
 <tr>
 <td>Точная громкость</td>
 <td><code>/ZidooMusicControl/v2/setDevicesVolume?volume=&lt;0-200&gt;</code></td>
 </tr>
 <tr>
 <td>Mute</td>
 <td><code>/ZidooMusicControl/v2/setMuteVolume?isMute=1</code></td>
 </tr>
 <tr>
 <td>Unmute</td>
 <td><code>/ZidooMusicControl/v2/setMuteVolume?isMute=0</code></td>
 </tr>
 </tbody>
</table>
<h2 id="входывыходы">Входы/Выходы</h2>
<table>
 <thead>
 <tr>
 <th>Действие</th>
 <th>URL</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Получить список</td>
 <td><code>/ZidooMusicControl/v2/getInputAndOutputList</code></td>
 </tr>
 <tr>
 <td>Установить вход</td>
 <td><code>/ZidooMusicControl/v2/setInputList?tag=&lt;tag&gt;&amp;index=&lt;n&gt;</code></td>
 </tr>
 <tr>
 <td>Установить выход</td>
 <td><code>/ZidooMusicControl/v2/setOutInputList?tag=&lt;tag&gt;&amp;index=&lt;n&gt;</code></td>
 </tr>
 </tbody>
</table>
<p>Теги выхода: RCA, XLRRCA, XLR, HDMI, SPDIF, USB</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Реализовать управление Eversolo из OpenClaw</title>
|
||||
<link>/plans/eversolo-control/</link>
|
||||
<link>/yasha/plans/eversolo-control/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/plans/eversolo-control/</guid>
|
||||
<guid>/yasha/plans/eversolo-control/</guid>
|
||||
<description><h2 id="описание">Описание</h2>
<p>Добавить инструменты управления Eversolo T8 в OpenClaw.</p>
<h2 id="что-сделано">Что сделано</h2>
<ul>
<li>Изучен полный API Eversolo T8 (см. <a href="../../kb/eversolo-api/">Базу знаний</a>)</li>
</ul>
<h2 id="проблема">Проблема</h2>
<p>Sandbox OpenClaw не имеет доступа к локальной сети, где находится Eversolo.</p>
<h2 id="возможные-решения">Возможные решения</h2>
<ol>
<li>Настроить проброс портов</li>
<li>Запустить OpenClaw без sandbox-ограничений</li>
<li>Использовать промежуточный proxy-сервис</li>
</ol></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,9 +125,9 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../leadera/leadera-websocket-gantt/">Leadera — WebSocket для диаграмм Ганта</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-websocket-gantt/">Leadera — WebSocket для диаграмм Ганта</a></li>
|
||||
|
||||
<li><a href="../../leadera/leadera-audit/">Аудит Leadera — полный отчёт</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-audit/">Аудит Leadera — полный отчёт</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
<atom:link href="/tags/architecture/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>Аудит Leadera — полный отчёт</title>
|
||||
<link>/leadera/leadera-audit/</link>
|
||||
<link>/yasha/leadera/leadera-audit/</link>
|
||||
<pubDate>Mon, 30 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/leadera/leadera-audit/</guid>
|
||||
<guid>/yasha/leadera/leadera-audit/</guid>
|
||||
<description><h1 id="аудит-проекта-leadera">Аудит проекта Leadera</h1>
<p><strong>Дата:</strong> 30.03.2026<br>
<strong>Версия:</strong> pre-production, миграции 1–5</p>
<hr>
<h2 id="1-обзор-проекта">1. Обзор проекта</h2>
<p>Leadera — SaaS-система управления IT-ландшафтом с диаграммами Ганта.</p>
<h3 id="стек">Стек</h3>
<table>
 <thead>
 <tr>
 <th>Компонент</th>
 <th>Технологии</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Backend</td>
 <td>Go 1.21+, Gin, PostgreSQL 16, pgx/v5 + sqlx, JWT (HMAC-SHA256)</td>
 </tr>
 <tr>
 <td>Frontend</td>
 <td>Angular 21.1, Bootstrap 5, NgBootstrap, RxJS, Signals</td>
 </tr>
 <tr>
 <td>Инфраструктура</td>
 <td>Docker (Colima), pm2, nginx reverse proxy, VPS reg.ru</td>
 </tr>
 </tbody>
</table>
<h3 id="доменная-модель">Доменная модель</h3>
<pre tabindex="0"><code>User ──┬── Space (через space_members с role)
 │
 └── GanttChart (принадлежит Space)
 ├── GanttSection
 └── GanttTask
</code></pre><p><strong>Роли:</strong> admin, editor, viewer — назначаются <strong>на уровне Space</strong> через таблицу <code>space_members</code>.</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Leadera — WebSocket для диаграмм Ганта</title>
|
||||
<link>/leadera/leadera-websocket-gantt/</link>
|
||||
<link>/yasha/leadera/leadera-websocket-gantt/</link>
|
||||
<pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/leadera/leadera-websocket-gantt/</guid>
|
||||
<guid>/yasha/leadera/leadera-websocket-gantt/</guid>
|
||||
<description><h1 id="websocket-для-диаграмм-ганта--realtime-совместное-редактирование">WebSocket для диаграмм Ганта — realtime-совместное редактирование</h1>
<p><strong>Дата:</strong> 07.04.2026
<strong>Статус:</strong> Планирование
<strong>Проект:</strong> Leadera (dev — sand.a2v.space)</p>
<hr>
<h2 id="1-постановка-задачи">1. Постановка задачи</h2>
<p>Диаграммы Ганта должны обновляться в реальном времени при совместной работе: если два или более пользователей редактируют один Гант, изменения каждого мгновенно отображаются у остальных — без перезагрузки страницы и ручного обновления.</p>
<hr>
<h2 id="2-архитектура">2. Архитектура</h2>
<pre tabindex="0"><code>Angular frontend ←── WebSocket ──→ Go backend (Hub) ──→ PostgreSQL
 │ │
 │ HTTP (мутации) │ Broadcast
 └──→ REST API ──→ Service ──→ DB ──→ Hub ──→ все клиенты комнаты
</code></pre><p><strong>Ключевой принцип:</strong> мутации данных идут через HTTP (REST), WebSocket используется <strong>только для доставки уведомлений</strong>. Сервер — источник истины, клиент не может обойти проверки через WS.</p></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,25 +125,25 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../personal-site/netlify-node-version/">Устаревший Node.js 16 в Netlify</a></li>
|
||||
<li><a href="../../yasha/personal-site/netlify-node-version/">Устаревший Node.js 16 в Netlify</a></li>
|
||||
|
||||
<li><a href="../../personal-site/no-node-modules/">Отсутствуют node_modules — нужна установка</a></li>
|
||||
<li><a href="../../yasha/personal-site/no-node-modules/">Отсутствуют node_modules — нужна установка</a></li>
|
||||
|
||||
<li><a href="../../personal-site/binary-files-in-repo/">Бинарный файл в репозитории</a></li>
|
||||
<li><a href="../../yasha/personal-site/binary-files-in-repo/">Бинарный файл в репозитории</a></li>
|
||||
|
||||
<li><a href="../../personal-site/no-analytics/">Yandex Metrika отключена</a></li>
|
||||
<li><a href="../../yasha/personal-site/no-analytics/">Yandex Metrika отключена</a></li>
|
||||
|
||||
<li><a href="../../personal-site/twitter-handle-mismatch/">Twitter handle не соответствует имени</a></li>
|
||||
<li><a href="../../yasha/personal-site/twitter-handle-mismatch/">Twitter handle не соответствует имени</a></li>
|
||||
|
||||
<li><a href="../../personal-site/outdated-doks-theme/">Hugo Doks 0.5 — сильно устарел</a></li>
|
||||
<li><a href="../../yasha/personal-site/outdated-doks-theme/">Hugo Doks 0.5 — сильно устарел</a></li>
|
||||
|
||||
<li><a href="../../personal-site/digest-stale/">Digest не обновлялся с февраля 2025</a></li>
|
||||
<li><a href="../../yasha/personal-site/digest-stale/">Digest не обновлялся с февраля 2025</a></li>
|
||||
|
||||
<li><a href="../../personal-site/copyright-outdated/">Copyright без 2026 года</a></li>
|
||||
<li><a href="../../yasha/personal-site/copyright-outdated/">Copyright без 2026 года</a></li>
|
||||
|
||||
<li><a href="../../personal-site/">Личный сайт (agaltsovav.ru)</a></li>
|
||||
<li><a href="../../yasha/personal-site/">Личный сайт (agaltsovav.ru)</a></li>
|
||||
|
||||
<li><a href="../../leadera/leadera-audit/">Аудит Leadera — полный отчёт</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-audit/">Аудит Leadera — полный отчёт</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
+20
-20
@@ -10,72 +10,72 @@
|
||||
<atom:link href="/tags/audit/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>Личный сайт (agaltsovav.ru)</title>
|
||||
<link>/personal-site/</link>
|
||||
<link>/yasha/personal-site/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/</guid>
|
||||
<guid>/yasha/personal-site/</guid>
|
||||
<description></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Аудит Leadera — полный отчёт</title>
|
||||
<link>/leadera/leadera-audit/</link>
|
||||
<link>/yasha/leadera/leadera-audit/</link>
|
||||
<pubDate>Mon, 30 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/leadera/leadera-audit/</guid>
|
||||
<guid>/yasha/leadera/leadera-audit/</guid>
|
||||
<description><h1 id="аудит-проекта-leadera">Аудит проекта Leadera</h1>
<p><strong>Дата:</strong> 30.03.2026<br>
<strong>Версия:</strong> pre-production, миграции 1–5</p>
<hr>
<h2 id="1-обзор-проекта">1. Обзор проекта</h2>
<p>Leadera — SaaS-система управления IT-ландшафтом с диаграммами Ганта.</p>
<h3 id="стек">Стек</h3>
<table>
 <thead>
 <tr>
 <th>Компонент</th>
 <th>Технологии</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Backend</td>
 <td>Go 1.21+, Gin, PostgreSQL 16, pgx/v5 + sqlx, JWT (HMAC-SHA256)</td>
 </tr>
 <tr>
 <td>Frontend</td>
 <td>Angular 21.1, Bootstrap 5, NgBootstrap, RxJS, Signals</td>
 </tr>
 <tr>
 <td>Инфраструктура</td>
 <td>Docker (Colima), pm2, nginx reverse proxy, VPS reg.ru</td>
 </tr>
 </tbody>
</table>
<h3 id="доменная-модель">Доменная модель</h3>
<pre tabindex="0"><code>User ──┬── Space (через space_members с role)
 │
 └── GanttChart (принадлежит Space)
 ├── GanttSection
 └── GanttTask
</code></pre><p><strong>Роли:</strong> admin, editor, viewer — назначаются <strong>на уровне Space</strong> через таблицу <code>space_members</code>.</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Copyright без 2026 года</title>
|
||||
<link>/personal-site/copyright-outdated/</link>
|
||||
<link>/yasha/personal-site/copyright-outdated/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/copyright-outdated/</guid>
|
||||
<guid>/yasha/personal-site/copyright-outdated/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p>В <code>params.toml</code>:</p>
<pre tabindex="0"><code>copyRight = &#34;Copyright (c) 2020-2025 Антон Агальцов&#34;
</code></pre><p>Сейчас 2026 год — нужно обновить.</p>
<h3 id="рекомендация">Рекомендация</h3>
<p>Обновить на <code>2020-2026</code>. Или сделать динамическим через Hugo template:</p>
<pre tabindex="0"><code>Copyright (c) 2020-{{ now.Year }} Антон Агальцов
</code></pre></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Digest не обновлялся с февраля 2025</title>
|
||||
<link>/personal-site/digest-stale/</link>
|
||||
<link>/yasha/personal-site/digest-stale/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/digest-stale/</guid>
|
||||
<guid>/yasha/personal-site/digest-stale/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p>Последний дайджест — <strong>февраль 2025</strong>. С тех пор 12+ месяцев без новых выпусков.</p>
<h3 id="что-есть">Что есть</h3>
<ul>
<li>27 файлов дайджестов (январь 2023 — февраль 2025)</li>
<li>Автоматизация через <code>digest.js</code> — скрипт для генерации</li>
<li>Но скрипт не запускается автоматически</li>
</ul>
<h3 id="риск">Риск</h3>
<p>Low — контент устаревает, SEO-позиции падают для страниц дайджестов.</p>
<h3 id="рекомендация">Рекомендация</h3>
<ol>
<li>Настроить cron/CI для ежемесячной генерации дайджеста</li>
<li>Или интегрировать с OpenClaw — авто-сборка дайджеста на основе новых публикаций</li>
</ol></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Hugo Doks 0.5 — сильно устарел</title>
|
||||
<link>/personal-site/outdated-doks-theme/</link>
|
||||
<link>/yasha/personal-site/outdated-doks-theme/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/outdated-doks-theme/</guid>
|
||||
<guid>/yasha/personal-site/outdated-doks-theme/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p>Проект использует тему <strong>Hyas/Doks v0.5.0</strong> (package.json). Актуальная версия Doks — <strong>1.x</strong> с полной переработкой архитектуры.</p>
<h3 id="что-не-так">Что не так</h3>
<ul>
<li>Doks 0.5 использует устаревший Bootstrap 5.2.0-beta1</li>
<li>Hugo 0.148.2 в зависимостях — новый, но интеграция с темой старая</li>
<li>Конфигурация через <code>theme.toml</code> — в новых версиях перешли на другой формат</li>
<li><code>exec-bin</code> для вызова Hugo — устаревший подход, текущие версии Hugo ставятся глобально</li>
</ul>
<h3 id="риск">Риск</h3>
<p>Medium — работает, но миграция на Doks 1.x потребует значительного рефакторинга layout-ов и конфигурации. Чем дольше откладывать — тем сложнее.</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Twitter handle не соответствует имени</title>
|
||||
<link>/personal-site/twitter-handle-mismatch/</link>
|
||||
<link>/yasha/personal-site/twitter-handle-mismatch/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/twitter-handle-mismatch/</guid>
|
||||
<guid>/yasha/personal-site/twitter-handle-mismatch/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p>В <code>params.toml</code> указан Twitter: <code>@AntonTotoshkin</code></p>
<p>Но владелец сайта — <strong>Антон Агальцов</strong>. Ники не совпадают.</p>
<h3 id="два-варианта">Два варианта</h3>
<ol>
<li>Это твой старый/другой аккаунт — тогда ок, но стоит указать актуальный</li>
<li>Это чужой аккаунт — тогда нужно убрать или исправить</li>
</ol>
<h3 id="затронутые-места">Затронутые места</h3>
<ul>
<li><code>twitterSite = &quot;@AntonTotoshkin&quot;</code></li>
<li><code>schemaAuthorTwitter = &quot;https://twitter.com/AntonTotoshkin&quot;</code></li>
<li><code>schemaTwitter = &quot;https://twitter.com/AntonTotoshkin&quot;</code></li>
</ul>
<h3 id="рекомендация">Рекомендация</h3>
<p>Указать актуальный Twitter/X или убрать, если соцсеть не используется.</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Yandex Metrika отключена</title>
|
||||
<link>/personal-site/no-analytics/</link>
|
||||
<link>/yasha/personal-site/no-analytics/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/no-analytics/</guid>
|
||||
<guid>/yasha/personal-site/no-analytics/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p>В <code>params.toml</code>: <code>yandexMetrika = false</code></p>
<p>Аналитика с сайта не собирается. Непонятно, есть ли вообще посетители и какие страницы популярны.</p>
<h3 id="рекомендация">Рекомендация</h3>
<ol>
<li>Включить Yandex Metrika или перейти на <strong>Plausible</strong> / <strong>Umami</strong> (privacy-friendly)</li>
<li>Если сайт не нуждается в аналитике — оставить как есть</li>
<li>Альтернатива: Netlify Analytics (уже встроен в хостинг)</li>
</ol></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Бинарный файл в репозитории</title>
|
||||
<link>/personal-site/binary-files-in-repo/</link>
|
||||
<link>/yasha/personal-site/binary-files-in-repo/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/binary-files-in-repo/</guid>
|
||||
<guid>/yasha/personal-site/binary-files-in-repo/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p>В корне репозитория лежат два файла, которые не должны быть в git:</p>
<ul>
<li><strong><code>Шаблоны для сайта.key</code></strong> — Apple Keynote файл (бинарный)</li>
<li><strong><code>logo.psd</code></strong> — Photoshop файл (бинарный)</li>
</ul>
<h3 id="что-не-так">Что не так</h3>
<ul>
<li>Увеличивают размер репозитория</li>
<li>Git неэффективно хранит бинарные файлы (каждая версия — полностью)</li>
<li><code>.key</code> файлы могут содержать конфиденциальные данные шаблонов</li>
</ul>
<h3 id="рекомендация">Рекомендация</h3>
<ol>
<li>Перенести в отдельное хранилище (Google Drive, облако)</li>
<li>Удалить из git-истории через <code>git filter-repo</code></li>
<li>Добавить в <code>.gitignore</code>: <code>*.key</code>, <code>*.psd</code>, <code>*.sketch</code></li>
</ol></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Отсутствуют node_modules — нужна установка</title>
|
||||
<link>/personal-site/no-node-modules/</link>
|
||||
<link>/yasha/personal-site/no-node-modules/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/no-node-modules/</guid>
|
||||
<guid>/yasha/personal-site/no-node-modules/</guid>
|
||||
<description><h2 id="проблема">Проблема</h2>
<p><code>node_modules/</code> отсутствует — проект нельзя собрать без <code>npm install</code>.</p>
<h3 id="риск">Риск</h3>
<p>Low — стандартная ситуация. Но:</p>
<ul>
<li><code>package-lock.json</code> привязан к Node 16, а на Mac Studio текущий Node v24</li>
<li>Могут быть конфликты зависимостей (canvas, babel, postcss)</li>
<li>Hugo 0.148.2 ставится через <code>hugo-installer</code> в npm — может не совпасть с глобальным Hugo</li>
</ul>
<h3 id="рекомендация">Рекомендация</h3>
<ol>
<li>Убедиться что <code>npm install</code> проходит без ошибок на текущем Node</li>
<li>Если нет — обновить зависимости или использовать nvm для Node 16</li>
<li>Рассмотреть переход на глобальный Hugo вместо <code>exec-bin</code></li>
</ol></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Устаревший Node.js 16 в Netlify</title>
|
||||
<link>/personal-site/netlify-node-version/</link>
|
||||
<link>/yasha/personal-site/netlify-node-version/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/personal-site/netlify-node-version/</guid>
|
||||
<guid>/yasha/personal-site/netlify-node-version/</guid>
|
||||
<description><h1 id="устаревший-nodejs-16-в-netlify">Устаревший Node.js 16 в Netlify</h1>
<p><strong>Файл:</strong> <code>netlify.toml:5</code></p>
<pre tabindex="0"><code>NODE_VERSION = &#34;16.16.0&#34;
</code></pre><p>Node.js 16 вышел из поддержки (EOL) в сентябре 2023. Сборка на Netlify может начать падать или работать некорректно.</p>
<p><strong>Рекомендация:</strong> Обновить до Node.js 20 LTS:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#a6e22e">NODE_VERSION</span> = <span style="color:#e6db74">&#34;20&#34;</span>
</span></span></code></pre></div></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,7 +125,7 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../creds/docs-a2v-space-auth/">docs.a2v.space Basic Auth</a></li>
|
||||
<li><a href="../../yasha/creds/docs-a2v-space-auth/">docs.a2v.space Basic Auth</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<atom:link href="/tags/authentication/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>docs.a2v.space Basic Auth</title>
|
||||
<link>/creds/docs-a2v-space-auth/</link>
|
||||
<link>/yasha/creds/docs-a2v-space-auth/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/docs-a2v-space-auth/</guid>
|
||||
<guid>/yasha/creds/docs-a2v-space-auth/</guid>
|
||||
<description><h2 id="basic-authentication">Basic Authentication</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Username: agaltsovav
</span></span><span style="display:flex;"><span>Password: Magamet787!
</span></span></code></pre></div><h2 id="конфигурация-nginx">Конфигурация Nginx</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">8091</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">docs.a2v.space</span>;
</span></span><span style="display:flex;"><span> 
</span></span><span style="display:flex;"><span> <span style="color:#f92672">auth_basic</span> <span style="color:#e6db74">&#34;Restricted</span> <span style="color:#e6db74">Access&#34;</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">auth_basic_user_file</span> <span style="color:#e6db74">/etc/nginx/.htpasswd</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="доступ">Доступ</h2>
<ul>
<li><strong>URL</strong>: <a href="https://docs.a2v.space">https://docs.a2v.space</a> (через reverse proxy)</li>
<li><strong>Local</strong>: http://localhost:8091 (для разработки)</li>
<li><strong>Auth</strong>: всегда требуется</li>
</ul>
<h2 id="мастер-пароль-для-шифрования">Мастер-пароль для шифрования</h2>
<p><strong>Важно</strong>: Пароль для расшифровки файлов в разделе <code>creds/</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Master Password: Popoloka16!
</span></span></code></pre></div><h2 id="шифрование">Шифрование</h2>
<ul>
<li>Алгоритм: AES-256-GCM</li>
<li>Хранилище: client-side encryption</li>
<li>Файлы шифруются при сохранении</li>
<li>Расшифровываются при чтении</li>
</ul></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,7 +125,7 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../diary/2026-03-31/">31 марта 2026</a></li>
|
||||
<li><a href="../../yasha/diary/2026-03-31/">31 марта 2026</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<atom:link href="/tags/canvas/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>31 марта 2026</title>
|
||||
<link>/diary/2026-03-31/</link>
|
||||
<link>/yasha/diary/2026-03-31/</link>
|
||||
<pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/diary/2026-03-31/</guid>
|
||||
<guid>/yasha/diary/2026-03-31/</guid>
|
||||
<description><h2 id="timeline">Timeline</h2>
<ul>
<li><strong>Утро</strong> — Обсуждали аналоги htop: порекомендовал btm, btop, glances. Создан конфиг <code>~/.config/bottom/bottom.toml</code></li>
<li><strong>День</strong> — Разбирались со скиллами OpenCode: как работают, автоматический подбор по description</li>
<li><strong>День</strong> — Созданы скиллы для Leadera проектов (Go: build-and-fix, restart-api; Angular: build-and-fix)</li>
<li><strong>День</strong> — Обсудили миграцию Ганта с DOM на Canvas 2D (Konva.js) — real-time коллаборация, экспорт PDF/PNG, 500+ задач</li>
<li><strong>Вечер</strong> — Установлен gh CLI, авторизован как agaltsovav</li>
<li><strong>Вечер</strong> — Созданы GitHub Projects: Leadera Roadmap (21 задача, P0–P3), agaltsovav.ru Roadmap (7 задач)</li>
</ul>
<h2 id="системные-утилиты">Системные утилиты</h2>
<ul>
<li><strong>bottom</strong> (btm) — выбранный мониторинг, конфиг в <code>~/.config/bottom/bottom.toml</code></li>
<li>Альтернативы: btop, glances</li>
</ul>
<h2 id="opencode-skills">OpenCode Skills</h2>
<p>Созданы скиллы:</p></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,11 +125,11 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
<li><a href="../../yasha/plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
|
||||
<li><a href="../../creds/eversolo-companion-postgres/">Eversolo Companion PostgreSQL</a></li>
|
||||
<li><a href="../../yasha/creds/eversolo-companion-postgres/">Eversolo Companion PostgreSQL</a></li>
|
||||
|
||||
<li><a href="../../diary/2026-03-29/">29 марта 2026</a></li>
|
||||
<li><a href="../../yasha/diary/2026-03-29/">29 марта 2026</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,23 +10,23 @@
|
||||
<atom:link href="/tags/companion/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>29 марта 2026</title>
|
||||
<link>/diary/2026-03-29/</link>
|
||||
<link>/yasha/diary/2026-03-29/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/diary/2026-03-29/</guid>
|
||||
<guid>/yasha/diary/2026-03-29/</guid>
|
||||
<description><h2 id="timeline">Timeline</h2>
<ul>
<li><strong>20:03</strong> — Настроили Angular + Go проекты (leadera) через pm2, удалили proxy.conf, подняли PostgreSQL в Docker</li>
<li><strong>20:31</strong> — Изучили API Eversolo T8 — полный список REST-эндпоинтов для управления музыкой</li>
<li><strong>20:49</strong> — Обсудили важность записи контекста в файлы для сохранения памяти между сессиями</li>
<li><strong>21:13</strong> — Начали проект docs.a2v.space — персональная документация на Hugo</li>
<li><strong>21:44</strong> — Завершили настройку Identity (Братан, SOUL.md, USER.md, IDENTITY.md)</li>
<li><strong>22:15</strong> — Документировали инфраструктуру: VPS reverse proxy (claw.a2v.space, code.a2v.space, sand.a2v.space, docs.a2v.space)</li>
<li><strong>22:31</strong> — Настроили docs.a2v.space: Hugo сайт, 83 страницы, Bootstrap 5 тёмная тема, AES-256-GCM шифрование кредов (мастер-пароль: Popoloka16!)</li>
<li><strong>22:47</strong> — Добавили Basic auth: agaltsovav / Magamet787! для доступа к документации</li>
<li><strong>23:02</strong> — Создали cron задачу docs-a2v-daily-sync на ежедневное обновление в 03:00 МСК</li>
<li><strong>23:18</strong> — Полностью задокументировали Eversolo T8 API (воспроизведение, громкость, дисплей, питание, поиск и т.д.)</li>
<li><strong>23:45</strong> — Переписали TOOLS.md как полный справочник по инфраструктуре</li>
</ul>
<h2 id="eversolo-companion--статус-проекта">Eversolo Companion — статус проекта</h2>
<p><strong>Backend (Go + Gin):</strong></p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Eversolo Companion PostgreSQL</title>
|
||||
<link>/creds/eversolo-companion-postgres/</link>
|
||||
<link>/yasha/creds/eversolo-companion-postgres/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/eversolo-companion-postgres/</guid>
|
||||
<guid>/yasha/creds/eversolo-companion-postgres/</guid>
|
||||
<description><h2 id="docker-compose-креды-projectseversolo-companiondocker-composeyml">Docker Compose креды (~/Projects/eversolo-companion/docker-compose.yml)</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">postgres</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_USER</span>: <span style="color:#ae81ff">postgres</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_PASSWORD</span>: <span style="color:#ae81ff">password</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_DB</span>: <span style="color:#ae81ff">eversolo</span>
</span></span></code></pre></div><h2 id="локальные-креды-env-файл">Локальные креды (.env файл)</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>POSTGRES_USER<span style="color:#f92672">=</span>postgres
</span></span><span style="display:flex;"><span>POSTGRES_PASSWORD<span style="color:#f92672">=</span>password
</span></span><span style="display:flex;"><span>POSTGRES_DB<span style="color:#f92672">=</span>eversolo
</span></span></code></pre></div><h2 id="хостинг">Хостинг</h2>
<ul>
<li><strong>Host</strong>: localhost</li>
<li><strong>Port</strong>: 5433</li>
<li><strong>Database</strong>: eversolo</li>
</ul>
<h2 id="безопасность">Безопасность</h2>
<ul>
<li>Используйте разные пароли для production</li>
<li>Включите SSL для удаленного подключения</li>
<li>Регулярно делайте бэкапы</li>
</ul></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Завершить Eversolo Companion - этапы 3-9</title>
|
||||
<link>/plans/eversolo-companion-phases-3-9/</link>
|
||||
<link>/yasha/plans/eversolo-companion-phases-3-9/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/plans/eversolo-companion-phases-3-9/</guid>
|
||||
<guid>/yasha/plans/eversolo-companion-phases-3-9/</guid>
|
||||
<description><h2 id="описание">Описание</h2>
<p>Завершить разработку Eversolo Companion после решения проблемы с сетевым доступом.</p>
<h2 id="что-сделано">Что сделано</h2>
<ul>
<li><strong>Backend (Go + Gin)</strong>: собран, 17+ REST API эндпоинтов, WebSocket, CORS, state poller</li>
<li><strong>Frontend (Angular 17)</strong>: собран, тёмная тема (Spotify-like), 5 экранов, 5 сервисов</li>
<li><strong>PostgreSQL</strong>: Docker, порт 5433, миграции готовы</li>
<li><strong>Docker Compose</strong>: рабочий (postgres + api + frontend)</li>
<li><strong>Спецификация</strong>: полная в ~/Projects/eversolo-companion/SPEC.md</li>
</ul>
<h2 id="проблема">Проблема</h2>
<p>API не может достучаться до Eversolo T8 (192.168.0.156:9529) из-за ограничений OpenClaw sandbox.</p>
<h2 id="возможные-решения">Возможные решения</h2>
<ol>
<li>Настроить <code>tools.elevated.allowFrom.webchat</code> для разрешения сетевых соединений</li>
<li>Запустить API через launchd plist (как SSH туннели)</li>
<li>Использовать отдельный контейнер без ограничений</li>
</ol>
<h2 id="этапы-3-9-после-решения-сети">Этапы 3-9 (после решения сети)</h2>
<ol>
<li><strong>Библиотека синхронизации</strong> — двухсторонний sync с Eversolo</li>
<li><strong>Плейлисты</strong> — импорт/экспорт, редактирование</li>
<li><strong>Scrobbler</strong> — Last.fm / ListenBrainz</li>
<li><strong>Обложки</strong> — кэширование, отображение в UI</li>
<li><strong>Плеер</strong> — улучшенный интерфейс управления</li>
<li><strong>Система уведомлений</strong> — события от Eversolo</li>
<li><strong>Администрирование</strong> — настройка подключений</li>
</ol>
<h2 id="связанные-ресурсы">Связанные ресурсы</h2>
<ul>
<li><a href="../../docs/eversolo-companion-spec/">Спецификация проекта</a></li>
<li><a href="../../kb/eversolo-api/">API документация</a></li>
<li><a href="../../diary/2026-03-29/">Дневник разработки</a></li>
</ul></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,9 +125,9 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../creds/leadera-db-local/">Mac Studio — leadera-api БД (локальная)</a></li>
|
||||
<li><a href="../../yasha/creds/leadera-db-local/">Mac Studio — leadera-api БД (локальная)</a></li>
|
||||
|
||||
<li><a href="../../creds/leadera-db-docker/">Mac Studio — leadera-api БД (docker-compose)</a></li>
|
||||
<li><a href="../../yasha/creds/leadera-db-docker/">Mac Studio — leadera-api БД (docker-compose)</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
<atom:link href="/tags/database/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>Mac Studio — leadera-api БД (docker-compose)</title>
|
||||
<link>/creds/leadera-db-docker/</link>
|
||||
<link>/yasha/creds/leadera-db-docker/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/leadera-db-docker/</guid>
|
||||
<guid>/yasha/creds/leadera-db-docker/</guid>
|
||||
<description>NYVK4PEGwmOHmAnGk8IAUc+lyFJtnEAvX6ZddBro/ILRWHOXBGYywgglFvQZ18BLDLb5DuA8GPAIdB/LwTHRXYO0KsmtlZQVWGEeeXlXAoEXpa5theoOQhebkW6LmiKyNGAVW2z9rK3nz6NnztYdn49LvGMjrHuR4IwCLbl/pYa96CPNRnxGDFlduFi8lMSspM0rBFi/bZhNGhzy36ViCl+aKr5P9cle0ZvM8E8av/6c5JjgDt88QFI3VYdTaTCE0+uHsXlnJN7Qgg/KH7kD</description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Mac Studio — leadera-api БД (локальная)</title>
|
||||
<link>/creds/leadera-db-local/</link>
|
||||
<link>/yasha/creds/leadera-db-local/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/leadera-db-local/</guid>
|
||||
<guid>/yasha/creds/leadera-db-local/</guid>
|
||||
<description>p7Iw7Y3zbj1kLBcbOXGoO27oDwF85AhxBW7saT538hxi0ogJpyFeM49GDuLHzxuyknvdNC/rx3tb4AFnGkCeHSrrCmj+VK8Zxt7ujeujVJSRuOeeUlsqkHdlmaiXl2KQknrIsqVCi3Tnn0V5qcFxvo+1Ktc+surF6bBpWrTHzWV5mLtWVfD6C6kvvP/UFldFBD6v+FQs79yfoOe/j/bUrtpt6v5VndbbBmhUAQcy1BV2rpXxO373dTcLQ6coRWkt/RFo</description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,7 +125,7 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../guides/vps-reverse-proxy/">Настройка VPS как реверс-прокси</a></li>
|
||||
<li><a href="../../yasha/guides/vps-reverse-proxy/">Настройка VPS как реверс-прокси</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<atom:link href="/tags/devops/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>Настройка VPS как реверс-прокси</title>
|
||||
<link>/guides/vps-reverse-proxy/</link>
|
||||
<link>/yasha/guides/vps-reverse-proxy/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/guides/vps-reverse-proxy/</guid>
|
||||
<guid>/yasha/guides/vps-reverse-proxy/</guid>
|
||||
<description><h2 id="общая-схема">Общая схема</h2>
<pre tabindex="0"><code>Mac Studio (локальная сеть)
 → autossh (SSH-туннели)
 → VPS 95.163.232.9 (Debian)
 → nginx (HTTPS reverse proxy)
 → интернет
</code></pre><h2 id="что-нужно-на-vps">Что нужно на VPS</h2>
<h3 id="1-установленные-пакеты">1. Установленные пакеты</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>apt update
</span></span><span style="display:flex;"><span>apt install nginx certbot python3-certbot-nginx
</span></span></code></pre></div><h3 id="2-ssh-доступ">2. SSH-доступ</h3>
<ul>
<li>Авторизация только по ключам</li>
<li>Публичный ключ с Mac Studio добавлен в <code>/root/.ssh/authorized_keys</code></li>
</ul>
<h3 id="3-nginx">3. nginx</h3>
<p>Для каждого домена создать server block:</p>
<ul>
<li>HTTP → редирект на HTTPS</li>
<li>HTTPS с SSL-сертификатом Let&rsquo;s Encrypt</li>
<li><code>proxy_pass</code> на localhost-порт туннеля</li>
</ul>
<p>Пример структуры:</p></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,7 +125,7 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../creds/leadera-db-docker/">Mac Studio — leadera-api БД (docker-compose)</a></li>
|
||||
<li><a href="../../yasha/creds/leadera-db-docker/">Mac Studio — leadera-api БД (docker-compose)</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<atom:link href="/tags/docker-compose/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>Mac Studio — leadera-api БД (docker-compose)</title>
|
||||
<link>/creds/leadera-db-docker/</link>
|
||||
<link>/yasha/creds/leadera-db-docker/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/leadera-db-docker/</guid>
|
||||
<guid>/yasha/creds/leadera-db-docker/</guid>
|
||||
<description>NYVK4PEGwmOHmAnGk8IAUc+lyFJtnEAvX6ZddBro/ILRWHOXBGYywgglFvQZ18BLDLb5DuA8GPAIdB/LwTHRXYO0KsmtlZQVWGEeeXlXAoEXpa5theoOQhebkW6LmiKyNGAVW2z9rK3nz6NnztYdn49LvGMjrHuR4IwCLbl/pYa96CPNRnxGDFlduFi8lMSspM0rBFi/bZhNGhzy36ViCl+aKr5P9cle0ZvM8E8av/6c5JjgDt88QFI3VYdTaTCE0+uHsXlnJN7Qgg/KH7kD</description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,15 +125,15 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../guides/sand-a2v-space/">Подключение sand.a2v.space (Leadera Project)</a></li>
|
||||
<li><a href="../../yasha/guides/sand-a2v-space/">Подключение sand.a2v.space (Leadera Project)</a></li>
|
||||
|
||||
<li><a href="../../plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
<li><a href="../../yasha/plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
|
||||
<li><a href="../../creds/leadera-db-local/">Mac Studio — leadera-api БД (локальная)</a></li>
|
||||
<li><a href="../../yasha/creds/leadera-db-local/">Mac Studio — leadera-api БД (локальная)</a></li>
|
||||
|
||||
<li><a href="../../creds/eversolo-companion-postgres/">Eversolo Companion PostgreSQL</a></li>
|
||||
<li><a href="../../yasha/creds/eversolo-companion-postgres/">Eversolo Companion PostgreSQL</a></li>
|
||||
|
||||
<li><a href="../../diary/2026-03-29/">29 марта 2026</a></li>
|
||||
<li><a href="../../yasha/diary/2026-03-29/">29 марта 2026</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
+44
-40
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,9 +125,9 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../creds/docs-a2v-space-auth/">docs.a2v.space Basic Auth</a></li>
|
||||
<li><a href="../../yasha/creds/docs-a2v-space-auth/">docs.a2v.space Basic Auth</a></li>
|
||||
|
||||
<li><a href="../../diary/2026-03-29/">29 марта 2026</a></li>
|
||||
<li><a href="../../yasha/diary/2026-03-29/">29 марта 2026</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
<atom:link href="/tags/docs/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>29 марта 2026</title>
|
||||
<link>/diary/2026-03-29/</link>
|
||||
<link>/yasha/diary/2026-03-29/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/diary/2026-03-29/</guid>
|
||||
<guid>/yasha/diary/2026-03-29/</guid>
|
||||
<description><h2 id="timeline">Timeline</h2>
<ul>
<li><strong>20:03</strong> — Настроили Angular + Go проекты (leadera) через pm2, удалили proxy.conf, подняли PostgreSQL в Docker</li>
<li><strong>20:31</strong> — Изучили API Eversolo T8 — полный список REST-эндпоинтов для управления музыкой</li>
<li><strong>20:49</strong> — Обсудили важность записи контекста в файлы для сохранения памяти между сессиями</li>
<li><strong>21:13</strong> — Начали проект docs.a2v.space — персональная документация на Hugo</li>
<li><strong>21:44</strong> — Завершили настройку Identity (Братан, SOUL.md, USER.md, IDENTITY.md)</li>
<li><strong>22:15</strong> — Документировали инфраструктуру: VPS reverse proxy (claw.a2v.space, code.a2v.space, sand.a2v.space, docs.a2v.space)</li>
<li><strong>22:31</strong> — Настроили docs.a2v.space: Hugo сайт, 83 страницы, Bootstrap 5 тёмная тема, AES-256-GCM шифрование кредов (мастер-пароль: Popoloka16!)</li>
<li><strong>22:47</strong> — Добавили Basic auth: agaltsovav / Magamet787! для доступа к документации</li>
<li><strong>23:02</strong> — Создали cron задачу docs-a2v-daily-sync на ежедневное обновление в 03:00 МСК</li>
<li><strong>23:18</strong> — Полностью задокументировали Eversolo T8 API (воспроизведение, громкость, дисплей, питание, поиск и т.д.)</li>
<li><strong>23:45</strong> — Переписали TOOLS.md как полный справочник по инфраструктуре</li>
</ul>
<h2 id="eversolo-companion--статус-проекта">Eversolo Companion — статус проекта</h2>
<p><strong>Backend (Go + Gin):</strong></p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>docs.a2v.space Basic Auth</title>
|
||||
<link>/creds/docs-a2v-space-auth/</link>
|
||||
<link>/yasha/creds/docs-a2v-space-auth/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/docs-a2v-space-auth/</guid>
|
||||
<guid>/yasha/creds/docs-a2v-space-auth/</guid>
|
||||
<description><h2 id="basic-authentication">Basic Authentication</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Username: agaltsovav
</span></span><span style="display:flex;"><span>Password: Magamet787!
</span></span></code></pre></div><h2 id="конфигурация-nginx">Конфигурация Nginx</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">8091</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">docs.a2v.space</span>;
</span></span><span style="display:flex;"><span> 
</span></span><span style="display:flex;"><span> <span style="color:#f92672">auth_basic</span> <span style="color:#e6db74">&#34;Restricted</span> <span style="color:#e6db74">Access&#34;</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">auth_basic_user_file</span> <span style="color:#e6db74">/etc/nginx/.htpasswd</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="доступ">Доступ</h2>
<ul>
<li><strong>URL</strong>: <a href="https://docs.a2v.space">https://docs.a2v.space</a> (через reverse proxy)</li>
<li><strong>Local</strong>: http://localhost:8091 (для разработки)</li>
<li><strong>Auth</strong>: всегда требуется</li>
</ul>
<h2 id="мастер-пароль-для-шифрования">Мастер-пароль для шифрования</h2>
<p><strong>Важно</strong>: Пароль для расшифровки файлов в разделе <code>creds/</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Master Password: Popoloka16!
</span></span></code></pre></div><h2 id="шифрование">Шифрование</h2>
<ul>
<li>Алгоритм: AES-256-GCM</li>
<li>Хранилище: client-side encryption</li>
<li>Файлы шифруются при сохранении</li>
<li>Расшифровываются при чтении</li>
</ul></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,15 +125,15 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../plans/eversolo-control/">Реализовать управление Eversolo из OpenClaw</a></li>
|
||||
<li><a href="../../yasha/plans/eversolo-control/">Реализовать управление Eversolo из OpenClaw</a></li>
|
||||
|
||||
<li><a href="../../plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
<li><a href="../../yasha/plans/eversolo-companion-phases-3-9/">Завершить Eversolo Companion - этапы 3-9</a></li>
|
||||
|
||||
<li><a href="../../kb/eversolo-api/">Eversolo T8 API</a></li>
|
||||
<li><a href="../../yasha/kb/eversolo-api/">Eversolo T8 API</a></li>
|
||||
|
||||
<li><a href="../../creds/eversolo-companion-postgres/">Eversolo Companion PostgreSQL</a></li>
|
||||
<li><a href="../../yasha/creds/eversolo-companion-postgres/">Eversolo Companion PostgreSQL</a></li>
|
||||
|
||||
<li><a href="../../diary/2026-03-29/">29 марта 2026</a></li>
|
||||
<li><a href="../../yasha/diary/2026-03-29/">29 марта 2026</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -10,37 +10,37 @@
|
||||
<atom:link href="/tags/eversolo/index.xml" rel="self" type="application/rss+xml" />
|
||||
<item>
|
||||
<title>29 марта 2026</title>
|
||||
<link>/diary/2026-03-29/</link>
|
||||
<link>/yasha/diary/2026-03-29/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/diary/2026-03-29/</guid>
|
||||
<guid>/yasha/diary/2026-03-29/</guid>
|
||||
<description><h2 id="timeline">Timeline</h2>
<ul>
<li><strong>20:03</strong> — Настроили Angular + Go проекты (leadera) через pm2, удалили proxy.conf, подняли PostgreSQL в Docker</li>
<li><strong>20:31</strong> — Изучили API Eversolo T8 — полный список REST-эндпоинтов для управления музыкой</li>
<li><strong>20:49</strong> — Обсудили важность записи контекста в файлы для сохранения памяти между сессиями</li>
<li><strong>21:13</strong> — Начали проект docs.a2v.space — персональная документация на Hugo</li>
<li><strong>21:44</strong> — Завершили настройку Identity (Братан, SOUL.md, USER.md, IDENTITY.md)</li>
<li><strong>22:15</strong> — Документировали инфраструктуру: VPS reverse proxy (claw.a2v.space, code.a2v.space, sand.a2v.space, docs.a2v.space)</li>
<li><strong>22:31</strong> — Настроили docs.a2v.space: Hugo сайт, 83 страницы, Bootstrap 5 тёмная тема, AES-256-GCM шифрование кредов (мастер-пароль: Popoloka16!)</li>
<li><strong>22:47</strong> — Добавили Basic auth: agaltsovav / Magamet787! для доступа к документации</li>
<li><strong>23:02</strong> — Создали cron задачу docs-a2v-daily-sync на ежедневное обновление в 03:00 МСК</li>
<li><strong>23:18</strong> — Полностью задокументировали Eversolo T8 API (воспроизведение, громкость, дисплей, питание, поиск и т.д.)</li>
<li><strong>23:45</strong> — Переписали TOOLS.md как полный справочник по инфраструктуре</li>
</ul>
<h2 id="eversolo-companion--статус-проекта">Eversolo Companion — статус проекта</h2>
<p><strong>Backend (Go + Gin):</strong></p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Eversolo Companion PostgreSQL</title>
|
||||
<link>/creds/eversolo-companion-postgres/</link>
|
||||
<link>/yasha/creds/eversolo-companion-postgres/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/creds/eversolo-companion-postgres/</guid>
|
||||
<guid>/yasha/creds/eversolo-companion-postgres/</guid>
|
||||
<description><h2 id="docker-compose-креды-projectseversolo-companiondocker-composeyml">Docker Compose креды (~/Projects/eversolo-companion/docker-compose.yml)</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">postgres</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_USER</span>: <span style="color:#ae81ff">postgres</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_PASSWORD</span>: <span style="color:#ae81ff">password</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">POSTGRES_DB</span>: <span style="color:#ae81ff">eversolo</span>
</span></span></code></pre></div><h2 id="локальные-креды-env-файл">Локальные креды (.env файл)</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>POSTGRES_USER<span style="color:#f92672">=</span>postgres
</span></span><span style="display:flex;"><span>POSTGRES_PASSWORD<span style="color:#f92672">=</span>password
</span></span><span style="display:flex;"><span>POSTGRES_DB<span style="color:#f92672">=</span>eversolo
</span></span></code></pre></div><h2 id="хостинг">Хостинг</h2>
<ul>
<li><strong>Host</strong>: localhost</li>
<li><strong>Port</strong>: 5433</li>
<li><strong>Database</strong>: eversolo</li>
</ul>
<h2 id="безопасность">Безопасность</h2>
<ul>
<li>Используйте разные пароли для production</li>
<li>Включите SSL для удаленного подключения</li>
<li>Регулярно делайте бэкапы</li>
</ul></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Eversolo T8 API</title>
|
||||
<link>/kb/eversolo-api/</link>
|
||||
<link>/yasha/kb/eversolo-api/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/kb/eversolo-api/</guid>
|
||||
<guid>/yasha/kb/eversolo-api/</guid>
|
||||
<description><p>Eversolo T8 — музыкальный стример.</p>
<p><strong>IP:</strong> 192.168.0.156
<strong>Порт:</strong> 9529
<strong>Авторизация:</strong> нет</p>
<p>Базовый URL: <code>http://192.168.0.156:9529</code></p>
<h2 id="воспроизведение">Воспроизведение</h2>
<table>
 <thead>
 <tr>
 <th>Действие</th>
 <th>URL</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Play/Pause</td>
 <td><code>/ZidooMusicControl/v2/playOrPause</code></td>
 </tr>
 <tr>
 <td>Следующий трек</td>
 <td><code>/ZidooMusicControl/v2/playNext</code></td>
 </tr>
 <tr>
 <td>Предыдущий трек</td>
 <td><code>/ZidooMusicControl/v2/playLast</code></td>
 </tr>
 <tr>
 <td>Перемотка (ms)</td>
 <td><code>/ZidooMusicControl/v2/seekTo?time=&lt;ms&gt;</code></td>
 </tr>
 <tr>
 <td>Воспроизвести по ID</td>
 <td><code>/ZidooMusicControl/v2/playMusic?type=4&amp;id=&lt;id&gt;</code></td>
 </tr>
 <tr>
 <td>Состояние</td>
 <td><code>/ZidooMusicControl/v2/getState</code></td>
 </tr>
 </tbody>
</table>
<h2 id="громкость">Громкость</h2>
<table>
 <thead>
 <tr>
 <th>Действие</th>
 <th>URL</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Громкость вверх</td>
 <td><code>/ZidooControlCenter/RemoteControl/sendkey?key=Key.VolumeUp</code></td>
 </tr>
 <tr>
 <td>Громкость вниз</td>
 <td><code>/ZidooControlCenter/RemoteControl/sendkey?key=Key.VolumeDown</code></td>
 </tr>
 <tr>
 <td>Точная громкость</td>
 <td><code>/ZidooMusicControl/v2/setDevicesVolume?volume=&lt;0-200&gt;</code></td>
 </tr>
 <tr>
 <td>Mute</td>
 <td><code>/ZidooMusicControl/v2/setMuteVolume?isMute=1</code></td>
 </tr>
 <tr>
 <td>Unmute</td>
 <td><code>/ZidooMusicControl/v2/setMuteVolume?isMute=0</code></td>
 </tr>
 </tbody>
</table>
<h2 id="входывыходы">Входы/Выходы</h2>
<table>
 <thead>
 <tr>
 <th>Действие</th>
 <th>URL</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>Получить список</td>
 <td><code>/ZidooMusicControl/v2/getInputAndOutputList</code></td>
 </tr>
 <tr>
 <td>Установить вход</td>
 <td><code>/ZidooMusicControl/v2/setInputList?tag=&lt;tag&gt;&amp;index=&lt;n&gt;</code></td>
 </tr>
 <tr>
 <td>Установить выход</td>
 <td><code>/ZidooMusicControl/v2/setOutInputList?tag=&lt;tag&gt;&amp;index=&lt;n&gt;</code></td>
 </tr>
 </tbody>
</table>
<p>Теги выхода: RCA, XLRRCA, XLR, HDMI, SPDIF, USB</p></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Завершить Eversolo Companion - этапы 3-9</title>
|
||||
<link>/plans/eversolo-companion-phases-3-9/</link>
|
||||
<link>/yasha/plans/eversolo-companion-phases-3-9/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/plans/eversolo-companion-phases-3-9/</guid>
|
||||
<guid>/yasha/plans/eversolo-companion-phases-3-9/</guid>
|
||||
<description><h2 id="описание">Описание</h2>
<p>Завершить разработку Eversolo Companion после решения проблемы с сетевым доступом.</p>
<h2 id="что-сделано">Что сделано</h2>
<ul>
<li><strong>Backend (Go + Gin)</strong>: собран, 17+ REST API эндпоинтов, WebSocket, CORS, state poller</li>
<li><strong>Frontend (Angular 17)</strong>: собран, тёмная тема (Spotify-like), 5 экранов, 5 сервисов</li>
<li><strong>PostgreSQL</strong>: Docker, порт 5433, миграции готовы</li>
<li><strong>Docker Compose</strong>: рабочий (postgres + api + frontend)</li>
<li><strong>Спецификация</strong>: полная в ~/Projects/eversolo-companion/SPEC.md</li>
</ul>
<h2 id="проблема">Проблема</h2>
<p>API не может достучаться до Eversolo T8 (192.168.0.156:9529) из-за ограничений OpenClaw sandbox.</p>
<h2 id="возможные-решения">Возможные решения</h2>
<ol>
<li>Настроить <code>tools.elevated.allowFrom.webchat</code> для разрешения сетевых соединений</li>
<li>Запустить API через launchd plist (как SSH туннели)</li>
<li>Использовать отдельный контейнер без ограничений</li>
</ol>
<h2 id="этапы-3-9-после-решения-сети">Этапы 3-9 (после решения сети)</h2>
<ol>
<li><strong>Библиотека синхронизации</strong> — двухсторонний sync с Eversolo</li>
<li><strong>Плейлисты</strong> — импорт/экспорт, редактирование</li>
<li><strong>Scrobbler</strong> — Last.fm / ListenBrainz</li>
<li><strong>Обложки</strong> — кэширование, отображение в UI</li>
<li><strong>Плеер</strong> — улучшенный интерфейс управления</li>
<li><strong>Система уведомлений</strong> — события от Eversolo</li>
<li><strong>Администрирование</strong> — настройка подключений</li>
</ol>
<h2 id="связанные-ресурсы">Связанные ресурсы</h2>
<ul>
<li><a href="../../docs/eversolo-companion-spec/">Спецификация проекта</a></li>
<li><a href="../../kb/eversolo-api/">API документация</a></li>
<li><a href="../../diary/2026-03-29/">Дневник разработки</a></li>
</ul></description>
|
||||
</item>
|
||||
<item>
|
||||
<title>Реализовать управление Eversolo из OpenClaw</title>
|
||||
<link>/plans/eversolo-control/</link>
|
||||
<link>/yasha/plans/eversolo-control/</link>
|
||||
<pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate>
|
||||
<guid>/plans/eversolo-control/</guid>
|
||||
<guid>/yasha/plans/eversolo-control/</guid>
|
||||
<description><h2 id="описание">Описание</h2>
<p>Добавить инструменты управления Eversolo T8 в OpenClaw.</p>
<h2 id="что-сделано">Что сделано</h2>
<ul>
<li>Изучен полный API Eversolo T8 (см. <a href="../../kb/eversolo-api/">Базу знаний</a>)</li>
</ul>
<h2 id="проблема">Проблема</h2>
<p>Sandbox OpenClaw не имеет доступа к локальной сети, где находится Eversolo.</p>
<h2 id="возможные-решения">Возможные решения</h2>
<ol>
<li>Настроить проброс портов</li>
<li>Запустить OpenClaw без sandbox-ограничений</li>
<li>Использовать промежуточный proxy-сервис</li>
</ol></description>
|
||||
</item>
|
||||
</channel>
|
||||
|
||||
@@ -26,33 +26,47 @@
|
||||
<div class="collapse navbar-collapse" id="navbarMain">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../diary/">Дневник</a>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Яша
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/diary/">Дневник</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/plans/">Планы</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/guides/">Инструкции</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/creds/">Креды</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/leadera/">Leadera</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../yasha/personal-site/">Личный сайт</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../kb/">База знаний</a>
|
||||
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Семен
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/changelog/">История изменений</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/kb/">База знаний</a></li>
|
||||
|
||||
<li><a class="dropdown-item" href="../../semen/diary/">Дневник</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../plans/">Планы</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../leadera/">Leadera</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../guides/">Инструкции</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../creds/">Креды</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="../../personal-site/">Личный сайт</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -87,25 +101,15 @@
|
||||
<aside class="col-md-3 col-lg-2 d-md-block sidebar collapse" id="sidebar">
|
||||
<div class="sidebar-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h6>Разделы</h6>
|
||||
<ul class="nav flex-column">
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../diary/">Дневник</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../kb/">База знаний</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../plans/">Планы</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../leadera/">Leadera</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../guides/">Инструкции</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../creds/">Креды</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../personal-site/">Личный сайт</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="../../yasha/">Яша</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="../../semen/">Семен</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -121,7 +125,7 @@
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="../../leadera/leadera-gantt-excel-export/">Leadera — Экспорт диаграммы Ганта в Excel</a></li>
|
||||
<li><a href="../../yasha/leadera/leadera-gantt-excel-export/">Leadera — Экспорт диаграммы Ганта в Excel</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user