Add task progress tracking methods and enhance UI components

- Introduced a comprehensive guide for users on task progress tracking methods, including manual, weighted, and time-based progress.
- Implemented backend support for progress calculations, including SQL functions and migrations to accommodate new progress features.
- Enhanced frontend components to support progress input and display, including updates to task and project drawers.
- Added localization for new progress-related terms and validation messages.
- Integrated real-time updates for task progress and weight changes through socket events.
This commit is contained in:
chamiakJ
2025-04-30 15:24:07 +05:30
parent a2bfdb682b
commit 6128c64c31
24 changed files with 1466 additions and 150 deletions

View File

@@ -32,7 +32,7 @@ const TaskDrawer = () => {
const [refreshTimeLogTrigger, setRefreshTimeLogTrigger] = useState(0);
const { showTaskDrawer, timeLogEditing } = useAppSelector(state => state.taskDrawerReducer);
const { taskFormViewModel, selectedTaskId } = useAppSelector(state => state.taskDrawerReducer);
const taskNameInputRef = useRef<InputRef>(null);
const isClosingManually = useRef(false);
@@ -47,20 +47,32 @@ const TaskDrawer = () => {
const dispatch = useAppDispatch();
const handleOnClose = () => {
// Set flag to indicate we're manually closing the drawer
isClosingManually.current = true;
setActiveTab('info');
// Explicitly clear the task parameter from URL
clearTaskFromUrl();
// Update the Redux state
const resetTaskState = () => {
dispatch(setShowTaskDrawer(false));
dispatch(setSelectedTaskId(null));
dispatch(setTaskFormViewModel({}));
dispatch(setTaskSubscribers([]));
};
const handleOnClose = (
e?: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element>
) => {
// Set flag to indicate we're manually closing the drawer
isClosingManually.current = true;
setActiveTab('info');
clearTaskFromUrl();
const isClickOutsideDrawer =
e?.target && (e.target as HTMLElement).classList.contains('ant-drawer-mask');
if (isClickOutsideDrawer || !taskFormViewModel?.task?.is_sub_task) {
resetTaskState();
} else {
dispatch(setSelectedTaskId(null));
dispatch(setTaskFormViewModel({}));
dispatch(setTaskSubscribers([]));
dispatch(setSelectedTaskId(taskFormViewModel?.task?.parent_task_id || null));
}
// Reset the flag after a short delay
setTimeout(() => {
isClosingManually.current = false;
@@ -176,8 +188,8 @@ const TaskDrawer = () => {
// Get conditional body style
const getBodyStyle = () => {
const baseStyle = {
padding: '24px',
overflow: 'auto'
padding: '24px',
overflow: 'auto',
};
if (activeTab === 'timeLog' && timeLogEditing.isEditing) {