Merge branch 'release-v2.1.4' into feature/task-activities-by-user

This commit is contained in:
Chamika J
2025-07-29 08:46:05 +05:30
committed by GitHub
626 changed files with 17159 additions and 3505 deletions

View File

@@ -1,4 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { IAccountSetupSurveyData } from '@/types/account-setup/survey.types';
interface Task {
id: number;
@@ -17,6 +18,8 @@ interface AccountSetupState {
tasks: Task[];
teamMembers: Email[];
currentStep: number;
surveyData: IAccountSetupSurveyData;
surveySubStep: number;
}
const initialState: AccountSetupState = {
@@ -26,6 +29,8 @@ const initialState: AccountSetupState = {
tasks: [{ id: 0, value: '' }],
teamMembers: [{ id: 0, value: '' }],
currentStep: 0,
surveyData: {},
surveySubStep: 0,
};
const accountSetupSlice = createSlice({
@@ -50,6 +55,16 @@ const accountSetupSlice = createSlice({
setCurrentStep: (state, action: PayloadAction<number>) => {
state.currentStep = action.payload;
},
setSurveyData: (state, action: PayloadAction<Partial<IAccountSetupSurveyData>>) => {
state.surveyData = { ...state.surveyData, ...action.payload };
},
setSurveySubStep: (state, action: PayloadAction<number>) => {
state.surveySubStep = action.payload;
},
resetSurveyData: (state) => {
state.surveyData = {};
state.surveySubStep = 0;
},
resetAccountSetup: () => initialState,
},
});
@@ -61,6 +76,9 @@ export const {
setTasks,
setTeamMembers,
setCurrentStep,
setSurveyData,
setSurveySubStep,
resetSurveyData,
resetAccountSetup,
} = accountSetupSlice.actions;

View File

@@ -575,7 +575,6 @@ const enhancedKanbanSlice = createSlice({
action: PayloadAction<ITaskListPriorityChangeResponse>
) => {
const { id, priority_id, color_code, color_code_dark } = action.payload;
// Find the task in any group
const taskInfo = findTaskInAllGroups(state.taskGroups, id);
if (!taskInfo || !priority_id) return;
@@ -603,7 +602,6 @@ const enhancedKanbanSlice = createSlice({
// Update cache
state.taskCache[id] = task;
},
// Enhanced Kanban assignee update (for use in task drawer dropdown)
updateEnhancedKanbanTaskAssignees: (
state,

View File

@@ -1,4 +1,4 @@
import { Button, Dropdown } from 'antd';
import { Button, Dropdown } from '@/shared/antd-imports';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { ILanguageType, setLanguage } from './localesSlice';

View File

@@ -1,5 +1,5 @@
import { QuestionCircleOutlined } from '@ant-design/icons';
import { Button, Tooltip } from 'antd';
import { QuestionCircleOutlined } from '@/shared/antd-imports';
import { Button, Tooltip } from '@/shared/antd-imports';
import React from 'react';
import { useTranslation } from 'react-i18next';
import './HelpButton.css';

View File

@@ -1,5 +1,5 @@
import { UsergroupAddOutlined } from '@ant-design/icons';
import { Button, Tooltip } from 'antd';
import { UsergroupAddOutlined } from '@/shared/antd-imports';
import { Button, Tooltip } from '@/shared/antd-imports';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { colors } from '../../../styles/colors';

View File

@@ -5,8 +5,8 @@ import {
ProjectOutlined,
QuestionCircleOutlined,
ReadOutlined,
} from '@ant-design/icons';
import { Button, Card, Dropdown, Flex, MenuProps, Space, Typography } from 'antd';
} from '@/shared/antd-imports';
import { Button, Card, Dropdown, Flex, MenuProps, Space, Typography } from '@/shared/antd-imports';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { colors } from '../../../styles/colors';

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useState, useMemo } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Col, ConfigProvider, Flex, Menu, MenuProps, Alert } from 'antd';
import { Col, ConfigProvider, Flex, Menu, MenuProps, Alert } from '@/shared/antd-imports';
import { createPortal } from 'react-dom';
import InviteTeamMembers from '../../components/common/invite-team-members/invite-team-members';

View File

@@ -1,8 +1,8 @@
// Ant Design Icons
import { BankOutlined, CaretDownFilled, CheckCircleFilled } from '@ant-design/icons';
import { BankOutlined, CaretDownFilled, CheckCircleFilled } from '@/shared/antd-imports';
// Ant Design Components
import { Card, Divider, Dropdown, Flex, Tooltip, Typography } from 'antd';
import { Card, Divider, Dropdown, Flex, Tooltip, Typography } from '@/shared/antd-imports';
// Redux Hooks
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,5 +1,5 @@
import { ClockCircleOutlined, StopOutlined } from '@ant-design/icons';
import { Badge, Button, Dropdown, List, Tooltip, Typography, Space, Divider, theme } from 'antd';
import { ClockCircleOutlined, StopOutlined } from '@/shared/antd-imports';
import { Badge, Button, Dropdown, List, Tooltip, Typography, Space, Divider, theme } from '@/shared/antd-imports';
import React, { useEffect, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { taskTimeLogsApiService, IRunningTimer } from '@/api/tasks/task-time-logs.api.service';

View File

@@ -1,4 +1,4 @@
import { Button, Tooltip } from 'antd';
import { Button, Tooltip } from '@/shared/antd-imports';
import React from 'react';
import { colors } from '../../../styles/colors';
import { useTranslation } from 'react-i18next';

View File

@@ -1,5 +1,5 @@
import { UserOutlined } from '@ant-design/icons';
import { Button, Card, Dropdown, Flex, MenuProps, Tooltip, Typography } from 'antd';
import { UserOutlined } from '@/shared/antd-imports';
import { Button, Card, Dropdown, Flex, MenuProps, Tooltip, Typography } from '@/shared/antd-imports';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';

View File

@@ -7,8 +7,8 @@ import {
TagsOutlined,
UserAddOutlined,
UsergroupAddOutlined,
} from '@ant-design/icons';
import { Button, Flex, Tooltip, Typography } from 'antd';
} from '@/shared/antd-imports';
import { Button, Flex, Tooltip, Typography } from '@/shared/antd-imports';
import { colors } from '../../../styles/colors';
type BulkTasksActionProps = {

View File

@@ -8,6 +8,7 @@ interface ProjectMembersState {
currentMembersList: IMentionMemberViewModel[];
isDrawerOpen: boolean;
isLoading: boolean;
isFromAssigner: boolean;
error: string | null;
}
@@ -16,6 +17,7 @@ const initialState: ProjectMembersState = {
currentMembersList: [],
isDrawerOpen: false,
isLoading: false,
isFromAssigner: false,
error: null,
};
@@ -89,6 +91,12 @@ const projectMembersSlice = createSlice({
reducers: {
toggleProjectMemberDrawer: state => {
state.isDrawerOpen = !state.isDrawerOpen;
if (state.isDrawerOpen === false) {
state.isFromAssigner = false;
}
},
setIsFromAssigner: (state, action: PayloadAction<boolean>) => {
state.isFromAssigner = action.payload;
},
},
extraReducers: builder => {
@@ -139,7 +147,7 @@ const projectMembersSlice = createSlice({
},
});
export const { toggleProjectMemberDrawer } = projectMembersSlice.actions;
export const { toggleProjectMemberDrawer, setIsFromAssigner } = projectMembersSlice.actions;
export {
getProjectMembers,
getAllProjectMembers,

View File

@@ -1,10 +1,9 @@
import { SettingOutlined } from '@ant-design/icons';
import { Button, Tooltip } from 'antd';
import React from 'react';
import { useAppDispatch } from '../../../../hooks/useAppDispatch';
import { SettingOutlined } from '@/shared/antd-imports';
import { Button, Tooltip } from '@/shared/antd-imports';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { toggleDrawer } from './phases.slice';
import { useAppSelector } from '../../../../hooks/useAppSelector';
import { colors } from '../../../../styles/colors';
import { useAppSelector } from '@/hooks/useAppSelector';
import { colors } from '@/styles/colors';
import { useTranslation } from 'react-i18next';
const ConfigPhaseButton = () => {

View File

@@ -1,4 +1,4 @@
import { Button, Drawer, Flex, Input, Skeleton, Spin, Typography } from 'antd';
import { Button, Drawer, Flex, Input, Spin, Typography } from '@/shared/antd-imports';
import { useState } from 'react';
import { useAppSelector } from '../../../../hooks/useAppSelector';
import { useAppDispatch } from '../../../../hooks/useAppDispatch';
@@ -11,7 +11,7 @@ import {
updateProjectPhaseLabel,
} from './phases.slice';
import { Divider } from 'antd/lib';
import { PlusOutlined } from '@ant-design/icons';
import { PlusOutlined } from '@/shared/antd-imports';
import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import PhaseOptionItem from './PhaseOptionItem';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { useAppSelector } from '../../../../hooks/useAppSelector';
import { Flex } from 'antd';
import { Flex } from '@/shared/antd-imports';
import ConfigPhaseButton from './ConfigPhaseButton';
import { colors } from '../../../../styles/colors';
import { useTranslation } from 'react-i18next';

View File

@@ -1,5 +1,5 @@
import { Button, ColorPicker, ConfigProvider, Flex, Input } from 'antd';
import { CloseCircleOutlined, HolderOutlined } from '@ant-design/icons';
import { Button, ColorPicker, ConfigProvider, Flex, Input } from '@/shared/antd-imports';
import { CloseCircleOutlined, HolderOutlined } from '@/shared/antd-imports';
import { nanoid } from '@reduxjs/toolkit';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import {

View File

@@ -11,14 +11,14 @@ import {
Select,
Tag,
Typography,
} from 'antd';
} from '@/shared/antd-imports';
import React, { useRef, useState } from 'react';
import {
healthStatusData,
projectColors,
statusData,
} from '../../../lib/project/project-constants';
import { PlusCircleOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { PlusCircleOutlined, PlusOutlined, QuestionCircleOutlined } from '@/shared/antd-imports';
import { colors } from '../../../styles/colors';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,4 +1,4 @@
import { Card, ConfigProvider, Tag, Timeline, Typography } from 'antd';
import { Card, ConfigProvider, Tag, Timeline, Typography } from '@/shared/antd-imports';
import { simpleDateFormat } from '@/utils/simpleDateFormat';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { colors } from '../../../../../styles/colors';

View File

@@ -1,4 +1,4 @@
import { Flex, Skeleton } from 'antd';
import { Flex, Skeleton } from '@/shared/antd-imports';
import React, { useEffect, useMemo, useState } from 'react';
import EmptyListPlaceholder from '@/components/EmptyListPlaceholder';
import ActivityLogCard from './activity-log-card';

View File

@@ -1,4 +1,4 @@
import { Tabs } from 'antd';
import { Tabs } from '@/shared/antd-imports';
import { TabsProps } from 'antd/lib';
import React from 'react';
import MembersReportsOverviewTab from './overviewTab/MembersReportsOverviewTab';

View File

@@ -1,8 +1,8 @@
import { Drawer, Typography, Flex, Button, Space, Dropdown } from 'antd';
import { Drawer, Typography, Flex, Button, Space, Dropdown } from '@/shared/antd-imports';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { toggleMembersReportsDrawer } from '../membersReportsSlice';
import { DownOutlined } from '@ant-design/icons';
import { DownOutlined } from '@/shared/antd-imports';
import MembersReportsDrawerTabs from './members-reports-drawer-tabs';
import { useTranslation } from 'react-i18next';
import MembersOverviewTasksStatsDrawer from './overviewTab/members-overview-tasks-stats-drawer/members-overview-tasks-stats-drawer';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { Chart, ArcElement, Tooltip } from 'chart.js';
import { Badge, Card, Flex, Typography } from 'antd';
import { Badge, Card, Flex, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { IRPTOverviewMemberChartData } from '@/types/reporting/reporting.types';

View File

@@ -1,6 +1,6 @@
import { Doughnut } from 'react-chartjs-2';
import { Chart, ArcElement, Tooltip } from 'chart.js';
import { Badge, Card, Flex, Typography, Tooltip as AntTooltip } from 'antd';
import { Badge, Card, Flex, Typography, Tooltip as AntTooltip } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { IRPTOverviewMemberChartData } from '@/types/reporting/reporting.types';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { Chart, ArcElement, Tooltip } from 'chart.js';
import { Badge, Card, Flex, Typography } from 'antd';
import { Badge, Card, Flex, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { IRPTOverviewMemberChartData } from '@/types/reporting/reporting.types';

View File

@@ -1,4 +1,4 @@
import { Drawer, Typography } from 'antd';
import { Drawer, Typography } from '@/shared/antd-imports';
import React, { useEffect, useState } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,5 +1,5 @@
import { memo } from 'react';
import { ConfigProvider, Flex, Skeleton, Spin, Table, TableColumnsType, Typography } from 'antd';
import { ConfigProvider, Flex, Skeleton, Spin, Table, TableColumnsType, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import CustomTableTitle from '@components/CustomTableTitle';
import { simpleDateFormat } from '@/utils/simpleDateFormat';

View File

@@ -1,4 +1,4 @@
import { Drawer, Typography } from 'antd';
import { Drawer, Typography } from '@/shared/antd-imports';
import React, { useMemo, useState } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,9 +1,9 @@
import { Badge, Collapse, Flex, Table, TableColumnsType, Tag, Typography } from 'antd';
import { Badge, Collapse, Flex, Table, TableColumnsType, Tag, Typography } from '@/shared/antd-imports';
import CustomTableTitle from '@components/CustomTableTitle';
import { colors } from '@/styles/colors';
import dayjs from 'dayjs';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { DoubleRightOutlined } from '@ant-design/icons';
import { DoubleRightOutlined } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { setShowTaskDrawer } from '@/features/task-drawer/task-drawer.slice';

View File

@@ -2,8 +2,8 @@ import {
ClockCircleOutlined,
ExclamationCircleOutlined,
FileExcelOutlined,
} from '@ant-design/icons';
import { Button, Card, Flex } from 'antd';
} from '@/shared/antd-imports';
import { Button, Card, Flex } from '@/shared/antd-imports';
import React, { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,4 +1,4 @@
import { Flex } from 'antd';
import { Flex } from '@/shared/antd-imports';
import React, { useEffect, useMemo, useState } from 'react';
import CustomSearchbar from '../../../../../components/CustomSearchbar';
import { fetchData } from '@/utils/fetchData';

View File

@@ -1,7 +1,7 @@
import { Badge, Flex, Table, TableColumnsType, Tag, Typography } from 'antd';
import { Badge, Flex, Table, TableColumnsType, Tag, Typography } from '@/shared/antd-imports';
import React from 'react';
import dayjs from 'dayjs';
import { DoubleRightOutlined } from '@ant-design/icons';
import { DoubleRightOutlined } from '@/shared/antd-imports';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { setSelectedTaskId, setShowTaskDrawer } from '@/features/task-drawer/task-drawer.slice';
import CustomTableTitle from '@/components/CustomTableTitle';

View File

@@ -1,5 +1,5 @@
import { IRPTOverviewProject } from '@/types/reporting/reporting.types';
import { Flex, Select, Typography } from 'antd';
import { Flex, Select, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
type ProjectFilterProps = {

View File

@@ -1,5 +1,5 @@
import { CaretDownFilled } from '@ant-design/icons';
import { Button, Card, Checkbox, Dropdown, List, Space } from 'antd';
import { CaretDownFilled } from '@/shared/antd-imports';
import { Button, Card, Checkbox, Dropdown, List, Space } from '@/shared/antd-imports';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';

View File

@@ -1,4 +1,4 @@
import { Flex, Skeleton } from 'antd';
import { Flex, Skeleton } from '@/shared/antd-imports';
import React, { useEffect, useState } from 'react';
import BillableFilter from './billable-filter';
import { fetchData } from '@/utils/fetchData';

View File

@@ -1,4 +1,4 @@
import { Card, ConfigProvider, Tag, Timeline, Typography } from 'antd';
import { Card, ConfigProvider, Tag, Timeline, Typography } from '@/shared/antd-imports';
import { simpleDateFormat } from '@/utils/simpleDateFormat';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { useTranslation } from 'react-i18next';

View File

@@ -1,9 +1,9 @@
import { Drawer, Typography, Flex, Button, Dropdown } from 'antd';
import { Drawer, Typography, Flex, Button, Dropdown } from '@/shared/antd-imports';
import React, { useState } from 'react';
import { useAppSelector } from '../../../../hooks/useAppSelector';
import { useAppDispatch } from '../../../../hooks/useAppDispatch';
import { setSelectedProject, toggleProjectReportsDrawer } from '../project-reports-slice';
import { BankOutlined, DownOutlined } from '@ant-design/icons';
import { BankOutlined, DownOutlined } from '@/shared/antd-imports';
import ProjectReportsDrawerTabs from './ProjectReportsDrawerTabs';
import { colors } from '../../../../styles/colors';
import { useTranslation } from 'react-i18next';

View File

@@ -1,4 +1,4 @@
import { Tabs } from 'antd';
import { Tabs } from '@/shared/antd-imports';
import { TabsProps } from 'antd/lib';
import { useTranslation } from 'react-i18next';

View File

@@ -1,4 +1,4 @@
import { Flex } from 'antd';
import { Flex } from '@/shared/antd-imports';
import { useEffect, useMemo, useState } from 'react';
import CustomSearchbar from '../../../../../components/CustomSearchbar';
import ProjectReportsMembersTable from './ProjectReportsMembersTable';

View File

@@ -1,4 +1,4 @@
import { Progress, Table, TableColumnsType } from 'antd';
import { Progress, Table, TableColumnsType } from '@/shared/antd-imports';
import React from 'react';
import CustomTableTitle from '../../../../../components/CustomTableTitle';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,6 +1,6 @@
import { Drawer, Typography, Flex, Button } from 'antd';
import { Drawer, Typography, Flex, Button } from '@/shared/antd-imports';
import React, { useMemo, useState } from 'react';
import { FileOutlined } from '@ant-design/icons';
import { FileOutlined } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,9 +1,9 @@
import { useTranslation } from 'react-i18next';
import React from 'react';
import { createPortal } from 'react-dom';
import { Badge, Flex, Table, TableColumnsType, Tag, Typography } from 'antd';
import { Badge, Flex, Table, TableColumnsType, Tag, Typography } from '@/shared/antd-imports';
import dayjs from 'dayjs';
import { DoubleRightOutlined } from '@ant-design/icons';
import { DoubleRightOutlined } from '@/shared/antd-imports';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { setShowTaskDrawer } from '@/features/task-drawer/task-drawer.slice';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { Chart, ArcElement, Tooltip } from 'chart.js';
import { Badge, Card, Flex, Typography } from 'antd';
import { Badge, Card, Flex, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { IRPTOverviewProjectTasksByDue } from '@/types/reporting/reporting.types';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { Chart, ArcElement, Tooltip } from 'chart.js';
import { Badge, Card, Flex, Typography } from 'antd';
import { Badge, Card, Flex, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { IRPTOverviewProjectTasksByPriority } from '@/types/reporting/reporting.types';

View File

@@ -3,8 +3,8 @@ import {
ClockCircleOutlined,
ExclamationCircleOutlined,
FileExcelOutlined,
} from '@ant-design/icons';
import { Card, Flex, Typography } from 'antd';
} from '@/shared/antd-imports';
import { Card, Flex, Typography } from '@/shared/antd-imports';
import React, { ReactNode } from 'react';
import { colors } from '../../../../../styles/colors';
import { useTranslation } from 'react-i18next';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { Chart, ArcElement, Tooltip } from 'chart.js';
import { Badge, Card, Flex, Typography } from 'antd';
import { Badge, Card, Flex, Typography } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { IRPTOverviewProjectTasksByStatus } from '@/types/reporting/reporting.types';

View File

@@ -1,4 +1,4 @@
import { Badge, Collapse, Flex, Table, TableColumnsType, Tag, Typography } from 'antd';
import { Badge, Collapse, Flex, Table, TableColumnsType, Tag, Typography } from '@/shared/antd-imports';
import { useEffect } from 'react';
import CustomTableTitle from '@/components/CustomTableTitle';
import { colors } from '@/styles/colors';
@@ -9,7 +9,7 @@ import {
fetchTask,
setSelectedTaskId,
} from '@/features/task-drawer/task-drawer.slice';
import { DoubleRightOutlined } from '@ant-design/icons';
import { DoubleRightOutlined } from '@/shared/antd-imports';
import { useTranslation } from 'react-i18next';
import { fetchPriorities } from '@/features/taskAttributes/taskPrioritySlice';
import { fetchPhasesByProjectId } from '@/features/projects/singleProject/phase/phases.slice';

View File

@@ -1,4 +1,4 @@
import { Flex } from 'antd';
import { Flex } from '@/shared/antd-imports';
import React, { useEffect, useMemo, useState } from 'react';
import CustomSearchbar from '@components/CustomSearchbar';
import GroupByFilter from './group-by-filter';

View File

@@ -1,6 +1,6 @@
import { IGroupBy } from '@/features/board/board-slice';
import { CaretDownFilled } from '@ant-design/icons';
import { Flex, Select } from 'antd';
import { CaretDownFilled } from '@/shared/antd-imports';
import { Flex, Select } from '@/shared/antd-imports';
import React from 'react';
import { useTranslation } from 'react-i18next';

View File

@@ -1,4 +1,4 @@
import { Button, Col, DatePicker, Flex, Input, Row } from 'antd';
import { Button, Col, DatePicker, Flex, Input, Row } from '@/shared/antd-imports';
import React from 'react';
import { useDispatch } from 'react-redux';
import { toggleModal } from './scheduleSlice';

View File

@@ -1,4 +1,4 @@
import { Avatar, Drawer, Tabs, TabsProps } from 'antd';
import { Avatar, Drawer, Tabs, TabsProps } from '@/shared/antd-imports';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { toggleScheduleDrawer } from './scheduleSlice';

View File

@@ -1,4 +1,4 @@
import { Button, Checkbox, Col, Drawer, Form, Input, Row } from 'antd';
import { Button, Checkbox, Col, Drawer, Form, Input, Row } from '@/shared/antd-imports';
import React, { ReactHTMLElement, useState } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { toggleSettingsDrawer, updateSettings } from './scheduleSlice';

View File

@@ -1,6 +1,6 @@
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { ScheduleData } from '@/types/schedule/schedule-v2.types';
import { Button, Col, DatePicker, Flex, Form, Input, Row } from 'antd';
import { Button, Col, DatePicker, Flex, Form, Input, Row } from '@/shared/antd-imports';
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { createSchedule, fetchTeamData } from './scheduleSlice';

View File

@@ -1,4 +1,4 @@
import { Avatar, Drawer, Tabs, TabsProps } from 'antd';
import { Avatar, Drawer, Tabs, TabsProps } from '@/shared/antd-imports';
import React from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,4 +1,4 @@
import { Button, Checkbox, Col, Drawer, Form, Input, Row } from 'antd';
import { Button, Checkbox, Col, Drawer, Form, Input, Row } from '@/shared/antd-imports';
import React, { ReactHTMLElement, useEffect, useState } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Tag, Typography } from 'antd';
import { Tag, Typography } from '@/shared/antd-imports';
import { colors } from '@/styles/colors';
import { IProjectCategory } from '@/types/project/projectCategory.types';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Select, Tag, Tooltip } from 'antd';
import { Select, Tag, Tooltip } from '@/shared/antd-imports';
import { CategoryType } from '../../../types/categories.types';
import { useTranslation } from 'react-i18next';
import { PhaseColorCodes } from '../../../shared/constants';

View File

@@ -1,4 +1,4 @@
import { Button, Drawer, Form, Input, message, Typography } from 'antd';
import { Button, Drawer, Form, Input, message, Typography } from '@/shared/antd-imports';
import React from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,4 +1,4 @@
import { Button, Drawer, Form, Input, message, Typography } from 'antd';
import { Button, Drawer, Form, Input, message, Typography } from '@/shared/antd-imports';
import React, { useEffect } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,4 +1,4 @@
import { Button, Drawer, Form, Input, message, Typography } from 'antd';
import { Button, Drawer, Form, Input, message, Typography } from '@/shared/antd-imports';
import React from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,4 +1,4 @@
import { Button, Drawer, Form, Input, message, Typography } from 'antd';
import { Button, Drawer, Form, Input, message, Typography } from '@/shared/antd-imports';
import React, { useEffect } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -7,7 +7,7 @@ import {
EntityId,
createSelector,
} from '@reduxjs/toolkit';
import { Task, TaskManagementState, TaskGroup, TaskGrouping } from '@/types/task-management.types';
import { Task, TaskManagementState, TaskGroup, TaskGrouping, getSortOrderField } from '@/types/task-management.types';
import { ITaskListColumn } from '@/types/tasks/taskList.types';
import { RootState } from '@/app/store';
import {
@@ -64,6 +64,9 @@ const initialState: TaskManagementState = {
loadingColumns: false,
columns: [],
customColumns: [],
// Add sort-related state
sortField: '',
sortOrder: 'ASC',
};
// Async thunk to fetch tasks from API
@@ -233,12 +236,16 @@ export const fetchTasksV3 = createAsyncThunk(
// Get archived state from task management slice
const archivedState = state.taskManagement.archived;
// Get sort state from task management slice
const sortField = state.taskManagement.sortField;
const sortOrder = state.taskManagement.sortOrder;
const config: ITaskListConfigV2 = {
id: projectId,
archived: archivedState,
group: currentGrouping || '',
field: '',
order: '',
field: sortField,
order: sortOrder,
search: searchValue,
statuses: '',
members: selectedAssignees,
@@ -526,9 +533,25 @@ const taskManagementSlice = createSlice({
},
addTaskToGroup: (state, action: PayloadAction<{ task: Task; groupId: string }>) => {
const { task, groupId } = action.payload;
state.ids.push(task.id);
state.entities[task.id] = task;
const group = state.groups.find(g => g.id === groupId);
let group = state.groups.find(g => g.id === groupId);
// If group doesn't exist and it's "Unmapped", create it dynamically
if (!group && groupId === 'Unmapped') {
const unmappedGroup = {
id: 'Unmapped',
title: 'Unmapped',
taskIds: [],
type: 'phase' as const,
color: '#fbc84c69',
groupValue: 'Unmapped'
};
state.groups.push(unmappedGroup);
group = unmappedGroup;
}
if (group) {
group.taskIds.push(task.id);
}
@@ -660,12 +683,12 @@ const taskManagementSlice = createSlice({
const [removed] = newTasks.splice(newTasks.indexOf(sourceTaskId), 1);
newTasks.splice(newTasks.indexOf(destinationTaskId), 0, removed);
group.taskIds = newTasks;
// Update order for affected tasks. Assuming simple reordering affects order.
// This might need more sophisticated logic based on how `order` is used.
// Update order for affected tasks using the appropriate sort field
const sortField = getSortOrderField(state.grouping?.id);
newTasks.forEach((id, index) => {
if (newEntities[id]) {
newEntities[id] = { ...newEntities[id], order: index };
newEntities[id] = { ...newEntities[id], [sortField]: index };
}
});
}
@@ -673,11 +696,11 @@ const taskManagementSlice = createSlice({
// Moving between different groups
const sourceGroup = state.groups.find(g => g.id === sourceGroupId);
const destinationGroup = state.groups.find(g => g.id === destinationGroupId);
if (sourceGroup && destinationGroup) {
// Remove from source group
sourceGroup.taskIds = sourceGroup.taskIds.filter(id => id !== sourceTaskId);
// Add to destination group at the correct position relative to destinationTask
const destinationIndex = destinationGroup.taskIds.indexOf(destinationTaskId);
if (destinationIndex !== -1) {
@@ -685,50 +708,17 @@ const taskManagementSlice = createSlice({
} else {
destinationGroup.taskIds.push(sourceTaskId); // Add to end if destination task not found
}
// Update task's grouping field to reflect new group (e.g., status, priority, phase)
// This assumes the group ID directly corresponds to the task's field value
if (sourceTask) {
let updatedTask = { ...sourceTask };
switch (state.grouping?.id) {
case IGroupBy.STATUS:
updatedTask.status = destinationGroup.id;
break;
case IGroupBy.PRIORITY:
updatedTask.priority = destinationGroup.id;
break;
case IGroupBy.PHASE:
// Handle unmapped group specially
if (destinationGroup.id === 'Unmapped' || destinationGroup.title === 'Unmapped') {
updatedTask.phase = ''; // Clear phase for unmapped group
} else {
updatedTask.phase = destinationGroup.id;
}
break;
case IGroupBy.MEMBERS:
// If moving to a member group, ensure task is assigned to that member
// This assumes the group ID is the member ID
if (!updatedTask.assignees) {
updatedTask.assignees = [];
}
if (!updatedTask.assignees.includes(destinationGroup.id)) {
updatedTask.assignees.push(destinationGroup.id);
}
// If moving from a member group, and the task is no longer in any member group,
// consider removing the assignment (more complex logic might be needed here)
break;
default:
break;
}
newEntities[sourceTaskId] = updatedTask;
}
// Update order for affected tasks in both groups if necessary
// Do NOT update the task's grouping field (priority, phase, status) here.
// This will be handled by the socket event handler after backend confirmation.
// Update order for affected tasks in both groups using the appropriate sort field
const sortField = getSortOrderField(state.grouping?.id);
sourceGroup.taskIds.forEach((id, index) => {
if (newEntities[id]) newEntities[id] = { ...newEntities[id], order: index };
if (newEntities[id]) newEntities[id] = { ...newEntities[id], [sortField]: index };
});
destinationGroup.taskIds.forEach((id, index) => {
if (newEntities[id]) newEntities[id] = { ...newEntities[id], order: index };
if (newEntities[id]) newEntities[id] = { ...newEntities[id], [sortField]: index };
});
}
}
@@ -754,6 +744,16 @@ const taskManagementSlice = createSlice({
toggleArchived: (state) => {
state.archived = !state.archived;
},
setSortField: (state, action: PayloadAction<string>) => {
state.sortField = action.payload;
},
setSortOrder: (state, action: PayloadAction<'ASC' | 'DESC'>) => {
state.sortOrder = action.payload;
},
setSort: (state, action: PayloadAction<{ field: string; order: 'ASC' | 'DESC' }>) => {
state.sortField = action.payload.field;
state.sortOrder = action.payload.order;
},
resetTaskManagement: state => {
state.loading = false;
state.error = null;
@@ -762,6 +762,8 @@ const taskManagementSlice = createSlice({
state.selectedPriorities = [];
state.search = '';
state.archived = false;
state.sortField = '';
state.sortOrder = 'ASC';
state.ids = [];
state.entities = {};
},
@@ -958,8 +960,26 @@ const taskManagementSlice = createSlice({
.addCase(fetchTasksV3.fulfilled, (state, action) => {
state.loading = false;
const { allTasks, groups, grouping } = action.payload;
tasksAdapter.setAll(state as EntityState<Task, string>, allTasks || []); // Ensure allTasks is an array
state.ids = (allTasks || []).map(task => task.id); // Also update ids
// Preserve existing timer state from old tasks before replacing
const oldTasks = state.entities;
const tasksWithTimers = (allTasks || []).map(task => {
const oldTask = oldTasks[task.id];
if (oldTask?.timeTracking?.activeTimer) {
// Preserve the timer state from the old task
return {
...task,
timeTracking: {
...task.timeTracking,
activeTimer: oldTask.timeTracking.activeTimer
}
};
}
return task;
});
tasksAdapter.setAll(state as EntityState<Task, string>, tasksWithTimers); // Ensure allTasks is an array
state.ids = tasksWithTimers.map(task => task.id); // Also update ids
state.groups = groups;
state.grouping = grouping;
})
@@ -1010,7 +1030,7 @@ const taskManagementSlice = createSlice({
order: subtask.sort_order || subtask.order || 0,
parent_task_id: parentTaskId,
is_sub_task: true,
sub_tasks_count: 0,
sub_tasks_count: subtask.sub_tasks_count || 0, // Use actual count from backend
show_sub_tasks: false,
}));
@@ -1128,6 +1148,9 @@ export const {
setSearch,
setArchived,
toggleArchived,
setSortField,
setSortOrder,
setSort,
resetTaskManagement,
toggleTaskExpansion,
addSubtaskToParent,
@@ -1159,6 +1182,9 @@ export const selectLoading = (state: RootState) => state.taskManagement.loading;
export const selectError = (state: RootState) => state.taskManagement.error;
export const selectSelectedPriorities = (state: RootState) => state.taskManagement.selectedPriorities;
export const selectSearch = (state: RootState) => state.taskManagement.search;
export const selectSortField = (state: RootState) => state.taskManagement.sortField;
export const selectSortOrder = (state: RootState) => state.taskManagement.sortOrder;
export const selectSort = (state: RootState) => ({ field: state.taskManagement.sortField, order: state.taskManagement.sortOrder });
export const selectSubtaskLoading = (state: RootState, taskId: string) => state.taskManagement.loadingSubtasks[taskId] || false;
// Memoized selectors to prevent unnecessary re-renders
@@ -1185,7 +1211,7 @@ export default taskManagementSlice.reducer;
// V3 API selectors - no processing needed, data is pre-processed by backend
export const selectTaskGroupsV3 = (state: RootState) => state.taskManagement.groups;
export const selectCurrentGroupingV3 = (state: RootState) => state.taskManagement.grouping;
export const selectCurrentGroupingV3 = (state: RootState) => state.grouping.currentGrouping;
// Column-related selectors
export const selectColumns = (state: RootState) => state.taskManagement.columns;

View File

@@ -14,10 +14,10 @@ const DEFAULT_FIELDS: TaskListField[] = [
{ key: 'KEY', label: 'Key', visible: false, order: 1 },
{ key: 'DESCRIPTION', label: 'Description', visible: false, order: 2 },
{ key: 'PROGRESS', label: 'Progress', visible: true, order: 3 },
{ key: 'ASSIGNEES', label: 'Assignees', visible: true, order: 4 },
{ key: 'LABELS', label: 'Labels', visible: true, order: 5 },
{ key: 'PHASE', label: 'Phase', visible: true, order: 6 },
{ key: 'STATUS', label: 'Status', visible: true, order: 7 },
{ key: 'STATUS', label: 'Status', visible: true, order: 4 },
{ key: 'ASSIGNEES', label: 'Assignees', visible: true, order: 5 },
{ key: 'LABELS', label: 'Labels', visible: true, order: 6 },
{ key: 'PHASE', label: 'Phase', visible: true, order: 7 },
{ key: 'PRIORITY', label: 'Priority', visible: true, order: 8 },
{ key: 'TIME_TRACKING', label: 'Time Tracking', visible: true, order: 9 },
{ key: 'ESTIMATION', label: 'Estimation', visible: false, order: 10 },

View File

@@ -1,4 +1,4 @@
import { ConfigProvider, theme } from 'antd';
import { ConfigProvider, theme } from '@/shared/antd-imports';
import React, { useEffect, useRef, memo, useMemo, useCallback } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';

View File

@@ -1,9 +1,9 @@
import { Avatar, Button, Card, Divider, Drawer, Tag, Timeline, Typography } from 'antd';
import { Avatar, Button, Card, Divider, Drawer, Tag, Timeline, Typography } from '@/shared/antd-imports';
import React, { useState, useEffect } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { toggleTimeLogDrawer } from './timeLogSlice';
import { DownloadOutlined } from '@ant-design/icons';
import { DownloadOutlined } from '@/shared/antd-imports';
import jsonData from './ProjectTimeLog.json';
import { AvatarNamesMap, durations } from '../../../shared/constants';
import './ProjectTimeLogDrawer.css';