diff --git a/apps/web/app/api/organization-projects/[id]/route.ts b/apps/web/app/api/organization-projects/[id]/route.ts index 072bf41d9..12280aae7 100644 --- a/apps/web/app/api/organization-projects/[id]/route.ts +++ b/apps/web/app/api/organization-projects/[id]/route.ts @@ -1,6 +1,6 @@ import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app'; -import { editOrganizationProjectsRequest } from '@app/services/server/requests'; +import { editOrganizationProjectsRequest, getOrganizationProjectRequest } from '@app/services/server/requests'; import { NextResponse } from 'next/server'; export async function PUT(req: Request, { params }: { params: { id: string } }) { @@ -23,3 +23,22 @@ export async function PUT(req: Request, { params }: { params: { id: string } }) return $res(response.data); } + +export async function GET(req: Request, { params }: { params: { id: string } }) { + const res = new NextResponse(); + if (!params.id) { + return; + } + + const { $res, user, access_token, tenantId } = await authenticatedGuard(req, res); + + if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + + const response = await getOrganizationProjectRequest({ + bearer_token: access_token, + id: params.id, + tenantId + }); + + return $res(response.data); +} diff --git a/apps/web/app/api/organization-projects/route.ts b/apps/web/app/api/organization-projects/route.ts index c76dfa9b0..b78c6d73c 100644 --- a/apps/web/app/api/organization-projects/route.ts +++ b/apps/web/app/api/organization-projects/route.ts @@ -1,6 +1,6 @@ import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app'; -import { createOrganizationProjectRequest } from '@app/services/server/requests'; +import { createOrganizationProjectRequest, getOrganizationProjectsRequest } from '@app/services/server/requests'; import { NextResponse } from 'next/server'; export async function POST(req: Request) { @@ -19,3 +19,20 @@ export async function POST(req: Request) { return $res(response.data); } + +export async function GET(req: Request) { + const res = new NextResponse(); + + const { $res, user, access_token, tenantId, organizationId } = await authenticatedGuard(req, res); + + if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + + + const response = await getOrganizationProjectsRequest({ + bearer_token: access_token, + tenantId, + organizationId + }); + + return $res(response.data); +} diff --git a/apps/web/app/hooks/features/useOrganizationProjects.ts b/apps/web/app/hooks/features/useOrganizationProjects.ts index fdacff18c..121c4dc8e 100644 --- a/apps/web/app/hooks/features/useOrganizationProjects.ts +++ b/apps/web/app/hooks/features/useOrganizationProjects.ts @@ -1,59 +1,83 @@ import { editOrganizationProjectSettingAPI, - editOrganizationProjectAPI + editOrganizationProjectAPI, + getOrganizationProjectAPI, + getOrganizationProjectsAPI } from '@app/services/client/api'; import { userState } from '@app/stores'; import { useCallback } from 'react'; import { useAtom } from 'jotai'; import { useQuery } from '../useQuery'; +import { organizationProjectsState } from '@/app/stores/organization-projects'; export function useOrganizationProjects() { - const [user] = useAtom(userState); - - const { - loading: editOrganizationProjectLoading, - queryCall: editOrganizationProjectQueryCall - } = useQuery(editOrganizationProjectAPI); - - const { - loading: editOrganizationProjectSettingLoading, - queryCall: editOrganizationProjectSettingQueryCall - } = useQuery(editOrganizationProjectSettingAPI); - - const editOrganizationProjectSetting = useCallback( - (id: string, data: any) => { - if (user?.tenantId) { - return editOrganizationProjectSettingQueryCall( - id, - data, - user?.tenantId || '' - ).then((res) => { - return res; - }); - } - }, - [user, editOrganizationProjectSettingQueryCall] - ); - - const editOrganizationProject = useCallback( - (id: string, data: any) => { - if (user?.tenantId) { - return editOrganizationProjectQueryCall( - id, - data, - user?.tenantId || '' - ).then((res) => { - return res; - }); - } - }, - [user, editOrganizationProjectQueryCall] - ); - - return { - editOrganizationProjectSetting, - editOrganizationProjectSettingLoading, - editOrganizationProject, - editOrganizationProjectLoading - }; + const [user] = useAtom(userState); + const [organizationProjects, setOrganizationProjects] = useAtom(organizationProjectsState); + + const { loading: editOrganizationProjectLoading, queryCall: editOrganizationProjectQueryCall } = + useQuery(editOrganizationProjectAPI); + + const { loading: editOrganizationProjectSettingLoading, queryCall: editOrganizationProjectSettingQueryCall } = + useQuery(editOrganizationProjectSettingAPI); + + const { loading: getOrganizationProjectLoading, queryCall: getOrganizationProjectQueryCall } = + useQuery(getOrganizationProjectAPI); + + const { loading: getOrganizationProjectsLoading, queryCall: getOrganizationProjectsQueryCall } = + useQuery(getOrganizationProjectsAPI); + + const editOrganizationProjectSetting = useCallback( + (id: string, data: any) => { + if (user?.tenantId) { + return editOrganizationProjectSettingQueryCall(id, data, user?.tenantId || '').then((res) => { + return res; + }); + } + }, + [user, editOrganizationProjectSettingQueryCall] + ); + + const editOrganizationProject = useCallback( + (id: string, data: any) => { + if (user?.tenantId) { + return editOrganizationProjectQueryCall(id, data, user?.tenantId || '').then((res) => { + return res; + }); + } + }, + [user, editOrganizationProjectQueryCall] + ); + + const getOrganizationProject = useCallback( + async (id: string) => { + try { + return await getOrganizationProjectQueryCall(id); + } catch (error) { + console.log(error); + } + }, + [getOrganizationProjectQueryCall] + ); + + const getOrganizationProjects = useCallback(async () => { + try { + const res = await getOrganizationProjectsQueryCall(); + + setOrganizationProjects(res.data.items); + } catch (error) { + console.log(error); + } + }, [getOrganizationProjectsQueryCall, setOrganizationProjects]); + + return { + editOrganizationProjectSetting, + editOrganizationProjectSettingLoading, + editOrganizationProject, + editOrganizationProjectLoading, + getOrganizationProject, + getOrganizationProjectLoading, + getOrganizationProjects, + getOrganizationProjectsLoading, + organizationProjects, + }; } diff --git a/apps/web/app/interfaces/ITask.ts b/apps/web/app/interfaces/ITask.ts index 0bb4459b3..1a50b539c 100644 --- a/apps/web/app/interfaces/ITask.ts +++ b/apps/web/app/interfaces/ITask.ts @@ -18,7 +18,7 @@ export type ITeamTask = { estimateMinutes?: number; dueDate: string; startDate?: string | null; - projectId: string; + projectId: string | null; public: boolean; taskStatusId?: string; resolvedAt?: string; diff --git a/apps/web/app/services/client/api/organization-projects.ts b/apps/web/app/services/client/api/organization-projects.ts index 1f2d7243f..107225e44 100644 --- a/apps/web/app/services/client/api/organization-projects.ts +++ b/apps/web/app/services/client/api/organization-projects.ts @@ -1,5 +1,7 @@ -import { IProject } from '@app/interfaces'; -import { put } from '../axios'; +import { IProject, PaginationResponse } from '@app/interfaces'; +import { get, put } from '../axios'; +import qs from 'qs'; +import { getOrganizationIdCookie, getTenantIdCookie } from '@/app/helpers'; export function editOrganizationProjectSettingAPI(id: string, data: any, tenantId?: string) { return put(`/organization-projects/setting/${id}`, data, { @@ -12,3 +14,25 @@ export function editOrganizationProjectAPI(id: string, data: any, tenantId?: str tenantId }); } + +export function getOrganizationProjectAPI(id: string, tenantId?: string) { + return get(`/organization-projects/${id}`, { + tenantId + }); +} + +export function getOrganizationProjectsAPI() { + + const organizationId = getOrganizationIdCookie(); + const tenantId = getTenantIdCookie(); + + const obj = { + 'where[organizationId]': organizationId, + 'where[tenantId]': tenantId, + } + const query = qs.stringify(obj); + + return get>(`/organization-projects?${query}`, { + tenantId + }); +} diff --git a/apps/web/app/services/server/requests/organization-projects.ts b/apps/web/app/services/server/requests/organization-projects.ts index d4ce9f971..643995491 100644 --- a/apps/web/app/services/server/requests/organization-projects.ts +++ b/apps/web/app/services/server/requests/organization-projects.ts @@ -1,4 +1,6 @@ +import qs from 'qs'; import { serverFetch } from '../fetch'; +import { IProject, PaginationResponse } from '@/app/interfaces'; export function editOrganizationProjectsSettingsRequest({ id, @@ -39,3 +41,44 @@ export function editOrganizationProjectsRequest({ tenantId }); } + +export function getOrganizationProjectRequest({ + id, + tenantId, + bearer_token +}: { + id: string; + tenantId: string; + bearer_token: string; +}) { + return serverFetch({ + path: `/organization-projects/${id}`, + method: 'GET', + bearer_token, + tenantId + }); +} + +export function getOrganizationProjectsRequest({ + tenantId, + organizationId, + bearer_token +}: { + tenantId: string; + bearer_token: string; + organizationId : string; +}) { + + const obj = { + 'where[organizationId]': organizationId, + 'where[tenantId]': tenantId, + } + const query = qs.stringify(obj); + + return serverFetch>({ + path: `/organization-projects?${query}`, + method: 'GET', + bearer_token, + tenantId + }); +} diff --git a/apps/web/app/stores/organization-projects.ts b/apps/web/app/stores/organization-projects.ts new file mode 100644 index 000000000..e928707b5 --- /dev/null +++ b/apps/web/app/stores/organization-projects.ts @@ -0,0 +1,4 @@ +import { atom } from "jotai"; +import { IProject } from "../interfaces"; + +export const organizationProjectsState = atom([]) diff --git a/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx b/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx index 687671af3..88c8690fd 100644 --- a/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx +++ b/apps/web/components/pages/task/details-section/blocks/task-secondary-info.tsx @@ -1,8 +1,8 @@ -import { useModal, useTeamTasks } from '@app/hooks'; -import { ITaskVersionCreate, ITeamTask } from '@app/interfaces'; +import { useModal, useOrganizationProjects, useTeamTasks } from '@app/hooks'; +import { IProject, ITaskVersionCreate, ITeamTask } from '@app/interfaces'; import { detailedTaskState } from '@app/stores'; import { PlusIcon } from '@heroicons/react/20/solid'; -import { Button, Card, Modal, Tooltip } from 'lib/components'; +import { Button, Card, Modal, SpinnerLoader, Tooltip } from 'lib/components'; import { ActiveTaskPropertiesDropdown, ActiveTaskSizesDropdown, @@ -21,11 +21,14 @@ import { import { VersionForm } from 'lib/settings/version-form'; import { cloneDeep } from 'lodash'; import Link from 'next/link'; -import { useCallback, useMemo, useState } from 'react'; +import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; import { useAtomValue } from 'jotai'; import TaskRow from '../components/task-row'; import { useTranslations } from 'next-intl'; -import { Square4OutlineIcon } from 'assets/svg'; +import { ChevronDownIcon, Square4OutlineIcon } from 'assets/svg'; +import { Listbox, Transition } from '@headlessui/react'; +import { clsxm } from '@/app/utils'; +import { organizationProjectsState } from '@/app/stores/organization-projects'; type StatusType = 'version' | 'epic' | 'status' | 'label' | 'size' | 'priority'; @@ -89,163 +92,149 @@ const TaskSecondaryInfo = () => { }, [taskLabels, task?.tags]); return ( -
- {/* Version */} - - - - - - - {/* Epic */} - {task && task.issueType === 'Story' && ( - - { - onTaskSelect({ - id: d - } as ITeamTask); - }} - className="lg:min-w-[170px] text-black" - forDetails={true} - sidebarUI={true} - taskStatusClassName="text-[0.625rem] h-[1.5625rem] max-w-[7.6875rem] rounded 3xl:text-xs" - defaultValue={task.parentId || ''} - /> - - )} - - {task && } - - {/* Task Status */} - - - - - - - {/* Task Labels */} - - - - {tags.length > 0 && ( - -
- {tags.map((tag, i) => { - return ( - - - - ); - })} -
-
- )} +
+ {/* Version */} + + + + + - {/* Task Size */} - - - - - - - {/* Task Properties */} - - - - - - - - - {formTarget === 'version' && ( - - )} - {formTarget === 'status' && ( - - )} - {formTarget === 'priority' && ( - - )} - {formTarget === 'size' && ( - - )} - - -
+ {/* Epic */} + {task && task.issueType === 'Story' && ( + + { + onTaskSelect({ + id: d + } as ITeamTask); + }} + className="lg:min-w-[170px] text-black" + forDetails={true} + sidebarUI={true} + taskStatusClassName="text-[0.625rem] w-[7.6875rem] h-[2.35rem] max-w-[7.6875rem] rounded 3xl:text-xs" + defaultValue={task.parentId || ''} + /> + + )} + + {task && } + + {/* Task Status */} + + + + + + + {/* Task Labels */} + + + + {tags.length > 0 && ( + +
+ {tags.map((tag, i) => { + return ( + + + + ); + })} +
+
+ )} + + {/* Task Size */} + + + + + + + {/* Task Properties */} + + + + + + + {/* Task project */} + {task && ( + + + + )} + + + {formTarget === 'version' && ( + + )} + {formTarget === 'status' && } + {formTarget === 'priority' && } + {formTarget === 'size' && } + + +
); }; @@ -280,4 +269,137 @@ const EpicParent = ({ task }: { task: ITeamTask }) => { ); }; + + +interface ITaskProjectDropdownProps { + task: ITeamTask; +} + export default TaskSecondaryInfo; + +/** + * TaskProject dropdown + * + * @param {Object} props - The props object + * @param {ITeamTask} props.task - The ITeamTask object which + * + * @returns {JSX.Element} - The Dropdown element + */ +function ProjectDropDown (props : ITaskProjectDropdownProps) { + + const {task} = props + + const organizationProjects = useAtomValue(organizationProjectsState) + const {getOrganizationProjects} = useOrganizationProjects() + const {updateTask, updateLoading} = useTeamTasks() + const t = useTranslations() + + useEffect(() => { + getOrganizationProjects() + },[getOrganizationProjects]) + + + const [selected, setSelected] = useState(); + + // Set the task project if any + useEffect(() => { + setSelected(organizationProjects.find(project => { + return project.id === task.projectId + })) + },[organizationProjects, task.projectId]) + + // Update the project + const handleUpdateProject = useCallback(async (project : IProject) => { + try { + await updateTask({ ...task, projectId: project.id }); + + setSelected(project); + } catch (error) { + console.error(error); + } + },[task, updateTask]) + + + // Remove the project + const handleRemoveProject = useCallback(async () => { + try { + await updateTask({ ...task, projectId: null }); + + setSelected(undefined); + } catch (error) { + console.error(error); + } + }, [task, updateTask]); + + return ( +
+ + {({ open }) => { + return ( + <> + + {updateLoading ? ( + + ) : ( +

{selected?.name ?? 'Project'}

+ )} +
+ + + + + {organizationProjects.map((item, i) => { + return ( + +
  • + {item.name} +
  • +
    + ); + })} + +
    +
    +
    + + ); + }} +
    +
    + ); +} diff --git a/apps/web/locales/ar.json b/apps/web/locales/ar.json index 2b45b804d..c64c8e161 100644 --- a/apps/web/locales/ar.json +++ b/apps/web/locales/ar.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "تعذر علينا تحديث عنوان المهمة.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "لا يمكن أن يتجاوز عنوان المهمة 255 حرفًا.", "TASK_IS_ALREADY_EPIC": "لا يمكن تغيير نوع المهمة الملحمية.", - "TASK_HAS_PARENT": "لا يمكن تغيير نوع المهمة حيث أن لديها بالفعل والد." + "TASK_HAS_PARENT": "لا يمكن تغيير نوع المهمة حيث أن لديها بالفعل والد.", + "PROJECT": "مشروع" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "أنت على وشك حذف الحالة {statusName} التي يتم استخدامها من قبل المهام النشطة؛ يرجى تأكيد الإجراء" diff --git a/apps/web/locales/bg.json b/apps/web/locales/bg.json index 6a35a5b89..a504c9f88 100644 --- a/apps/web/locales/bg.json +++ b/apps/web/locales/bg.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Не можахме да обновим заглавието на задачата.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Заглавието на задачата не може да надвишава 255 символа.", "TASK_IS_ALREADY_EPIC": "Епичният тип задача не може да бъде променен.", - "TASK_HAS_PARENT": "Типът задача не може да бъде променен, тъй като задачата вече има родител." + "TASK_HAS_PARENT": "Типът задача не може да бъде променен, тъй като задачата вече има родител.", + "PROJECT": "Проект" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Вие сте на път да изтриете състоянието {statusName}, което се използва от активни задачи; моля, потвърдете действието" diff --git a/apps/web/locales/de.json b/apps/web/locales/de.json index a8cd98b43..a29130ced 100644 --- a/apps/web/locales/de.json +++ b/apps/web/locales/de.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Die Aufgabenbezeichnung konnte nicht aktualisiert werden.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Die Aufgabenbezeichnung darf nicht mehr als 255 Zeichen umfassen.", "TASK_IS_ALREADY_EPIC": "Epische Aufgabentypen können nicht geändert werden.", - "TASK_HAS_PARENT": "Der Aufgabentyp kann nicht geändert werden, da die Aufgabe bereits ein übergeordnetes Element hat." + "TASK_HAS_PARENT": "Der Aufgabentyp kann nicht geändert werden, da die Aufgabe bereits ein übergeordnetes Element hat.", + "PROJECT": "Projekt" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Sie sind dabei, den Status {statusName} zu löschen, der von aktiven Aufgaben verwendet wird; bitte bestätigen Sie die Aktion" diff --git a/apps/web/locales/en.json b/apps/web/locales/en.json index e230c7a31..7ad4c6701 100644 --- a/apps/web/locales/en.json +++ b/apps/web/locales/en.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "We couldn't update Task Title.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Task Title can't exceed 255 characters.", "TASK_IS_ALREADY_EPIC": "Epic Task Type can not be changed.", - "TASK_HAS_PARENT": "Task Type can not be changed as Task has already Parent." + "TASK_HAS_PARENT": "Task Type can not be changed as Task has already Parent.", + "PROJECT": "Project" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "You are about to Delete the Status {statusName} that is used by active tasks; please confirm action" diff --git a/apps/web/locales/es.json b/apps/web/locales/es.json index 7e8997c94..072a30752 100644 --- a/apps/web/locales/es.json +++ b/apps/web/locales/es.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "No pudimos actualizar el título de la tarea.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "El título de la tarea no puede exceder 255 caracteres.", "TASK_IS_ALREADY_EPIC": "La tarea de tipo Épico no se puede cambiar.", - "TASK_HAS_PARENT": "El tipo de tarea no se puede cambiar porque la tarea ya tiene un padre." + "TASK_HAS_PARENT": "El tipo de tarea no se puede cambiar porque la tarea ya tiene un padre.", + "PROJECT": "Proyecto" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Está a punto de eliminar el estado {statusName} que está siendo utilizado por tareas activas; por favor confirme la acción" diff --git a/apps/web/locales/fr.json b/apps/web/locales/fr.json index 2c70c0917..03e6d72ae 100644 --- a/apps/web/locales/fr.json +++ b/apps/web/locales/fr.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Impossible de mettre à jour le titre de la tâche.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Le titre de la tâche ne peut pas dépasser 255 caractères.", "TASK_IS_ALREADY_EPIC": "Le type de tâche épique ne peut pas être modifié.", - "TASK_HAS_PARENT": "Le type de tâche ne peut pas être modifié car la tâche a déjà un parent." + "TASK_HAS_PARENT": "Le type de tâche ne peut pas être modifié car la tâche a déjà un parent.", + "PROJECT": "Projet" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Vous êtes sur le point de supprimer le statut {statusName} qui est utilisé par des tâches actives ; veuillez confirmer l'action" diff --git a/apps/web/locales/he.json b/apps/web/locales/he.json index e6c81b8fc..009eaf700 100644 --- a/apps/web/locales/he.json +++ b/apps/web/locales/he.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "לא יכולנו לעדכן את כותרת המשימה.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "כותרת משימה לא יכולה לעלות על 255 תווים.", "TASK_IS_ALREADY_EPIC": "לא ניתן לשנות סוג משימה אפית.", - "TASK_HAS_PARENT": "לא ניתן לשנות סוג משימה מכיוון שלמשימה כבר יש הורה." + "TASK_HAS_PARENT": "לא ניתן לשנות סוג משימה מכיוון שלמשימה כבר יש הורה.", + "PROJECT": "פרויקט" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "אתה עומד למחוק את המצב {statusName} המשמש במשימות פעילות; נא לאשר פעולה" diff --git a/apps/web/locales/it.json b/apps/web/locales/it.json index 945980bd8..c9810b03a 100644 --- a/apps/web/locales/it.json +++ b/apps/web/locales/it.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Non è stato possibile aggiornare il Titolo del Compito.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Il Titolo del Compito non può superare i 255 caratteri.", "TASK_IS_ALREADY_EPIC": "Il tipo di Compito Epico non può essere cambiato.", - "TASK_HAS_PARENT": "Il tipo di Compito non può essere cambiato poiché il Compito ha già un Genitore." + "TASK_HAS_PARENT": "Il tipo di Compito non può essere cambiato poiché il Compito ha già un Genitore.", + "PROJECT": "Progetto" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Stai per eliminare lo stato {statusName} utilizzato da attività attive; per favore conferma l'azione" diff --git a/apps/web/locales/nl.json b/apps/web/locales/nl.json index 2445311c8..15022dd3d 100644 --- a/apps/web/locales/nl.json +++ b/apps/web/locales/nl.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "We konden de taaktitel niet bijwerken.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "De taaktitel kan niet langer zijn dan 255 tekens.", "TASK_IS_ALREADY_EPIC": "Epic taaktype kan niet worden gewijzigd.", - "TASK_HAS_PARENT": "Taaktype kan niet worden gewijzigd omdat de taak al een bovenliggende taak heeft." + "TASK_HAS_PARENT": "Taaktype kan niet worden gewijzigd omdat de taak al een bovenliggende taak heeft.", + "PROJECT": "Project" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "U staat op het punt de status {statusName} te verwijderen die wordt gebruikt door actieve taken; bevestig alstublieft de actie" diff --git a/apps/web/locales/pl.json b/apps/web/locales/pl.json index 198f39004..3ff42ee43 100644 --- a/apps/web/locales/pl.json +++ b/apps/web/locales/pl.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Nie udało się zaktualizować Tytułu Zadania.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Tytuł Zadania nie może przekraczać 255 znaków.", "TASK_IS_ALREADY_EPIC": "Typ Zadania jako 'Epic' nie może zostać zmieniony.", - "TASK_HAS_PARENT": "Typ Zadania nie może zostać zmieniony, ponieważ Zadanie ma już przypisanego rodzica." + "TASK_HAS_PARENT": "Typ Zadania nie może zostać zmieniony, ponieważ Zadanie ma już przypisanego rodzica.", + "PROJECT": "Projekt" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Zaraz usuniesz status {statusName}, który jest używany przez aktywne zadania; proszę potwierdzić akcję" diff --git a/apps/web/locales/pt.json b/apps/web/locales/pt.json index 033cc1a79..4ae42a04d 100644 --- a/apps/web/locales/pt.json +++ b/apps/web/locales/pt.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Não foi possível atualizar o Título da Tarefa.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "O Título da Tarefa não pode exceder 255 caracteres.", "TASK_IS_ALREADY_EPIC": "O Tipo de Tarefa Épica não pode ser alterado.", - "TASK_HAS_PARENT": "O Tipo de Tarefa não pode ser alterado, pois a Tarefa já possui um Pai." + "TASK_HAS_PARENT": "O Tipo de Tarefa não pode ser alterado, pois a Tarefa já possui um Pai.", + "PROJECT": "Projeto" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Está prestes a eliminar o status {statusName} que está a ser usado por tarefas ativas; por favor, confirme a ação" diff --git a/apps/web/locales/ru.json b/apps/web/locales/ru.json index 3ab812538..a64a38134 100644 --- a/apps/web/locales/ru.json +++ b/apps/web/locales/ru.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "Мы не смогли обновить заголовок задачи.", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "Заголовок задачи не может превышать 255 символов.", "TASK_IS_ALREADY_EPIC": "Тип задачи 'Epic' не может быть изменен.", - "TASK_HAS_PARENT": "Тип задачи не может быть изменен, так как у задачи уже есть родитель." + "TASK_HAS_PARENT": "Тип задачи не может быть изменен, так как у задачи уже есть родитель.", + "PROJECT": "Проект" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "Вы собираетесь удалить статус {statusName}, который используется активными задачами; пожалуйста, подтвердите действие" diff --git a/apps/web/locales/zh.json b/apps/web/locales/zh.json index 50d39d2d2..311077623 100644 --- a/apps/web/locales/zh.json +++ b/apps/web/locales/zh.json @@ -343,7 +343,8 @@ "TASK_TITLE_CHARACTER_LIMIT_ERROR_TITLE": "无法更新任务标题。", "TASK_TITLE_CHARACTER_LIMIT_ERROR_DESCRIPTION": "任务标题不能超过255个字符。", "TASK_IS_ALREADY_EPIC": "史诗类型任务无法更改。", - "TASK_HAS_PARENT": "任务已有父任务,无法更改任务类型。" + "TASK_HAS_PARENT": "任务已有父任务,无法更改任务类型。", + "PROJECT": "项目" }, "taskStatus": { "DELETE_STATUS_CONFIRMATION": "您即将删除正在被活跃任务使用的状态 {statusName};请确认操作"