Platforma webinarowa
01 / 13
Rozdział 01

Instrukcja uruchomienia i przeprowadzenia webinaru

Dokument prowadzi krok po kroku od pustego środowiska do zakończonego webinaru z nagraniem i certyfikatami. Opisuje uruchomienie lokalne, na localhost, przeznaczone do testów przed wdrożeniem u klienta.

Dla kogo. Dla osoby, która ma uruchomić platformę na własnym komputerze i przeprowadzić na niej pełny webinar testowy: od utworzenia wydarzenia, przez zapis uczestnika, spotkanie na żywo, aż po podsumowanie i certyfikat.

Co obejmuje ten dokument

Rozdziały 2-5 to przygotowanie środowiska, wykonywane raz. Rozdziały 6-10 to cykl życia pojedynczego webinaru, powtarzany przy każdym wydarzeniu. Rozdział 12 to gotowy scenariusz testu, rozdział 12 to katalog typowych problemów.

2-5
Przygotowanie środowiska, jednorazowo
6-10
Cykl życia webinaru, przy każdym wydarzeniu
11-12
Test end-to-end i diagnostyka

Czym jest ta platforma

Aplikacja obsługuje pełny cykl życia szkolenia online: rejestrację uczestnika, przypomnienia mailowe i SMS, spotkanie wideo, interakcje na żywo (czat, pytania, zapisy na zadania, zapytania ofertowe), nagranie, podsumowanie i certyfikaty uczestnictwa.

Model wdrożenia zakłada osobną instancję dla każdego klienta, na jego serwerze i jego domenie. Jedno repozytorium, jedna wersja kodu, a różnice między klientami wyłącznie w konfiguracji.

Mapa cyklu życia wydarzenia

Utworzenie status DRAFT Publikacja PUBLISHED Zapisy + przypomnienia Spotkanie wideo + interakcje Nagranie obecność Podsum. certyfikat automat: przypomnienia wg reguł automat: 60 min po końcu
Rysunek 1. Cykl życia webinaru. Kroki niebieskie wykonuje organizator, szare dzieją się same.
Rozdział 02

Uruchomienie środowiska

Całość działa w Dockerze. Do testów lokalnych wystarczą cztery usługi, a wideo we własnym serwerze dokłada kolejne cztery.

Wymagania

SkładnikWersjaUwagi
Docker DesktopaktualnyZ obsługą Docker Compose v2
Wolna pamięć RAMmin. 4 GB8 GB przy profilu livekit: Egress uruchamia przeglądarkę
Wolne porty8080, 8081, 5432, 9000, 9001Dodatkowo 7880, 7881 i zakres UDP przy LiveKit
PrzeglądarkaChrome / EdgeDo testu wideo najlepiej dwie różne albo okno prywatne

Krok po kroku

Przygotuj plik konfiguracyjny

W katalogu projektu skopiuj wzorzec i uzupełnij sekrety. Plik .env nie trafia do repozytorium i jest inny dla każdej instancji.

# w katalogu Webinar-platform
cp .env.example .env

Uzupełnij co najmniej: JWT_SECRET (minimum 32 znaki, inaczej aplikacja nie wystartuje), DB_PASSWORD, MINIO_SECRET_KEY oraz ADMIN_EMAIL i ADMIN_PASSWORD.

Zbuduj i uruchom kontenery

Pierwsze uruchomienie buduje obrazy i pobiera zależności, więc trwa kilka minut.

docker compose up -d --build

Startują cztery usługi: postgres, minio, backend i frontend. Backend sam wykonuje migracje Flyway, więc baza jest gotowa bez dodatkowych poleceń.

Sprawdź, czy wszystko wstało

docker compose ps
curl http://localhost:8080/api/health

Poprawna odpowiedź to {"status":"UP","version":"0.1.0"}. Jeśli backend nie odpowiada, zajrzyj do logów: docker compose logs -f backend.

Uruchom wideo, jeśli chcesz testować spotkanie u siebie

Serwer LiveKit siedzi w osobnym profilu, wyłączonym domyślnie: instancja w trybie NONE albo na Jitsi nie ma powodu go uruchamiać.

docker compose --profile livekit up -d

Profil dokłada cztery kontenery: livekit (serwer), coturn (TURN), redis i livekit-egress (nagrywanie). Same spotkania działają bez dwóch ostatnich, ale nagrywanie bez nich nie działa wcale.

Do uruchomienia lokalnego ustaw LIVEKIT_NODE_IP=127.0.0.1 w .env. Bez tego serwer rozgłasza publiczny adres łącza, a przeglądarka na tej samej maszynie nie zestawi połączenia: uczestnik wejdzie do pokoju i zobaczy listę obecnych, ale nie popłynie ani obraz, ani dźwięk.

Adresy po uruchomieniu

AdresCo to jest
http://localhost:8081Aplikacja: panel i strony publiczne
http://localhost:8080/apiAPI backendu
http://localhost:8080/api/healthStan aplikacji
http://localhost:9001Konsola MinIO (nagrania, materiały, pliki)
localhost:5432PostgreSQL, do podłączenia klientem SQL

Nigdy nie używaj docker compose down -v. Flaga -v kasuje wolumeny, czyli bazę i MinIO razem z całą konfiguracją instancji: danymi SMTP, kluczami bramki SMS i kluczami dostawcy wideo. Tych wartości nie ma nigdzie indziej, bo konfiguracja poczty i SMS idzie wyłącznie przez panel, a nie przez .env. Do zatrzymania służy docker compose down bez flagi.

Rozdział 03

Pierwsze logowanie

Konto administratora powstaje automatycznie przy pierwszym starcie backendu, na podstawie zmiennych z .env.

Otwórz panel

Wejdź na http://localhost:8081. Aplikacja przekieruje na ekran logowania pod /logowanie.

Ekran logowania. Login to wartość ADMIN_EMAIL z pliku .env.
Ekran logowania. Login to wartość ADMIN_EMAIL z pliku .env.

Zaloguj się danymi z .env

Login to wartość ADMIN_EMAIL, hasło to ADMIN_PASSWORD. Jeśli hasła nie podano, aplikacja wylosowała je i wypisała raz w logu przy pierwszym starcie:

docker compose logs backend | grep -i has

Zmień hasło, jeśli aplikacja o to poprosi

Konto z hasłem wygenerowanym automatycznie ma ustawioną flagę wymuszającą zmianę przy pierwszym logowaniu.

Trzy pomyłki i konto czeka. Aplikacja liczy nieudane logowania: po pięciu próbach na ten sam adres konto jest blokowane na 15 minut. Wszystkie błędy logowania dają identyczny komunikat: złe hasło, nieznany adres i konto nieaktywne wyglądają tak samo, żeby nie dało się ustalić, które konta istnieją.

Co widzisz po zalogowaniu

Podsumowanie. Ekran główny panelu: nadchodzące wydarzenia i sprawy czekające na obsługę.
Podsumowanie. Ekran główny panelu: nadchodzące wydarzenia i sprawy czekające na obsługę.

Ekranem głównym panelu jest Podsumowanie pod adresem /. Pokazuje wyłącznie rzeczy, na które można zareagować: co się zbliża i co czeka na obsługę. Lewe menu ma następujące pozycje:

PozycjaAdresDo czego służyRola
Podsumowanie/Nadchodzące wydarzenia i sprawy do obsługiwszyscy
Webinary/webinaryLista wydarzeń, tworzenie i edycjawszyscy
Kontakty/kontaktyBaza kontaktów, grupy, import, zaproszeniawszyscy
Zapytania/zapytaniaZapytania ofertowe ze wszystkich webinarówwszyscy
Banery/baneryReklamy globalne instancjitylko ADMIN
Ustawienia/ustawieniaKonfiguracja instancjitylko ADMIN
Użytkownicy/uzytkownicyKonta panelutylko ADMIN

Dwie role. ADMIN ma dostęp do wszystkiego. MODERATOR prowadzi webinary i obsługuje zapytania, ale nie widzi ustawień, banerów globalnych ani użytkowników. Ukrycie pozycji menu to wygoda, a nie zabezpieczenie: regułą jest kontrola po stronie backendu.

Rozdział 04

Konfiguracja instancji

Wszystko poza sekretami startowymi ustawia się w panelu, w /ustawienia. Zmiany działają natychmiast, bez restartu aplikacji.

