Skip to content

Commit 8cb5286

Browse files
committed
update Dashboard code
1 parent aac8c9c commit 8cb5286

1 file changed

Lines changed: 152 additions & 176 deletions

File tree

  • rdmo/projects/assets/js/project/components/areas

rdmo/projects/assets/js/project/components/areas/Dashboard.js

Lines changed: 152 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,212 +1,188 @@
11
import React, { useState } from 'react'
2-
import { useDispatch } from 'react-redux'
2+
import { useDispatch, useSelector } from 'react-redux'
33

44
import { navigateDashboard } from '../../actions/projectActions'
55
import { Tile } from '../helper'
66

77
const Dashboard = () => {
88
const dispatch = useDispatch()
9+
const issues = useSelector((state) => state.project.project.tasks) ?? []
910

10-
const [selectedTask, setSelectedTask] = useState(null)
11+
const [selectedTaskIssue, setSelectedTaskIssue] = useState(null)
1112
const [showClosedTasks, setShowClosedTasks] = useState(false)
1213

13-
const [tasks, setTasks] = useState([
14-
{
15-
id: 1,
16-
title: 'Recommendation: Consider reuse scenarios',
17-
progress: '0 / 2',
18-
date: '14 August 2024',
19-
isDone: false,
20-
},
21-
{
22-
id: 2,
23-
title: 'Consider Open Access Policy',
24-
progress: '1 / 3',
25-
date: '15 May 2024',
26-
isDone: false,
27-
},
28-
{
29-
id: 3,
30-
title: 'Consider Open Access Policy',
31-
progress: '3 / 3',
32-
date: '15 May 2024',
33-
isDone: true,
34-
},
35-
])
36-
37-
const visibleTasks = tasks
38-
.filter((task) => showClosedTasks || !task.isDone)
39-
.sort((a, b) => Number(a.isDone) - Number(b.isDone))
40-
41-
const toggleTaskDone = (taskId) => {
42-
setTasks((prevTasks) =>
43-
prevTasks.map((task) =>
44-
task.id === taskId ? { ...task, isDone: !task.isDone } : task
45-
)
46-
)
14+
const isClosed = (issue) => issue.status === 'closed'
15+
const isActive = (issue) => ['open', 'in_progress'].includes(issue.status)
16+
const getTaskType = (issue) => issue.task?.task_type
17+
18+
const stepIssues = issues.filter((issue) =>
19+
getTaskType(issue) === 'step' && isActive(issue)
20+
)
21+
22+
const taskIssues = issues.filter((issue) =>
23+
getTaskType(issue) === 'task'
24+
)
25+
26+
const visibleTaskIssues = taskIssues
27+
.filter((issue) => showClosedTasks || !isClosed(issue))
28+
.sort((a, b) => Number(isClosed(a)) - Number(isClosed(b)))
29+
30+
const guidanceIssues = issues.filter((issue) =>
31+
getTaskType(issue) === 'guidance' && isActive(issue)
32+
)
33+
34+
const toggleTaskDone = (issueId) => {
35+
// local placeholder until backend POST/PATCH exists
36+
console.log('toggle issue', issueId)
4737
}
4838

4939
return (
5040
<div>
5141
<h1>{gettext('Dashboard')}</h1>
5242

53-
<h2>{gettext('Create your data management plan')}</h2>
54-
<div className="row mb-4">
55-
<Tile
56-
title={gettext('Answer questions')}
57-
label={gettext('Step 1')}
58-
buttonLabel={gettext('Interview')}
59-
onClick={() => dispatch(navigateDashboard({ area: 'interview'}))}
60-
>
61-
<p>{gettext('Fill out the selected questionnaire as completely as possible.')}</p>
62-
</Tile>
63-
<Tile
64-
title={gettext('Export data management plan')}
65-
label={gettext('Step 2')}
66-
buttonLabel={gettext('Documents')}
67-
onClick={() => dispatch(navigateDashboard({ area: 'documents'}))}
68-
>
69-
<p>{gettext('Export your data management plan in various formats.')}</p>
70-
</Tile>
71-
</div>
72-
73-
{/* <h2>{gettext('Tasks')}</h2>
74-
<div className="row">
75-
{
76-
tasks.map((task) => (
77-
<Tile key={task.id} size="normal">
78-
<div className="d-flex align-items-start">
79-
<div className="me-3 mt-1">
80-
<button
81-
type="button"
82-
className="btn p-0 border-0 bg-transparent"
83-
onClick={() => toggleTaskDone(task.id)}
84-
aria-label={task.isDone ? 'Mark task as not done' : 'Mark task as done'}
43+
{
44+
stepIssues.length > 0 && (
45+
<>
46+
<h2>{gettext('Create your data management plan')}</h2>
47+
<div className="row mb-4">
48+
{
49+
stepIssues.map((issue, index) => (
50+
<Tile
51+
key={issue.id}
52+
title={issue.task.title}
53+
label={gettext('Step %(number)s').replace('%(number)s', index + 1)}
54+
buttonLabel={issue.task.task_area_display}
55+
onClick={
56+
issue.task.task_area ? (
57+
() => dispatch(navigateDashboard({ area: issue.task.task_area }))
58+
) : undefined
59+
}
8560
>
86-
<i className={`bi ${task.isDone ? 'bi-check-circle-fill' : 'bi-circle'}`} />
87-
</button>
88-
</div>
61+
<p>{issue.task.text}</p>
62+
</Tile>
63+
))
64+
}
65+
</div>
66+
</>
67+
)
68+
}
8969

90-
<div className="flex-grow-1">
91-
<div className={task.isDone ? 'fw-semibold text-muted' : 'fw-semibold'}>
92-
{task.title}
93-
</div>
94-
95-
<div className="d-flex justify-content-between text-muted small mt-2">
96-
<div>
97-
<i className="bi bi-check2-square me-1" />
98-
{task.progress}
99-
</div>
100-
101-
<div>
102-
<i className="bi bi-clock me-1" />
103-
{task.date}
104-
</div>
105-
</div>
106-
</div>
107-
</div>
108-
</Tile>
109-
))
110-
}
111-
</div> */}
112-
<h2>{gettext('Tasks')}</h2>
113-
114-
<div className="form-check form-switch mb-3">
115-
<input
116-
className="form-check-input"
117-
type="checkbox"
118-
id="showClosedTasks"
119-
checked={showClosedTasks}
120-
onChange={() => setShowClosedTasks((prev) => !prev)}
121-
/>
122-
<label className="form-check-label" htmlFor="showClosedTasks">
123-
{gettext('Show closed tasks')}
124-
</label>
125-
</div>
126-
127-
<div className="row">
128-
{
129-
visibleTasks.map((task) => (
130-
<Tile
131-
key={task.id}
132-
size="normal"
133-
onCardClick={() => setSelectedTask(task)}
134-
>
135-
<div className="d-flex align-items-start">
136-
<div className="me-3 mt-1">
137-
<button
138-
type="button"
139-
className="btn p-0 border-0 bg-transparent"
70+
{
71+
taskIssues.length > 0 && (
72+
<>
73+
<h2>{gettext('Tasks')}</h2>
74+
75+
<div className="form-check form-switch mb-3">
76+
<input
77+
className="form-check-input"
78+
type="checkbox"
79+
id="showClosedTasks"
80+
checked={showClosedTasks}
81+
onChange={() => setShowClosedTasks((prev) => !prev)}
82+
/>
83+
<label className="form-check-label" htmlFor="showClosedTasks">
84+
{gettext('Show closed tasks')}
85+
</label>
86+
</div>
87+
88+
<div className="row">
89+
{
90+
visibleTaskIssues.map((issue) => {
91+
const closed = isClosed(issue)
92+
93+
return (
94+
<Tile
95+
key={issue.id}
96+
size="normal"
97+
onCardClick={() => setSelectedTaskIssue(issue)}
98+
>
99+
<div className="d-flex align-items-start">
100+
<div className="me-3 mt-1">
101+
<button
102+
type="button"
103+
className="btn p-0 border-0 bg-transparent"
104+
onClick={
105+
(e) => {
106+
e.stopPropagation()
107+
toggleTaskDone(issue.id)
108+
}
109+
}
110+
aria-label={closed ? 'Mark task as not done' : 'Mark task as done'}
111+
>
112+
<i className={`bi ${closed ? 'bi-check-circle-fill' : 'bi-circle'}`} />
113+
</button>
114+
</div>
115+
116+
<div className="flex-grow-1">
117+
<div className={closed ? 'fw-semibold text-muted' : 'fw-semibold'}>
118+
{issue.task.title}
119+
</div>
120+
121+
<div className="d-flex justify-content-between text-muted small mt-2">
122+
<div>
123+
<i className="bi bi-check2-square me-1" />
124+
{issue.resolve ? '1 / 1' : '0 / 1'}
125+
</div>
126+
127+
<div>
128+
<i className="bi bi-clock me-1" />
129+
{issue.dates?.[0] ?? ''}
130+
</div>
131+
</div>
132+
</div>
133+
</div>
134+
</Tile>
135+
)
136+
})
137+
}
138+
</div>
139+
</>
140+
)
141+
}
142+
143+
{
144+
guidanceIssues.length > 0 && (
145+
<>
146+
<h2>{gettext('More actions')}</h2>
147+
<div className="row mb-4">
148+
{
149+
guidanceIssues.map((issue) => (
150+
<Tile
151+
key={issue.id}
152+
title={issue.task.title}
153+
buttonLabel={issue.task.task_area_display}
140154
onClick={
141-
(e) => {
142-
e.stopPropagation()
143-
toggleTaskDone(task.id)
144-
}
155+
issue.task.task_area ? (
156+
() => dispatch(navigateDashboard({ area: issue.task.task_area }))
157+
) : undefined
145158
}
146-
aria-label={task.isDone ? 'Mark task as not done' : 'Mark task as done'}
159+
size="compact"
147160
>
148-
<i className={`bi ${task.isDone ? 'bi-check-circle-fill' : 'bi-circle'}`} />
149-
</button>
150-
</div>
161+
<p>{issue.task.text}</p>
162+
</Tile>
163+
))
164+
}
165+
</div>
166+
</>
167+
)
168+
}
151169

152-
<div className="flex-grow-1">
153-
<div className={task.isDone ? 'fw-semibold text-muted' : 'fw-semibold'}>
154-
{task.title}
155-
</div>
156-
157-
<div className="d-flex justify-content-between text-muted small mt-2">
158-
<div>
159-
<i className="bi bi-check2-square me-1" />
160-
{task.progress}
161-
</div>
162-
163-
<div>
164-
<i className="bi bi-clock me-1" />
165-
{task.date}
166-
</div>
167-
</div>
168-
</div>
169-
</div>
170-
</Tile>
171-
))
172-
}
173-
</div>
174-
175-
<h2>{gettext('More actions')}</h2>
176-
<div className="row mb-4">
177-
<Tile
178-
title={gettext('Invite team members')}
179-
buttonLabel={gettext('Project team')}
180-
onClick={() => dispatch(navigateDashboard({ area: 'memberships'}))}
181-
size="compact"
182-
>
183-
<p>{gettext('Invite additional people to collaborate on creating your data management plan.')}</p>
184-
</Tile>
185-
<Tile
186-
title={gettext('Create snapshot')}
187-
buttonLabel={gettext('Snapshots')}
188-
onClick={() => dispatch(navigateDashboard({ area: 'snapshots'}))}
189-
size="compact"
190-
>
191-
<p>{gettext('Save a snapshot to view or restore later.')}</p>
192-
</Tile>
193-
</div>
194170
{
195-
selectedTask && (
171+
selectedTaskIssue && (
196172
<div className="modal d-block" tabIndex="-1">
197173
<div className="modal-dialog">
198174
<div className="modal-content">
199175
<div className="modal-header">
200-
<h5 className="modal-title">{selectedTask.title}</h5>
176+
<h5 className="modal-title">{selectedTaskIssue.task.title}</h5>
201177
<button
202178
type="button"
203179
className="btn-close"
204-
onClick={() => setSelectedTask(null)}
180+
onClick={() => setSelectedTaskIssue(null)}
205181
/>
206182
</div>
207183
<div className="modal-body">
208-
<p>{gettext('Task popup placeholder')}</p>
209-
<p>{selectedTask.date}</p>
184+
<p>{selectedTaskIssue.task.text}</p>
185+
<p>{selectedTaskIssue.dates?.[0]}</p>
210186
</div>
211187
</div>
212188
</div>

0 commit comments

Comments
 (0)