Uloziste pro vsechna data, oprava .gitignore, dodelany navrh rozsireni

.gitignore mel vzorec `data/`, ktery se shodl i se `src/data/`. Sestnact
zdrojovych souboru tim tise chybelo v gitu vcetne cele slozky
`src/data/store/`. Opraveno na `/data/`, stejne v .dockerignore.

Tickety vcetne logu, automatizace, incidenty a rozlozeni dashboardu se po
kazde zmene ukladaji. Pomocnik `withMirror` je opak `withCache`: data se meni
v pameti a zapisuji cela, misto aby se po zapisu znovu nacitala. Citace ID se
pri startu dopocitaji z ulozenych zaznamu, takze novy ticket neprepise stary.

Detail ticketu umi typ, tagy, vlastni pole typu a prehozeni na skupinu.
Nastaveni ma prepnuti spravce na jiny ucet, vychozi jen pro cteni.
Skupiny resitelu chodi spolu s lidmi jednim requestem.

Dokumentace: rejstrik znovupouzitelnych funkci (15), navrh monetizace
a ceny za krok (16), popis nastaveni a prav (17). Doplneny endpointy
do openapi.ts, petice CRUD rout se generuje jednou funkci.

Overeno v rezimu souboru: zmeny prezily tvrde ukonceni procesu a po restartu
byly zpatky vcetne logu ticketu.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-13 07:46:22 +02:00
co-authored by Claude Opus 5
parent e7cf499a0b
commit afbe948da3
37 changed files with 5594 additions and 106 deletions
+12 -2
View File
@@ -217,13 +217,23 @@ dashboardRouter.delete('/layout', (req, res) => {
// ------------------------------------------------------------------- tickety
/** Resitele vybrane firmy. Klient je potrebuje do nabidky prirazeni i do prehledu. */
/**
* Resitele vybrane firmy. Klient je potrebuje do nabidky prirazeni i do prehledu.
*
* Skupiny jdou stejnym endpointem zamerne: kdo smi prirazovat ticket, smi ho
* prirazit i skupine, a druhy request na dve polozky nema smysl. Sprava skupin
* je jina vec a ma vlastni pravo v nastaveni.
*/
dashboardRouter.get('/people', (req, res) => {
const scope = scopeOrDeny(req, res);
if (!scope) return;
const me = findPersonByEmail(req.user!.email);
return res.json({ items: listPeople(scope.tenantIds), meId: me?.id ?? null });
return res.json({
items: listPeople(scope.tenantIds),
groups: listGroups(scope.tenantIds).map((group) => ({ id: group.id, name: group.name })),
meId: me?.id ?? null,
});
});
const ticketStatuses: TicketStatus[] = ['new', 'open', 'waiting', 'resolved'];