Dlaczego przez panel, a nie przez .env. Konfiguracja poczty i SMS trafia do tabeli app_settings, dzięki czemu klient zmienia ją sam, bez dostępu do serwera i bez restartu. W .env zostają wyłącznie rzeczy potrzebne do wystartowania: sekret JWT, hasło bazy i klucze MinIO.

Podstrony ustawień

PodstronaAdresCo ustawia
Aplikacja/ustawieniaNazwa marki, adres publiczny, strefa czasowa, wideo, pokój, limity
Grafika/ustawienia/grafikaLogo i ikona karty przeglądarki, z kadrowaniem
E-mail/ustawienia/emailSerwer SMTP, nadawca, tryb bezpieczny, limit godzinowy
SMS/ustawienia/smsBramka SMS, klucz API, tryb bezpieczny
Przypomnienia/ustawienia/przypomnieniaDomyślny harmonogram przypomnień dla nowych webinarów
Zgody/ustawienia/zgodyTreść zgód i ich wersja
Ustawienia aplikacji. Adres publiczny, nazwa marki, strefa czasowa i wybór dostawcy wideo.
Ustawienia aplikacji. Adres publiczny, nazwa marki, strefa czasowa i wybór dostawcy wideo.

Minimum do przeprowadzenia webinaru

Ustaw adres publiczny instancji

W /ustawienia pole APP_PUBLIC_URL. Lokalnie: http://localhost:8081.

To jest przedrostek każdego linku wysyłanego w mailu: potwierdzenia zapisu, przypomnienia, wejścia do pokoju. Nie ma wartości domyślnej i to jest celowe: adres localhost wstawiony automatycznie trafiłby do linków na produkcji i nic nie sygnalizowałoby błędu.

Nazwa marki i strefa czasowa

APP_BRAND_NAME pojawia się w panelu, na stronach publicznych i w mailach. APP_TIMEZONE to domyślna strefa nowych webinarów, standardowo Europe/Warsaw.

Skonfiguruj pocztę

W /ustawienia/email uzupełnij serwer SMTP, port, login, hasło i nazwę nadawcy. Bez działającej poczty uczestnik nie dostanie potwierdzenia zapisu ani linku do pokoju.

Pod formularzem jest test wysyłki: wpisz adres i wyślij wiadomość próbną. Test zwraca pełną treść błędu z serwera SMTP, więc od razu widać, czy problem jest w porcie, w SSL czy w haśle.

Sprawdź tryb bezpieczny

Zanim wyślesz cokolwiek, przeczytaj rozdział 5. Domyślnie cała wysyłka jest przekierowana na jeden adres i to jest zachowanie zamierzone.

Ustawienia poczty. Pole hasła jest puste, a obok widnieje oznaczenie „ustawione”. Pod formularzem jest test wysyłki.
Ustawienia poczty. Pole hasła jest puste, a obok widnieje oznaczenie „ustawione”. Pod formularzem jest test wysyłki.

Pole sekretne zachowuje się inaczej

Hasła i klucze API nigdy nie wracają z API. Pole jest zawsze puste, a obok widnieje oznaczenie „ustawione”, gdy wartość jest w bazie. Puste pole przy zapisie oznacza „nie zmieniaj”, a nie „wyczyść”. Dzięki temu zapis formularza nie kasuje hasła, którego nigdy nie widziałeś.

Rozdział 05

Tryb bezpieczny wysyłki

Najważniejszy rozdział dla testów. Domyślnie włączony bezpiecznik kieruje całą pocztę i wszystkie SMS-y na jeden wskazany adres.

Ten mechanizm powstał po realnym incydencie. Zadanie podsumowań potraktowało webinary z danymi testowymi jako zakończone i wysłało 12 wiadomości przez produkcyjny serwer SMTP klienta, w tym 10 na nieistniejące adresy. Dane testowe z terminem w przeszłości wystarczą, żeby scheduler ruszył.

Jak to działa

UstawienieDomyślnieZnaczenie
MAIL_SAFE_MODEtrueCała poczta idzie na adres z MAIL_SAFE_RECIPIENT
MAIL_SAFE_RECIPIENTpusteAdres zastępczy odbiorcy
SMS_SAFE_MODEtrueWszystkie SMS-y na numer z SMS_SAFE_RECIPIENT
MAIL_RATE_LIMIT_PER_HOUR100Bezpiecznik ilościowy poczty
SMS_RATE_LIMIT_PER_HOUR20Bezpiecznik ilościowy SMS

Tryb włączony bez ustawionego adresu wstrzymuje wysyłkę, zamiast przepuścić ją do prawdziwego odbiorcy. Jeśli maile „nie wychodzą”, sprawdź najpierw, czy MAIL_SAFE_RECIPIENT jest uzupełnione. Cicha wysyłka przy włączonym zabezpieczeniu byłaby najgorszym z możliwych zachowań: administrator jest wtedy przekonany, że nic nie wychodzi.

Sprawdzenie stanu przed testem

Ustawienia zmieniają się przez panel, bez restartu aplikacji, więc wartość sprzed kilku minut może już nie obowiązywać. Przed każdym krokiem, który może wysłać wiadomość, sprawdź faktyczny stan w bazie:

docker exec webinar-postgres psql -U webinar -d webinar -c \
  "SELECT \"key\", value FROM app_settings
   WHERE \"key\" LIKE '%SAFE%' OR \"key\"='SMS_ENABLED';"

Zalecenie na czas testów lokalnych: zostaw oba tryby bezpieczne włączone i ustaw w nich swój własny adres oraz numer. Zobaczysz każdą wiadomość, którą system chciał wysłać, i nikt postronny jej nie dostanie.

Co zapisuje dziennik

Wpis w tabeli notifications zachowuje prawdziwego odbiorcę, nie zastępczego. Dziennik dokumentuje zamiar wysyłki, więc po wyłączeniu trybu bezpiecznego nadal wiadomo, kto co miał dostać.

Przekroczenie limitu to nie błąd

Wiadomość ponad limit godzinowy dostaje status oczekującej, a nie nieudanej. Ma pójść, tylko później: zadanie w tle podejmie ją przy kolejnym przebiegu. Zaproszenie na całą bazę kontaktów to największy jednorazowy ruch w aplikacji, więc to tam bezpiecznik zadziała najczęściej.

Rozdział 06

Webinar testowy: komplet danych do wpisania

Wszystkie kolejne rozdziały pokazują jeden konkretny webinar: szkolenie o ocenie ryzyka i bezpieczeństwie wody po nowelizacji z 13 marca 2026 r. Ten rozdział zbiera wartości do wpisania, a następne pokazują je na zrzutach z działającej instancji.

Dlaczego akurat ten temat. Szkolenie o zmianie przepisów jest typowym zastosowaniem tej platformy: ma ostry termin wynikający z kalendarza ustawowego, precyzyjnie określoną grupę odbiorców i naturalny powód, by zbierać zapytania ofertowe. Sprawdza więc te mechanizmy, które przy sztucznych danych testowych zwykle zostają nietknięte.

Zakładka Podstawowe

Wartości do wpisania
TytułOcena ryzyka i bezpieczeństwo wody - obowiązki, terminy i sankcje 2026
Adres strony zapisuocena-ryzyka-i-bezpieczenstwo-wody-obowiazki-terminy-i-sankcje-2026
Krótki opisTrzy warstwy oceny ryzyka, kalendarz terminów i katalog kar po nowelizacji z 13 marca 2026 r. Dla wodociągów, zakładów przemysłowych i zarządców obiektów priorytetowych.

Adresu nie wpisuj ręcznie. Powstaje sam z tytułu: polskie znaki są transliterowane, spacje zamieniane na łączniki, a konflikt z istniejącym adresem rozstrzyga sufiks liczbowy. Powyższa wartość to dokładnie to, co wygeneruje aplikacja.

Zakładka Termin

Wartości do wpisania
Strefa czasowaEurope/Warsaw
Rozpoczęciedziś, za 10 minut (do testu)
Zakończeniedziś, za 70 minut (godzina szkolenia)

Start za 10 minut to celowy wybór. Okno wejścia otwiera się 15 minut przed startem, więc pokój jest dostępny natychmiast, a termin pozostaje w przyszłości i nie uruchamia zadania podsumowań. Przy prawdziwym szkoleniu wpisz oczywiście rzeczywistą datę.

