Revize 6a250c18
Přidáno uživatelem Lukáš Vlček před téměř 3 roky(ů)
webapp/components/annotation/DocumentAnnotationView.tsx | ||
---|---|---|
26 | 26 |
if (!annotation) { |
27 | 27 |
return <p>Probíhá načítání anotace ...</p>; |
28 | 28 |
} |
29 |
|
|
29 |
|
|
30 | 30 |
const onChangeNote = (e: ChangeEvent<HTMLTextAreaElement>) => { |
31 | 31 |
changeDocumentNote(e.currentTarget.value); |
32 | 32 |
}; |
... | ... | |
76 | 76 |
|
77 | 77 |
return ( |
78 | 78 |
<div> |
79 |
<div className="mb-3">
|
|
79 |
<div className="mb-3">
|
|
80 | 80 |
<h5>Poznámka</h5> |
81 | 81 |
<Input.TextArea |
82 | 82 |
defaultValue={annotation.note ?? ''} |
83 | 83 |
onBlur={onChangeNote} |
84 | 84 |
/> |
85 | 85 |
</div> |
86 |
<hr /> |
|
87 |
|
|
86 | 88 |
{getCss()} |
87 | 89 |
<div onClick={detectSelectedElement}> |
88 | 90 |
{parse(annotation.documentToRender ?? '')} |
webapp/components/navigation/AdminNavBar.tsx | ||
---|---|---|
3 | 3 |
import { useRouter } from 'next/router'; |
4 | 4 |
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; |
5 | 5 |
import { LoggedUserContext } from '../../contexts/LoggedUserContext'; |
6 |
import { |
|
7 |
faUser, |
|
8 |
faFileExport, |
|
9 |
faFileLines, |
|
10 |
faUsers, |
|
11 |
faTags, |
|
12 |
faBookmark, |
|
13 |
} from '@fortawesome/free-solid-svg-icons'; |
|
6 |
import { faFileLines, faTags, faUser, faUsers } from '@fortawesome/free-solid-svg-icons'; |
|
14 | 7 |
import { userController } from '../../controllers'; |
15 |
import { UserInfo } from '../../api';
|
|
8 |
import { COLOR_NAVBAR } from '../../constants';
|
|
16 | 9 |
|
17 | 10 |
const AdminNavBar = () => { |
18 | 11 |
const router = useRouter(); |
... | ... | |
20 | 13 |
const { SubMenu } = Menu; |
21 | 14 |
const [name, setName] = useState<string>(''); |
22 | 15 |
|
23 |
const handleLogout = useCallback(() => { |
|
24 |
logout(); |
|
25 |
router.push('/login'); |
|
16 |
const handleLogout = useCallback(async () => {
|
|
17 |
await logout();
|
|
18 |
await router.push('/login');
|
|
26 | 19 |
}, [logout, router]); |
27 | 20 |
|
28 | 21 |
async function fetchUsername() { |
... | ... | |
35 | 28 |
}, []); |
36 | 29 |
|
37 | 30 |
return ( |
38 |
<Menu theme="dark" mode="horizontal"> |
|
39 |
<Menu.Item style={{}} key="1" onClick={() => router.push('/documents/admin')}> |
|
40 |
<FontAwesomeIcon icon={faFileLines} /> Dokumenty |
|
41 |
</Menu.Item> |
|
42 |
<Menu.Item style={{}} key="2" onClick={() => router.push('/users')}> |
|
43 |
<FontAwesomeIcon icon={faUsers} /> Uživatelé |
|
44 |
</Menu.Item> |
|
45 |
<Menu.Item style={{}} key="3" onClick={() => router.push('/tags')}> |
|
46 |
<FontAwesomeIcon icon={faTags} /> Značky |
|
47 |
</Menu.Item> |
|
48 |
<Menu.Item style={{}} key="5" onClick={() => router.push('/export')}> |
|
49 |
<FontAwesomeIcon icon={faFileExport} /> Export |
|
50 |
</Menu.Item> |
|
51 |
|
|
52 |
<SubMenu icon={<FontAwesomeIcon icon={faUser} />} key="account" title={name}> |
|
53 |
<Menu.Item key="setting:2" onClick={() => handleLogout()}> |
|
54 |
Odhlásit se |
|
31 |
<div className={'navbar-wrapper'}> |
|
32 |
<Menu theme="dark" mode="horizontal" style={{ flexGrow: 1 }}> |
|
33 |
<Menu.Item |
|
34 |
style={{}} |
|
35 |
key="1" |
|
36 |
onClick={() => router.push('/documents/admin')} |
|
37 |
> |
|
38 |
<FontAwesomeIcon icon={faFileLines} /> Dokumenty |
|
39 |
</Menu.Item> |
|
40 |
<Menu.Item style={{}} key="2" onClick={() => router.push('/users')}> |
|
41 |
<FontAwesomeIcon icon={faUsers} /> Uživatelé |
|
42 |
</Menu.Item> |
|
43 |
<Menu.Item style={{}} key="3" onClick={() => router.push('/tags')}> |
|
44 |
<FontAwesomeIcon icon={faTags} /> Značky |
|
55 | 45 |
</Menu.Item> |
56 |
</SubMenu> |
|
57 |
</Menu> |
|
46 |
</Menu> |
|
47 |
<Menu theme="dark" mode="horizontal" style={{}}> |
|
48 |
<SubMenu |
|
49 |
icon={<FontAwesomeIcon icon={faUser} />} |
|
50 |
key="account" |
|
51 |
title={name} |
|
52 |
> |
|
53 |
<Menu.Item key="setting:2" onClick={() => handleLogout()}> |
|
54 |
Odhlásit se |
|
55 |
</Menu.Item> |
|
56 |
</SubMenu> |
|
57 |
</Menu> |
|
58 |
</div> |
|
58 | 59 |
); |
59 | 60 |
}; |
60 | 61 |
|
webapp/components/navigation/UserNavBar.tsx | ||
---|---|---|
27 | 27 |
}, []); |
28 | 28 |
|
29 | 29 |
return ( |
30 |
<Menu theme="dark" mode="horizontal"> |
|
31 |
<Menu.Item key="1" onClick={() => router.push('/documents/annotator')}> |
|
32 |
<FontAwesomeIcon icon={faFileLines} /> Dokumenty |
|
33 |
</Menu.Item> |
|
34 |
|
|
35 |
<SubMenu key="account" icon={<FontAwesomeIcon icon={faUser} />} title={name}> |
|
36 |
<Menu.Item key="setting:2" onClick={() => handleLogout()}> |
|
37 |
Odhlásit se |
|
30 |
<div className={'navbar-wrapper'}> |
|
31 |
<Menu theme="dark" mode="horizontal" style={{ flexGrow: 1 }}> |
|
32 |
<Menu.Item key="1" onClick={() => router.push('/documents/annotator')}> |
|
33 |
<FontAwesomeIcon icon={faFileLines} /> Dokumenty |
|
38 | 34 |
</Menu.Item> |
39 |
</SubMenu> |
|
40 |
</Menu> |
|
35 |
</Menu> |
|
36 |
<Menu theme="dark" mode="horizontal"> |
|
37 |
<SubMenu |
|
38 |
key="account" |
|
39 |
icon={<FontAwesomeIcon icon={faUser} />} |
|
40 |
title={name} |
|
41 |
> |
|
42 |
<Menu.Item key="setting:2" onClick={() => handleLogout()}> |
|
43 |
Odhlásit se |
|
44 |
</Menu.Item> |
|
45 |
</SubMenu> |
|
46 |
</Menu> |
|
47 |
</div> |
|
41 | 48 |
); |
42 | 49 |
}; |
43 | 50 |
|
webapp/constants.ts | ||
---|---|---|
16 | 16 |
export const COLOR_WARNING = 'darkorange'; |
17 | 17 |
export const COLOR_ERROR = 'indianred'; |
18 | 18 |
|
19 |
export const COLOR_HIGHLIGHTED_TAG = '#97BDC4'; |
|
20 |
export const COLOR_HIGHLIGHTED_OCCURRENCE = '#D8E1E9'; |
|
19 |
export const COLOR_NAVBAR = '#343434'; |
|
20 |
|
|
21 |
export const COLOR_HIGHLIGHTED_TAG = '#CBDEE2'; |
|
22 |
export const COLOR_HIGHLIGHTED_OCCURRENCE = '#B1CDD3'; |
|
21 | 23 |
|
22 | 24 |
export const COLOR_ALL_OCCURRENCES_ACCEPTED = '#B6CEB7'; |
23 | 25 |
export const COLOR_OCCURRENCE_ACCEPTED = '#9DBE9E'; |
webapp/layouts/AnnotationLayout.tsx | ||
---|---|---|
1 |
import 'antd/dist/antd.css'; |
|
2 |
import styles from '/styles/MainLayout.module.scss'; |
|
3 |
import Navbar from './Navbar'; |
|
4 |
|
|
5 |
/** |
|
6 |
* Creates layout of main screens. |
|
7 |
* @param props Html structure of a login form. |
|
8 |
* @returns The login screen. |
|
9 |
*/ |
|
10 |
export function AnnotationLayout(props: { children: React.ReactNode }) { |
|
11 |
return ( |
|
12 |
<div className={styles.layoutWrapper}> |
|
13 |
<Navbar /> |
|
14 |
<main className={styles.contentAnnotator}>{props.children}</main> |
|
15 |
</div> |
|
16 |
); |
|
17 |
} |
|
18 |
|
|
19 |
export default AnnotationLayout; |
webapp/layouts/MainLayout.tsx | ||
---|---|---|
1 | 1 |
import 'antd/dist/antd.css'; |
2 | 2 |
import styles from '/styles/MainLayout.module.scss'; |
3 |
import { useContext } from 'react'; |
|
4 |
import { LoggedUserContext } from '../contexts/LoggedUserContext'; |
|
5 |
import AdminNavBar from '../components/navigation/AdminNavBar'; |
|
6 |
import UserNavBar from '../components/navigation/UserNavBar'; |
|
3 |
import Navbar from './Navbar'; |
|
7 | 4 |
|
8 | 5 |
/** |
9 | 6 |
* Creates layout of main screens. |
... | ... | |
11 | 8 |
* @returns The login screen. |
12 | 9 |
*/ |
13 | 10 |
export function MainLayout(props: { children: React.ReactNode }) { |
14 |
const { role } = useContext(LoggedUserContext); |
|
15 |
const isAdmin = role === 'ADMINISTRATOR'; |
|
16 |
const isAnnotator = role === 'ANNOTATOR'; |
|
17 |
|
|
18 | 11 |
return ( |
19 | 12 |
<div className={styles.layoutWrapper}> |
20 |
<div className={styles.header}> |
|
21 |
{(isAdmin && <AdminNavBar />) || (isAnnotator && <UserNavBar />)} |
|
22 |
</div> |
|
13 |
<Navbar /> |
|
23 | 14 |
<main className={styles.content}>{props.children}</main> |
24 |
<div className={styles.footer} /> |
|
25 | 15 |
</div> |
26 | 16 |
); |
27 | 17 |
} |
18 |
|
|
19 |
export default MainLayout; |
webapp/layouts/Navbar.tsx | ||
---|---|---|
1 |
import styles from '/styles/MainLayout.module.scss'; |
|
2 |
import AdminNavBar from '../components/navigation/AdminNavBar'; |
|
3 |
import UserNavBar from '../components/navigation/UserNavBar'; |
|
4 |
import { useContext } from 'react'; |
|
5 |
import { LoggedUserContext } from '../contexts/LoggedUserContext'; |
|
6 |
|
|
7 |
export function Navbar() { |
|
8 |
const { role } = useContext(LoggedUserContext); |
|
9 |
const isAdmin = role === 'ADMINISTRATOR'; |
|
10 |
const isAnnotator = role === 'ANNOTATOR'; |
|
11 |
|
|
12 |
return ( |
|
13 |
<div className={styles.header}> |
|
14 |
{(isAdmin && <AdminNavBar />) || (isAnnotator && <UserNavBar />)} |
|
15 |
</div> |
|
16 |
); |
|
17 |
} |
|
18 |
|
|
19 |
export default Navbar; |
webapp/pages/annotation/[id].tsx | ||
---|---|---|
8 | 8 |
import TagCategoryProvider from '../../contexts/TagCategoryContext'; |
9 | 9 |
|
10 | 10 |
import { useRouter } from 'next/router'; |
11 |
import AnnotationLayout from '../../layouts/AnnotationLayout'; |
|
11 | 12 |
|
12 | 13 |
/** |
13 | 14 |
* Creates an annotation screen. |
... | ... | |
35 | 36 |
return ( |
36 | 37 |
<AnnotationProvider annotationId={annotationId} isFinal={isFinal}> |
37 | 38 |
<TagCategoryProvider> |
38 |
<MainLayout>
|
|
39 |
<AnnotationLayout>
|
|
39 | 40 |
<div className={styles.layoutWrapper}> |
40 | 41 |
<div className={styles.tags}> |
41 | 42 |
<TagPanel /> |
... | ... | |
47 | 48 |
<AnnotationPanel /> |
48 | 49 |
</div> |
49 | 50 |
</div> |
50 |
</MainLayout>
|
|
51 |
</AnnotationLayout>
|
|
51 | 52 |
</TagCategoryProvider> |
52 | 53 |
</AnnotationProvider> |
53 | 54 |
); |
webapp/pages/tags/index.tsx | ||
---|---|---|
462 | 462 |
/> |
463 | 463 |
)} |
464 | 464 |
|
465 |
<Container> |
|
466 |
<Row> |
|
467 |
<Typography.Title level={2}> |
|
468 |
<FontAwesomeIcon icon={faTags} /> Značky |
|
469 |
</Typography.Title> |
|
470 |
</Row> |
|
471 |
<Row> |
|
472 |
<Table |
|
473 |
columns={columns} |
|
474 |
dataSource={shownData} |
|
475 |
scroll={{ y: 'calc(100vh - 300px)' }} |
|
476 |
size="small" |
|
477 |
title={() => ( |
|
478 |
<Stack direction="horizontal" gap={3}> |
|
479 |
<Button type="primary" onClick={openAddCategoryModal}> |
|
480 |
Přidat kategorii |
|
481 |
</Button> |
|
482 |
<Search |
|
483 |
placeholder="Vyhledání tagu" |
|
484 |
onSearch={searchTag} |
|
485 |
style={{ width: 200 }} |
|
486 |
className="ms-auto" |
|
487 |
allowClear |
|
488 |
/> |
|
489 |
</Stack> |
|
490 |
)} |
|
491 |
/> |
|
492 |
</Row> |
|
493 |
</Container> |
|
465 |
<Row> |
|
466 |
<Typography.Title level={2}> |
|
467 |
<FontAwesomeIcon icon={faTags} /> Značky |
|
468 |
</Typography.Title> |
|
469 |
</Row> |
|
470 |
<Row> |
|
471 |
<Table |
|
472 |
columns={columns} |
|
473 |
dataSource={shownData} |
|
474 |
scroll={{ y: 'calc(100vh - 300px)' }} |
|
475 |
size="small" |
|
476 |
title={() => ( |
|
477 |
<Stack direction="horizontal" gap={3}> |
|
478 |
<Button type="primary" onClick={openAddCategoryModal}> |
|
479 |
Přidat kategorii |
|
480 |
</Button> |
|
481 |
<Search |
|
482 |
placeholder="Vyhledání tagu" |
|
483 |
onSearch={searchTag} |
|
484 |
style={{ width: 200 }} |
|
485 |
className="ms-auto" |
|
486 |
allowClear |
|
487 |
/> |
|
488 |
</Stack> |
|
489 |
)} |
|
490 |
/> |
|
491 |
</Row> |
|
494 | 492 |
</MainLayout> |
495 | 493 |
); |
496 | 494 |
} |
webapp/styles/Annotation.module.scss | ||
---|---|---|
9 | 9 |
height:100%; |
10 | 10 |
place-items: stretch; |
11 | 11 |
place-content: stretch; |
12 |
gap: 3px; |
|
12 |
gap: 8px; |
|
13 |
|
|
14 |
background-color: #AA6373; |
|
13 | 15 |
} |
14 | 16 |
|
15 | 17 |
%annotationContent { |
16 | 18 |
background-color: white; |
17 |
padding: 10px 0px 10px 10px;
|
|
19 |
padding: 10px; |
|
18 | 20 |
overflow-y: scroll; |
21 |
background-color: white; |
|
22 |
|
|
23 |
-webkit-box-shadow: 5px 5px 5px 5px rgba(138,138,138,0.75); |
|
24 |
box-shadow: 5px 5px 5px 5px rgba(138,138,138,0.75); |
|
19 | 25 |
} |
20 | 26 |
|
21 | 27 |
.tags { |
... | ... | |
26 | 32 |
.annotations { |
27 | 33 |
@extend %annotationContent; |
28 | 34 |
grid-area: annotations; |
29 |
|
|
30 |
|
|
31 | 35 |
} |
32 | 36 |
|
33 | 37 |
.document { |
webapp/styles/MainLayout.module.scss | ||
---|---|---|
4 | 4 |
|
5 | 5 |
grid: |
6 | 6 |
[header-start] 'header' 50px [header-end] |
7 |
[main-start] 'content' [main-end] |
|
8 |
[footer-start] 'footer' 30px [footer-end]; |
|
7 |
[main-start] 'content' [main-end]; |
|
9 | 8 |
|
10 | 9 |
place-items: stretch; |
11 | 10 |
place-content: stretch; |
... | ... | |
13 | 12 |
width: 100vw; |
14 | 13 |
height: 100vh; |
15 | 14 |
|
16 |
gap: 3px; |
|
15 |
gap: 0; |
|
16 |
background-color: dimgray; |
|
17 | 17 |
} |
18 | 18 |
|
19 | 19 |
.header { |
20 | 20 |
grid-area: header; |
21 |
|
|
22 | 21 |
} |
23 | 22 |
|
24 | 23 |
.content { |
25 | 24 |
grid-area: content; |
26 | 25 |
overflow-y: hidden; |
26 |
padding: 20px; |
|
27 |
background-color: white; |
|
28 |
margin: 8px; |
|
29 |
border-radius: 6px; |
|
30 |
|
|
31 |
-webkit-box-shadow: 5px 5px 5px 5px rgba(138,138,138,0.75); |
|
32 |
box-shadow: 5px 5px 5px 5px rgba(138,138,138,0.75); |
|
33 |
} |
|
34 |
|
|
35 |
.contentAnnotator { |
|
36 |
grid-area: content; |
|
37 |
//@extend .content; |
|
38 |
margin: 8px; |
|
39 |
|
|
40 |
padding: 0; |
|
41 |
overflow-y: hidden; |
|
27 | 42 |
} |
28 | 43 |
|
29 | 44 |
.footer { |
webapp/styles/globals.css | ||
---|---|---|
14 | 14 |
* { |
15 | 15 |
box-sizing: border-box; |
16 | 16 |
} |
17 |
|
|
18 |
.navbar-wrapper{ |
|
19 |
width: 100vw; |
|
20 |
margin: 0; |
|
21 |
display: flex; |
|
22 |
justify-content: space-around; |
|
23 |
padding-left: 10px; |
|
24 |
padding-right: 10px; |
|
25 |
background: #001529; |
|
26 |
} |
Také k dispozici: Unified diff
Layout and minor color changes