Enhance localization support in Kanban board
- Added new localized messages for error handling, task management, and filter loading across multiple languages (Albanian, German, English, Spanish, Portuguese, Chinese). - Updated the EnhancedKanbanBoardNativeDnD component to utilize these localized messages for improved user experience during task operations and error notifications.
This commit is contained in:
@@ -37,5 +37,17 @@
|
|||||||
"noDueDate": "Pa datë përfundimi",
|
"noDueDate": "Pa datë përfundimi",
|
||||||
"save": "Ruaj",
|
"save": "Ruaj",
|
||||||
"clear": "Pastro",
|
"clear": "Pastro",
|
||||||
"nextWeek": "Javën e ardhshme"
|
"nextWeek": "Javën e ardhshme",
|
||||||
|
"noSubtasks": "Pa nëndetyra",
|
||||||
|
"showSubtasks": "Shfaq nëndetyrat",
|
||||||
|
"hideSubtasks": "Fshih nëndetyrat",
|
||||||
|
|
||||||
|
"errorLoadingTasks": "Gabim gjatë ngarkimit të detyrave",
|
||||||
|
"noTasksFound": "Nuk u gjetën detyra",
|
||||||
|
"loadingFilters": "Duke ngarkuar filtra...",
|
||||||
|
"failedToUpdateColumnOrder": "Dështoi përditësimi i rendit të kolonave",
|
||||||
|
"failedToUpdatePhaseOrder": "Dështoi përditësimi i rendit të fazave",
|
||||||
|
"pleaseTryAgain": "Ju lutemi provoni përsëri",
|
||||||
|
"taskNotCompleted": "Detyra nuk është përfunduar",
|
||||||
|
"completeTaskDependencies": "Ju lutemi përfundoni varësitë e detyrës para se të vazhdoni"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,5 +37,17 @@
|
|||||||
"noDueDate": "Kein Fälligkeitsdatum",
|
"noDueDate": "Kein Fälligkeitsdatum",
|
||||||
"save": "Speichern",
|
"save": "Speichern",
|
||||||
"clear": "Löschen",
|
"clear": "Löschen",
|
||||||
"nextWeek": "Nächste Woche"
|
"nextWeek": "Nächste Woche",
|
||||||
|
"noSubtasks": "Keine Unteraufgaben",
|
||||||
|
"showSubtasks": "Unteraufgaben anzeigen",
|
||||||
|
"hideSubtasks": "Unteraufgaben ausblenden",
|
||||||
|
|
||||||
|
"errorLoadingTasks": "Fehler beim Laden der Aufgaben",
|
||||||
|
"noTasksFound": "Keine Aufgaben gefunden",
|
||||||
|
"loadingFilters": "Filter werden geladen...",
|
||||||
|
"failedToUpdateColumnOrder": "Fehler beim Aktualisieren der Spaltenreihenfolge",
|
||||||
|
"failedToUpdatePhaseOrder": "Fehler beim Aktualisieren der Phasenreihenfolge",
|
||||||
|
"pleaseTryAgain": "Bitte versuchen Sie es erneut",
|
||||||
|
"taskNotCompleted": "Aufgabe ist nicht abgeschlossen",
|
||||||
|
"completeTaskDependencies": "Bitte schließen Sie die Aufgabenabhängigkeiten ab, bevor Sie fortfahren"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,5 +40,14 @@
|
|||||||
"nextWeek": "Next week",
|
"nextWeek": "Next week",
|
||||||
"noSubtasks": "No subtasks",
|
"noSubtasks": "No subtasks",
|
||||||
"showSubtasks": "Show subtasks",
|
"showSubtasks": "Show subtasks",
|
||||||
"hideSubtasks": "Hide subtasks"
|
"hideSubtasks": "Hide subtasks",
|
||||||
|
|
||||||
|
"errorLoadingTasks": "Error loading tasks",
|
||||||
|
"noTasksFound": "No tasks found",
|
||||||
|
"loadingFilters": "Loading filters...",
|
||||||
|
"failedToUpdateColumnOrder": "Failed to update column order",
|
||||||
|
"failedToUpdatePhaseOrder": "Failed to update phase order",
|
||||||
|
"pleaseTryAgain": "Please try again",
|
||||||
|
"taskNotCompleted": "Task is not completed",
|
||||||
|
"completeTaskDependencies": "Please complete the task dependencies before proceeding"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,5 +37,17 @@
|
|||||||
"noDueDate": "Sin fecha de vencimiento",
|
"noDueDate": "Sin fecha de vencimiento",
|
||||||
"save": "Guardar",
|
"save": "Guardar",
|
||||||
"clear": "Limpiar",
|
"clear": "Limpiar",
|
||||||
"nextWeek": "Próxima semana"
|
"nextWeek": "Próxima semana",
|
||||||
|
"noSubtasks": "Sin subtareas",
|
||||||
|
"showSubtasks": "Mostrar subtareas",
|
||||||
|
"hideSubtasks": "Ocultar subtareas",
|
||||||
|
|
||||||
|
"errorLoadingTasks": "Error al cargar tareas",
|
||||||
|
"noTasksFound": "No se encontraron tareas",
|
||||||
|
"loadingFilters": "Cargando filtros...",
|
||||||
|
"failedToUpdateColumnOrder": "Error al actualizar el orden de las columnas",
|
||||||
|
"failedToUpdatePhaseOrder": "Error al actualizar el orden de las fases",
|
||||||
|
"pleaseTryAgain": "Por favor, inténtalo de nuevo",
|
||||||
|
"taskNotCompleted": "La tarea no está completada",
|
||||||
|
"completeTaskDependencies": "Por favor, completa las dependencias de la tarea antes de continuar"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,5 +37,17 @@
|
|||||||
"noDueDate": "Sem data de vencimento",
|
"noDueDate": "Sem data de vencimento",
|
||||||
"save": "Salvar",
|
"save": "Salvar",
|
||||||
"clear": "Limpar",
|
"clear": "Limpar",
|
||||||
"nextWeek": "Próxima semana"
|
"nextWeek": "Próxima semana",
|
||||||
|
"noSubtasks": "Sem subtarefas",
|
||||||
|
"showSubtasks": "Mostrar subtarefas",
|
||||||
|
"hideSubtasks": "Ocultar subtarefas",
|
||||||
|
|
||||||
|
"errorLoadingTasks": "Erro ao carregar tarefas",
|
||||||
|
"noTasksFound": "Nenhuma tarefa encontrada",
|
||||||
|
"loadingFilters": "Carregando filtros...",
|
||||||
|
"failedToUpdateColumnOrder": "Falha ao atualizar a ordem das colunas",
|
||||||
|
"failedToUpdatePhaseOrder": "Falha ao atualizar a ordem das fases",
|
||||||
|
"pleaseTryAgain": "Por favor, tente novamente",
|
||||||
|
"taskNotCompleted": "Tarefa não está concluída",
|
||||||
|
"completeTaskDependencies": "Por favor, complete as dependências da tarefa antes de prosseguir"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,5 +23,24 @@
|
|||||||
"deleteStatusTitle": "删除状态",
|
"deleteStatusTitle": "删除状态",
|
||||||
"deleteStatusContent": "您确定要删除此状态吗?此操作无法撤销。",
|
"deleteStatusContent": "您确定要删除此状态吗?此操作无法撤销。",
|
||||||
"deletePhaseTitle": "删除阶段",
|
"deletePhaseTitle": "删除阶段",
|
||||||
"deletePhaseContent": "您确定要删除此阶段吗?此操作无法撤销。"
|
"deletePhaseContent": "您确定要删除此阶段吗?此操作无法撤销。",
|
||||||
|
"untitledSection": "未命名部分",
|
||||||
|
"unmapped": "未映射",
|
||||||
|
"clickToChangeDate": "点击更改日期",
|
||||||
|
"noDueDate": "无截止日期",
|
||||||
|
"save": "保存",
|
||||||
|
"clear": "清除",
|
||||||
|
"nextWeek": "下周",
|
||||||
|
"noSubtasks": "无子任务",
|
||||||
|
"showSubtasks": "显示子任务",
|
||||||
|
"hideSubtasks": "隐藏子任务",
|
||||||
|
|
||||||
|
"errorLoadingTasks": "加载任务时出错",
|
||||||
|
"noTasksFound": "未找到任务",
|
||||||
|
"loadingFilters": "正在加载过滤器...",
|
||||||
|
"failedToUpdateColumnOrder": "更新列顺序失败",
|
||||||
|
"failedToUpdatePhaseOrder": "更新阶段顺序失败",
|
||||||
|
"pleaseTryAgain": "请重试",
|
||||||
|
"taskNotCompleted": "任务未完成",
|
||||||
|
"completeTaskDependencies": "请先完成任务依赖项,然后再继续"
|
||||||
}
|
}
|
||||||
@@ -24,8 +24,10 @@ import { useTaskSocketHandlers } from '@/hooks/useTaskSocketHandlers';
|
|||||||
import { phasesApiService } from '@/api/taskAttributes/phases/phases.api.service';
|
import { phasesApiService } from '@/api/taskAttributes/phases/phases.api.service';
|
||||||
import { ITaskListGroup } from '@/types/tasks/taskList.types';
|
import { ITaskListGroup } from '@/types/tasks/taskList.types';
|
||||||
import { fetchPhasesByProjectId, updatePhaseListOrder } from '@/features/projects/singleProject/phase/phases.slice';
|
import { fetchPhasesByProjectId, updatePhaseListOrder } from '@/features/projects/singleProject/phase/phases.slice';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ projectId }) => {
|
const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ projectId }) => {
|
||||||
|
const { t } = useTranslation('kanban-board');
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const authService = useAuthService();
|
const authService = useAuthService();
|
||||||
const { socket } = useSocket();
|
const { socket } = useSocket();
|
||||||
@@ -109,7 +111,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
const [movedBackGroup] = revertedGroups.splice(toIdx, 1);
|
const [movedBackGroup] = revertedGroups.splice(toIdx, 1);
|
||||||
revertedGroups.splice(fromIdx, 0, movedBackGroup);
|
revertedGroups.splice(fromIdx, 0, movedBackGroup);
|
||||||
dispatch(reorderGroups({ fromIndex: toIdx, toIndex: fromIdx, reorderedGroups: revertedGroups }));
|
dispatch(reorderGroups({ fromIndex: toIdx, toIndex: fromIdx, reorderedGroups: revertedGroups }));
|
||||||
alertService.error('Failed to update column order', 'Please try again');
|
alertService.error(t('failedToUpdateColumnOrder'), t('pleaseTryAgain'));
|
||||||
}
|
}
|
||||||
} else if (groupBy === 'phase') {
|
} else if (groupBy === 'phase') {
|
||||||
const newPhaseList = [...phaseList];
|
const newPhaseList = [...phaseList];
|
||||||
@@ -124,7 +126,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
};
|
};
|
||||||
const response = await phasesApiService.updatePhaseOrder(projectId, requestBody);
|
const response = await phasesApiService.updatePhaseOrder(projectId, requestBody);
|
||||||
if (!response.done) {
|
if (!response.done) {
|
||||||
alertService.error('Failed to update phase order', 'Please try again');
|
alertService.error(t('failedToUpdatePhaseOrder'), t('pleaseTryAgain'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -133,7 +135,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
const [movedBackGroup] = revertedGroups.splice(toIdx, 1);
|
const [movedBackGroup] = revertedGroups.splice(toIdx, 1);
|
||||||
revertedGroups.splice(fromIdx, 0, movedBackGroup);
|
revertedGroups.splice(fromIdx, 0, movedBackGroup);
|
||||||
dispatch(reorderGroups({ fromIndex: toIdx, toIndex: fromIdx, reorderedGroups: revertedGroups }));
|
dispatch(reorderGroups({ fromIndex: toIdx, toIndex: fromIdx, reorderedGroups: revertedGroups }));
|
||||||
alertService.error('Failed to update column order', 'Please try again');
|
alertService.error(t('failedToUpdateColumnOrder'), t('pleaseTryAgain'));
|
||||||
logger.error('Failed to update column order', error);
|
logger.error('Failed to update column order', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,11 +145,23 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
|
|
||||||
// Utility to recalculate all task orders for all groups
|
// Utility to recalculate all task orders for all groups
|
||||||
function getAllTaskUpdates(allGroups: ITaskListGroup[], groupBy: string) {
|
function getAllTaskUpdates(allGroups: ITaskListGroup[], groupBy: string) {
|
||||||
const taskUpdates = [];
|
const taskUpdates: Array<{
|
||||||
|
task_id: string | undefined;
|
||||||
|
sort_order: number;
|
||||||
|
status_id?: string;
|
||||||
|
priority_id?: string;
|
||||||
|
phase_id?: string;
|
||||||
|
}> = [];
|
||||||
let currentSortOrder = 0;
|
let currentSortOrder = 0;
|
||||||
for (const group of allGroups) {
|
for (const group of allGroups) {
|
||||||
for (const task of group.tasks) {
|
for (const task of group.tasks) {
|
||||||
const update = {
|
const update: {
|
||||||
|
task_id: string | undefined;
|
||||||
|
sort_order: number;
|
||||||
|
status_id?: string;
|
||||||
|
priority_id?: string;
|
||||||
|
phase_id?: string;
|
||||||
|
} = {
|
||||||
task_id: task.id,
|
task_id: task.id,
|
||||||
sort_order: currentSortOrder,
|
sort_order: currentSortOrder,
|
||||||
};
|
};
|
||||||
@@ -200,8 +214,8 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
const canContinue = await checkTaskDependencyStatus(movedTask.id, targetGroupId);
|
const canContinue = await checkTaskDependencyStatus(movedTask.id, targetGroupId);
|
||||||
if (!canContinue) {
|
if (!canContinue) {
|
||||||
alertService.error(
|
alertService.error(
|
||||||
'Task is not completed',
|
t('taskNotCompleted'),
|
||||||
'Please complete the task dependencies before proceeding'
|
t('completeTaskDependencies')
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -295,7 +309,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
team_id: teamId,
|
team_id: teamId,
|
||||||
from_index: taskIdx,
|
from_index: taskIdx,
|
||||||
to_index: insertIdx,
|
to_index: insertIdx,
|
||||||
to_last_index: insertIdx === (targetGroup.id === sourceGroup.id ? newTaskGroups.find(g => g.id === targetGroup.id)?.tasks.length - 1 : targetGroup.tasks.length),
|
to_last_index: insertIdx === (targetGroup.id === sourceGroup.id ? (newTaskGroups.find(g => g.id === targetGroup.id)?.tasks.length || 0) - 1 : targetGroup.tasks.length),
|
||||||
task: {
|
task: {
|
||||||
id: movedTask.id,
|
id: movedTask.id,
|
||||||
project_id: movedTask.project_id || projectId,
|
project_id: movedTask.project_id || projectId,
|
||||||
@@ -336,7 +350,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<Empty description={`Error loading tasks: ${error}`} image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
<Empty description={`${t('errorLoadingTasks')}: ${error}`} image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -344,7 +358,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<React.Suspense fallback={<div>Loading filters...</div>}>
|
<React.Suspense fallback={<div>{t('loadingFilters')}</div>}>
|
||||||
<ImprovedTaskFilters position="board" />
|
<ImprovedTaskFilters position="board" />
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</div>
|
</div>
|
||||||
@@ -358,7 +372,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
</div>
|
</div>
|
||||||
) : taskGroups.length === 0 ? (
|
) : taskGroups.length === 0 ? (
|
||||||
<Card>
|
<Card>
|
||||||
<Empty description="No tasks found" image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
<Empty description={t('noTasksFound')} image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||||
</Card>
|
</Card>
|
||||||
) : (
|
) : (
|
||||||
<div className="kanban-groups-container">
|
<div className="kanban-groups-container">
|
||||||
|
|||||||
Reference in New Issue
Block a user