Zakładka Zapisy

Wartości do wpisania
Zapisy otwartewłączone
Limit miejsc50
Termin zapisówpuste (bez terminu granicznego)
Link do spotkaniapuste - pokój zakłada LiveKit

Zakładka Treść strony

Treść buduje program szkolenia z materiału źródłowego. Struktura, która sprawdza się w praktyce: dla kogo, program, podstawa prawna, zastrzeżenie.

Nagłówek: Dla kogo jest to szkolenie
Dla przedsiębiorstw wodociągowo-kanalizacyjnych, zakładów przemysłowych z własnym ujęciem wody oraz właścicieli i zarządców obiektów priorytetowych, w których ponad 50 osób dziennie jest narażonych na ryzyko związane z wodą.
Nagłówek: Program (lista numerowana)
1Trzy warstwy oceny ryzyka: obszar zasilania ujęcia, system zaopatrzenia w wodę, wewnętrzny system wodociągowy.
2Kto podlega i od jakiego progu: 10 m3 na dobę, 50 osób, 500 osób, 100 m3 na dobę.
3Kalendarz terminów: 31 grudnia 2026 r. dla obszaru zasilania, 30 czerwca 2028 r. dla pozostałych warstw.
4Katalog sankcji: 10 zł za każdy dzień zwłoki, pasmo do 60 000 zł dla dostawcy wody, do 10 000 zł dla obiektu priorytetowego.
5Kto może wykonać ocenę ryzyka wewnętrznego systemu wodociągowego: wymagania kwalifikacyjne z art. 4l.
6Sześć kwestii, które przemysł musi rozstrzygnąć przed 31 grudnia 2026 r.
7Najczęstsze błędy w opracowaniach obiegowych i jak ich uniknąć w dokumentacji.
Nagłówek: Podstawa prawna
Materiał opiera się na ustawie z dnia 13 marca 2026 r. (Dz.U. 2026 poz. 605), obowiązującej od 21 maja 2026 r., oraz na rozporządzeniu Ministra Zdrowia z dnia 22 maja 2026 r. (Dz.U. 2026 poz. 748).
Szkolenie nie stanowi porady prawnej. Kwalifikacja konkretnego podmiotu jako dostawcy wody lub obiektu priorytetowego wymaga potwierdzenia u właściwego organu nadzoru sanitarnego.

Listę numeruje edytor, nie Ty. Wpisanie własnych numerów na początku pozycji daje na stronie „2. 2.”. Użyj przycisku listy numerowanej i wpisuj samą treść. To zdarzyło się przy przygotowaniu tej dokumentacji i widać było na pierwszym zrzucie.

Zakładka Wideo

Wartości do wpisania
DostawcaDomyślny z instancji (LiveKit)
Pokójprzycisk „Utwórz pokój u dostawcy”
Prelegent: imię i nazwiskoDr inż. Anna Wiśniewska
Prelegent: adres e-mailprelegent@example.test

Zakładka Przypomnienia

Przy szkoleniu z terminem ustawowym harmonogram domyślny instancji jest wystarczający:

Harmonogram domyślny
24 godziny przede-mail
1 godzina przede-mail
15 minut przedSMS (tylko za zgodą i z numerem telefonu)

Dane uczestnika testowego

Formularz zapisu na stronie publicznej
ImięPiotr
NazwiskoZatorski
Adres e-mailpzators@go2.pl
Telefon453193605
FirmaSoftSPM
Zgodywszystkie trzy zaznaczone

Użyj własnego adresu i numeru. Przy włączonym trybie bezpiecznym i tak wszystko trafi na adres zastępczy, ale zapis z prawdziwym adresem pozwala sprawdzić, czy wiadomość dotarła i jak wygląda.

Materiał źródłowy

Treść merytoryczna pochodzi z opracowania „Plany bezpieczeństwa wody i ocena ryzyka - podstawy prawne, terminy i sankcje”, stan prawny na 27 sierpnia 2026 r. Kluczowe liczby, przydatne przy budowaniu zadań i tematów zapytań:

WartośćZnaczenie
31.12.2026Pierwsza ocena ryzyka obszaru zasilania ujęcia - najbliższy twardy termin
30.06.2028Pierwsza ocena systemu zaopatrzenia i wewnętrznego systemu wodociągowego
50 osóbPróg obiektu priorytetowego: powyżej tej liczby dziennie narażonych na ryzyko
10 zł / dzieńKara za zwłokę w przekazaniu oceny, maksymalnie za 365 dni (3 650 zł)
do 60 000 złPasmo kar dla dostawcy wody za naruszenia operacyjne
do 10 000 złPasmo kar dla właściciela lub zarządcy obiektu priorytetowego
12 latOkres przechowywania oceny ryzyka wewnętrznego systemu wodociągowego
Rozdział 07

Utworzenie webinaru

Formularz jest podzielony na zakładki, ale zapis jest jeden. Przechodzenie między zakładkami nie gubi niezapisanych zmian.

Wejdź w Webinary i kliknij Nowy webinar (adres /webinary/nowy).

Zakładka Podstawowe. Adres strony zapisu powstał sam z tytułu, z transliteracją polskich znaków.
Zakładka Podstawowe. Adres strony zapisu powstał sam z tytułu, z transliteracją polskich znaków.

Trzy zakładki są dostępne dopiero po zapisaniu. Nagrania i materiały, Przypomnienia oraz Wideo wymagają istniejącego webinaru, bo pliki, reguły i pokój muszą być do czegoś przypisane. Przy tworzeniu zobaczysz w nich komunikat wyjaśniający.

Zakładka: Podstawowe

PoleWymaganeOpis
TytułtakMaksymalnie 255 znaków. Widoczny wszędzie: na stronie zapisu, w mailach, na certyfikacie
Adres strony zapisunieKońcówka adresu po /w/. Podpowiadana z tytułu, dopóki jej nie dotkniesz. Konflikty rozstrzyga backend sufiksem liczbowym
Krótki opisnieJedno, dwa zdania bez formatowania. Trafia do zajawki linku w komunikatorach i do treści maili

Przy adresie strony są przyciski Kopiuj oraz, w trybie edycji, Otwórz. Jeśli nie ustawiłeś adresu publicznego instancji, pojawi się tu ostrzeżenie.

Opis to nie treść strony. To dwie różne rzeczy: opis jest krótką zajawką, a treść strony to długi materiał z edytora. Nie zastępuj jednego drugim.

Zakładka: Treść strony

Zakładka Treść strony. Edytor wizualny z programem szkolenia. Numerację listy nadaje edytor.
Zakładka Treść strony. Edytor wizualny z programem szkolenia. Numerację listy nadaje edytor.

Edytor wizualny, w którym buduje się zawartość publicznej strony zapisu: nagłówki, listy, obrazki, linki i wyrównanie. Treść pojawia się nad formularzem zapisu. Pusta treść oznacza stronę z samym formularzem.

Obrazki wstawia się z biblioteki mediów. Trafiają do MinIO, a do treści wchodzi adres, nigdy dane w base64.

Treść jest czyszczona na backendzie przy każdym zapisie, według białej listy. Do bazy trafia wyłącznie wersja oczyszczona. Obrazek z obcego serwera jest usuwany, bo ujawniałby adresy IP odwiedzających właścicielowi obcego serwera.

Zakładka: Termin

Godziny podaje się w strefie webinaru, a nie w strefie przeglądarki. Strefa jest wypisana przy każdym polu.

PoleWymaganeOpis
Strefa czasowanieDomyślnie Europe/Warsaw
RozpoczęcietakData i godzina startu
ZakończenietakMusi być późniejsze niż rozpoczęcie. Wyznacza moment startu automatów po webinarze
Zakładka Termin. Godziny podawane są w strefie webinaru, wypisanej przy każdym polu.
Zakładka Termin. Godziny podawane są w strefie webinaru, wypisanej przy każdym polu.

Do testu ustaw termin w przyszłości. Termin w przeszłości uruchamia zadanie podsumowań i zamyka zapisy. Jeśli chcesz od razu wejść do pokoju, patrz scenariusz w rozdziale 12.

Zakładka: Zapisy

