Files
csbot-prototype/documentation/08-dashboard-widgety.md
T
JiriUhlir 22dda2d139 Struktura podle zasad: rozdeleni souboru, lint, testy, prisny TypeScript
Projekt srovnan se zasadami v D:\GitHubRepository\CLAUDE.md bez zmeny chovani.

Struktura: scripts/ (skripty konektoru) -> connectors/, src/scripts ->
src/runtime/scripts; src/index.ts jen startuje, novy src/app.ts s createApp();
routes/dashboard.ts a routes/settings.ts rozdeleny do slozek; openapi.ts
rozdelen na openapi/{index,helpers,components} a paths/* (98 cest overeno
shodnych); ticketStore, automationStore a services jsou fasady nad slozkami
data/tickets, data/automations a data/services/catalog. process.env se cte
jen v config.ts. Web: hooky v hooks/, sdilena ui/Table a ui/ServiceIcon,
surove inputy nahrazeny komponentami, sedm velkych souboru rozdeleno.

Nastroje: eslint (typescript-eslint, react-hooks v7), prettier, editorconfig,
nvmrc, .env.example, vitest; skripty lint, format, test. Lint je cisty bez
jedineho eslint-disable (nove hooky useLatest a useSyncFromSource, odvozeny
stav misto setState v effectu). noUncheckedIndexedAccess v obou tsconfig,
84 mist zuzeno bez non-null operatoru; odhalilo zalohu backoffu fronty pri
nule pokusu a Retry-After NaN pri max 0. Cely kod naformatovan prettierem.

Testy: 8 souboru, 105 testu (prava, viditelnost, podminky a opakovani
v executoru, redaktor tajemstvi, sitove guardy, migrace resitelu, tickety,
health a prihlaseni pres supertest). Testy odhalily dve chyby ve vyhodnoceni
podminek, obe opravene: chybejici castka se porovnavala jako nula a podminka
nad vystupem druheho kroku cetla hodnotu prvniho se stejnym nazvem.

Pojmenovane konstanty misto magickych hodnot, ctx.util.base64 pro skripty
konektoru, README a dokumentace aktualizovany vcetne znamych odchylek.
2026-09-09 15:11:02 +02:00

5.2 KiB

08 - Widgety na prehledu

Kde se to nastavuje

/dashboard, tlacitko Upravit dashboard vpravo nahore. V rezimu uprav dostane kazdy widget listu s ovladanim:

  • vyber sirky (tretina, polovina, cela sirka),
  • sipky vlevo a vpravo pro poradi,
  • kos pro odebrani.

K tomu Pridat widget s nabidkou toho, co jeste na dashboardu neni, Vychozi pro vraceni do puvodniho stavu a Ulozit nebo Zrusit.

Dokud se neklikne na Ulozit, nic se neuklada. Zrusit vrati puvodni rozlozeni.

Ulozeni je za dvojici uzivatel a firma

Ne za uzivatele. Clovek ve dvou firmach chce v kazde videt neco jineho a smichat mu to dohromady by bylo horsi nez zadne nastaveni.

Klic je ${userId}:${tenantId}, uloziste je src/data/dashboardLayouts.ts (pres withMirror, prezije restart). Kdo si dashboard jeste neupravil, dostane vychozi rozlozeni a custom: false. Ulozene rozlozeni si drzi createdAt i po uprave.

Vychozi rozlozeni dostava stejne hasPerson jako katalog: hasPerson znamena "je clenem firmy" (resitel je clenstvi uctu). Kdo clenstvi nema, typicky spravce platformy, nema v katalogu list.myTickets, a tak ho nesmi mit ani ve vychozi sade (misto nej jsou nezarazene tickety pres celou sirku). Jinak by novy ucet videl jako prvni vec hlasku o widgetu, ktery "uz v katalogu neni".

Katalog widgetu

src/data/widgets.ts, stejny princip jako katalog konektoru: server je zdroj pravdy o tom, co jde na dashboard polozit.

interface WidgetDefinition {
  id: string;
  name: string;
  description: string;
  kind: 'stat' | 'chart' | 'ticketList' | 'incidentList' | 'workload';
  sizes: WidgetSize[];      // ktere sirky ma smysl nabizet
  defaultSize: WidgetSize;
  metric?: ...;             // jen u `stat`: ktere cislo ze souhrnu
}

sizes neni kosmetika. Graf v tretine sloupce se necte, proto tam tretinu nenabizime vubec, misto abychom cekali, ze si to uzivatel rozmysli.

kind rika klientovi, kterou komponentu vykreslit. Novy druh znamena i novou komponentu na webu, proto jich je zamerne malo a jsou obecne. Novy statisticky widget je naopak jen zaznam v katalogu, zadny kod navic.

Data si nacita prehled, ne widgety

Widget dostane data v propsu. Kdyby si je nacital sam, deset dlazdic by znamenalo deset stejnych dotazu na server.

Prehled drzi ctyri dotazy (souhrn, tickety, incidenty, vytizeni) a rozdava je vsem widgetum. Dlazdice, ktera zadna data nepotrebuje, o nich proste nevi.

Totez plati na serveru: POST /widget-data nacte seznam ticketu jednou na request a kazdy widget si z nej filtruje svoje. Driv sel listTickets za kazdy widget zvlast, tedy desetkrat za otevreni prehledu.

Pri udalosti ze streamu se dotazy obnovi na pozadi (refreshing) a dlazdice zustavaji vykreslene. Driv se cely prehled pri kazde udalosti odmontoval a ukazal spinner, viz 05-dashboard-a-builder.md.

Ukazkove widgety "Moje tickety" a "Fronta bez resitele" filtruji closed: false, ne podle nazvu stavu - stav je volny retezec a slovnik defaultStatuses je cesky (Novy, V reseni, Ceka na klienta, Vyreseno).

Mrizka

Sest sloupcu, sirky mapuji na col-span: tretina 2, polovina 3, cela 6. Na uzkem displeji zabira vsechno celou sirku.

Pouzivaji se container queries (@container a @2xl:), ne sm: a lg:. Duvod je stejny jako u stromu automatizaci, viz 05-dashboard-a-builder.md, sekce o sirce karet.

Validace

Server overuje ulozene rozlozeni proti katalogu:

Situace Vysledek
neznamy widget 400
sirka, kterou widget nepodporuje 400
duplicitni ID instance 400
vic nez 12 widgetu 400

Neulozit je tady spravne. Klient by dostal zpatky neco, co neumi vykreslit.

Widget, ktery mezitim z katalogu zmizel, se v prehledu ukaze jako cervena karta s jeho ID. Nesmi tise vypadnout z rozlozeni.

Kde to je na klientovi

Stranka pages/dashboard/Overview.tsx sklada widgets/WidgetCard.tsx (vykresleni podle druhu), widgets/WidgetPicker.tsx (nabidka z katalogu), widgets/CustomWidget.tsx (widgety, jejichz data pocita server) a widgets/EditBar.tsx (lista rezimu uprav: ulozit, zahodit, obnovit vychozi). Vstupy v rezimu uprav jsou z components/ui/form, stranka si zadny vlastni nekresli. Server: src/routes/dashboard/layout.ts, src/data/widgets.ts, src/data/dashboardLayouts.ts.

Jak pridat widget

  1. Zaznam do widgets v src/data/widgets.ts.
  2. Kdyz je to stat, pridat i metriku do metricMeta v WidgetCard.tsx a pole do souhrnu, pokud tam jeste neni.
  3. Kdyz je to novy kind, dopsat vetev do WidgetCard.tsx.

Nabidka i rozlozeni ho vezmou automaticky.

Co chybi

Chybi Poznamka
Drag and drop poradi se meni sipkami, stejne jako ve strome
Nastaveni jednotlivych widgetu napr. kolik radku ukazat, za jake obdobi
Vlastni metriky katalog je pevny, nejde si nadefinovat vlastni
Sdilene rozlozeni pro firmu kazdy si upravuje jen to svoje