Skip to content

Commit 1d2341d

Browse files
committed
WIP Add to MyDay
1 parent e4daefa commit 1d2341d

File tree

10 files changed

+151
-18
lines changed

10 files changed

+151
-18
lines changed

src/base/TreeModelHelper.ts

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,108 @@
1-
import { ITreeItem } from '../types/ITreeItem';
1+
import { ITreeItem, ITreeItemWithParent } from '../types/ITreeItem';
2+
import { TaskModelProxy } from '../modules/tasks/models/TaskModelProxy';
3+
import TaskModel from '../modules/tasks/models/TaskModel';
24

35
const TreeModelHelper = {
6+
getPathToNode<T extends ITreeItemWithParent>(node: T) {
7+
const result: string[] = [];
8+
9+
let ptrNode = node;
10+
while (ptrNode) {
11+
result.unshift(ptrNode.key);
12+
// @ts-ignore
13+
ptrNode = ptrNode.parent;
14+
}
15+
16+
return result;
17+
},
18+
copyItemsToTree(
19+
sourceTree: TaskModel[],
20+
destTree: TaskModelProxy[],
21+
keysToTask: string[]
22+
) {
23+
let keyIdx = 0;
24+
let sourceChild = sourceTree;
25+
let destChild = destTree;
26+
27+
if (keysToTask.length === 1) {
28+
const source = sourceChild.find((node) => node.key === keysToTask[0]);
29+
destChild.push(
30+
// @ts-ignore
31+
new TaskModelProxy({
32+
...source,
33+
children: [],
34+
})
35+
);
36+
return true;
37+
}
38+
39+
do {
40+
const nextSourceNode = sourceChild.find(
41+
(task) => task.key === keysToTask[keyIdx]
42+
);
43+
if (!nextSourceNode) {
44+
return false;
45+
}
46+
47+
const nextDestNode = destChild.find(
48+
(task) => task.key === keysToTask[keyIdx]
49+
);
50+
51+
if (nextDestNode) {
52+
keyIdx++;
53+
destChild = nextDestNode.children;
54+
} else {
55+
const restKeysToTask = keysToTask.slice(keyIdx);
56+
return TreeModelHelper.copySubItemsToTree(
57+
sourceChild,
58+
destChild,
59+
restKeysToTask
60+
);
61+
}
62+
} while (keyIdx >= keysToTask.length);
63+
64+
return true;
65+
},
66+
67+
copySubItemsToTree(
68+
sourceTree: TaskModel[],
69+
destTree: TaskModelProxy[],
70+
keysToTask: string[]
71+
) {
72+
if (!sourceTree) {
73+
return false;
74+
}
75+
76+
let keyIdx = 0;
77+
let dest = destTree;
78+
let source = sourceTree.find((node) => node.key === keysToTask[keyIdx]);
79+
80+
if (!source) {
81+
return false;
82+
}
83+
84+
while (true) {
85+
// @ts-ignore
86+
let copy = new TaskModelProxy({
87+
...source,
88+
children: [],
89+
});
90+
91+
dest.push(copy);
92+
93+
keyIdx++;
94+
if (keyIdx === keysToTask.length) {
95+
return true;
96+
}
97+
98+
dest = copy.children;
99+
source = source.children.find((node) => node.key === keysToTask[keyIdx]);
100+
if (!source) {
101+
return false;
102+
}
103+
}
104+
},
105+
4106
walkRecursive<T extends ITreeItem<any>>(
5107
fn: (t: T, p?: T) => void,
6108
treeItems: T[],

src/modules/tasks/TaskFactory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ import AbstractFactory from '../../base/AbstractFactory';
22
import TasksByProject from './models/TasksByProject';
33
import TaskModel from './models/TaskModel';
44
import { TaskModelProxy, taskModelProxyHandler } from './models/TaskModelProxy';
5+
import { DEFAULT_PROJECT_ID } from '../projects/models/ProjectModel';
56

67
export default class TaskFactory extends AbstractFactory {
78
createTasks(data: TasksByProject): TasksByProject {
89
const newData: TasksByProject = {};
910
Object.keys(data).forEach((projectId) => {
1011
newData[projectId] = this.createList(TaskModel, data[projectId]);
1112
});
13+
14+
newData[DEFAULT_PROJECT_ID.MyDay] = [];
15+
1216
return newData;
1317
}
1418

src/modules/tasks/TaskStore.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ETasksEvents,
1313
ETimeRangeEvents,
1414
} from '../../services/gaService/EEvents';
15+
import { DEFAULT_PROJECT_ID } from '../projects/models/ProjectModel';
1516

1617
export default class TaskStore {
1718
tasks: TasksByProject = {};
@@ -92,6 +93,19 @@ export default class TaskStore {
9293
GaService.event(EEventCategory.Tasks, ETasksEvents.Create);
9394
}
9495

96+
addToMyDay(task: TaskModel) {
97+
task.inMyDay = new Date();
98+
// @ts-ignore
99+
const pathToNode = TreeModelHelper.getPathToNode(task);
100+
101+
TreeModelHelper.copyItemsToTree(
102+
this.tasks[task.projectId],
103+
// @ts-ignore
104+
this.tasks[DEFAULT_PROJECT_ID.MyDay],
105+
pathToNode
106+
);
107+
}
108+
95109
delete(task: TaskModel) {
96110
function condition(_task: TaskModel) {
97111
return _task.key === task.key;

src/modules/tasks/models/TaskModel.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ export interface ITimeRangeModel {
1717
}
1818

1919
interface IJsonTaskModel extends ITreeItem<IJsonTaskModel> {
20-
projectId: string;
21-
checked: boolean;
22-
active: boolean;
23-
expanded: boolean;
24-
inMyDay: string;
25-
time: string[][] | IJsonTimeRangeModel[];
26-
datesInProgress: string[];
27-
details: string[];
20+
projectId?: string;
21+
checked?: boolean;
22+
active?: boolean;
23+
expanded?: boolean;
24+
inMyDay?: string;
25+
time?: string[][] | IJsonTimeRangeModel[];
26+
datesInProgress?: string[];
27+
details?: string[];
2828
}
2929

3030
const parseTimeRageItems = (

src/modules/tasks/models/TaskModelProxy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import TaskModel from './TaskModel';
22

33
export class TaskModelProxy extends TaskModel {
44
origin: TaskModel | null = null;
5+
children: TaskModelProxy[] = [];
56
}
67

78
export const taskModelProxyHandler: ProxyHandler<TaskModelProxy> = {

src/screens/projects/ProjectsScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const TaskList = TreeList(
2929
},
3030
{
3131
checkable: true,
32-
get draggable() {
32+
isDraggable() {
3333
return projectStore.activeProject !== DEFAULT_PROJECT_ID.MyDay;
3434
},
3535
onExpand(keys: Key[]) {

src/screens/projects/components/TaskNode/TaskNode.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import React, { SyntheticEvent } from 'react';
1+
import React, { SyntheticEvent, useCallback } from 'react';
22
import {
33
CaretRightFilled,
44
DeleteOutlined,
5+
EnterOutlined,
56
PauseOutlined,
67
} from '@ant-design/icons';
78
import { observer } from 'mobx-react';
@@ -22,18 +23,21 @@ export default observer(function TaskNode({ task }: TaskNodeProps) {
2223

2324
const duration = TaskHooks.useTaskDuration(task);
2425

25-
function preventDefault(fn: () => void) {
26+
const preventDefault = useCallback((fn: () => void) => {
2627
return (e: SyntheticEvent) => {
2728
e.stopPropagation();
2829
fn();
2930
};
30-
}
31+
}, []);
3132

3233
return (
3334
<div className={classes.taskNode}>
3435
<span className={classes.taskTitle}>{task.title}</span>
3536
<span>{duration}</span>
3637
<span className={classes.taskNodeActions}>
38+
<EnterOutlined
39+
onClick={preventDefault(() => tasksStore.addToMyDay(task))}
40+
/>
3741
{!task.active ? (
3842
<CaretRightFilled
3943
onClick={preventDefault(() => tasksStore.startTimer(task))}

src/screens/projects/components/TreeList.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ interface TreePropsExtended<T>
1616
getCheckedKeys?: () => Key[];
1717
getExpandedKeys?: () => Key[];
1818
titleRender?: (item: T) => React.ReactNode;
19+
isDraggable?: () => boolean;
1920
}
2021

2122
export default function TreeList<T extends ITreeItem<any>>(
2223
getData: () => T[],
2324
updateData: (items: T[]) => void,
2425
options: TreePropsExtended<T>
2526
) {
26-
const { getCheckedKeys, getExpandedKeys, ...rest } = options;
27+
const { getCheckedKeys, getExpandedKeys, isDraggable, ...rest } = options;
2728

2829
return observer(({ onSelect }: TreeListProps) => {
2930
const data = getData();
@@ -112,12 +113,15 @@ export default function TreeList<T extends ITreeItem<any>>(
112113
);
113114
}
114115

116+
const draggable = isDraggable ? isDraggable() : rest.draggable;
117+
115118
return (
116119
<Tree
117120
className="draggable-tree"
118121
defaultExpandParent={false}
119122
checkedKeys={getCheckedKeys?.()}
120123
expandedKeys={getExpandedKeys?.()}
124+
draggable={draggable}
121125
blockNode
122126
treeData={data}
123127
// @ts-ignore

src/types/ITreeItem.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ export interface ITreeItem<T extends ITreeItem<any> = ITreeItem<any>> {
33
key: string;
44
children?: T[];
55
}
6+
7+
export interface ITreeItemWithParent extends ITreeItem<ITreeItemWithParent> {
8+
parent: ITreeItemWithParent | undefined;
9+
}

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10391,10 +10391,10 @@ typedarray@^0.0.6:
1039110391
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
1039210392
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
1039310393

10394-
typescript@^4.0.5:
10395-
version "4.0.5"
10396-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
10397-
integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
10394+
typescript@^4.3.5:
10395+
version "4.3.5"
10396+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
10397+
integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
1039810398

1039910399
typical@^5.0.0, typical@^5.2.0:
1040010400
version "5.2.0"

0 commit comments

Comments
 (0)