PoleOpis
Zapisy otwartePrzełącznik, domyślnie włączony. To intencja, a nie stan faktyczny
Termin zapisówNie może być późniejszy niż początek webinaru. Puste oznacza brak terminu granicznego
Limit miejscLiczba całkowita, minimum 1. Puste oznacza brak limitu
Link do spotkaniaWysyłany w mailu potwierdzającym. Nie jest pokazywany publicznie. Wypełniany ręcznie w trybie NONE
Zakładka Zapisy. Limit 50 miejsc, zapisy otwarte, bez terminu granicznego.
Zakładka Zapisy. Limit 50 miejsc, zapisy otwarte, bez terminu granicznego.

Przełącznik „zapisy otwarte” to intencja, a nie stan faktyczny. Aplikacja nigdy nie zmienia go sama. Rzeczywistą dostępność wylicza z intencji, terminu, limitu miejsc i statusu, dzięki czemu po rezygnacji uczestnika zapisy wracają do stanu ustawionego przez Ciebie, zamiast otwierać się same.

Limit miejsc jest pilnowany pod blokadą wiersza w bazie. Kilkadziesiąt równoczesnych zapisów na dziesięć miejsc skończy się dokładnie dziesięcioma wpisami.

Zakładka: Przypomnienia

Lista reguł, każda z odstępem przed startem i kanałem. Nowy webinar dostaje harmonogram domyślny z ustawień instancji, a tu można go zmienić dla konkretnego wydarzenia.

Odstęp wybiera się z gotowych wartości albo podaje własny w dniach, godzinach lub minutach. Pod spodem widać skutek zwykłym zdaniem, na przykład „Zostanie dodane przypomnienie 7 dni przed, wysyłane przez e-mail”.

SMS wymaga zgody marketingowej i numeru telefonu. Uczestnik bez zgody dostanie tylko przypomnienia mailowe. Treść SMS jest celowo bez polskich znaków: ogonki przełączają bramkę na kodowanie, w którym limit spada ze 160 do 70 znaków i jedna wiadomość rozbija się na kilka płatnych części.

Przypomnienie spóźnione bardziej niż okno tolerancji (domyślnie 30 minut) nie idzie w ogóle. Chroni to przed lawiną wysyłek wstecz po restarcie aplikacji.

Pozostałe zakładki

Zakładka Przypomnienia. Każda reguła to odstęp i kanał, a pod spodem zdanie opisujące skutek.
Zakładka Przypomnienia. Każda reguła to odstęp i kanał, a pod spodem zdanie opisujące skutek.

Wideo - wybór dostawcy dla tego webinaru, zakładanie pokoju i lista prelegentów. Opisane w rozdziale 8.

Nagrania i materiały - wgrywanie plików do własnego składu, z ustawieniem widoczności.

Po webinarze - adresy nagrania i materiałów, gdy pliki leżą poza systemem (dysk sieciowy, YouTube), oraz przycisk Wyślij powiadomienie o nagraniu.

Przycisk powiadomienia działa na zapisanym adresie nagrania, a nie na treści pola. Inaczej powiadomienie niosłoby link sprzed edycji.

Walidacja

Formularz sprawdza dane przed wysłaniem i pokazuje zbiorczy komunikat „Formularz zawiera błędy”. Reguły:

  • tytuł nie może być pusty,
  • oba terminy są wymagane, a zakończenie musi być późniejsze niż rozpoczęcie,
  • termin zapisów nie może być późniejszy niż początek webinaru,
  • limit miejsc musi być liczbą dodatnią.

Błąd walidacji na nieaktywnej zakładce jest widoczny. Zakładka z błędem dostaje kropkę, a próba zapisu przeskakuje na pierwszą wadliwą. Komunikat nigdy nie wskazuje pola, którego nie widać.

Lista po zapisaniu. Webinar ma status roboczy i nie jest jeszcze widoczny publicznie.
Lista po zapisaniu. Webinar ma status roboczy i nie jest jeszcze widoczny publicznie.

Zapis i status

Po zapisaniu webinar ma status DRAFT. Nie jest widoczny publicznie: strona zapisu zwraca 404, a zajawka dla robotów też go nie pokaże. To stan roboczy, w którym można spokojnie dopracować treść.

Rozdział 08

Wideo i prelegenci

Platforma nie jest przywiązana do jednego dostawcy wideo. Wybór jest świadomą decyzją, bo dostawcy różnią się tym, czy uprawnienia są egzekwowane, czy jedynie deklarowane.

Co gwarantuje który dostawca

DostawcaUprawnienia egzekwujeRozróżnia audio i wideoNagrywanie
LIVEKITserwer, na podstawie podpisanego tokenutakWymaga kontenerów Egress i Redis
DAILYserwertakPobierane od dostawcy po zakończeniu
JITSI z JWTserwer, ale tylko rolę moderatoranieRęczne wgranie pliku
JITSI bez JWTnikt: pokój otwartynieRęczne wgranie pliku
NONEnie dotyczy, obraz poza platformąnie dotyczyRęczne wgranie pliku

Przy Jitsi bez JWT role są umowne. Pokój jest otwarty dla każdego, kto zna adres, a ukrycie przycisku kamery w interfejsie to jedyne, co dzieli uczestnika od publikacji: wystarczy otworzyć ten sam pokój wprost na domenie Jitsi, żeby to obejść. Panel ostrzega o tym przy wyborze dostawcy. Kto potrzebuje gwarancji, wybiera LiveKit.

Tryb NONE jest równoprawny, nie awaryjny. Instancja bez dostawcy w pełni obsługuje webinary: organizator wkleja własny link do spotkania, a czat, pytania, zadania i banery zostają w platformie. Wielu klientów zostaje przy tym na stałe.

Trzy role w pokoju

RolaUprawnienia
PrelegentPublikuje obraz i dźwięk
UczestnikTylko odbiera, ma czat i pytania
Uczestnik z głosemPublikuje wyłącznie dźwięk, po zgodzie moderatora

Wideo uczestników jest zawsze wyłączone na poziomie uprawnień w tokenie, także po podniesieniu do roli z głosem. Przy LiveKit uczestnik nie włączy kamery, choćby podmienił kod strony albo wszedł własnym klientem: serwer odrzuci strumień.

Założenie pokoju

Otwórz zakładkę Wideo w formularzu webinaru

Możesz zostawić dostawcę instancji albo wybrać innego tylko dla tego wydarzenia.

Kliknij „Utwórz pokój u dostawcy”

Konfiguracja jest sprawdzana od razu, żebyś zobaczył brak klucza teraz, a nie dowiedział się o nim od uczestnika minutę przed startem.

W trybie NONE nie ma czego zakładać: zamiast tego wklej własny link w polu „Link do spotkania” w zakładce Zapisy. Panel ostrzeże, jeśli link jest pusty, bo uczestnik nie miałby wtedy gdzie wejść.

Dodaj prelegentów

W sekcji Prelegenci podaj Imię i nazwisko oraz Adres e-mail, po czym kliknij Dodaj prelegenta. Aplikacja wygeneruje indywidualny link wejścia.

Adres służy wyłącznie do odróżnienia prelegentów. Zaproszenie wysyłasz sam, kopiując link przyciskiem Kopiuj link.

Dodawanie prelegenta. Imię, nazwisko i adres. Adres służy tylko do odróżnienia prelegentów.
Dodawanie prelegenta. Imię, nazwisko i adres. Adres służy tylko do odróżnienia prelegentów.
Prelegent dodany. Przycisk „Kopiuj link” podaje indywidualny adres wejścia. Zaproszenie wysyłasz sam.
Prelegent dodany. Przycisk „Kopiuj link” podaje indywidualny adres wejścia. Zaproszenie wysyłasz sam.

Prelegent nie jest uczestnikiem. Nie przechodzi przez formularz zapisu i nie wyraża zgód, więc nie liczy się do liczby zapisanych ani do statystyk zgód. Wchodzi bez ograniczenia okna czasowego, bo musi sprawdzić sprzęt przed uczestnikami.

Pokój założony u dostawcy. Zielona ramka potwierdza, że uprawnienia egzekwuje serwer na podstawie podpisanego tokenu.
Pokój założony u dostawcy. Zielona ramka potwierdza, że uprawnienia egzekwuje serwer na podstawie podpisanego tokenu.

Podniesienie głosu zapisanemu uczestnikowi

