3 |
3 |
|
4 |
4 |
import { useUnauthRedirect } from '../../../hooks';
|
5 |
5 |
import { useRouter } from 'next/router';
|
6 |
|
import { Button, Space, Table, Typography } from 'antd';
|
|
6 |
import { Button, Row, Space, Table, Tag, Typography } from 'antd';
|
7 |
7 |
import { faFileLines, faUser } from '@fortawesome/free-solid-svg-icons';
|
8 |
8 |
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
9 |
9 |
import { LoggedUserContext } from '../../../contexts/LoggedUserContext';
|
... | ... | |
17 |
17 |
} from '../../../api';
|
18 |
18 |
import { documentController, userController } from '../../../controllers';
|
19 |
19 |
import AssignDocumentModal from '../../../components/modals/AssignDocumentModal';
|
20 |
|
import { ShowConfirmDelete, ShowToast } from '../../../utils/alerts';
|
|
20 |
import { ShowConfirm, ShowToast } from '../../../utils/alerts';
|
21 |
21 |
import { TableDocInfo } from '../../../components/types/TableDocInfo';
|
22 |
22 |
import {
|
23 |
23 |
getAnnotationStateColor,
|
|
24 |
getAnnotationStateString,
|
24 |
25 |
getNameTruncated,
|
25 |
26 |
getUserInfoAlt,
|
26 |
27 |
} from '../../../utils/strings';
|
... | ... | |
29 |
30 |
import DocPreviewModal from '../../../components/modals/DocPreviewModal';
|
30 |
31 |
import { UserFilter } from '../../../components/types/UserFilter';
|
31 |
32 |
import { getColumnSearchProps, getLocaleProps } from '../../../utils/tableUtils';
|
32 |
|
import { UserOutlined } from '@ant-design/icons';
|
33 |
|
import Swal from 'sweetalert2';
|
|
33 |
import {
|
|
34 |
CheckCircleOutlined,
|
|
35 |
ClockCircleOutlined,
|
|
36 |
SyncOutlined,
|
|
37 |
} from '@ant-design/icons';
|
|
38 |
import { SweetAlertIcon } from 'sweetalert2';
|
34 |
39 |
|
35 |
40 |
function AdminDocumentPage() {
|
36 |
41 |
const redirecting = useUnauthRedirect('/login');
|
37 |
42 |
const { logout, role } = useContext(LoggedUserContext);
|
|
43 |
const [finalizing, setFinalizing] = React.useState(false);
|
38 |
44 |
const [visibleAdd, setVisibleAdd] = React.useState(false);
|
39 |
45 |
const [visibleAssign, setVisibleAssign] = React.useState(false);
|
40 |
46 |
const [visiblePreview, setVisiblePreview] = React.useState(false);
|
... | ... | |
78 |
84 |
}
|
79 |
85 |
}, [logout, redirecting, role, router]);
|
80 |
86 |
|
|
87 |
const finalizeDocumentConfirm = async (
|
|
88 |
document: DocumentListInfo,
|
|
89 |
recreate: boolean
|
|
90 |
) => {
|
|
91 |
let desc = recreate ? 'Dosavadní změny finální verze budou smazány' : '';
|
|
92 |
let icon: SweetAlertIcon = recreate ? 'warning' : 'question';
|
|
93 |
|
|
94 |
const doneAnnotations = document.annotatingUsers?.filter(
|
|
95 |
(usr) => usr.state === EState.Done
|
|
96 |
).length;
|
|
97 |
|
|
98 |
if (
|
|
99 |
doneAnnotations !== undefined &&
|
|
100 |
document.requiredAnnotations !== undefined &&
|
|
101 |
doneAnnotations < document.requiredAnnotations
|
|
102 |
) {
|
|
103 |
icon = 'warning';
|
|
104 |
desc =
|
|
105 |
'Není dokončen požadovaný počet anotací <br /> (dokončeno ' +
|
|
106 |
doneAnnotations +
|
|
107 |
' z ' +
|
|
108 |
document.requiredAnnotations +
|
|
109 |
')';
|
|
110 |
}
|
|
111 |
recreate
|
|
112 |
? ShowConfirm(
|
|
113 |
() => finalizeDocument(document.id),
|
|
114 |
'vytvořit novou finální verzi dokumentu',
|
|
115 |
desc,
|
|
116 |
icon
|
|
117 |
)
|
|
118 |
: ShowConfirm(
|
|
119 |
() => finalizeDocument(document.id),
|
|
120 |
'vytvořit finální verzi dokumentu',
|
|
121 |
desc,
|
|
122 |
icon
|
|
123 |
);
|
|
124 |
};
|
|
125 |
|
|
126 |
const finalizeDocument = async (documentId: string | undefined) => {
|
|
127 |
setFinalizing(true);
|
|
128 |
const finalAnnotationId = (
|
|
129 |
await documentController.documentDocumentIdFinalPost(
|
|
130 |
documentId ? documentId : ''
|
|
131 |
)
|
|
132 |
).data.finalAnnotationId;
|
|
133 |
if (!finalAnnotationId) {
|
|
134 |
ShowToast('Finální verzi se nepovedlo vytvořit', 'error');
|
|
135 |
} else {
|
|
136 |
router.push({
|
|
137 |
pathname: '/annotation/[annotationId]',
|
|
138 |
query: { annotationId: finalAnnotationId, final: true },
|
|
139 |
});
|
|
140 |
}
|
|
141 |
setFinalizing(false);
|
|
142 |
};
|
|
143 |
|
|
144 |
const editFinalizedDocument = async (finalAnnotationId: string) => {
|
|
145 |
setFinalizing(true);
|
|
146 |
if (!finalAnnotationId) {
|
|
147 |
ShowToast('Finální verze dosud neexistuje', 'warning');
|
|
148 |
} else {
|
|
149 |
router.push({
|
|
150 |
pathname: '/annotation/[annotationId]',
|
|
151 |
query: { annotationId: finalAnnotationId, final: true },
|
|
152 |
});
|
|
153 |
}
|
|
154 |
setFinalizing(false);
|
|
155 |
};
|
|
156 |
|
|
157 |
const getFinalizationStateIcon = (state: EState) => {
|
|
158 |
const color = getAnnotationStateColor(state);
|
|
159 |
const label = getAnnotationStateString(state);
|
|
160 |
let icon = <CheckCircleOutlined />;
|
|
161 |
if (state === 'NEW') {
|
|
162 |
icon = <ClockCircleOutlined />;
|
|
163 |
}
|
|
164 |
if (state === 'IN_PROGRESS') {
|
|
165 |
icon = <SyncOutlined />;
|
|
166 |
}
|
|
167 |
|
|
168 |
return (
|
|
169 |
<Tag icon={icon} color={color} key={label}>
|
|
170 |
{label.toUpperCase()}
|
|
171 |
</Tag>
|
|
172 |
);
|
|
173 |
};
|
|
174 |
|
81 |
175 |
const showAssignModal = () => {
|
82 |
176 |
if (selectedDocs.length == 0) {
|
83 |
177 |
ShowToast('Vyberte dokument pro přiřazení', 'warning', 3000, 'top-end');
|
... | ... | |
124 |
218 |
title: 'Název dokumentu',
|
125 |
219 |
dataIndex: 'name',
|
126 |
220 |
key: 'name',
|
|
221 |
width: '15%',
|
127 |
222 |
...getColumnSearchProps('name', 'název'),
|
128 |
223 |
sorter: {
|
129 |
224 |
// @ts-ignore
|
... | ... | |
135 |
230 |
title: 'Délka',
|
136 |
231 |
dataIndex: 'length',
|
137 |
232 |
key: 'length',
|
|
233 |
width: '6%',
|
|
234 |
align: 'center' as 'center',
|
138 |
235 |
sorter: {
|
139 |
236 |
// @ts-ignore
|
140 |
237 |
compare: (a, b) => a.length - b.length,
|
... | ... | |
144 |
241 |
{
|
145 |
242 |
title: 'Dokončeno | přiřazeno | vyžadováno',
|
146 |
243 |
key: 'annotationCounts',
|
|
244 |
width: '15%',
|
|
245 |
align: 'center' as 'center',
|
147 |
246 |
render: (
|
148 |
247 |
columnData: DocumentListResponse,
|
149 |
248 |
record: DocumentListInfo,
|
... | ... | |
187 |
286 |
title: 'Anotátoři',
|
188 |
287 |
dataIndex: 'annotatingUsers',
|
189 |
288 |
key: 'annotatingUsers',
|
|
289 |
width: '20%',
|
190 |
290 |
render: (
|
191 |
291 |
columnData: DocumentUserInfo[],
|
192 |
292 |
record: DocumentListInfo,
|
... | ... | |
209 |
309 |
title={getUserInfoAlt(e)}
|
210 |
310 |
className={'me-2'}
|
211 |
311 |
/>
|
212 |
|
{getNameTruncated(e)}
|
|
312 |
{record.finalAnnotations?.some(
|
|
313 |
(annot) => annot.userId === e.id
|
|
314 |
) ? (
|
|
315 |
<u>{getNameTruncated(e)}</u>
|
|
316 |
) : (
|
|
317 |
getNameTruncated(e)
|
|
318 |
)}
|
213 |
319 |
</span>
|
214 |
320 |
))}
|
215 |
321 |
</div>
|
... | ... | |
231 |
337 |
title: '',
|
232 |
338 |
key: 'action',
|
233 |
339 |
dataIndex: ['id', 'name'],
|
|
340 |
width: '10%',
|
|
341 |
align: 'center' as 'center',
|
234 |
342 |
// @ts-ignore
|
235 |
343 |
render: (text, row) => (
|
236 |
344 |
<Button key={row.id} onClick={() => showPreviewModal(row.id, row.name)}>
|
... | ... | |
238 |
346 |
</Button>
|
239 |
347 |
),
|
240 |
348 |
},
|
|
349 |
{
|
|
350 |
title: 'Finální verze dokumentu',
|
|
351 |
key: 'final',
|
|
352 |
dataIndex: ['id', 'finalizedExists'],
|
|
353 |
// @ts-ignore
|
|
354 |
render: (text, row) =>
|
|
355 |
row.finalizedExists ? (
|
|
356 |
<Row>
|
|
357 |
<Space>
|
|
358 |
<Button
|
|
359 |
disabled={finalizing}
|
|
360 |
onClick={() => finalizeDocumentConfirm(row.id, true)}
|
|
361 |
>
|
|
362 |
Znovu vytvořit
|
|
363 |
</Button>
|
|
364 |
<Button
|
|
365 |
disabled={finalizing}
|
|
366 |
onClick={() =>
|
|
367 |
editFinalizedDocument(row.finalizedAnnotationId)
|
|
368 |
}
|
|
369 |
>
|
|
370 |
Upravit
|
|
371 |
</Button>
|
|
372 |
{getFinalizationStateIcon(row.finalizedState)}
|
|
373 |
</Space>
|
|
374 |
</Row>
|
|
375 |
) : (
|
|
376 |
<Button
|
|
377 |
disabled={finalizing}
|
|
378 |
onClick={() => finalizeDocumentConfirm(row, false)}
|
|
379 |
>
|
|
380 |
Finalizovat
|
|
381 |
</Button>
|
|
382 |
),
|
|
383 |
filters: [
|
|
384 |
{
|
|
385 |
text: 'Nefinalizováno',
|
|
386 |
value: null,
|
|
387 |
},
|
|
388 |
{
|
|
389 |
text: 'Nový',
|
|
390 |
value: 'NEW',
|
|
391 |
},
|
|
392 |
{
|
|
393 |
text: 'Rozpracováno',
|
|
394 |
value: 'IN_PROGRESS',
|
|
395 |
},
|
|
396 |
{
|
|
397 |
text: 'Hotovo',
|
|
398 |
value: 'DONE',
|
|
399 |
},
|
|
400 |
],
|
|
401 |
// @ts-ignore
|
|
402 |
onFilter: (value, record) => record.finalizedState === value,
|
|
403 |
},
|
241 |
404 |
];
|
242 |
405 |
|
243 |
406 |
const rowSelection = {
|
Finalization - buttons, confirm toasters and navigation were implemented