-- ===================================================================== -- GameDev Tracker — Mise à jour complète (v2 + v3 + v4) -- À coller dans : Supabase > SQL Editor > New query > Run -- Sans danger si une partie a déjà été appliquée (tout est idempotent). -- ===================================================================== -- --------------------------------------------------------------------- -- v2 — Pôles, assignation multiple, notifications, suppression jalons -- --------------------------------------------------------------------- alter table public.tasks add column if not exists pole member_role; alter table public.bugs add column if not exists pole member_role; alter table public.tasks add column if not exists assignee_ids uuid[] not null default '{}'; -- Reprend l'assigné unique existant dans le tableau (si la colonne existe encore). do $$ begin if exists (select 1 from information_schema.columns where table_schema='public' and table_name='tasks' and column_name='assignee_id') then update public.tasks set assignee_ids = array[assignee_id] where assignee_id is not null and (assignee_ids is null or assignee_ids = '{}'); alter table public.tasks drop column assignee_id; end if; end $$; alter table public.tasks drop column if exists milestone_id; drop table if exists public.milestones cascade; drop type if exists milestone_status; create table if not exists public.notifications ( id uuid primary key default gen_random_uuid(), user_id uuid not null references public.profiles(id) on delete cascade, project_id uuid references public.projects(id) on delete cascade, kind text not null, title text not null, body text, entity_id uuid, pole member_role, read boolean not null default false, created_at timestamptz not null default now() ); create index if not exists idx_notifications_user on public.notifications(user_id); alter table public.notifications enable row level security; drop policy if exists notifications_select on public.notifications; drop policy if exists notifications_insert on public.notifications; drop policy if exists notifications_update on public.notifications; drop policy if exists notifications_delete on public.notifications; create policy notifications_select on public.notifications for select to authenticated using (user_id = auth.uid()); create policy notifications_insert on public.notifications for insert to authenticated with check (true); create policy notifications_update on public.notifications for update to authenticated using (user_id = auth.uid()) with check (user_id = auth.uid()); create policy notifications_delete on public.notifications for delete to authenticated using (user_id = auth.uid()); do $$ begin alter publication supabase_realtime add table public.notifications; exception when duplicate_object then null; end $$; -- --------------------------------------------------------------------- -- v3 — Feuille de temps : entrées libres (réunion, etc.) -- --------------------------------------------------------------------- -- Crée la table si elle n'a jamais existé (ancienne base sans suivi du temps). create table if not exists public.time_logs ( id uuid primary key default gen_random_uuid(), project_id uuid references public.projects(id) on delete cascade, task_id uuid references public.tasks(id) on delete cascade, label text, user_id uuid references public.profiles(id) on delete set null, minutes integer not null check (minutes > 0), note text, logged_at date not null default current_date, created_at timestamptz not null default now() ); -- Si la table existait déjà (ancienne version), on l'aligne sur le nouveau format. alter table public.time_logs alter column task_id drop not null; alter table public.time_logs add column if not exists label text; alter table public.time_logs add column if not exists project_id uuid references public.projects(id) on delete cascade; update public.time_logs tl set project_id = t.project_id from public.tasks t where tl.task_id = t.id and tl.project_id is null; create index if not exists idx_time_logs_task on public.time_logs(task_id); create index if not exists idx_time_logs_project on public.time_logs(project_id); create index if not exists idx_time_logs_user on public.time_logs(user_id); alter table public.time_logs enable row level security; drop policy if exists time_logs_all on public.time_logs; create policy time_logs_all on public.time_logs for all to authenticated using (true) with check (true); do $$ begin alter publication supabase_realtime add table public.time_logs; exception when duplicate_object then null; end $$; -- --------------------------------------------------------------------- -- v4 — Plusieurs pôles (rôles) par membre -- --------------------------------------------------------------------- alter table public.profiles add column if not exists roles member_role[] not null default '{}'; update public.profiles set roles = array[role] where roles = '{}'; -- --------------------------------------------------------------------- -- v5 — Accueil (onboarding) des nouveaux membres -- --------------------------------------------------------------------- alter table public.profiles add column if not exists onboarded boolean not null default false; -- Les membres déjà présents ne sont pas ré-embarqués : on les marque « fait ». update public.profiles set onboarded = true where onboarded = false; -- --------------------------------------------------------------------- -- v6 — Photo de profil (avatar image) : colonne + bucket de stockage -- --------------------------------------------------------------------- alter table public.profiles add column if not exists avatar_url text; -- Bucket public "avatars" pour héberger les photos de profil. insert into storage.buckets (id, name, public) values ('avatars', 'avatars', true) on conflict (id) do nothing; -- Lecture publique ; écriture réservée aux membres connectés. drop policy if exists avatars_read on storage.objects; drop policy if exists avatars_insert on storage.objects; drop policy if exists avatars_update on storage.objects; drop policy if exists avatars_delete on storage.objects; create policy avatars_read on storage.objects for select using (bucket_id = 'avatars'); create policy avatars_insert on storage.objects for insert to authenticated with check (bucket_id = 'avatars'); create policy avatars_update on storage.objects for update to authenticated using (bucket_id = 'avatars'); create policy avatars_delete on storage.objects for delete to authenticated using (bucket_id = 'avatars'); -- --------------------------------------------------------------------- -- v7 — Plusieurs pôles par tâche -- --------------------------------------------------------------------- alter table public.tasks add column if not exists poles member_role[] not null default '{}'; -- Reprend le pôle unique existant dans le tableau (si présent). update public.tasks set poles = array[pole] where pole is not null and poles = '{}';