Poza prelegentami można nadać prawo głosu osobie, która zapisała się normalnie. Służy do tego kolumna Głos na liście zapisanych. Taki uczestnik dostaje prawo publikacji wyłącznie dźwięku: uprawnienia moderatora ma tylko prelegent wchodzący własnym linkiem.

Dwie kolumny dostawcy, nie jedna

Webinar pamięta dwie różne rzeczy: kto ma go obsługiwać (wybór administratora) i u kogo pokój faktycznie stoi (stan zapisany przez aplikację). Rozbieżność między nimi nie jest błędem, tylko sygnałem: „zmieniono dostawcę, pokój wciąż stoi u poprzedniego”. Panel pyta wtedy o potwierdzenie i zamyka stary pokój.

Rozdział 09

Publikacja i zapisy

Publikacja otwiera stronę zapisu dla świata. Do tego momentu wydarzenie jest niewidoczne.

Statusy webinaru

StatusZnaczenieStrona publiczna
DRAFTWersja robocza, stan początkowy404, także dla robotów
PUBLISHEDOpublikowany, zapisy wg reguł dostępnościWidoczna
CANCELLEDOdwołany, zapisy zamykają się sameWidoczna z informacją o odwołaniu
FINISHEDStatus istnieje w modelu, ale nic go nie ustawia-

Podział na wydarzenia aktywne i zakończone idzie po terminie zakończenia, nie po statusie. Zakładka „Zakończone” na liście pokazuje webinary po ich terminie końca. Filtrowanie po statusie FINISHED dawałoby zawsze pustą listę, bo nic w aplikacji tego statusu nie ustawia.

Warunki publikacji

Przycisk publikacji jest w wierszu listy webinarów, widoczny dopóki wydarzenie nie jest opublikowane ani odwołane. Publikacja przechodzi tylko wtedy, gdy webinar ma:

  • niepusty tytuł,
  • niepusty adres strony zapisu,
  • oba terminy uzupełnione,
  • status inny niż odwołany - webinaru odwołanego nie da się opublikować ponownie.

Sprawdź stronę przed publikacją

Ikona oka w wierszu listy otwiera kartę webinaru /webinary/{id} w nowej karcie przeglądarki. Zakładka „Treść strony” pokazuje dokładnie to, co zobaczy uczestnik.

Opublikuj

Status zmienia się na PUBLISHED, strona zapisu staje się dostępna, a w wierszu listy pojawia się ikona Prowadź spotkanie.

Otwórz stronę zapisu

Adres to http://localhost:8081/w/{slug}. Ta sama strona, którą dostanie uczestnik.

Po publikacji. Status zmienia się na opublikowany, a w wierszu pojawia się ikona prowadzenia spotkania.
Po publikacji. Status zmienia się na opublikowany, a w wierszu pojawia się ikona prowadzenia spotkania.

Karta webinaru

Karta pod /webinary/{id} zbiera wszystko, co należy do jednego wydarzenia, w ośmiu zakładkach:

ZakładkaZawartość
Treść stronyPodgląd tego, co widzi uczestnik
ZaproszeniaWysyłka do kontaktów z bazy, z podglądem liczby odbiorców
ZapisaniLista uczestników z licznikiem
BaneryReklamy tego webinaru
CertyfikatyWydawanie i unieważnianie dokumentów
StatystykiObecność, aktywność, skuteczność
Zapytania ofertoweKontakty handlowe z tego wydarzenia, z licznikiem
Historia czatuArchiwum rozmowy, z wiadomościami usuniętymi przez moderatora
Karta webinaru. Osiem zakładek zbiera wszystko, co należy do jednego wydarzenia.
Karta webinaru. Osiem zakładek zbiera wszystko, co należy do jednego wydarzenia.

Zapis uczestnika

Uczestnik podaje dane, zaznacza zgody i wysyła formularz. Po zapisie dostaje mail z potwierdzeniem, załącznikiem kalendarza invite.ics i linkiem do własnego zapisu pod /zapis/{token}, gdzie może sprawdzić szczegóły albo zrezygnować.

Publiczna strona zapisu. Treść nad formularzem, licznik wolnych miejsc, formularz zawsze na dole.
Publiczna strona zapisu. Treść nad formularzem, licznik wolnych miejsc, formularz zawsze na dole.

Zgody

Żadna zgoda nie jest zaznaczona domyślnie, także ta wymagana. Zaznaczanie zgody za użytkownika jest niedopuszczalne.

Zgody są dopisywane, nigdy nadpisywane. Ponowny zapis tworzy nowe wpisy, a stare zostają jako ślad rozliczalny. Zapisywana jest także odmowa.

Brak enumeracji uczestników

Przy próbie zapisu na już zapisany adres API zwraca tę samą odpowiedź co przy sukcesie i wysyła mail informujący, że zapis już istnieje.

Gdyby zwracało błąd, dałoby się sprawdzać, kto jest zapisany na dane szkolenie.

Link do spotkania nie trafia do publicznego API. Idzie wyłącznie do maila potwierdzającego i do podglądu własnego zapisu po tokenie, i tylko wtedy, gdy zapis nie jest anulowany.

Formularz zapisu wypełniony. Żadna zgoda nie jest zaznaczona domyślnie, także wymagana.
Formularz zapisu wypełniony. Żadna zgoda nie jest zaznaczona domyślnie, także wymagana.
Potwierdzenie zapisu. Ten sam ekran zobaczy osoba, która zapisuje się drugi raz tym samym adresem.
Potwierdzenie zapisu. Ten sam ekran zobaczy osoba, która zapisuje się drugi raz tym samym adresem.

Rezygnacja z udziału jest możliwa ze strony własnego zapisu. Ponowny zapis po rezygnacji jest dozwolony, a zakolejkowane przypomnienia są przy rezygnacji kasowane.

Zaproszenia z bazy kontaktów

Poza publiczną stroną zapisu można zaprosić kontakty z bazy. Zakładka Zaproszenia pozwala wybrać grupy, zobaczyć podgląd liczby odbiorców po odfiltrowaniu wypisanych, osób bez zgody i już zaproszonych, a potem wysłać.

Jedno zaproszenie na osobę i wydarzenie. Powtórna wysyłka po dołożeniu kontaktów do grupy nie zaprosi drugi raz tych, którzy już dostali wiadomość. Warunki są sprawdzane ponownie tuż przed wysyłką: kontakt mógł się wypisać między zakolejkowaniem a wysłaniem.

Każda wiadomość marketingowa ma stopkę z linkiem wypisania. Maile transakcyjne - potwierdzenie, przypomnienie, podsumowanie - jej nie mają i nie podlegają wypisaniu: to obsługa zamówionej usługi, a nie marketing.

Rozdział 10

Przeprowadzenie webinaru

W dniu wydarzenia pracujesz na dwóch ekranach: sali spotkania i panelu prowadzenia. Uczestnik ma jeden ekran, na którym ma wszystko.

Okno czasowe pokoju

Uczestnik wchodzi od 15 minut przed startem do 30 minut po zakończeniu (wartości domyślne, do zmiany w ustawieniach). Poza tym oknem dostaje czytelny komunikat z odliczaniem „Pokój otworzy się za...”, a strona odświeży się sama, gdy nadejdzie pora. Prelegent wchodzi bez tego ograniczenia.

To najczęstsza przyczyna zgłoszenia „link nie działa” przy poprawnie skonfigurowanej instancji.

Ekran uczestnika

Adres /spotkanie/{token} jest wspólny dla uczestnika i prelegenta: strona sama rozpoznaje, kto wchodzi, więc organizator nie musi pamiętać, który link komu wysłał.

Przedpokój

Najpierw uczestnik widzi tytuł, godzinę w strefie webinaru i ramkę „Wchodzisz jako” z imieniem i nazwiskiem z zapisu. Prelegent ma tam dodatkowo oznaczenie roli.

Link otwiera się bez logowania, więc bez tego ekranu osoba z przekazanym linkiem zaczynałaby występować pod cudzym nazwiskiem, nie mając szansy tego zauważyć.

Wejście na salę

Uczestnik klika Dołącz do webinaru, prelegent Wejdź i rozpocznij. Pod przyciskiem jest informacja, że mikrofon i kamera są wyłączone, a o głos można poprosić w trakcie.

Sala

Obraz spotkania i panel interakcji obok. Nad panelem jest pasek akcji, widoczny zawsze, niezależnie od otwartej zakładki: schowany w zakładce byłby bezużyteczny dokładnie wtedy, gdy jest potrzebny.

