Skip to content

Commit 0d7ae32

Browse files
author
Dmitry Yadrikhinsky
committed
Edit/remove project
1 parent 15685b8 commit 0d7ae32

File tree

8 files changed

+175
-12
lines changed

8 files changed

+175
-12
lines changed

src/screens/projects/Projects.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import rootStore from '../../services/RootStore';
1010
import TreeList from './components/TreeList';
1111
import TaskModel from '../../models/TaskModel';
1212
import ProjectModel from '../../models/ProjectModel';
13-
import ProjectModal from './components/ProjectModal';
13+
import ProjectModal from './components/ProjectModals/ProjectModal';
1414
import TaskNode from './components/TaskNode/TaskNode';
1515
import DrawerTask from './components/DrawerTask/DrawerTask';
16+
import ProjectNode from './components/ProjectNode/ProjectNode';
17+
import EditProjectModal from './components/ProjectModals/EditProjectModal';
1618

1719
const { Sider } = Layout;
1820

@@ -41,11 +43,16 @@ const ProjectList = TreeList(
4143
() => projectStore.projects,
4244
(list: ProjectModel[]) => {
4345
projectStore.set(list);
46+
},
47+
{
48+
titleRender(project: ProjectModel) {
49+
return <ProjectNode project={project} />;
50+
},
4451
}
4552
);
4653

