diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 47f44c10f..018c7fe14 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -28,4 +28,4 @@ jobs: version: latest - run: supabase link --project-ref $SUPABASE_PROJECT_ID - - run: supabase db push + - run: supabase db push diff --git a/components/ProjectEdit/Participants/Participants.js b/components/ProjectEdit/Participants/Participants.js index 52fb87408..406f21651 100644 --- a/components/ProjectEdit/Participants/Participants.js +++ b/components/ProjectEdit/Participants/Participants.js @@ -4,6 +4,7 @@ import { useRouter } from 'next/router' import axios from 'axios' import { useTranslation } from 'next-i18next' +import toast from 'react-hot-toast' import Modal from 'components/Modal' @@ -15,7 +16,7 @@ import TranslatorsList from './TranslatorsList' import { useCoordinators, useProject, useTranslators } from 'utils/hooks' import useSupabaseClient from 'utils/supabaseClient' -function Parcticipants({ users, access: { isCoordinatorAccess, isAdminAccess } }) { +function Participants({ users, access: { isCoordinatorAccess, isAdminAccess } }) { const supabase = useSupabaseClient() const { t } = useTranslation(['common', 'project-edit', 'projects']) @@ -90,14 +91,24 @@ function Parcticipants({ users, access: { isCoordinatorAccess, isAdminAccess } } } }, [translators]) const remove = (userId, role) => { - axios + return axios .delete(`/api/projects/${code}/${role}/${userId}`) .then(() => { roleActions[role].reset(false) roleActions[role].mutate() }) - .catch(console.log) + .catch((error) => { + if ( + error.response?.data?.error === 'Cannot remove translator with assigned verses' + ) { + toast.error(t('project-edit:CannotRemoveTranslatorWithVerses')) + } else { + toast.error(t('common:SomethingWentWrong')) + } + throw error + }) } + return ( <>
@@ -281,4 +292,4 @@ function Parcticipants({ users, access: { isCoordinatorAccess, isAdminAccess } } ) } -export default Parcticipants +export default Participants diff --git a/pages/api/projects/[code]/translators/[id].js b/pages/api/projects/[code]/translators/[id].js index 70629dfe6..0c64fecf5 100644 --- a/pages/api/projects/[code]/translators/[id].js +++ b/pages/api/projects/[code]/translators/[id].js @@ -12,35 +12,48 @@ export default async function languageProjectTranslatorHandler(req, res) { method, } = req let project_id = null + switch (method) { case 'DELETE': try { const { data: project, error } = await supabase .from('projects') - .select('id, code') + .select('id') .eq('code', code) - .limit(1) - .maybeSingle() + .single() if (error) throw error - if (project?.id) { - project_id = project?.id - } else { - throw { error: 'Missing id of project' } + if (!project?.id) throw { error: 'Missing id of project' } + + const { data: translator, error: translatorError } = await supabase + .from('project_translators') + .select('id') + .match({ project_id: project.id, user_id: id }) + .single() + if (translatorError) throw translatorError + + const { data: hasVerses, error: checkError } = await supabase.rpc( + 'has_assigned_verses', + { project_translator_id: translator.id } + ) + if (checkError) throw checkError + if (hasVerses) { + return res.status(400).json({ + error: 'Cannot remove translator with assigned verses', + }) } - } catch (error) { - return res.status(404).json({ error }) - } - try { - const { data, error } = await supabase + + const { data, error: deleteError } = await supabase .from('project_translators') .delete() - .match({ project_id: project_id, user_id: id }) + .match({ id: translator.id }) .select() - if (error) throw error + if (deleteError) throw deleteError + return res.status(200).json(data) } catch (error) { return res.status(404).json({ error }) } + default: res.setHeader('Allow', ['DELETE']) return res.status(405).end(`Method ${method} Not Allowed`) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 558b0325b..43f902d28 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -148,6 +148,7 @@ "ShowAll": "Show all", "ShowAllUpdates": "Version history", "ShowCurrUpdates": "Latest version", + "SomethingWentWrong": "Something went wrong. Please try again", "SomeTranslatorsNotFinish": "Some translators are still working on the previous step. You will now be automatically redirected.", "Start": "Start", "Step": "Step", diff --git a/public/locales/en/project-edit.json b/public/locales/en/project-edit.json index 0339f8290..1aadca4c4 100644 --- a/public/locales/en/project-edit.json +++ b/public/locales/en/project-edit.json @@ -15,6 +15,7 @@ "BriefToggleError": "Failed to toggle the brief", "BriefToggleisenableSuccessDisabled": "The brief has been disabled", "BriefToggleisenableSuccessEnabled": "The brief has been enabled", + "CannotRemoveTranslatorWithVerses": "Cannot remove translator with verses in unfinished chapters. Please reassign verses or finish chapters first", "CodeLanguageNotUnique": "The code of the language is not unique", "CodeLanguageRequired": "The code of the language is required", "CreateNewProject": "Create a new project", diff --git a/supabase/migrations/20241211162405_add_has_assigned_verses.sql b/supabase/migrations/20241211162405_add_has_assigned_verses.sql new file mode 100644 index 000000000..a711c4b4d --- /dev/null +++ b/supabase/migrations/20241211162405_add_has_assigned_verses.sql @@ -0,0 +1,12 @@ +CREATE OR REPLACE FUNCTION public.has_assigned_verses(project_translator_id bigint) + RETURNS boolean + LANGUAGE plpgsql +AS $function$ +BEGIN + RETURN EXISTS ( + SELECT 1 FROM verses + WHERE verses.project_translator_id = has_assigned_verses.project_translator_id + ); +END; +$function$ +; diff --git a/supabase/migrations/20241218085500_remote_schema.sql b/supabase/migrations/20241218085500_remote_schema.sql index d109a3954..2289d9e48 100644 --- a/supabase/migrations/20241218085500_remote_schema.sql +++ b/supabase/migrations/20241218085500_remote_schema.sql @@ -1,7 +1,5 @@ drop function if exists "public"."update_project_basic"(project_code text, title text, orig_title text, code text, language_id bigint, is_rtl boolean); -alter table "public"."users" add column "comcheck_token" text; - set check_function_bodies = off; CREATE OR REPLACE FUNCTION public.has_assigned_verses(project_translator_id bigint)