Przedpokój. Ramka „Wchodzisz jako” pokazuje imię i nazwisko z zapisu, do potwierdzenia przed wejściem.
Przedpokój. Ramka „Wchodzisz jako” pokazuje imię i nazwisko z zapisu, do potwierdzenia przed wejściem.
Sala uczestnika. Obraz spotkania, pasek akcji nad panelem i cztery zakładki interakcji.
Sala uczestnika. Obraz spotkania, pasek akcji nad panelem i cztery zakładki interakcji.

Pasek akcji uczestnika

PrzyciskZachowanie
Chcę zabrać głosZmienia się w „Czekasz na głos” z możliwością wycofania, a po przyznaniu w „Masz głos, mikrofon jest włączony” z opcją oddania. Przy otwartym mikrofonie zamiast przycisku jest napis „Możesz mówić bez zgłaszania się”
Proszę o kontaktZapytanie bez pisania treści. Uczestnik w trakcie webinaru często nie ma pomysłu, co napisać, a wymuszanie treści kończy się tym, że nie wysyła nic
Interesuje mnie ofertaPełny formularz zapytania, w oknie, bez opuszczania sali

Po wysłaniu przycisk pokazuje potwierdzenie, a kolejne zapytanie wymaga świadomego kliknięcia „Wyślij kolejne”. Bez widocznej zmiany uczestnik kliknąłby trzeci raz, a handlowiec dostałby trzy zgłoszenia od tej samej osoby.

Zgoda na kontakt handlowy jest wymagana tak samo w obu trybach: uproszczenie dotyczy tego, ile uczestnik pisze, a nie tego, na co się zgadza.

Cztery zakładki panelu uczestnika

ZakładkaZawartość
CzatRozmowa na żywo. Autor pokazany jako imię i pierwsza litera nazwiska, nigdy adres e-mail
PytaniaPytania do prowadzącego, z głosowaniem. Jedna osoba głosuje raz
ZadaniaZapisy na zadania ogłoszone podczas webinaru, z limitem miejsc
OfertaZapytanie ofertowe

Licznik przy zakładce pokazuje nowe pozycje od ostatniego zajrzenia, a nie łączną liczbę wpisów. Łączna liczba przy czacie rośnie cały czas i po kwadransie nie niesie żadnej informacji.

Uczestnik po wysłaniu wiadomości i zgłoszeniu się po głos. Przycisk zmienia się w „Czekasz na głos”.
Uczestnik po wysłaniu wiadomości i zgłoszeniu się po głos. Przycisk zmienia się w „Czekasz na głos”.

W trybie NONE panel interakcji zostaje. Zamiast osadzonego obrazu jest przycisk otwierający spotkanie w nowej karcie, ale czat, pytania, zadania i banery działają dalej u nas. To jest sedno tego trybu: bez dostawcy platforma nadal ma sens.

Panel prowadzenia

Adres /webinary/{id}/prowadzenie, wejście ikoną w wierszu listy. Nagłówek pokazuje stan połączenia i ma przełącznik sygnału dźwiękowego. Poniżej cztery kolumny, każda to niezależny strumień pracy:

Zgłoszenia do głosu

Osoby z przyznanym głosem na górze („Mówi od...”), pod nimi oczekujący, najstarsi na górze, z informacją, ile już czekają. Akcje: Daj głos, Odrzuć, Odbierz.

Tu też jest przełącznik otwartego mikrofonu.

Czat na żywo

Podgląd rozmowy, wypowiedzi prelegenta wyróżnione. Ikona kosza usuwa wiadomość, zostawiając ślad dla moderatora zamiast kasować wpis.

Kolejka pytań

Najpierw sekcja oczekujących na zatwierdzenie: Zatwierdź albo Odrzuć. Opublikowane są sortowane: przypięte pierwsze, potem po liczbie głosów.

Do każdego można przypiąć, ukryć albo wpisać odpowiedź widoczną dla uczestników.

Zadania

Lista zadań z licznikiem zapisanych i limitem, z możliwością zamknięcia i otwarcia zapisów. Na dole formularz: tytuł, opcjonalny limit miejsc i przycisk Ogłoś.

Panel prowadzenia w trakcie spotkania. Zgłoszenie w kolejce głosu i wiadomość na czacie: autor jako imię i pierwsza litera nazwiska.
Panel prowadzenia w trakcie spotkania. Zgłoszenie w kolejce głosu i wiadomość na czacie: autor jako imię i pierwsza litera nazwiska.

Pytanie oczekujące nie jest widoczne dla uczestników. To jedyna bariera przed pokazaniem niezatwierdzonej treści całej sali, więc kolejka wymaga świadomego zatwierdzenia każdej pozycji.

Gdy przyjdzie nowe zapytanie ofertowe, na górze panelu pojawia się baner z odnośnikiem do listy zapytań. Jest też sygnał dźwiękowy, domyślnie włączony: to zgłoszenie, którego prowadzący najbardziej nie chce przegapić, a w trakcie mówienia nie patrzy na ekran.

Przeglądarki blokują dźwięk do pierwszej interakcji użytkownika. Kliknij cokolwiek w panelu, żeby sygnał zaczął działać. Wybór jest zapamiętywany w przeglądarce.

Tryb otwartego mikrofonu

Przełącznik pozwala mówić każdemu bez proszenia o głos. Domyślnie wyłączony i to jest świadome: otwarty mikrofon na webinarze dla stu osób oznacza sto otwartych mikrofonów naraz. Ma sens przy warsztacie dla kilkunastu osób.

Włączenie pyta o potwierdzenie, wyłączenie nie: otwarcie mikrofonów całej sali jest słyszalne natychmiast i trudno to cofnąć po fakcie.

Włączenie nie kasuje kolejki. Przy włączonym trybie jest ona nieaktywna, a nie nieaktualna, więc po wyłączeniu osoby czekające od kwadransa nie tracą miejsca.

Wyłączenie nie odbiera głosu osobom, którym przyznano go indywidualnie: ich uprawnienie wynika z roli w zapisie, a nie z trybu.

Wideo pozostaje wyłączone także w tym trybie: otwarty mikrofon nie włącza nikomu kamery.

Obecność

Obecność liczy się z sesji, a nie z flagi. Ludzie wchodzą i wychodzą, tracą połączenie, wracają z telefonu; dopiero suma sesji mówi, ile ktoś naprawdę był obecny, i pozwala narysować wykres obecności w czasie.

Przeglądarka wysyła sygnał co minutę istniejącym już połączeniem, więc działa to także w trybie NONE, gdzie żadnego dostawcy nie ma. Sesje porzucone - zamknięta karta bez wylogowania - domyka zadanie w tle, przyjmując jako koniec ostatni sygnał, a nie chwilę zamknięcia.

Rozdział 11

Po webinarze

Część dzieje się sama, część wymaga decyzji organizatora.

Co dzieje się automatycznie

Godzinę po zakończeniu (wartość SUMMARY_DELAY_MINUTES) zadanie w tle kolejkuje maile: uczestnikom podziękowanie z listą zadań i linkami, prowadzącemu zestawienie.

Podsumowanie dostaje tylko uczestnik ze statusem potwierdzonym. Osoba, która zrezygnowała, nie dostanie maila po wydarzeniu.

Podsumowania nie da się wysłać drugi raz i to jest celowe: uczestnik nie ma dostać dwa razy tej samej wiadomości. Gwarancję „dokładnie raz” daje ograniczenie w bazie, a nie samo sprawdzenie w kodzie.

Zestawienie dla prowadzącego zawiera dane kontaktowe, więc idzie wyłącznie na adresy wpisane w ustawieniach, nigdy na adres wzięty z formularza.

Nagranie

Wgraj plik albo poczekaj na pobranie

Przy LiveKit z Egress nagranie trafia prosto do MinIO. Przy pozostałych dostawcach wgrywasz plik ręcznie w zakładce Nagrania i materiały. Dopuszczone są MP4 i WEBM, a typ jest rozpoznawany z zawartości pliku, nie z rozszerzenia.

Ustaw widoczność

Trzy poziomy: prywatne, dla zapisanych i publiczne. Domyślnie dla zapisanych, a nie publicznie, bo nagranie zawiera wypowiedzi uczestników i pytania z imionami: udostępnienie go całemu internetowi musi być świadomą decyzją.