4754
export default observer(function Projects() {
48-
const [showProjectModal, setShowProjectModal] = useState<boolean>();
55+
const [showProjectModal, setShowProjectModal] = useState<boolean>(false);
4956
const [drawerVisible, setDrawerVisible] = useState<boolean>(false);
5057
const [selectedTask, setSelectedTask] = useState<TaskModel | undefined>();
5158

@@ -84,6 +91,10 @@ export default observer(function Projects() {
8491
{showProjectModal && (
8592
<ProjectModal onClose={() => setShowProjectModal(false)} />
8693
)}
94+
<EditProjectModal
95+
project={projectStore.editProject}
96+
onClose={() => projectStore.setEditableProject(undefined)}
97+
/>
8798
<DrawerTask
8899
task={selectedTask}
89100
visible={drawerVisible}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React, { useEffect, useState } from 'react';
2+
import ProjectModel from '../../../../models/ProjectModel';
3+
import { Button, Input, Modal, Space } from 'antd';
4+
import rootStore from '../../../../services/RootStore';
5+
import { DeleteFilled } from '@ant-design/icons';
6+
7+
const { projectStore } = rootStore;
8+
9+
interface EditProjectModalProps {
10+
project?: ProjectModel;
11+
onClose: () => void;
12+
}
13+
14+
export default function EditProjectModal({ project }: EditProjectModalProps) {
15+
const [title, setTitle] = useState<string>('');
16+
17+
useEffect(() => {
18+
const editProject = projectStore.editProject;
19+
if (editProject) {
20+
setTitle(editProject.title);
21+
}
22+
}, [projectStore.editProject]);
23+
24+
useEffect(() => {
25+
setTitle(project?.title || '');
26+
}, [project]);
27+
28+
function handleOk() {
29+
if (project) {
30+
projectStore.setTitle(project, title);
31+
}
32+
onClose();
33+
}
34+
35+
function handleCancel() {
36+
onClose();
37+
}
38+
39+
function handleDelete() {
40+
if (project) {
41+
rootStore.deleteProject(project);
42+
}
43+
onClose();
44+
}
45+
46+
function onClose() {
47+
projectStore.setEditableProject(undefined);
48+
}
49+
50+
return (
51+
<Modal
52+
title="Edit project"
53+
visible={!!projectStore.editProject}
54+
onOk={handleOk}
55+
onCancel={handleCancel}
56+
okText="Save"
57+
>
58+
<Space direction="vertical">
59+
<Input
60+
placeholder="Project name..."
61+
value={title}
62+
onChange={(e) => setTitle(e.target.value)}
63+
/>
64+
<Button icon={<DeleteFilled />} onClick={handleDelete}>
65+
Delete
66+
</Button>
67+
</Space>
68+
</Modal>
69+
);
70+
}

src/screens/projects/components/ProjectModal.tsx renamed to src/screens/projects/components/ProjectModals/ProjectModal.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
1-
import React, { useState } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import { observer } from 'mobx-react';
3-
import { Input, Modal } from 'antd';
4-
import rootStore from '../../../services/RootStore';
5-
import ProjectModel from '../../../models/ProjectModel';
3+
import { Button, Input, Modal, Space } from 'antd';
4+
5+
import rootStore from '../../../../services/RootStore';
6+
import ProjectModel from '../../../../models/ProjectModel';
7+
8+
const { projectStore } = rootStore;
69

710
interface ProjectModalProps {
11+
project?: ProjectModel;
812
onClose: () => void;
913
}
1014

11-
export default observer(function ProjectModal({ onClose }: ProjectModalProps) {
15+
export default observer(function ProjectModal({
16+
project,
17+
onClose,
18+
}: ProjectModalProps) {
1219
const [projectName, setProjectName] = useState<string>('');
1320

21+
useEffect(() => {
22+
setProjectName(project?.title || '');
23+
}, [project]);
24+
1425
function handleOk() {
15-
const { projectStore } = rootStore;
1626
projectStore.add(
1727
new ProjectModel({
1828
key: String(Date.now()),
@@ -21,13 +31,14 @@ export default observer(function ProjectModal({ onClose }: ProjectModalProps) {
2131
);
2232
onClose();
2333
}
34+
2435
function handleCancel() {
2536
onClose();
2637
}
2738

2839
return (
2940
<Modal
30-
title="Basic Modal"
41+
title="Create project"
3142
visible
3243
onOk={handleOk}
3344
onCancel={handleCancel}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.project-node {
2+
display: flex;
3+
flex-direction: row;
4+
justify-content: space-between;
5+
align-items: center;
6+
7+
.edit-button {
8+
display: none;
9+
}
10+
11+
&:hover .edit-button {
12+
display: inline;
13+
}
14+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React, { SyntheticEvent } from 'react';
2+
import { EditOutlined } from '@ant-design/icons';
3+
4+
import './ProjectNode.less';
5+
6+
import ProjectModel from '../../../../models/ProjectModel';
7+
import rootStore from '../../../../services/RootStore';
8+
9+
const {projectStore} = rootStore;
10+
11+
interface ProjectNodeProps {
12+
project: ProjectModel;
13+
}
14+
15+
export default function ProjectNode({ project }: ProjectNodeProps) {
16+
function onClick(e: SyntheticEvent) {
17+
e.stopPropagation();
18+
projectStore.setEditableProject(project);
19+
}
20+
21+
return (
22+
<div className="project-node">
23+
<div>{project.title}</div>
24+
<EditOutlined className="edit-button" onClick={onClick} />
25+
</div>
26+
);
27+
};

src/services/RootStore.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import TaskStore from './tasks/TaskStore';
22
import ProjectStore from './projects/ProjectStore';
3-
import { toJS } from 'mobx';
3+
import ProjectModel from '../models/ProjectModel';
44

55
class RootStore {
66
tasksStore = new TaskStore();
@@ -10,6 +10,11 @@ class RootStore {
1010
this.tasksStore.restore();
1111
this.projectStore.restore();
1212
}
13+
14+
deleteProject(project: ProjectModel) {
15+
this.tasksStore.deleteProjectTasks(project.key);
16+
this.projectStore.delete(project);
17+
}
1318
}
1419

1520
const rootStore = new RootStore();

src/services/projects/ProjectStore.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { makeAutoObservable } from 'mobx';
33
import ProjectModel from '../../models/ProjectModel';
44
import ProjectService from './ProjectService';
55
import TreeModelStoreHelper from '../../base/TreeModelStoreHelper';
6+
import { Undefined } from '../../types/CommonTypes';
67

78
export default class ProjectStore {
89
projects: ProjectModel[] = [];
910
activeProject: string = '';
11+
editProject: Undefined<ProjectModel>;
1012

1113
private projectService = new ProjectService();
1214

@@ -19,6 +21,19 @@ export default class ProjectStore {
1921
this.projectService.save(this.projects);
2022
}
2123

24+
setEditableProject(project?: ProjectModel) {
25+
this.editProject = project;
26+
}
27+
28+
setActiveProject(projectId: string) {
29+
this.activeProject = projectId;
30+
}
31+
32+
setTitle(project: ProjectModel, title: string) {
33+
project.title = title;
34+
this.projectService.save(this.projects);
35+
}
36+
2237
get(projectKey: string): ProjectModel | undefined {
2338
function compare(project: ProjectModel) {
2439
return project.key === projectKey;
@@ -32,8 +47,13 @@ export default class ProjectStore {
3247
this.projectService.save(this.projects);
3348
}
3449

35-
setActiveProject(projectId: string) {
36-
this.activeProject = projectId;
50+
delete(project: ProjectModel) {
51+
function condition(_project: ProjectModel) {
52+
return _project.key === project.key;
53+
}
54+
55+
this.projects = TreeModelStoreHelper.deleteItems(this.projects, condition);
56+
// this.projectService.save(this.projects);
3757
}
3858

3959
restore() {

src/services/tasks/TaskStore.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ export default class TaskStore {
9393
this.tasksService.save(this.tasks);
9494
}
9595

96+
deleteProjectTasks(projectKey: string) {
97+
delete this.tasks[projectKey];
98+
this.tasksService.save(this.tasks);
99+
}
100+
96101
startTimer(task: TaskModel) {
97102
if (this.activeTask) {
98103
this.stopTimer(this.activeTask);

0 commit comments

Comments
 (0)