Projekt

Obecné

Profil

Stáhnout (10.5 KB) Statistiky
| Větev: | Tag: | Revize:
1
import 'antd/dist/antd.css';
2
import React, { useContext, useEffect, useState } from 'react';
3

    
4
import { useUnauthRedirect } from '../../../hooks';
5
import { useRouter } from 'next/router';
6
import { Button, Space, Table, Typography } from 'antd';
7
import { faFileLines, faUser } from '@fortawesome/free-solid-svg-icons';
8
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
import { LoggedUserContext } from '../../../contexts/LoggedUserContext';
10
import { MainLayout } from '../../../layouts/MainLayout';
11
import AddDocumentModal from '../../../components/modals/AddDocumentModal';
12
import {
13
    DocumentListInfo,
14
    DocumentListResponse,
15
    DocumentUserInfo,
16
    EState,
17
} from '../../../api';
18
import { documentController, userController } from '../../../controllers';
19
import AssignDocumentModal from '../../../components/modals/AssignDocumentModal';
20
import { ShowConfirmDelete, ShowToast } from '../../../utils/alerts';
21
import { TableDocInfo } from '../../../components/types/TableDocInfo';
22
import {
23
    getAnnotationStateColor,
24
    getNameTruncated,
25
    getUserInfoAlt,
26
} from '../../../utils/strings';
27
import { ABadge, BadgeStyle } from '../../../components/common/ABadge';
28
import SetRequiredAnnotationsCountModal from '../../../components/modals/SetRequiredAnnotationsCountModal';
29
import DocPreviewModal from '../../../components/modals/DocPreviewModal';
30
import { UserFilter } from '../../../components/types/UserFilter';
31
import { getColumnSearchProps, getLocaleProps } from '../../../utils/tableUtils';
32
import { UserOutlined } from '@ant-design/icons';
33
import Swal from 'sweetalert2';
34

    
35
function AdminDocumentPage() {
36
    const redirecting = useUnauthRedirect('/login');
37
    const { logout, role } = useContext(LoggedUserContext);
38
    const [visibleAdd, setVisibleAdd] = React.useState(false);
39
    const [visibleAssign, setVisibleAssign] = React.useState(false);
40
    const [visiblePreview, setVisiblePreview] = React.useState(false);
41
    const [visibleSetCount, setVisibleSetCount] = React.useState(false);
42

    
43
    const router = useRouter();
44

    
45
    const [documents, setDocuments] = useState<TableDocInfo[]>([]);
46
    const [userFilters, setUserFilters] = useState<UserFilter[]>([]);
47
    const [selectedDocs, setSelectedDocs] = useState<string[]>([]);
48
    const [previewDocContent, setPreviewDocContent] = useState<string>();
49
    const [previewDocName, setPreviewDocName] = useState<string>();
50

    
51
    async function fetchData() {
52
        const docs = (await documentController.documentsGet(0, 1000)).data.documents;
53
        // @ts-ignore
54
        const tableDocs: TableDocInfo[] = docs?.map((doc, index) => {
55
            return { key: index, ...doc };
56
        });
57

    
58
        const users = (await userController.usersGet()).data.users;
59
        // @ts-ignore
60
        const filters: UserFilter[] = users?.map((user) => {
61
            return {
62
                text: user.name + ' ' + user.surname,
63
                value: user.username,
64
            };
65
        });
66
        setUserFilters(filters);
67

    
68
        if (!docs) {
69
            setDocuments([]);
70
        } else {
71
            setDocuments(tableDocs);
72
        }
73
    }
74

    
75
    useEffect(() => {
76
        if (!redirecting && role === 'ADMINISTRATOR') {
77
            fetchData();
78
        }
79
    }, [logout, redirecting, role, router]);
80

    
81
    const showAssignModal = () => {
82
        if (selectedDocs.length == 0) {
83
            ShowToast('Vyberte dokument pro přiřazení', 'warning', 3000, 'top-end');
84
        } else {
85
            setVisibleAssign(true);
86
        }
87
    };
88
    const showRequiredAnnotationsCountModal = () => {
89
        if (selectedDocs.length == 0) {
90
            ShowToast(
91
                'Vyberte dokument, pro které chcete nastavit požadovaný počet anotací',
92
                'warning',
93
                3000,
94
                'top-end'
95
            );
96
        } else {
97
            setVisibleSetCount(true);
98
        }
99
    };
100
    const showAddModal = () => {
101
        setVisibleAdd(true);
102
    };
103

    
104
    const showPreviewModal = async (id: string, name: string) => {
105
        const documentContent = (await documentController.documentDocumentIdGet(id)).data
106
            .content;
107
        if (documentContent) {
108
            setPreviewDocName(name);
109
            setPreviewDocContent(documentContent);
110
            setVisiblePreview(true);
111
        }
112
    };
113

    
114
    const hideModal = () => {
115
        fetchData();
116
        setVisibleAdd(false);
117
        setVisibleAssign(false);
118
        setVisibleSetCount(false);
119
        setVisiblePreview(false);
120
    };
121

    
122
    const columns = [
123
        {
124
            title: 'Název dokumentu',
125
            dataIndex: 'name',
126
            key: 'name',
127
            ...getColumnSearchProps('name', 'název'),
128
            sorter: {
129
                // @ts-ignore
130
                compare: (a, b) => a.name.localeCompare(b.name),
131
                multiple: 2,
132
            },
133
        },
134
        {
135
            title: 'Délka',
136
            dataIndex: 'length',
137
            key: 'length',
138
            sorter: {
139
                // @ts-ignore
140
                compare: (a, b) => a.length - b.length,
141
                multiple: 1,
142
            },
143
        },
144
        {
145
            title: 'Dokončeno | přiřazeno | vyžadováno',
146
            key: 'annotationCounts',
147
            render: (
148
                columnData: DocumentListResponse,
149
                record: DocumentListInfo,
150
                index: number
151
            ) => {
152
                const finished =
153
                    record.annotatingUsers?.filter((d) => d.state === EState.Done)
154
                        .length ?? 0;
155

    
156
                return (
157
                    <div>
158
                        <ABadge
159
                            style={
160
                                finished === record.annotatingUsers?.length
161
                                    ? BadgeStyle.SUCCESS
162
                                    : BadgeStyle.WARNING
163
                            }
164
                        >
165
                            {finished}
166
                        </ABadge>
167
                        {' | '}
168
                        <ABadge
169
                            style={
170
                                (record.annotatingUsers?.length ?? 0) >=
171
                                (record.requiredAnnotations ?? 0)
172
                                    ? BadgeStyle.SUCCESS
173
                                    : BadgeStyle.WARNING
174
                            }
175
                        >
176
                            {record.annotatingUsers?.length}
177
                        </ABadge>
178
                        {' | '}
179
                        <ABadge style={BadgeStyle.GENERAL}>
180
                            {record.requiredAnnotations}
181
                        </ABadge>
182
                    </div>
183
                );
184
            },
185
        },
186
        {
187
            title: 'Anotátoři',
188
            dataIndex: 'annotatingUsers',
189
            key: 'annotatingUsers',
190
            render: (
191
                columnData: DocumentUserInfo[],
192
                record: DocumentListInfo,
193
                index: number
194
            ) => {
195
                return (
196
                    <div>
197
                        {columnData.map((e) => (
198
                            <span
199
                                key={e.username + '.' + record.id}
200
                                title={getUserInfoAlt(e) + '\nStav: ' + e.state}
201
                                style={{
202
                                    color: getAnnotationStateColor(e.state),
203
                                    padding: 3,
204
                                }}
205
                                className={'me-3'}
206
                            >
207
                                <FontAwesomeIcon
208
                                    icon={faUser}
209
                                    title={getUserInfoAlt(e)}
210
                                    className={'me-2'}
211
                                />
212
                                {getNameTruncated(e)}
213
                            </span>
214
                        ))}
215
                    </div>
216
                );
217
            },
218
            filters: userFilters,
219
            filterSearch: true,
220
            // @ts-ignore
221
            onFilter: (value, record) =>
222
                // @ts-ignore
223
                record.annotatingUsers.find((user) => user['username'] === value),
224
            sorter: {
225
                // @ts-ignore
226
                compare: (a, b) => a.annotatingUsers.length - b.annotatingUsers.length,
227
                multiple: 3,
228
            },
229
        },
230
        {
231
            title: '',
232
            key: 'action',
233
            dataIndex: ['id', 'name'],
234
            // @ts-ignore
235
            render: (text, row) => (
236
                <Button key={row.id} onClick={() => showPreviewModal(row.id, row.name)}>
237
                    Náhled
238
                </Button>
239
            ),
240
        },
241
    ];
242

    
243
    const rowSelection = {
244
        onChange: (selectedRowKeys: React.Key[], selectedRows: DocumentListInfo[]) => {
245
            // @ts-ignore
246
            setSelectedDocs(selectedRows.map((row) => row.id));
247
        },
248
    };
249

    
250
    return redirecting || role !== 'ADMINISTRATOR' ? null : (
251
        <MainLayout>
252
            <Typography.Title level={2}>
253
                <FontAwesomeIcon icon={faFileLines} /> Dokumenty
254
            </Typography.Title>
255
            <Button type={'primary'} onClick={showAddModal}>
256
                Nahrát dokument
257
            </Button>
258
            <Button onClick={showAssignModal}>Přiřadit dokumenty</Button>
259
            <Button onClick={showRequiredAnnotationsCountModal}>
260
                Nastavit požadovaný počet anotací
261
            </Button>
262
            {visibleAdd && <AddDocumentModal onCancel={hideModal} />}
263
            {visibleAssign && (
264
                <AssignDocumentModal documentsIds={selectedDocs} onCancel={hideModal} />
265
            )}
266
            {visiblePreview && (
267
                <DocPreviewModal
268
                    onCancel={hideModal}
269
                    documentName={previewDocName ?? ''}
270
                    content={
271
                        previewDocContent ?? 'Nastala chyba při načítání obsahu dokumentu'
272
                    }
273
                />
274
            )}
275
            {visibleSetCount && (
276
                <SetRequiredAnnotationsCountModal
277
                    documentsIds={selectedDocs}
278
                    onCancel={hideModal}
279
                />
280
            )}
281

    
282
            <Table
283
                locale={{ ...getLocaleProps() }}
284
                rowSelection={{
285
                    type: 'checkbox',
286
                    ...rowSelection,
287
                }}
288
                // @ts-ignore
289
                columns={columns}
290
                dataSource={documents}
291
                size="middle"
292
                scroll={{ y: 600 }}
293
            />
294
        </MainLayout>
295
    );
296
}
297

    
298
export default AdminDocumentPage;
    (1-1/1)