Powiadom uczestników

Przycisk w zakładce „Po webinarze”. To osobna wysyłka, bo montaż zwykle trwa dłużej niż godzina, a podsumowania nie da się powtórzyć. Każdy odbiorca dostaje ją dokładnie raz.

Pliki idą przez backend, nie prosto z MinIO. Dzięki temu każde pobranie przechodzi przez kontrolę widoczności. Token musi dotyczyć tego webinaru, a po rezygnacji przestaje działać natychmiast.

Własny skład ma pierwszeństwo przed adresem zewnętrznym. Mail najpierw szuka nagrania w składzie, a dopiero potem sięga po wpisany adres.

Certyfikaty

Zakładka Certyfikaty na karcie webinaru. Można wydać dokument pojedynczej osobie albo wszystkim naraz.

Certyfikat to dokument, nie widok danych. Plik powstaje raz i leży w składzie: wydany dziś ma wyglądać tak samo za rok, niezależnie od tego, czy ktoś zmienił tytuł webinaru, szablon albo logo.

Automat wydaje wyłącznie uczestnikom z odnotowaną obecnością. Certyfikat dla osoby bez obecności jest decyzją organizatora, a nie automatu; panel pyta o nią wprost.

Unieważnienie nie kasuje dokumentu. Weryfikacja pokaże wtedy „nieważny”, a nie „nie znaleziono”, bo dokument mógł już trafić do teczki uczestnika albo do pracodawcy. Unieważniony certyfikat znika za to ze strony uczestnika i z maila.

Weryfikacja publiczna pod /certyfikat/{numer} zwraca minimum: numer, tytuł, datę, imię z pierwszą literą nazwiska i informację o ważności. Endpoint jest otwarty dla całego internetu, więc nigdy nie pokazuje adresu e-mail, pełnego nazwiska ani linku do pliku.

Dostęp do pliku certyfikatu jest węższy niż do nagrania. Nagranie jest wspólne dla webinaru, więc wystarcza token dowolnego uczestnika. Certyfikat to dokument jednej osoby, z jej imieniem i nazwiskiem, więc token musi wskazywać właśnie ją.

Zapytania ofertowe. Ekran zbiorczy dla handlowca, ten sam komponent co zakładka na karcie webinaru.
Zapytania ofertowe. Ekran zbiorczy dla handlowca, ten sam komponent co zakładka na karcie webinaru.

Statystyki

Zakładka Statystyki pokazuje liczby zapisów i obecnych, wykres obecności w czasie, aktywność na czacie oraz skuteczność banerów i zaproszeń. Wszystko liczone w bazie, zapytaniami agregującymi.

Wykres obecności kończy się na chwili bieżącej, gdy webinar jeszcze trwa: rysowanie do przyszłego końca dawałoby długą linię zer. Skuteczność zaproszeń liczy się po wysłanych, nie po zakolejkowanych: zaproszenie, które nie wyszło, nie miało szansy przynieść zapisu.

Statystyki webinaru. Liczby zapisów i obecnych, wykres obecności w czasie, aktywność i skuteczność.
Statystyki webinaru. Liczby zapisów i obecnych, wykres obecności w czasie, aktywność i skuteczność.

Eksport listy zapisanych

Na liście zapisanych jest eksport CSV. Obejmuje wszystkich zapisanych, a nie bieżącą stronę, i zawiera czas obecności oraz wersję i datę zgody. Flaga obecności jest przy okazji przeliczana, żeby liczba na ekranie nie rozjechała się z kolumną w pliku.

Lista zapisanych. Kolumny statusu, głosu i obecności; eksport CSV obejmuje wszystkich, nie tylko bieżącą stronę.
Lista zapisanych. Kolumny statusu, głosu i obecności; eksport CSV obejmuje wszystkich, nie tylko bieżącą stronę.

Kopiowanie webinaru

Przy szkoleniach cyklicznych najczęstszą czynnością jest skopiowanie istniejącego wydarzenia ikoną kopiowania w wierszu listy.

Co przechodzi

Treść strony, treść zaproszenia, ustawienia certyfikatów, reguły przypomnień, tematy zapytań i materiały. Reguła wyłączona świadomie zostaje wyłączona także w kopii.

Czego nie ma w kopii

Zapisy, obecność, interakcje, nagrania, certyfikaty i pokój u dostawcy. Skopiowanie czegokolwiek z tej listy oznaczałoby uczestników zapisanych na wydarzenie, które się nie odbyło, albo certyfikaty z cudzego szkolenia.

Kopia dostaje termin zastępczy: pełną godzinę za tydzień, o długości przepisanej z oryginału. Data jest w przyszłości, a nie w przeszłości, żeby przy przypadkowej publikacji zapisy się otworzyły, a nie zamknęły natychmiast. Panel mówi o tym wprost i od razu przechodzi do edycji kopii.

Usunięcie webinaru

Panel najpierw sprawdza, ile przepadnie: liczbę zapisów i wydanych certyfikatów, i dopiero z tymi liczbami pyta o potwierdzenie. Przy webinarze ze setką zapisów odpowiedź jest zupełnie inna niż przy pustym szkicu.

Pytanie podpowiada odwołanie jako łagodniejszą alternatywę, bo w większości przypadków chodzi o zamknięcie zapisów, a nie skasowanie danych. Pliki w MinIO zostają: utrata pliku jest gorsza niż zajęte miejsce.

Rozdział 12

Scenariusz testowy na localhost

Gotowa ścieżka, która przechodzi przez wszystkie mechanizmy w jednym posiedzeniu, w około 30 minut.

Wartości do wpisania są w rozdziale 6. Ten rozdział podaje kolejność czynności, a nie treść pól: komplet danych webinaru o ocenie ryzyka i bezpieczeństwie wody zebrany jest w jednym miejscu, żeby dało się go przepisać bez przewijania instrukcji.

Zanim zaczniesz: potwierdź, że tryby bezpieczne są włączone i mają ustawiony Twój adres oraz numer (rozdział 5). Cała wysyłka trafi wtedy do Ciebie.

Przygotowanie

  • Kontenery działają: docker compose ps pokazuje usługi jako Up
  • curl http://localhost:8080/api/health zwraca UP
  • Profil wideo uruchomiony, jeśli testujesz spotkanie: docker compose --profile livekit up -d
  • Adres publiczny instancji ustawiony na http://localhost:8081
  • Poczta skonfigurowana i test wysyłki przechodzi
  • Tryb bezpieczny włączony, adres i numer zastępczy uzupełnione

Przebieg

Utwórz webinar z terminem tuż przed nosem

Ustaw rozpoczęcie za 10 minut, zakończenie za 70 minut. Dzięki oknu wejścia otwartemu 15 minut przed startem pokój będzie dostępny od razu, a jednocześnie termin jest w przyszłości, więc nie ruszy zadanie podsumowań.

Nie ustawiaj terminu w przeszłości. Dane testowe z terminem wstecz wystarczą, żeby scheduler potraktował webinar jako zakończony i rozesłał podsumowania.

Dodaj treść strony i limit miejsc

Wpisz kilka akapitów w edytorze i ustaw limit, na przykład 5 miejsc. Pozwoli to później sprawdzić licznik wolnych miejsc. Zapisz webinar.

Załóż pokój i dodaj siebie jako prelegenta

Wejdź w edycję, zakładka Wideo: „Utwórz pokój u dostawcy”, potem dodaj prelegenta i skopiuj jego link. Zapisz go, będzie potrzebny za chwilę.

Opublikuj i zapisz się jako uczestnik

Opublikuj webinar, otwórz http://localhost:8081/w/{slug} w oknie prywatnym i wypełnij formularz swoim adresem. Zaznacz zgodę wymaganą i marketingową.

Sprawdź skrzynkę: powinien przyjść mail z potwierdzeniem, załącznikiem kalendarza i linkiem do własnego zapisu.

Sprawdź brak enumeracji

Wyślij formularz drugi raz tym samym adresem. Ekran potwierdzenia ma być identyczny jak za pierwszym razem, a na skrzynkę przyjdzie wiadomość o istniejącym już zapisie.

Wejdź na salę z dwóch stron

W zwykłym oknie otwórz link prelegenta, w oknie prywatnym link uczestnika z maila. W obu przypadkach potwierdź tożsamość w przedpokoju i wejdź na salę.

