Katalog srovnany s tim, co opravdu bezi na services.csbot.cz/apps: trinact sluzeb dostalo pristupove udaje a levne cteci overeni, opravena appId, ktera nikam nevedla (ppl, microsoft365, transcription), a GA4, Search Console, Google Ads i Sklik ted stoji na aplikaci analytics, kazda s vlastnimi udaji. Nove sluzby SAP Business One, Google Workspace a Meta Ads. K tomu 23 skriptu, ktere s nimi opravdu neco delaji. OpenAI jako prvni sluzba, ktera nebezi u nas: Service.baseUrl s absolutni adresou, prepis pres <SLUZBA>_BASE_URL nebo adresu u konektoru, predpona hlavicky u pole udaju (uzivatel vlepi holy klic, Bearer dopise runtime). Dotaz na model, nahrani souboru, otazka nad souborem, prepis zvuku. Skript umi odeslat soubor pres ctx.http.postForm (multipart, obsah Base64). Sluzba E-mail pres SMTP. Neni to skript, ale vnitrni krok - SMTP neni HTTP. Konektor nese schranku firmy, krok ma HTML telo, ve kterem se dosazene hodnoty escapuji (znacky autora sablony jsou zamer, ostre zavorky od zakaznika ne). Overeni konektoru se prihlasi na server a nic neodesle. Helpdesk: Ticket.helpdeskSourceId drzi firmu, ktera pozadavek poslala, vlastnikem zustava ta, ktera ho resi - jinak by ho resitel nemel ve sve fronte. Komu pozadavek pripadne, urcuje Tenant.helpdeskProviderId. Zadavatel vidi jen svoje pozadavky a smi k nim pripsat komentar. Opravy v portalu: - hlasky o ulozisti a odchozi IP vidi jen spravce platformy - typ ticketu se v automatizaci vybira ze seznamu firmy, nebo dosadi z dat - stav ticketu je otevreny naseptavac, ne ciselnik - ticket jde zalozit rucne, zakaznik u nej neni povinny - kanal se prejmenoval a parametry u webhooku jsou oznacene jako nepovinne - srovnane markdown tabulky v cele dokumentaci Co z teto davky jeste neni: prepinac firmy je porad jen stav uvnitr stranky Prehled, takze se prepnuti neprojevi v Lidech ani jinde. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
10 KiB
05 - Dashboard, builder automatizaci a simulace
Stranky portalu
/dashboard prehled: dlazdice, graf za 14 dni, posledni tickety a incidenty
/dashboard/automatizace seznam a zalozeni nove
/dashboard/automatizace/:id builder: strom akci
/dashboard/konektory katalog sluzeb, jejich spousteču a akci
/dashboard/tickety seznam, filtry, prehled vytizeni tymu
/dashboard/tickety/:id detail ticketu: prubeh a log, resitel, zakaznik
/dashboard/incidenty prehled incidentu
/dashboard/nastaveni udaje o uctu
V postrannim menu je pod Nastavenim tlacitko Simulace.
Zivy dashboard
Portal drzi jedno SSE spojeni pro celou aplikaci. Zajistuje ho
EventStreamProvider v web/src/components/dashboard/.
- Stav spojeni ukazuje
LiveIndicatorv horni liste. Uzivatel musi poznat, ze data nejsou ziva. - Prichozi udalosti ukazuje
EventToastsjako bubliny vpravo dole. - Data se obnovuji sama.
useApiQueryma volitelnyrefetchOnse seznamem typu udalosti, po kterych se ma dotaz zopakovat. Vice udalosti tesne po sobe se slouci do jednoho nacteni.
Pri vypadku se stream znovu pripojuje s exponencialne rostoucim odstupem az do 15 sekund, aby pri vypadku serveru neubijel provoz.
Simulace provozu
Modalni okno se otevre tlacitkem Simulace. Umoznuje:
- zalozit ticket z vybraneho kanalu vcetne celeho logu, ktery k nemu vede, a s prepinacem, jestli se zakaznik v CRM dohleda nebo ne,
- vyvolat incident s vlastnim popisem, sluzbou a zavaznosti,
- vyresit prvni nevyrizeny ticket nebo bezici incident,
- spustit automatizaci uspesne nebo s chybou.
Kazda akce opravdu meni data na serveru, takze se projevi i v seznamech a v souhrnu, ne jen v bublinach.
Strom akci
Automatizace se sklada z spoustece a kroku. Krok je bud akce nad konektorem, nebo podminka se dvema vetvemi - proto je to strom, ne seznam.
interface AutomationFlow {
trigger: {
connectorId: string;
operationId: string;
fields: TriggerField[]; // vstupni parametry
webhookToken?: string; // generuje vyhradne server
} | null;
steps: FlowStep[];
}
type FlowStep =
| { id: string; kind: 'action'; connectorId: string; operationId: string }
| { id: string; kind: 'condition'; fieldId: string; operator: string;
value?: string; yes: FlowStep[]; no: FlowStep[] };
Podminka odkazuje na field.id, ne na nazev. Prejmenovani parametru proto
existujici podminky nerozbije.
Misto vlozeni urcuje FlowPath v web/src/lib/flow.ts: prazdne pole je hlavni
sekvence, [{ stepId, branch }] je vetev konkretni podminky.
Odkud se berou vstupni parametry
Jsou dva druhy spousteču a lisi se tim, kdo urcuje jejich parametry.
Parametry deklaruje uzivatel (webhook, formular). V katalogu maji
customPayload: true. V builderu se pridavaji rucne: nazev, typ (text, cislo,
ano-ne, datum) a povinnost.
Parametry urcuje sluzba (e-mail, WhatsApp, hlasova linka, ticket). V katalogu
je nese providedFields. Builder je ukazuje jen ke cteni a server je pri ulozeni
stromu vzdy dosadi z katalogu, jeste pred validaci. Podrobnosti a duvody jsou
v 06-tickety.md, sekce "Parametry od sluzby".
U spoustece typu webhook vygeneruje server pri ulozeni adresu
POST <verejna-adresa>/webhook/<token>.
Podminky pak porovnavaji hodnotu parametru, napriklad score >= 15. Nabidka
operatoru se ridi typem, na cislo nejde pustit "obsahuje". Tabulka operatoru je
na obou stranach - src/data/conditions.ts a web/src/lib/flow.ts. Server je
autorita, kopie na klientovi existuje jen proto, aby UI nenabidlo nesmysl.
Pri zmene upravit obe.
Dokud spoustec nema zadny parametr, nejde pridat podminka - nebylo by podle ceho se rozhodovat. Dialog to vysvetli.
Sirka karet pri zanoreni
Vetve ANO a NE jsou vedle sebe jen tehdy, kdyz je na to v dane karte misto.
Rozhoduje sirka karty, ne sirka okna - pouzivaji se container queries
(@container a @2xl:grid-cols-2 v FlowCanvas.tsx).
Duvod: kazde zanoreni pulí dostupnou sirku. S beznym lg:grid-cols-2 vypadal
strom na sirokem monitoru dobre v prvni urovni a ve treti uz mel karty siroke
par desitek pixelu, takze se popisy lamaly po jednom slove. Container query se
od urcite hloubky sama prepne na vetve pod sebou.
Ze stejneho duvodu se v uzke karte skryva popis akce (hidden @xs:block),
zmensuje ikona a ovladaci tlacitka se skladaji do sloupce. Nazev kroku
a nastaveni poli zustavaji vzdy videt - to je to podstatne.
Pri uprave stromu nepouzivat sm: / lg: na veci uvnitr karet. Reaguji
na okno a v zanoreni lzou.
Co je v kterem kroku videt
Krok vidi parametry spoustece plus vystupy vsech kroku pred nim. Akce muze
v katalogu deklarovat outputFields, napriklad "Dohledat firmu" vraci
customerKnown a companyName. Podminka i sablona se na ne muzou odkazat.
Vetev podminky nepridava nic do sekvence za podminkou, protoze nemusela
probehnout. Vypocet je v src/data/flowScope.ts, kopie pro UI ve flow.ts.
Odkaz na parametr, ktery ve strome vubec neni, je chyba 400. Odkaz na parametr, ktery vznika az v pozdejsim kroku (typicky po presunuti kroku), je nedodelek - ulozi se a rekne se, ze podminku staci posunout niz.
Nastaveni kroku
Akce muze mit nastavitelna pole (inputs v katalogu). Vyplnuji se primo na karte
kroku ve strome. Hodnota je sablona, {{nazev}} se nahradi parametrem spoustece,
takze jde rict "do obsahu ticketu dej text zpravy z WhatsApp".
Pod poli je nabidka parametru, kliknuti vlozi odkaz na pozici kurzoru.
Zatim to maji ticket, e-mail a WhatsApp. Ostatni akce maji jen fields, coz je
pouha napoveda - builder u nich napise, ze je zatim nejde nastavit. Cilovy stav
je prevest vsechny.
Podrobnosti vcetne toho, proc se odkazuje jmenem a ne ID, jsou v 06-tickety.md, sekce "Sablony".
Validace
Rozlisuji se dve veci:
Chyby vraci 400 a neulozi se: neexistujici konektor nebo operace, operace spatneho druhu, podminka na neexistujici parametr, operator nesedici na typ, duplicitni nebo nevalidni nazev parametru, nastaveni pole, ktere akce nema.
Nedodelky se ulozi, jen brani zapnuti: chybi spoustec, zadny krok, webhook
bez adresy, podminka bez hodnoty, nevyplnene povinne pole akce, sablona
odkazujici na parametr, ktery uz neexistuje. Vraci se v poli issues a builder
je vypise. Rozdelana prace se nikdy nezahazuje.
Pridani konektoru
- Pridat zaznam do
connectorsvsrc/data/connectors.tsvcetnetriggersaactions. - Pokud pouziva novou ikonu, doplnit klic do
web/src/lib/connectorIcons.ts. Musi existovat vlucide-react. - Pokud patri do nove kategorie, doplnit ji do
connectorCategoriesa do typuConnectorCategoryna obou stranach. - Pokud spoustec predava vlastni data, deklarovat je v
providedFields. ID parametru musi zustat stabilni, odkazuji se na ne podminky v ulozenych stromech.
Builder i katalog ji vezmou automaticky.
Co chybi
| Chybi | Poznamka |
|---|---|
inputs u zbylych konektoru |
zatim ticket, kanaly, CRM a AI, ostatni maji jen fields |
| Vazba logu ticketu na beh | log plni simulace, ne vykonany strom |
| Kombinovane podminky | jedna podminka je jedno porovnani, AND a OR jen vnorenim |
| Beh automatizaci | ulozeny strom se nevykonava |
| Historie behu a logy | prazdne, chybi runtime |
| Drag and drop | presouvani je zatim tlacitky nahoru a dolu |
Co je videt v kterem kroku
Krok vidi parametry spoustece a vystupy kroku pred nim. Vystupy z vetvi podminky plati i za podminkou, jen jako nepovinne - probehla prece jen jedna vetev.
Diky tomu jde poskladat bezny postup, kde hodnotu dava jednou jedna vetev a jednou druha:
Najit kontakt (podle ICO)
podminka: nenalezeno?
ano -> Najit kontakt (podle e-mailu)
podminka: porad nenalezeno?
ano -> Zalozit kontakt
Vlastni skript: partnerId = prvni vyplnene z ICO / mailu / zalozeni
Odkaz se jmenem kroku je jednoznacny ({{st_ico.contactId}}), takze dva kroky
se stejne pojmenovanym vystupem si neprekazi. Hole jmeno ({{contactId}})
znamena ten posledni vystup, ktery probehl.
Prace nad celym modelem
Odesilatel neposila ploche telo. Objednavka ze Shoptetu ma zanoreni, ceny v podobjektech a seznam polozek - a to je bezny pripad, ne vyjimka.
Ukazka tela
U spoustece s vlastnimi daty (webhook, formular) se vlepi telo z realneho
volani. Server z nej odvodi model, tedy seznam cest i s typy
(src/data/model.ts), a ten se v krocich nabizi ke kliknuti.
Neni to kontrakt: telo se nezahodi, kdyz se od ukazky lisi. Je to napoveda pro cloveka - prave ta u modelu o padesati cestach chybela.
Tlacitko Doplnit parametry pro podminky z hodnot v ukazce udela deklarovane parametry. Podminka se totiz pta na parametr, ne na cestu.
Odkaz muze byt cesta
| Odkaz | Co vrati |
|---|---|
{{callSid}} |
deklarovany parametr, jako driv |
{{data.order.code}} |
hodnotu z prijateho tela |
{{data.order.items[0].name}} |
prvni polozku seznamu |
{{st_faktura.invoiceId}} |
vystup kroku st_faktura |
{{item.amount}} |
polozku uvnitr smycky |
Overuje se jen prvni cast odkazu. Zbytek je cesta a tu predem overit nejde - co presne prijde v tele, vime az pri behu. Diky tomu ploche odkazy funguji dal presne jako driv.
Pro kazdou polozku
Krok foreach projde seznam a za kazdou polozku vykona vnoreny podstrom.
Pro kazdou polozku: data.order.items
+- CRM: upsert produktu kod {{item.code}}, nazev {{item.name}}
Uvnitr je {{item}} a {{index}}. Po skonceni je
{{st_loop.results}} seznam vysledku, kde kazdy zaznam nese index,
celou puvodni polozku a vystupy kroku:
[{ "index": 0, "item": { "code": "PROD-001", "amount": 2 }, "crmItemId": "42" }]
Proc i puvodni polozka: radek objednavky potrebuje jak ID z CRM, tak mnozstvi z puvodnich dat. Kdyby se neslo obe, muselo by se to znovu parovat podle kodu.
Na tenhle seznam pak jde poslat krok Transformace s prevodem Za kazdou polozku seznamu a poskladat z nej radky objednavky jednim volanim.
Strop 200 polozek. Vic uz neni automatizace, ale zatez, kterou nikdo necekal. Beh se zastavi a rekne to, misto aby seznam tise usekl.
Kdyz na ceste neni seznam, krok selze a v hlasce stoji, co tam misto nej je.