diff --git a/worklenz-frontend/public/locales/alb/task-list-filters.json b/worklenz-frontend/public/locales/alb/task-list-filters.json index 1e1b649d..3ce3c704 100644 --- a/worklenz-frontend/public/locales/alb/task-list-filters.json +++ b/worklenz-frontend/public/locales/alb/task-list-filters.json @@ -55,5 +55,18 @@ "selectCategory": "Zgjidh një kategori", "pleaseEnterAName": "Ju lutemi vendosni një emër", "pleaseSelectACategory": "Ju lutemi zgjidhni një kategori", - "create": "Krijo" + "create": "Krijo", + + "searchTasks": "Kërko detyrat...", + "searchPlaceholder": "Kërko...", + "fieldsText": "Fushat", + "loadingFilters": "Duke ngarkuar filtrat...", + "noOptionsFound": "Nuk u gjetën opsione", + "filtersActive": "filtra aktiv", + "filterActive": "filtër aktiv", + "clearAll": "Pastro të gjitha", + "clearing": "Duke pastruar...", + "cancel": "Anulo", + "search": "Kërko", + "groupedBy": "Grupuar sipas" } diff --git a/worklenz-frontend/public/locales/de/task-list-filters.json b/worklenz-frontend/public/locales/de/task-list-filters.json index 4cc157c8..9197cb97 100644 --- a/worklenz-frontend/public/locales/de/task-list-filters.json +++ b/worklenz-frontend/public/locales/de/task-list-filters.json @@ -55,5 +55,18 @@ "selectCategory": "Kategorie auswählen", "pleaseEnterAName": "Bitte geben Sie einen Namen ein", "pleaseSelectACategory": "Bitte wählen Sie eine Kategorie aus", - "create": "Erstellen" + "create": "Erstellen", + + "searchTasks": "Aufgaben suchen...", + "searchPlaceholder": "Suchen...", + "fieldsText": "Felder", + "loadingFilters": "Filter werden geladen...", + "noOptionsFound": "Keine Optionen gefunden", + "filtersActive": "Filter aktiv", + "filterActive": "Filter aktiv", + "clearAll": "Alle löschen", + "clearing": "Löschen...", + "cancel": "Abbrechen", + "search": "Suchen", + "groupedBy": "Gruppiert nach" } diff --git a/worklenz-frontend/public/locales/en/task-list-filters.json b/worklenz-frontend/public/locales/en/task-list-filters.json index 72c79823..3941b0e0 100644 --- a/worklenz-frontend/public/locales/en/task-list-filters.json +++ b/worklenz-frontend/public/locales/en/task-list-filters.json @@ -55,5 +55,18 @@ "selectCategory": "Select a category", "pleaseEnterAName": "Please enter a name", "pleaseSelectACategory": "Please select a category", - "create": "Create" + "create": "Create", + + "searchTasks": "Search tasks...", + "searchPlaceholder": "Search...", + "fieldsText": "Fields", + "loadingFilters": "Loading filters...", + "noOptionsFound": "No options found", + "filtersActive": "filters active", + "filterActive": "filter active", + "clearAll": "Clear all", + "clearing": "Clearing...", + "cancel": "Cancel", + "search": "Search", + "groupedBy": "Grouped by" } diff --git a/worklenz-frontend/public/locales/es/task-list-filters.json b/worklenz-frontend/public/locales/es/task-list-filters.json index c6cf8c99..5a1941e0 100644 --- a/worklenz-frontend/public/locales/es/task-list-filters.json +++ b/worklenz-frontend/public/locales/es/task-list-filters.json @@ -51,5 +51,18 @@ "selectCategory": "Seleccionar una categoría", "pleaseEnterAName": "Por favor, ingrese un nombre", "pleaseSelectACategory": "Por favor, seleccione una categoría", - "create": "Crear" + "create": "Crear", + + "searchTasks": "Buscar tareas...", + "searchPlaceholder": "Buscar...", + "fieldsText": "Campos", + "loadingFilters": "Cargando filtros...", + "noOptionsFound": "No se encontraron opciones", + "filtersActive": "filtros activos", + "filterActive": "filtro activo", + "clearAll": "Limpiar todo", + "clearing": "Limpiando...", + "cancel": "Cancelar", + "search": "Buscar", + "groupedBy": "Agrupado por" } diff --git a/worklenz-frontend/public/locales/pt/task-list-filters.json b/worklenz-frontend/public/locales/pt/task-list-filters.json index cfbcf22e..76e9287f 100644 --- a/worklenz-frontend/public/locales/pt/task-list-filters.json +++ b/worklenz-frontend/public/locales/pt/task-list-filters.json @@ -52,5 +52,18 @@ "selectCategory": "Selecionar uma categoria", "pleaseEnterAName": "Por favor, insira um nome", "pleaseSelectACategory": "Por favor, selecione uma categoria", - "create": "Criar" + "create": "Criar", + + "searchTasks": "Pesquisar tarefas...", + "searchPlaceholder": "Pesquisar...", + "fieldsText": "Campos", + "loadingFilters": "Carregando filtros...", + "noOptionsFound": "Nenhuma opção encontrada", + "filtersActive": "filtros ativos", + "filterActive": "filtro ativo", + "clearAll": "Limpar tudo", + "clearing": "Limpando...", + "cancel": "Cancelar", + "search": "Pesquisar", + "groupedBy": "Agrupado por" } diff --git a/worklenz-frontend/src/components/task-list-v2/SubtaskLoadingSkeleton.tsx b/worklenz-frontend/src/components/task-list-v2/SubtaskLoadingSkeleton.tsx index 1f67a048..ce437500 100644 --- a/worklenz-frontend/src/components/task-list-v2/SubtaskLoadingSkeleton.tsx +++ b/worklenz-frontend/src/components/task-list-v2/SubtaskLoadingSkeleton.tsx @@ -32,6 +32,12 @@ const SubtaskLoadingSkeleton: React.FC = ({ visible
); + case 'description': + return ( +
+
+
+ ); case 'status': return (
diff --git a/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx b/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx index 823b43fe..a5468b1d 100644 --- a/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx +++ b/worklenz-frontend/src/components/task-list-v2/TaskRow.tsx @@ -352,6 +352,24 @@ const TaskRow: React.FC = memo(({ taskId, projectId, visibleColumn
); + case 'description': + return ( +
+
+
+ ); + case 'status': return (
diff --git a/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx b/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx index a2f52943..01780383 100644 --- a/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx +++ b/worklenz-frontend/src/components/task-list-v2/TaskRowWithSubtasks.tsx @@ -93,6 +93,8 @@ const AddSubtaskRow: React.FC = memo(({ return
; case 'taskKey': return
; + case 'description': + return
; case 'title': return (
diff --git a/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx b/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx index a023f7f4..367ed4f5 100644 --- a/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx +++ b/worklenz-frontend/src/components/task-list-v2/components/AddTaskRow.tsx @@ -92,6 +92,7 @@ const AddTaskRow: React.FC = memo(({ case 'dragHandle': case 'checkbox': case 'taskKey': + case 'description': return
; case 'title': return ( diff --git a/worklenz-frontend/src/components/task-list-v2/constants/columns.ts b/worklenz-frontend/src/components/task-list-v2/constants/columns.ts index c2dd6e79..8f105f12 100644 --- a/worklenz-frontend/src/components/task-list-v2/constants/columns.ts +++ b/worklenz-frontend/src/components/task-list-v2/constants/columns.ts @@ -17,6 +17,7 @@ export const BASE_COLUMNS = [ { id: 'checkbox', label: '', width: '28px', isSticky: true, key: 'checkbox' }, { id: 'taskKey', label: 'keyColumn', width: '100px', key: COLUMN_KEYS.KEY, minWidth: '100px', maxWidth: '150px' }, { id: 'title', label: 'taskColumn', width: '470px', isSticky: true, key: COLUMN_KEYS.NAME }, + { id: 'description', label: 'descriptionColumn', width: '260px', key: COLUMN_KEYS.DESCRIPTION }, { id: 'status', label: 'statusColumn', width: '120px', key: COLUMN_KEYS.STATUS }, { id: 'assignees', label: 'assigneesColumn', width: '150px', key: COLUMN_KEYS.ASSIGNEES }, { id: 'priority', label: 'priorityColumn', width: '120px', key: COLUMN_KEYS.PRIORITY }, diff --git a/worklenz-frontend/src/components/task-management/improved-task-filters.tsx b/worklenz-frontend/src/components/task-management/improved-task-filters.tsx index d12ea4fa..7ed94cdc 100644 --- a/worklenz-frontend/src/components/task-management/improved-task-filters.tsx +++ b/worklenz-frontend/src/components/task-management/improved-task-filters.tsx @@ -372,6 +372,7 @@ const FilterDropdown: React.FC<{ isDarkMode, className = '', }) => { + const { t } = useTranslation('task-list-filters'); // Add permission checks for groupBy section const isOwnerOrAdmin = useAuthService().isOwnerOrAdmin(); const isProjectManager = useIsProjectManager(); @@ -440,14 +441,14 @@ const FilterDropdown: React.FC<{ {/* Trigger Button */} ) : (
@@ -640,12 +651,12 @@ const SearchFilter: React.FC<{ type="text" value={localValue} onChange={e => setLocalValue(e.target.value)} - placeholder={placeholder} - className={`w-full pr-4 pl-8 py-1 rounded border focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors duration-150 ${ - isDarkMode - ? 'bg-gray-700 text-gray-100 placeholder-gray-400 border-gray-600' - : 'bg-white text-gray-900 placeholder-gray-400 border-gray-300' - }`} + placeholder={placeholder || t('searchTasks')} + className={`w-full pr-4 pl-8 py-1 rounded border focus:outline-none focus:ring-2 focus:ring-gray-500 transition-colors duration-150 ${ + isDarkMode + ? 'bg-gray-700 text-gray-100 placeholder-gray-400 border-gray-600' + : 'bg-white text-gray-900 placeholder-gray-400 border-gray-300' + }`} /> {localValue && ( + className={`px-2.5 py-1.5 text-xs font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition-colors duration-200 ${ + isDarkMode + ? 'text-white bg-gray-600 hover:bg-gray-700' + : 'text-gray-800 bg-gray-200 hover:bg-gray-300' + }`} + > + {t('search')} + + > + {t('cancel')} +
)}
@@ -682,6 +697,7 @@ const FieldsDropdown: React.FC<{ themeClasses: any; isDarkMode: boolean }> = ({ themeClasses, isDarkMode, }) => { + const { t } = useTranslation('task-list-filters'); const dispatch = useDispatch(); const fieldsRaw = useSelector((state: RootState) => state.taskManagementFields); const fields = Array.isArray(fieldsRaw) ? fieldsRaw : []; @@ -734,17 +750,17 @@ const FieldsDropdown: React.FC<{ themeClasses: any; isDarkMode: boolean }> = ({ visibleCount > 0 ? isDarkMode ? 'bg-gray-600 text-white border-gray-500' - : 'bg-blue-50 text-blue-800 border-blue-300 font-semibold' + : 'bg-gray-200 text-gray-800 border-gray-300 font-semibold' : `${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText}` } - hover:shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 + hover:shadow-sm focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 ${isDarkMode ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'} `} aria-expanded={open} aria-haspopup="true" > - Fields + {t('fieldsText')} {visibleCount > 0 && ( = ({ {/* Options List */}
{sortedFields.length === 0 ? ( -
- No fields available -
+
+ {t('noOptionsFound')} +
) : (
{sortedFields.map(field => { @@ -881,7 +897,7 @@ const ImprovedTaskFilters: React.FC = ({ position, cla const { projectView } = useTabSearchParam(); // Theme-aware class names - memoize to prevent unnecessary re-renders - // Using task list row colors for consistency: --task-bg-primary: #1f1f1f, --task-bg-secondary: #141414 + // Using greyish colors for both dark and light modes const themeClasses = useMemo( () => ({ containerBg: isDarkMode ? 'bg-[#1f1f1f]' : 'bg-white', @@ -897,8 +913,8 @@ const ImprovedTaskFilters: React.FC = ({ position, cla dividerBorder: isDarkMode ? 'border-[#404040]' : 'border-gray-200', pillBg: isDarkMode ? 'bg-[#141414]' : 'bg-gray-100', pillText: isDarkMode ? 'text-[#d9d9d9]' : 'text-gray-700', - pillActiveBg: isDarkMode ? 'bg-blue-600' : 'bg-blue-100', - pillActiveText: isDarkMode ? 'text-white' : 'text-blue-800', + pillActiveBg: isDarkMode ? 'bg-gray-600' : 'bg-gray-200', + pillActiveText: isDarkMode ? 'text-white' : 'text-gray-800', searchBg: isDarkMode ? 'bg-[#141414]' : 'bg-gray-50', searchBorder: isDarkMode ? 'border-[#303030]' : 'border-gray-300', searchText: isDarkMode ? 'text-[#d9d9d9]' : 'text-gray-900', @@ -1196,12 +1212,12 @@ const ImprovedTaskFilters: React.FC = ({ position, cla )) ) : ( // Loading state -
-
- Loading filters... -
+
+
+ {t('loadingFilters')} +
)}
@@ -1211,20 +1227,20 @@ const ImprovedTaskFilters: React.FC = ({ position, cla {activeFiltersCount > 0 && (
- {activeFiltersCount} filter{activeFiltersCount !== 1 ? 's' : ''} active + {activeFiltersCount} {activeFiltersCount !== 1 ? t('filtersActive') : t('filterActive')}
)} @@ -1236,13 +1252,13 @@ const ImprovedTaskFilters: React.FC = ({ position, cla type="checkbox" checked={showArchived} onChange={toggleArchived} - className={`w-3.5 h-3.5 text-blue-600 rounded focus:ring-blue-500 transition-colors duration-150 ${ + className={`w-3.5 h-3.5 text-gray-600 rounded focus:ring-gray-500 transition-colors duration-150 ${ isDarkMode ? 'border-[#303030] bg-[#141414] focus:ring-offset-gray-800' : 'border-gray-300 bg-white focus:ring-offset-white' }`} /> - Show archived + {t('showArchivedText')} )} @@ -1284,9 +1300,9 @@ const ImprovedTaskFilters: React.FC = ({ position, cla } } }} - className={`ml-1 rounded-full p-0.5 transition-colors duration-150 ${ - isDarkMode ? 'hover:bg-blue-800' : 'hover:bg-blue-200' - }`} + className={`ml-1 rounded-full p-0.5 transition-colors duration-150 ${ + isDarkMode ? 'hover:bg-gray-800' : 'hover:bg-gray-200' + }`} >