Labele
View on GitHubLabele
Labele issue'ów to zasób per-projekt, oparty na prawdziwej tabeli
bazodanowej labels (App\Models\Label) — a nie na sztywnym enumie
backendowym. Każdy projekt dostaje startową taksonomię sześciu labeli
(bug, feature, performance, design, ux, chore), zasiewaną
leniwie przy pierwszej potrzebie, a właściciele/administratorzy
projektu mogą zmienić nazwę, kolor, opis, dodać lub usunąć dowolny
label — również te zasiane — z poziomu Ustawienia → Labele.
Przewodniki, w kolejności, w jakiej naprawdę byś ich potrzebował
- Dodaj nowy domyślny labelLabeleDodaj nowy domyślny labelPrzećwiczony przykład: dodanie siódmego startowego labela, security, do sześciu, jakimi zasiewany jest każdy projekt (bug, feature, performance, design, ux… —
przećwiczony przykład dodania siódmego startowego labela,
security, do taksonomii, jaką dostaje każdy nowy projekt. - Udostępnij labele projektu nowej stronieLabeleUdostępnij labele projektu nowej stroniePrzećwiczony przykład: nadanie zupełnie nowej, jednoprojektowej stronie prawdziwych kolorów labeli (zamiast hashowanego fallbacku z useProjectLabels()) prz… —
przećwiczony przykład podpięcia prawdziwych kolorów labeli
per-projekt (zamiast hashowanego fallbacku) do zupełnie nowej
strony jednoprojektowej, na przykładzie hipotetycznej strony
Backlog, zbudowanej dokładnie w kształcie istniejącej stronyProjects/Show.
Architektura w jednym akapicie
labels (migracja 2026_09_12_120000_create_labels_table.php) ma
kolumny project_id, name, color, description, is_system, z
unikalnością na (project_id, name). App\Repositories\LabelRepository
i App\Services\LabelService idą za zwykłym w tym repozytorium
podziałem Controller → Service → Repository (zobacz
../architecture/02-backend-layered-architecture.mdArchitektura i technikalia projektuWarstwowa architektura backenduController → Service → Repository, bez wyjątków i bez skrótów — kontroler nigdy nie buduje zapytania Eloquent, a repozytorium nigdy nie zawiera logiki bizn…):
LabelService::ensureSystemLabels() zasiewa sześć startowych labeli
dokładnie raz dla danego projektu, śledzone przez znacznik czasu
projects.labels_seeded_at — a nie "wstaw wszystko, czego brakuje" przy
każdym odczycie, co po cichu wskrzeszałoby label, który właściciel
projektu świadomie usunął. App\Http\Controllers\LabelController
udostępnia projects.labels.store / .update / .destroy,
zabezpieczone przez App\Policies\ProjectPolicy::viewLabels() /
manageLabels() (podgląd: owner/admin/member/viewer; zarządzanie:
tylko owner/admin — dokładnie ten sam wzorzec, co
viewIntegrations()/updateIntegrations()). Kolumna labels issue'a
to nadal zwykła tablica JSON z nazwami labeli w postaci stringów
(Issue::casts()['labels'] = 'array', bez App\Enums\IssueLabel w
tle) — ale każda nazwa zapisywana przez
IssueController@store/@update jest teraz walidowana względem
prawdziwych wierszy labels danego projektu
(Rule::exists('labels', 'name')->where('project_id', ...)), zamiast
względem sztywnego enuma. To świadomy kompromis zakresu, o którym
warto wiedzieć, zanim się w to ruszy: label jest identyfikowany przez
nazwę, a nie przez relacyjną tabelę pośredniczącą do issue'ów, więc
zmiana nazwy albo usunięcie labela nie aktualizuje ani nie usuwa go
wstecznie z issue'ów, które już odwołują się do starej nazwy — issue
zachowuje ten sam string, dopóki ktoś ponownie nie edytuje jego
labeli. Po stronie frontendu resources/js/context/ProjectLabelsContext.tsx
z ProjectLabelsProvider/useProjectLabels() jest jedynym źródłem
prawdy dla "jakie labele istnieją i jaki kolor ma ten konkretny",
wszędzie tam, gdzie jest zamontowany (obecnie Pages/Projects/Show.tsx
i Pages/Issues/Show.tsx, każdy zasilany propsem labels, który
kontroler buduje małym prywatnym helperem mapLabels()) —
LabelBadge, EditableLabelList i FilterDropdown typu labels
czytają z niego zamiast z zaszytej na sztywno listy, a
useProjectLabels().getColor(name) wraca do hashLabelColor()
(deterministyczny hash w stałą 18-kolorową paletę
LABEL_COLOR_PALETTE w resources/js/utils/labelColors.ts), gdy nie
ma zamontowanego providera albo nazwa nie zostanie znaleziona — co
dokładnie dzieje się dziś na wieloprojektowej stronie Dashboard.
Sama zakładka Ustawienia → Labele
(WorkspaceSettingsLabelsTab.tsx) została odblokowana ze stanu
"coming soon" opisanego w
documentation/pl/settings-tabs/01-flip-a-placeholder-tab-live.md i
przebudowana z prawdziwym CRUD-em podpiętym pod trasy powyżej; jej UI
tworzenia/edycji to panel, który rozwija się w miejscu, zamiast
modala — zobacz WorkspaceSettingsLabelInlineEditor.tsx w tym pliku,
jeśli dodajesz kolejny edytowalny-w-miejscu wiersz ustawień i chcesz
dopasować się do tego wzorca zamiast sięgać po Modal.
