Revize fabfbe32
Přidáno uživatelem Jaroslav Hrubý před téměř 3 roky(ů)
Backend/Core/Seeding/Seeder.cs | ||
---|---|---|
131 | 131 |
Surname = "Admin", |
132 | 132 |
Role = ERole.ADMINISTRATOR, |
133 | 133 |
Username = "admin", |
134 |
Password = BCrypt.Net.BCrypt.HashPassword("123a456b789c")
|
|
134 |
Password = BCrypt.Net.BCrypt.HashPassword("admin")
|
|
135 | 135 |
}; |
136 | 136 |
context.Users.Add(admin); |
137 | 137 |
|
webapp/api/api.ts | ||
---|---|---|
1872 | 1872 |
* @type {number} |
1873 | 1873 |
* @memberof UserInfo |
1874 | 1874 |
*/ |
1875 |
'assignedDocumentsCount'?: number; |
|
1875 |
'finalizedDocumentsCount'?: number; |
|
1876 |
/** |
|
1877 |
* |
|
1878 |
* @type {number} |
|
1879 |
* @memberof UserInfo |
|
1880 |
*/ |
|
1881 |
'inProgressDocumentsCount'?: number; |
|
1882 |
/** |
|
1883 |
* |
|
1884 |
* @type {number} |
|
1885 |
* @memberof UserInfo |
|
1886 |
*/ |
|
1887 |
'newDocumentsCount'?: number; |
|
1876 | 1888 |
/** |
1877 | 1889 |
* |
1878 | 1890 |
* @type {ERole} |
webapp/components/modals/AssignDocumentModal.tsx | ||
---|---|---|
13 | 13 |
import { getColumnSearchProps, getLocaleProps } from '../../utils/tableUtils'; |
14 | 14 |
import { TableUserInfo } from '../types/TableUserInfo'; |
15 | 15 |
import { TableDocInfo } from '../types/TableDocInfo'; |
16 |
import { ABadge, BadgeStyle } from '../common/ABadge'; |
|
17 |
import { ok } from 'assert'; |
|
16 | 18 |
|
17 | 19 |
interface ModalProps { |
18 |
onCancel: () => void; |
|
20 |
onCancel: (ok: boolean) => void;
|
|
19 | 21 |
documentsIds: (string | undefined)[]; |
20 | 22 |
} |
21 | 23 |
|
... | ... | |
26 | 28 |
const [selectedUsers, setSelectedUsers] = useState<string[]>([]); |
27 | 29 |
|
28 | 30 |
const handleOk = () => { |
29 |
onCancel(); |
|
31 |
onCancel(true);
|
|
30 | 32 |
}; |
31 | 33 |
|
32 | 34 |
const handleCancel = () => { |
33 |
onCancel(); |
|
35 |
onCancel(false);
|
|
34 | 36 |
}; |
35 | 37 |
|
36 | 38 |
async function fetchData() { |
... | ... | |
64 | 66 |
3000, |
65 | 67 |
'top-end' |
66 | 68 |
); |
67 |
onCancel(); |
|
69 |
onCancel(true);
|
|
68 | 70 |
}); |
69 | 71 |
} |
70 | 72 |
}; |
... | ... | |
131 | 133 |
}, |
132 | 134 |
}, |
133 | 135 |
{ |
134 |
title: 'Přiřazeno dokumentů',
|
|
136 |
title: 'Aktivní | Hotovo | Celkem',
|
|
135 | 137 |
key: 'docCounts', |
136 | 138 |
align: 'center' as 'center', |
137 | 139 |
dataIndex: 'assignedDocumentsCount', |
138 | 140 |
// @ts-ignore |
139 |
render: (assignedDocumentsCount) => (
|
|
141 |
render: (text, row) => (
|
|
140 | 142 |
<div> |
141 |
<Space size={'middle'}> |
|
142 |
<Badge count={assignedDocumentsCount} /> |
|
143 |
</Space> |
|
143 |
<ABadge style={BadgeStyle.WARNING}> |
|
144 |
{row.newDocumentsCount + row.inProgressDocumentsCount} |
|
145 |
</ABadge> |
|
146 |
{' | '} |
|
147 |
<ABadge style={BadgeStyle.SUCCESS}> |
|
148 |
{row.finalizedDocumentsCount} |
|
149 |
</ABadge> |
|
150 |
{' | '} |
|
151 |
<ABadge style={BadgeStyle.GENERAL}> |
|
152 |
{row.finalizedDocumentsCount + |
|
153 |
row.newDocumentsCount + |
|
154 |
row.inProgressDocumentsCount} |
|
155 |
</ABadge> |
|
144 | 156 |
</div> |
145 | 157 |
), |
146 | 158 |
// @ts-ignore |
147 |
sorter: (a, b) => a.assignedDocumentsCount - b.assignedDocumentsCount, |
|
159 |
sorter: (a, b) => |
|
160 |
a.newDocumentsCount + |
|
161 |
a.inProgressDocumentsCount - |
|
162 |
(b.newDocumentsCount + b.inProgressDocumentsCount), |
|
148 | 163 |
}, |
149 | 164 |
]; |
150 | 165 |
|
... | ... | |
154 | 169 |
onOk={handleOk} |
155 | 170 |
visible={true} |
156 | 171 |
onCancel={handleCancel} |
157 |
width={1000}
|
|
172 |
width={1100}
|
|
158 | 173 |
footer={[ |
159 | 174 |
<Button key="back" onClick={handleCancel}> |
160 | 175 |
Storno |
webapp/components/modals/SetRequiredAnnotationsCountModal.tsx | ||
---|---|---|
6 | 6 |
import { ShowToast } from '../../utils/alerts'; |
7 | 7 |
|
8 | 8 |
interface ModalProps { |
9 |
onCancel: () => void; |
|
9 |
onCancel: (ok: boolean) => void;
|
|
10 | 10 |
documentsIds: string[]; |
11 | 11 |
} |
12 | 12 |
|
13 | 13 |
function SetRequiredAnnotationsCountModal({ onCancel, documentsIds }: ModalProps) { |
14 | 14 |
const handleOk = () => { |
15 |
onCancel(); |
|
15 |
onCancel(true);
|
|
16 | 16 |
}; |
17 | 17 |
|
18 | 18 |
const handleCancel = () => { |
19 |
onCancel(); |
|
19 |
onCancel(false);
|
|
20 | 20 |
}; |
21 | 21 |
|
22 | 22 |
const onFinish = async (values: any) => { |
webapp/components/modals/UserDocumentsModal.tsx | ||
---|---|---|
1 |
import { List, Modal, Skeleton, Tag } from 'antd'; |
|
1 |
import { List, Modal, Skeleton, Tag, Typography } from 'antd';
|
|
2 | 2 |
import 'antd/dist/antd.css'; |
3 | 3 |
import React, { useContext, useEffect, useState } from 'react'; |
4 |
import { AnnotationListInfo, EState } from '../../api'; |
|
4 |
import { AnnotationListInfo, EState, UserInfo } from '../../api';
|
|
5 | 5 |
import { userController } from '../../controllers'; |
6 | 6 |
import { useUnauthRedirect } from '../../hooks'; |
7 | 7 |
import { LoggedUserContext } from '../../contexts/LoggedUserContext'; |
... | ... | |
10 | 10 |
|
11 | 11 |
import { faCircleCheck, faClock } from '@fortawesome/free-regular-svg-icons'; |
12 | 12 |
import styles from '/styles/Icon.module.scss'; |
13 |
import { Badge, Tab, TabPane, Tabs } from 'react-bootstrap'; |
|
13 | 14 |
|
14 | 15 |
interface ModalProps { |
15 | 16 |
onCancel: () => void; |
16 |
userId: string | undefined;
|
|
17 |
user: UserInfo;
|
|
17 | 18 |
} |
18 | 19 |
|
19 |
function UserDocumentsModal({ onCancel, userId }: ModalProps) {
|
|
20 |
function UserDocumentsModal({ onCancel, user }: ModalProps) { |
|
20 | 21 |
const redirecting = useUnauthRedirect('/login'); |
21 | 22 |
const { role } = useContext(LoggedUserContext); |
22 | 23 |
const [annotations, setAnnotations] = useState<AnnotationListInfo[]>([]); |
24 |
const [finished, setFinished] = useState(0); |
|
25 |
const [inProgress, setInProgress] = useState(0); |
|
23 | 26 |
|
24 | 27 |
const handleOk = () => { |
25 | 28 |
onCancel(); |
... | ... | |
51 | 54 |
}; |
52 | 55 |
|
53 | 56 |
useEffect(() => { |
54 |
if (!redirecting && role === 'ADMINISTRATOR' && userId) {
|
|
57 |
if (!redirecting && role === 'ADMINISTRATOR' && user.id) {
|
|
55 | 58 |
userController |
56 |
.userUserIdAnnotationsGet(userId)
|
|
59 |
.userUserIdAnnotationsGet(user.id)
|
|
57 | 60 |
.then(({ data: { annotations } }) => { |
58 | 61 |
setAnnotations(annotations || []); |
59 | 62 |
}); |
63 |
if ( |
|
64 |
user && |
|
65 |
user.finalizedDocumentsCount !== undefined && |
|
66 |
user.inProgressDocumentsCount !== undefined && |
|
67 |
user.newDocumentsCount !== undefined |
|
68 |
) { |
|
69 |
setFinished(user.finalizedDocumentsCount); |
|
70 |
setInProgress(user.newDocumentsCount + user.inProgressDocumentsCount); |
|
71 |
} |
|
60 | 72 |
} |
61 |
}, [userId, redirecting, role]);
|
|
73 |
}, [redirecting, role]); |
|
62 | 74 |
|
63 | 75 |
return ( |
64 | 76 |
<Modal |
... | ... | |
68 | 80 |
onCancel={handleCancel} |
69 | 81 |
footer={[null]} |
70 | 82 |
> |
71 |
<List |
|
72 |
dataSource={annotations} |
|
73 |
size={'small'} |
|
74 |
grid={{ gutter: 10, column: 1 }} |
|
75 |
style={{ maxHeight: 400, overflowY: 'auto', overflowX: 'hidden' }} |
|
76 |
renderItem={(item) => ( |
|
77 |
<List.Item key={item.annotationId}> |
|
78 |
<List.Item.Meta |
|
79 |
title={item.documentName} |
|
80 |
// @ts-ignore |
|
81 |
avatar={getStateTag(item.state)} |
|
82 |
/> |
|
83 |
</List.Item> |
|
84 |
)} |
|
85 |
/> |
|
83 |
<Tabs defaultActiveKey="all" id="tabs" className="mb-3"> |
|
84 |
<Tab |
|
85 |
eventKey="all" |
|
86 |
title={ |
|
87 |
<div> |
|
88 |
<Typography.Text>Vše </Typography.Text> |
|
89 |
<Badge bg="info" pill> |
|
90 |
{inProgress + finished} |
|
91 |
</Badge> |
|
92 |
</div> |
|
93 |
} |
|
94 |
> |
|
95 |
<List |
|
96 |
dataSource={annotations} |
|
97 |
size={'small'} |
|
98 |
grid={{ gutter: 10, column: 1 }} |
|
99 |
style={{ maxHeight: 400, overflowY: 'auto', overflowX: 'hidden' }} |
|
100 |
renderItem={(item) => ( |
|
101 |
<List.Item key={item.annotationId}> |
|
102 |
<List.Item.Meta |
|
103 |
title={item.documentName} |
|
104 |
// @ts-ignore |
|
105 |
avatar={getStateTag(item.state)} |
|
106 |
/> |
|
107 |
</List.Item> |
|
108 |
)} |
|
109 |
/> |
|
110 |
</Tab> |
|
111 |
<Tab |
|
112 |
eventKey="profile" |
|
113 |
title={ |
|
114 |
<div> |
|
115 |
<Typography.Text>Nové a rozpracované </Typography.Text> |
|
116 |
<Badge bg="warning" pill> |
|
117 |
{inProgress} |
|
118 |
</Badge> |
|
119 |
</div> |
|
120 |
} |
|
121 |
> |
|
122 |
<List |
|
123 |
dataSource={annotations} |
|
124 |
size={'small'} |
|
125 |
grid={{ gutter: 10, column: 1 }} |
|
126 |
style={{ maxHeight: 400, overflowY: 'auto', overflowX: 'hidden' }} |
|
127 |
renderItem={(item) => |
|
128 |
item.state === EState.New || |
|
129 |
item.state === EState.InProgress ? ( |
|
130 |
<List.Item key={item.annotationId}> |
|
131 |
<List.Item.Meta |
|
132 |
title={item.documentName} |
|
133 |
// @ts-ignore |
|
134 |
avatar={getStateTag(item.state)} |
|
135 |
/> |
|
136 |
</List.Item> |
|
137 |
) : ( |
|
138 |
'' |
|
139 |
) |
|
140 |
} |
|
141 |
/> |
|
142 |
</Tab> |
|
143 |
<Tab |
|
144 |
eventKey="contact" |
|
145 |
title={ |
|
146 |
<div> |
|
147 |
<Typography.Text>Hotové </Typography.Text> |
|
148 |
<Badge bg="success" pill> |
|
149 |
{finished} |
|
150 |
</Badge> |
|
151 |
</div> |
|
152 |
} |
|
153 |
> |
|
154 |
<List |
|
155 |
dataSource={annotations} |
|
156 |
size={'small'} |
|
157 |
grid={{ gutter: 10, column: 1 }} |
|
158 |
style={{ maxHeight: 400, overflowY: 'auto', overflowX: 'hidden' }} |
|
159 |
renderItem={(item) => |
|
160 |
item.state === EState.Done ? ( |
|
161 |
<List.Item key={item.annotationId}> |
|
162 |
<List.Item.Meta |
|
163 |
title={item.documentName} |
|
164 |
// @ts-ignore |
|
165 |
avatar={getStateTag(item.state)} |
|
166 |
/> |
|
167 |
</List.Item> |
|
168 |
) : ( |
|
169 |
'' |
|
170 |
) |
|
171 |
} |
|
172 |
/> |
|
173 |
</Tab> |
|
174 |
</Tabs> |
|
86 | 175 |
</Modal> |
87 | 176 |
); |
88 | 177 |
} |
webapp/components/types/TableUserInfo.tsx | ||
---|---|---|
6 | 6 |
username?: string | null; |
7 | 7 |
name?: string | null; |
8 | 8 |
surname?: string | null; |
9 |
assignedDocumentsCount?: number; |
|
9 |
finalizedDocumentsCount?: number; |
|
10 |
inProgressDocumentsCount?: number; |
|
11 |
newDocumentsCount?: number; |
|
10 | 12 |
role?: ERole; |
11 | 13 |
}; |
webapp/pages/documents/admin/index.tsx | ||
---|---|---|
270 | 270 |
}); |
271 | 271 |
}; |
272 | 272 |
|
273 |
const hideModalWithClear = () => { |
|
273 |
const hideModalWithClear = (clear: boolean) => {
|
|
274 | 274 |
fetchData(); |
275 | 275 |
setVisibleAssign(false); |
276 | 276 |
setVisibleSetCount(false); |
277 |
clearSelection(); |
|
277 |
if (clear) { |
|
278 |
clearSelection(); |
|
279 |
} |
|
278 | 280 |
}; |
279 | 281 |
|
280 | 282 |
const hideModal = () => { |
webapp/pages/documents/annotator/index.tsx | ||
---|---|---|
32 | 32 |
if (!docs) { |
33 | 33 |
setDocuments([]); |
34 | 34 |
} else { |
35 |
setDocuments(docs); |
|
35 |
setDocuments(docs.filter((doc) => doc.state !== EState.Done));
|
|
36 | 36 |
} |
37 | 37 |
} |
38 | 38 |
|
webapp/pages/users/index.tsx | ||
---|---|---|
167 | 167 |
render: (text, row) => ( |
168 | 168 |
<div> |
169 | 169 |
<Space size={'middle'}> |
170 |
<Badge count={row.assignedDocumentsCount}> |
|
170 |
<Badge |
|
171 |
count={ |
|
172 |
row.finalizedDocumentsCount + |
|
173 |
row.inProgressDocumentsCount + |
|
174 |
row.newDocumentsCount |
|
175 |
} |
|
176 |
> |
|
171 | 177 |
<Button onClick={() => showDocsModal(row.id)}> |
172 | 178 |
Dokumenty |
173 | 179 |
</Button> |
... | ... | |
210 | 216 |
{passwordEditVisible && ( |
211 | 217 |
<EditUserPasswordModal userInfo={user} onCancel={hideModals} /> |
212 | 218 |
)} |
213 |
{docsVisible && <UserDocumentsModal userId={user.id} onCancel={hideModals} />}
|
|
219 |
{docsVisible && <UserDocumentsModal user={user} onCancel={hideModals} />}
|
|
214 | 220 |
|
215 | 221 |
<Table |
216 | 222 |
locale={{ ...getLocaleProps() }} |
Také k dispozici: Unified diff
Refactoring, fixes