Sprawdź, czy prelegent publikuje obraz i dźwięk, a uczestnik tylko odbiera.

Otwórz panel prowadzenia i przetestuj interakcje

W trzeciej karcie otwórz /webinary/{id}/prowadzenie. Z okna uczestnika kolejno:

  • napisz wiadomość na czacie i sprawdź, czy widać ją w panelu,
  • zadaj pytanie, zatwierdź je w panelu i sprawdź, czy pojawia się uczestnikom,
  • zgłoś się po głos i przyznaj go z panelu, sprawdzając, czy mikrofon się otwiera,
  • ogłoś zadanie z panelu i zapisz się na nie z okna uczestnika,
  • wyślij zapytanie ofertowe i sprawdź sygnał dźwiękowy oraz wpis w /zapytania.

Sprawdź otwarty mikrofon

Włącz przełącznik w kolumnie zgłoszeń i potwierdź. W oknie uczestnika przycisk proszenia o głos ma zniknąć na rzecz napisu o możliwości mówienia. Wyłącz go z powrotem i sprawdź, czy kolejka wróciła.

Sprawdź obecność i statystyki

Zostaw okno uczestnika otwarte na kilka minut, potem wejdź na kartę webinaru, zakładka Statystyki. Powinna pokazać obecność i wykres w czasie.

Zakończ i sprawdź automaty

Aby nie czekać godziny, skróć webinar: w edycji ustaw zakończenie na czas miniony i odczekaj do następnego przebiegu zadania. Sprawdź, czy przyszło podsumowanie i czy w dzienniku powiadomień jest wpis.

Pamiętaj, że w trybie bezpiecznym wszystkie te wiadomości przyjdą na Twój adres zastępczy, także te zaadresowane formalnie do kogoś innego.

Wgraj nagranie i wydaj certyfikat

W zakładce „Nagrania i materiały” wgraj dowolny plik MP4, ustaw widoczność „dla zapisanych” i wyślij powiadomienie o nagraniu. Następnie w zakładce Certyfikaty wydaj dokument i sprawdź go pod /certyfikat/{numer}.

Otwórz PDF i sprawdź, czy polskie znaki wyświetlają się poprawnie.

Skopiuj webinar

Na liście kliknij ikonę kopiowania. Sprawdź, czy kopia ma treść i przypomnienia, a nie ma zapisów ani certyfikatów, oraz czy dostała termin zastępczy za tydzień.

Lista kontrolna testu

  • Strona zapisu widoczna dopiero po publikacji
  • Mail potwierdzający z załącznikiem kalendarza
  • Powtórny zapis daje identyczny ekran
  • Przedpokój pokazuje imię z zapisu do potwierdzenia
  • Prelegent publikuje obraz, uczestnik tylko odbiera
  • Czat, pytania i głosowanie działają w obie strony
  • Kolejka głosu otwiera i zamyka mikrofon
  • Otwarty mikrofon nie kasuje kolejki
  • Zadanie ogłoszone w panelu widoczne u uczestnika
  • Zapytanie ofertowe trafia na listę i daje sygnał dźwiękowy
  • Obecność i wykres w statystykach
  • Podsumowanie po zakończeniu, dokładnie raz
  • Nagranie dostępne dla zapisanych, niedostępne bez tokenu
  • Certyfikat z poprawnymi polskimi znakami i działającą weryfikacją
  • Kopia bez zapisów, z terminem zastępczym
Rozdział 13

Rozwiązywanie problemów

Katalog objawów, które przy tej architekturze pojawiają się najczęściej, wraz z rzeczywistą przyczyną.

Najczęstsza przyczyna przy poprawnie skonfigurowanym serwerze: zablokowany zakres portów UDP. To główna droga ruchu audio i wideo. Sygnalizacja idzie osobno, więc pokój wygląda na działający.

Przy uruchomieniu lokalnym druga typowa przyczyna to brak LIVEKIT_NODE_IP=127.0.0.1: serwer rozgłasza wtedy publiczny adres łącza, pod który przeglądarka na tej samej maszynie się nie połączy.

Wersja serwera musi nadążać za biblioteką kliencką. Nowszy klient łączy się ścieżką, której starszy serwer nie zna: uczestnik wchodzi i widzi listę obecnych, ale media nie płyną. Podnosząc bibliotekę, sprawdź wersję obrazu serwera.

Sprawdź, czy tryb bezpieczny jest włączony bez ustawionego adresu zastępczego. Wtedy wysyłka jest celowo wstrzymywana, zamiast trafić do prawdziwego odbiorcy.

Druga możliwość to bezpiecznik ilościowy: wiadomość dostaje wtedy status oczekującej i pójdzie później. To nie jest błąd.

Stan sprawdzisz zapytaniem z rozdziału 5. Nie polegaj na tym, co było ustawione wcześniej: ustawienia zmieniają się bez restartu.

Objaw jest mylący i rzadko dotyczy logowania. Zwykle oznacza błąd 500 po stronie backendu, który front tłumaczy jako wygasłą sesję.

Typowa przyczyna to encja opuszczająca warstwę serwisu: pole doczytywane leniwie poza transakcją. Szukanie tego w warstwie logowania nie ma sensu, zajrzyj do logów backendu.

To nie błąd, tylko okno czasowe: wejście otwiera się 15 minut przed startem i zamyka 30 minut po zakończeniu. Uczestnik widzi odliczanie, a strona odświeży się sama.

Jeśli chcesz wejść wcześniej do testów, użyj linku prelegenta: on nie podlega temu ograniczeniu.

Publikacja wymaga tytułu, adresu strony zapisu i obu terminów. Sprawdź też status: webinaru odwołanego nie da się opublikować ponownie.

Typowy objaw braku rzutowania typu przy parametrze opcjonalnym w zapytaniu. Baza nie potrafi wywnioskować typu pustej wartości, więc lista psuje się dokładnie wtedy, gdy filtr nie jest używany, czyli w najzwyklejszym użyciu.

Czcionka musi być osadzona w pliku i rejestrowana w kodzie. Deklaracja czcionki w arkuszu stylów szablonu przykrywa tę rejestrację: generator próbuje pobrać plik, nie znajduje go i podstawia czcionkę zastępczą.

Certyfikat z błędem w nazwisku jest bezużyteczny, więc to jest błąd blokujący, a nie kosmetyczny.

Sam profil wideo bez usług nagrywania nie nagrywa. Serwer przyjmuje zadanie i przekazuje je przez pośrednika; bez niego zadanie nie ma odbiorcy i kończy się przekroczeniem czasu, przy w pełni sprawnym serwerze.

Uruchom cały profil: docker compose --profile livekit up -d.

Stan weryfikacji: nagrywanie automatyczne nie jest potwierdzone od początku do końca w środowisku lokalnym. Ręczne wgranie pliku działa i pozostaje drogą awaryjną.

Sprawdź, czy webinar ma reguły przypomnień i czy są włączone. Przypomnienie spóźnione bardziej niż okno tolerancji nie idzie w ogóle, co chroni przed lawiną wysyłek wstecz po restarcie.

SMS wymaga dodatkowo zgody marketingowej i numeru telefonu u uczestnika.

Pytanie oczekujące na zatwierdzenie nie jest widoczne publicznie. Zatwierdź je w kolejce pytań w panelu prowadzenia.

Przydatne polecenia

# logi backendu na żywo
docker compose logs -f backend

# stan kontenerów
docker compose ps

# restart pojedynczej usługi
docker compose restart backend

# zatrzymanie całości, dane w wolumenach zostają
docker compose down

# dziennik powiadomień: co i do kogo poszło
docker exec webinar-postgres psql -U webinar -d webinar -c \
  "SELECT created_at, template, recipient, status FROM notifications
   ORDER BY created_at DESC LIMIT 20;"

Nigdy nie kasuj wolumenów. Ani przez docker compose down -v, ani przez docker volume rm, ani przez docker system prune -a --volumes. Tabela ustawień i konto administratora są nietykalne: odtworzenie wymaga ręcznego wpisania od nowa danych SMTP, kluczy bramki SMS i kluczy dostawcy wideo, których nie ma nigdzie indziej.

Czyszczenie danych testowych ogranicza się do tabel operacyjnych: webinarów i wszystkiego, co od nich zależy, oraz powiadomień i plików multimedialnych.