Projekt

Obecné

Profil

« Předchozí | Další » 

Revize c73aecde

Přidáno uživatelem Dominik Poch před asi 2 roky(ů)

Renamed files, fixed overflow in annotation view, added access to the AnnotationContext in annotation view, deleted visiblity from add document modal window, deleted LayoutProps

Zobrazit rozdíly:

webapp/components/annotation/AnnotationItem.tsx
1
import { Col, Container, Row, Stack } from 'react-bootstrap';
2
import { Occurrence, Tag } from '../types/tag';
3
import { ChangeEvent, useContext, useState } from 'react';
4

  
5
import 'antd/dist/antd.css';
6
import { Button, Input } from 'antd';
7
import {
8
    PlusOutlined,
9
    EyeOutlined,
10
    DownOutlined,
11
    DeleteOutlined,
12
} from '@ant-design/icons';
13
import { AnnotationContext } from '../../contexts/AnnotationContext';
14

  
15
export function AnnotationItem(props: { tag: Tag }) {
16
    const [visibleProperties, setVisibleProperties] = useState(false);
17
    const {
18
        addOccurrence,
19
        deleteOccurrence,
20
        changeVisibility,
21
        changePosition,
22
        changeLength,
23
    } = useContext(AnnotationContext);
24

  
25
    const onAddOccurrence = () => {
26
        addOccurrence(props.tag);
27
    };
28

  
29
    const onDeleteOccurrence = (occurrence: Occurrence) => (e: any) => {
30
        deleteOccurrence(occurrence);
31
    };
32

  
33
    const onChangeVisibility = () => {
34
        changeVisibility(props.tag);
35
    };
36

  
37
    const onChangePosition =
38
        (occurrence: Occurrence) => (e: ChangeEvent<HTMLInputElement>) => {
39
            changePosition(occurrence, Number(e.currentTarget.value));
40
        };
41

  
42
    const onChangeLength =
43
        (occurrence: Occurrence) => (e: ChangeEvent<HTMLInputElement>) => {
44
            changeLength(occurrence, Number(e.currentTarget.value));
45
        };
46

  
47
    const changePropertiesVisibility = () => {
48
        setVisibleProperties(!visibleProperties);
49
    };
50

  
51
    return (
52
        <Container>
53
            <Row>
54
                <Col className="d-flex align-items-center">{props.tag.name}</Col>
55
                <Col sm="auto">
56
                    <Button
57
                        type="text"
58
                        shape="circle"
59
                        icon={<PlusOutlined />}
60
                        onClick={onAddOccurrence}
61
                    />
62
                    <Button
63
                        type="text"
64
                        shape="circle"
65
                        icon={<EyeOutlined />}
66
                        onClick={onChangeVisibility}
67
                    />
68
                    <Button
69
                        type="text"
70
                        shape="circle"
71
                        icon={<DownOutlined />}
72
                        onClick={changePropertiesVisibility}
73
                    />
74
                </Col>
75
            </Row>
76
            {visibleProperties && (
77
                <Stack>
78
                    <div>Kategorie: {props.tag.category}</div>
79
                    <div>Výskyty:</div>
80
                    {props.tag.occurrences.map((occurrence, index) => {
81
                        return (
82
                            <div key={index} id={props.tag.name + index}>
83
                                <Container>
84
                                    <Row>
85
                                        <Col>
86
                                            <Row>
87
                                                <Col className="d-flex align-items-center">
88
                                                    Pozice:
89
                                                </Col>
90
                                                <Col sm="auto">
91
                                                    <Input
92
                                                        value={occurrence.position}
93
                                                        onChange={onChangePosition(
94
                                                            occurrence
95
                                                        )}
96
                                                    />
97
                                                </Col>
98
                                            </Row>
99
                                            <Row>
100
                                                <Col className="d-flex align-items-center">
101
                                                    Délka:
102
                                                </Col>
103
                                                <Col sm="auto">
104
                                                    <Input
105
                                                        value={occurrence.length}
106
                                                        onChange={onChangeLength(
107
                                                            occurrence
108
                                                        )}
109
                                                    />
110
                                                </Col>
111
                                            </Row>
112
                                        </Col>
113
                                        <Col
114
                                            sm="auto"
115
                                            className="d-flex align-items-center"
116
                                        >
117
                                            <Button
118
                                                icon={<DeleteOutlined />}
119
                                                onClick={onDeleteOccurrence(occurrence)}
120
                                            ></Button>
121
                                        </Col>
122
                                    </Row>
123
                                </Container>
124
                            </div>
125
                        );
126
                    })}
127
                </Stack>
128
            )}
129
        </Container>
130
    );
131
}
webapp/components/annotation/AnnotationPanel.tsx
1
import { Stack } from 'react-bootstrap';
2
import { AnnotationItem } from './AnnotationItem';
3
import { useContext } from 'react';
4
import { AnnotationContext } from '../../contexts/AnnotationContext';
5
import { Tag } from '../types/tag';
6

  
7
/**
8
 * Creates a panel in the annotation screen that contains a list of annotations.
9
 * @returns Panel with a list of annotations.
10
 */
11
export function AnnotationPanel() {
12
    //const { tags } = useContext(AnnotationContext);
13

  
14
    const tags: Tag[] = [
15
        {
16
            name: 'tag a',
17
            category: 'kategorie 1',
18
            visible: true,
19
            occurrences: [
20
                { position: 2, length: 5 },
21
                { position: 10, length: 2 },
22
            ],
23
        },
24
        {
25
            name: 'tag b',
26
            category: 'kategorie 2',
27
            visible: true,
28
            occurrences: [
29
                { position: 546, length: 432 },
30
                { position: 767, length: 123 },
31
            ],
32
        },
33
    ];
34

  
35
    return (
36
        <div>
37
            <Stack>
38
                {tags?.map((tag, index) => {
39
                    return <AnnotationItem key={index} tag={tag} />;
40
                })}
41
            </Stack>
42
        </div>
43
    );
44
}
webapp/components/annotation/DocumentAnnotationView.tsx
1
/**
2
 * Creates an annotation view of a document.
3
 * @returns The annotation view.
4
 */
5
export function DocumentAnnotationView() {
6
    return (
7
        <div>
8
            <p>Main view with a rendered document</p>
9
        </div>
10
    );
11
}
webapp/components/annotation/TagPanel.tsx
1
/**
2
 * Creates a panel in the annotation screen that contains a list of tag.
3
 * @returns Panel with a list of tags.
4
 */
5
export function TagPanel() {
6
    return (
7
        <div>
8
            <p>Panel with a list of tags</p>
9
        </div>
10
    );
11
}
webapp/components/annotation/annotationItem.tsx
1
import { Col, Container, Row, Stack } from 'react-bootstrap';
2
import { Occurrence, Tag } from '../models/tag';
3
import { ChangeEvent, ChangeEventHandler, useState } from 'react';
4

  
5
import 'antd/dist/antd.css';
6
import { Button, Input } from 'antd';
7
import {
8
    PlusOutlined,
9
    EyeOutlined,
10
    DownOutlined,
11
    DeleteOutlined,
12
} from '@ant-design/icons';
13

  
14
type AnnotationItemProps = {
15
    tag: Tag;
16
    onAddOccurrence: (tag: Tag) => void;
17
    onDeleteOccurrence: (occurrence: Occurrence) => void;
18
    onChangeVisibility: (tag: Tag) => void;
19
    onChangePosition: (occurrence: Occurrence, newValue: number) => void;
20
    onChangeLength: (occurrence: Occurrence, newValue: number) => void;
21
};
22

  
23
export function AnnotationItem(props: AnnotationItemProps) {
24
    const [visibleProperties, setVisibleProperties] = useState(false);
25

  
26
    const addOccurrence = () => {
27
        props.onAddOccurrence(props.tag);
28
    };
29

  
30
    const deleteOccurrence = (occurrence: Occurrence) => (e: any) => {
31
        props.onDeleteOccurrence(occurrence);
32
    };
33

  
34
    const changeVisibility = () => {
35
        props.onChangeVisibility(props.tag);
36
    };
37

  
38
    const changePropertiesVisibility = () => {
39
        setVisibleProperties(!visibleProperties);
40
    };
41

  
42
    const changePosition =
43
        (occurrence: Occurrence) => (e: ChangeEvent<HTMLInputElement>) => {
44
            props.onChangePosition(occurrence, Number(e.currentTarget.value));
45
        };
46

  
47
    const changeLength =
48
        (occurrence: Occurrence) => (e: ChangeEvent<HTMLInputElement>) => {
49
            props.onChangeLength(occurrence, Number(e.currentTarget.value));
50
        };
51

  
52
    return (
53
        <div>
54
            <Row>
55
                <Col className="d-flex align-items-center">{props.tag.name}</Col>
56
                <Col sm="auto">
57
                    <Button
58
                        type="text"
59
                        shape="circle"
60
                        icon={<PlusOutlined />}
61
                        onClick={addOccurrence}
62
                    />
63
                    <Button
64
                        type="text"
65
                        shape="circle"
66
                        icon={<EyeOutlined />}
67
                        onClick={changeVisibility}
68
                    />
69
                    <Button
70
                        type="text"
71
                        shape="circle"
72
                        icon={<DownOutlined />}
73
                        onClick={changePropertiesVisibility}
74
                    />
75
                </Col>
76
            </Row>
77
            {visibleProperties && (
78
                <Stack>
79
                    <div>Kategorie: {props.tag.category}</div>
80
                    <div>Výskyty:</div>
81
                    {props.tag.occurrences.map((occurrence, index) => {
82
                        return (
83
                            <div key={index} id={props.tag.name + index}>
84
                                <Container>
85
                                    <Row>
86
                                        <Col>
87
                                            <Row>
88
                                                Pozice:
89
                                                <Input
90
                                                    value={occurrence.position}
91
                                                    onChange={changePosition(occurrence)}
92
                                                />
93
                                            </Row>
94
                                            <Row>
95
                                                Délka:
96
                                                <Input
97
                                                    value={occurrence.length}
98
                                                    onChange={changeLength(occurrence)}
99
                                                />
100
                                            </Row>
101
                                        </Col>
102
                                        <Col
103
                                            sm="auto"
104
                                            className="d-flex align-items-center"
105
                                        >
106
                                            <Button
107
                                                icon={<DeleteOutlined />}
108
                                                onClick={deleteOccurrence(occurrence)}
109
                                            ></Button>
110
                                        </Col>
111
                                    </Row>
112
                                </Container>
113
                            </div>
114
                        );
115
                    })}
116
                </Stack>
117
            )}
118
        </div>
119
    );
120
}
webapp/components/annotation/annotationPanel.tsx
1
import { Stack } from 'react-bootstrap';
2
import { AnnotationItem } from './annotationItem';
3
import { Occurrence, Tag } from '../models/tag';
4
import { useContext } from 'react';
5
import { AnnotationContext } from '../../contexts/AnnotationContext';
6

  
7
type AnnotationPanelProps = {
8
    tags: Tag[];
9
    onAddOccurrence: (tag: Tag) => void;
10
    onDeleteOccurrence: (occurrence: Occurrence) => void;
11
    onChangeVisibility: (tag: Tag) => void;
12
    onChangePosition: (occurrence: Occurrence, newValue: number) => void;
13
    onChangeLength: (occurrence: Occurrence, newValue: number) => void;
14
};
15

  
16
/**
17
 * Creates a panel in the annotation screen that contains a list of annotations.
18
 * @returns Panel with a list of annotations.
19
 */
20
export function AnnotationPanel(props: AnnotationPanelProps) {
21
    const { tags } = useContext(AnnotationContext);
22

  
23
    return (
24
        <div>
25
            <p>Panel with a list of annotations</p>
26
            <Stack>
27
                {props.tags.map((tag, index) => {
28
                    return (
29
                        <AnnotationItem
30
                            key={index}
31
                            tag={tag}
32
                            onAddOccurrence={props.onAddOccurrence}
33
                            onDeleteOccurrence={props.onDeleteOccurrence}
34
                            onChangeVisibility={props.onChangeVisibility}
35
                            onChangePosition={props.onChangePosition}
36
                            onChangeLength={props.onChangeLength}
37
                        />
38
                    );
39
                })}
40
            </Stack>
41
        </div>
42
    );
43
}
webapp/components/annotation/documentAnnotationView.tsx
1
/**
2
 * Creates an annotation view of a document.
3
 * @returns The annotation view.
4
 */
5
export function DocumentAnnotationView() {
6
    return (
7
        <div>
8
            <p>Main view with a rendered document</p>
9
        </div>
10
    );
11
}
webapp/components/annotation/tagPanel.tsx
1
/**
2
 * Creates a panel in the annotation screen that contains a list of tag.
3
 * @returns Panel with a list of tags.
4
 */
5
export function TagPanel() {
6
    return (
7
        <div>
8
            <p>Panel with a list of tags</p>
9
        </div>
10
    );
11
}
webapp/components/modals/AddDocument.tsx
1
import { message, Button, Modal, Upload } from 'antd';
2
import { InboxOutlined } from '@ant-design/icons';
3
import 'antd/dist/antd.css';
4

  
5
const { Dragger } = Upload;
6

  
7
/**
8
 * Creates a modal window that loads documents to the app.
9
 * @returns The modal window.
10
 */
11
export function AddDocument(afterClose: () => {}) {
12
    /**
13
     * Settings of a file loader.
14
     */
15
    const props = {
16
        name: 'file',
17
        multiple: true,
18
        directory: true,
19
        /**
20
            @todo: Probably will be needed to change the uploading URL
21
        **/
22
        action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
23
        onChange(info: any) {
24
            const { status } = info.file;
25

  
26
            if (status !== 'uploading') {
27
                console.log(info.file, info.fileList);
28
            }
29

  
30
            if (status === 'done') {
31
                message.success(`${info.file.name} file uploaded successfully.`);
32
            } else if (status === 'error') {
33
                message.error(`${info.file.name} file upload failed.`);
34
            }
35
        },
36
        onDrop(e: any) {
37
            console.log('Dropped files', e.dataTransfer.files);
38
        },
39
    };
40

  
41
    /**
42
     * Handles successfull closing of the modal window.
43
     */
44
    const handleOk = () => {
45
        /**
46
            @todo: Send documents to a server when all files are loaded
47
        **/
48
        console.log('Document is loaded');
49
        afterClose();
50
    };
51

  
52
    /**
53
     * Handles cancelling of the model window.
54
     */
55
    const handleCancel = () => {
56
        console.log('Loading of documents is cancelled.');
57
        afterClose();
58
    };
59

  
60
    return (
61
        <Modal
62
            title="Nový dokument"
63
            onOk={handleOk}
64
            onCancel={handleCancel}
65
            footer={[
66
                <Button key="back" onClick={handleCancel}>
67
                    Storno
68
                </Button>,
69
                <Button key="submit" type="primary" onClick={handleOk}>
70
                    Nahrát
71
                </Button>,
72
            ]}
73
        >
74
            <Dragger>
75
                <p className="ant-upload-drag-icon">
76
                    <InboxOutlined />
77
                </p>
78
                <p className="ant-upload-text">
79
                    Soubory lze nahrát stisknutím nebo přetažením...
80
                </p>
81
            </Dragger>
82
        </Modal>
83
    );
84
}
webapp/components/modals/addDocument.tsx
1
import { message, Button, Modal, Upload } from 'antd';
2
import { useState } from 'react';
3
import { InboxOutlined } from '@ant-design/icons';
4
import 'antd/dist/antd.css';
5

  
6
const { Dragger } = Upload;
7

  
8
/**
9
 * Creates a modal window that loads documents to the app.
10
 * @returns The modal window.
11
 */
12
export function AddDocument() {
13
    const [visible, setVisible] = useState(true);
14

  
15
    /**
16
     * Settings of a file loader.
17
     */
18
    const props = {
19
        name: 'file',
20
        multiple: true,
21
        directory: true,
22
        /**
23
            @todo: Probably will be needed to change the uploading URL
24
        **/
25
        action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
26
        onChange(info: any) {
27
            const { status } = info.file;
28

  
29
            if (status !== 'uploading') {
30
                console.log(info.file, info.fileList);
31
            }
32

  
33
            if (status === 'done') {
34
                message.success(`${info.file.name} file uploaded successfully.`);
35
            } else if (status === 'error') {
36
                message.error(`${info.file.name} file upload failed.`);
37
            }
38
        },
39
        onDrop(e: any) {
40
            console.log('Dropped files', e.dataTransfer.files);
41
        },
42
    };
43

  
44
    /**
45
     * Handles successfull closing of the modal window.
46
     */
47
    const handleOk = () => {
48
        setVisible(false);
49
        /**
50
            @todo: Send documents to a server when all files are loaded
51
        **/
52
        console.log('Document is loaded');
53
    };
54

  
55
    /**
56
     * Handles cancelling of the model window.
57
     */
58
    const handleCancel = () => {
59
        setVisible(false);
60
        console.log('Loading of documents is cancelled.');
61
    };
62

  
63
    return (
64
        <Modal
65
            visible={visible}
66
            title="Nový dokument"
67
            onOk={handleOk}
68
            onCancel={handleCancel}
69
            footer={[
70
                <Button key="back" onClick={handleCancel}>
71
                    Storno
72
                </Button>,
73
                <Button key="submit" type="primary" onClick={handleOk}>
74
                    Nahrát
75
                </Button>,
76
            ]}
77
        >
78
            <Dragger>
79
                <p className="ant-upload-drag-icon">
80
                    <InboxOutlined />
81
                </p>
82
                <p className="ant-upload-text">
83
                    Soubory lze nahrát stisknutím nebo přetažením...
84
                </p>
85
            </Dragger>
86
        </Modal>
87
    );
88
}
webapp/components/models/tag.tsx
1
export type Tag = {
2
    name: string;
3
    category: string;
4
    visible: boolean;
5
    occurrences: Occurrence[];
6
};
7

  
8
export type Occurrence = {
9
    position: number;
10
    length: number;
11
};
webapp/components/navigation/AdminNavBar.tsx
1
/**
2
 * Creates a navigation bar of an admin.
3
 * @returns Navigation bar of an admin.
4
 */
5
export function AdminNavBar() {
6
    return (
7
        <div>
8
            <p>Navigation bar of an admin.</p>
9
        </div>
10
    );
11
}
webapp/components/navigation/UserNavBar.tsx
1
/**
2
 * Creates a navigation bar of a normal user (annotator).
3
 * @returns Navigation bar of a user.
4
 */
5
export function UserNavBar() {
6
    return (
7
        <div>
8
            <p>Navigation bar of a normal user.</p>
9
        </div>
10
    );
11
}
webapp/components/navigation/adminNavBar.tsx
1
/**
2
 * Creates a navigation bar of an admin.
3
 * @returns Navigation bar of an admin.
4
 */
5
export function AdminNavBar() {
6
    return (
7
        <div>
8
            <p>Navigation bar of an admin.</p>
9
        </div>
10
    );
11
}
webapp/components/navigation/userNavBar.tsx
1
/**
2
 * Creates a navigation bar of a normal user (annotator).
3
 * @returns Navigation bar of a user.
4
 */
5
export function UserNavBar() {
6
    return (
7
        <div>
8
            <p>Navigation bar of a normal user.</p>
9
        </div>
10
    );
11
}
webapp/components/types/layoutProps.tsx
1
import React from 'react';
2

  
3
/**
4
 * Props prepared for a react stucture that is passed to a layout.
5
 */
6
export type LayoutProps = {
7
    children: React.ReactNode;
8
};
webapp/components/types/tag.tsx
1
export type Tag = {
2
    name: string;
3
    category: string;
4
    visible: boolean;
5
    occurrences: Occurrence[];
6
};
7

  
8
export type Occurrence = {
9
    position: number;
10
    length: number;
11
};
webapp/contexts/AnnotationContext.tsx
1 1
import React, { createContext, useContext, useEffect, useState } from 'react';
2 2
import { TagInstanceInfo } from '../api';
3
import { Occurrence, Tag } from '../components/models/tag';
3
import { Occurrence, Tag } from '../components/types/tag';
4 4

  
5 5
interface IAnnotationContextProvider {
6 6
    tags: TagInstanceInfo[] | null;
7 7
    setTags: (newTags: TagInstanceInfo[] | null) => void;
8
    addOccurrence: () => void;
8
    addOccurrence: (tag: Tag) => void;
9 9
    changeVisibility: (tag: Tag) => void;
10 10
    deleteOccurrence: (occurrence: Occurrence) => void;
11 11
    changePosition: (occurrence: Occurrence, newValue: number) => void;
......
17 17
    setTags: (v) => {
18 18
        return;
19 19
    },
20
    addOccurrence: () => {
20
    addOccurrence: (tag: Tag) => {
21 21
        return;
22 22
    },
23 23
    changeVisibility: (tag: Tag) => {
......
36 36

  
37 37
const AnnotationProvider = (props: { children: React.ReactNode }) => {
38 38
    const [tags, setTags] = useState<TagInstanceInfo[] | null>(null);
39
    const addOccurrence = () => {};
39
    const addOccurrence = (tag: Tag) => {};
40 40
    const changeVisibility = (tag: Tag) => {};
41 41
    const deleteOccurrence = (occurrence: Occurrence) => {};
42 42
    const changePosition = (occurrence: Occurrence, newValue: number) => {};
webapp/layouts/LoginLayout.tsx
1
import logo from '/public/usp-logo.svg';
2
import Image from 'next/image';
3
import styles from '/styles/Login.module.scss';
4
import { Col, Container, Row, Stack } from 'react-bootstrap';
5
import React from 'react';
6

  
7
/**
8
 * Creates layout of a login screen.
9
 * @param props Html structure of a login form.
10
 * @returns The login screen.
11
 */
12
export function LoginLayout(props: { children: React.ReactNode }) {
13
    return (
14
        <Container>
15
            <Row className="min-vh-100 align-items-center">
16
                <Col md={8}>
17
                    <Stack gap={5}>
18
                        <div>
19
                            <Image
20
                                src={logo}
21
                                alt="Ústav státu a práva Akademie věd ČR"
22
                            ></Image>
23
                        </div>
24
                        <h1 className={styles.title}>
25
                            Vítejte na stránkách Ústavu státu a práva Akademie věd ČR pro
26
                            anotaci dokumentů v rámci projektu TAČR TL03000152 - Umělá
27
                            inteligence, média a právo
28
                        </h1>
29
                    </Stack>
30
                </Col>
31
                <Col md={4}>
32
                    <main>{props.children}</main>
33
                </Col>
34
            </Row>
35
        </Container>
36
    );
37
}
webapp/layouts/MainLayout.tsx
1
import { UserNavBar } from '../components/navigation/UserNavBar';
2
import { AdminNavBar } from '../components/navigation/AdminNavBar';
3
import 'antd/dist/antd.css';
4
import styles from '/styles/MainLayout.module.scss';
5
import React from 'react';
6

  
7
/**
8
 * Creates layout of main screens.
9
 * @param props Html structure of a login form.
10
 * @returns The login screen.
11
 */
12
export function MainLayout(props: { children: React.ReactNode }) {
13
    return (
14
        <div className={styles.layoutWrapper}>
15
            <div className={styles.header}>
16
                {/**
17
                 @todo: Select correct navigation bar
18
                 {user && <UserNavBar />}
19
                 {admin && <AdminNavBar />}
20
                **/}
21
            </div>
22
            <main className={styles.content}>{props.children}</main>
23
            <div className={styles.footer}></div>
24
        </div>
25
    );
26
}
webapp/layouts/loginLayout.tsx
1
import logo from '/public/usp-logo.svg';
2
import Image from 'next/image';
3
import styles from '/styles/login.module.scss';
4
import { Col, Container, Row, Stack } from 'react-bootstrap';
5
import { LayoutProps } from '../components/types/layoutProps';
6

  
7
/**
8
 * Creates layout of a login screen.
9
 * @param props Html structure of a login form.
10
 * @returns The login screen.
11
 */
12
export function LoginLayout(props: LayoutProps) {
13
    return (
14
        <Container>
15
            <Row className="min-vh-100 align-items-center">
16
                <Col md={8}>
17
                    <Stack gap={5}>
18
                        <div>
19
                            <Image
20
                                src={logo}
21
                                alt="Ústav státu a práva Akademie věd ČR"
22
                            ></Image>
23
                        </div>
24
                        <h1 className={styles.title}>
25
                            Vítejte na stránkách Ústavu státu a práva Akademie věd ČR pro
26
                            anotaci dokumentů v rámci projektu TAČR TL03000152 - Umělá
27
                            inteligence, média a právo
28
                        </h1>
29
                    </Stack>
30
                </Col>
31
                <Col md={4}>
32
                    <main>{props.children}</main>
33
                </Col>
34
            </Row>
35
        </Container>
36
    );
37
}
webapp/layouts/mainLayout.tsx
1
import { LayoutProps } from '../components/types/layoutProps';
2
import { UserNavBar } from '../components/navigation/userNavBar';
3
import { AdminNavBar } from '../components/navigation/adminNavBar';
4
import 'antd/dist/antd.css';
5
import styles from '/styles/mainLayout.module.scss';
6

  
7
/**
8
 * Creates layout of main screens.
9
 * @param props Html structure of a login form.
10
 * @returns The login screen.
11
 */
12
export function MainLayout(props: LayoutProps) {
13
    return (
14
        <div className={styles.layoutwrapper}>
15
            <div className={styles.header}>
16
                {/**
17
                 @todo: Select correct navigation bar
18
                 {user && <UserNavBar />}
19
                 {admin && <AdminNavBar />}
20
                **/}
21
            </div>
22
            <main className={styles.content}>{props.children}</main>
23
            <div className={styles.footer}></div>
24
        </div>
25
    );
26
}
webapp/pages/annotation/index.tsx
1
import { AnnotationPanel } from '../../components/annotation/annotationPanel';
2
import { DocumentAnnotationView } from '../../components/annotation/documentAnnotationView';
3
import { TagPanel } from '../../components/annotation/tagPanel';
4
import { MainLayout } from '../../layouts/mainLayout';
1
import { AnnotationPanel } from '../../components/annotation/AnnotationPanel';
2
import { DocumentAnnotationView } from '../../components/annotation/DocumentAnnotationView';
3
import { TagPanel } from '../../components/annotation/TagPanel';
4
import { MainLayout } from '../../layouts/MainLayout';
5 5
import 'antd/dist/antd.css';
6
import styles from '/styles/annotation.module.scss';
7
import { Occurrence, Tag } from '../../components/models/tag';
8
import AnnotationProvider from '../../contexts/AnnotationContext';
6
import styles from '/styles/Annotation.module.scss';
7
import AnnotationProvider, { AnnotationContext } from '../../contexts/AnnotationContext';
9 8

  
10 9
/**
11 10
 * Creates an annotation screen.
12 11
 * @returns The annotation screen.
13 12
 */
14 13
function Annotation() {
15
    const tags = [
16
        {
17
            name: 'tag a',
18
            category: 'kategorie 1',
19
            visible: true,
20
            occurrences: [
21
                { position: 2, length: 5 },
22
                { position: 10, length: 2 },
23
            ],
24
        },
25
        {
26
            name: 'tag b',
27
            category: 'kategorie 2',
28
            visible: true,
29
            occurrences: [
30
                { position: 546, length: 432 },
31
                { position: 767, length: 123 },
32
            ],
33
        },
34
    ];
35

  
36
    const addOccurrence = () => {};
37

  
38
    const changeVisibility = (tag: Tag) => {};
39

  
40
    const deleteOccurrence = (occurrence: Occurrence) => {};
41

  
42
    const changePosition = (occurrence: Occurrence, newValue: number) => {};
43

  
44
    const changeLength = (occurrence: Occurrence, newValue: number) => {};
45

  
46 14
    return (
47 15
        <AnnotationProvider>
48 16
            <MainLayout>
49
                <div className={styles.layoutwrapper}>
17
                <div className={styles.layoutWrapper}>
50 18
                    <div className={styles.tags}>
51 19
                        <TagPanel />
52 20
                    </div>
......
54 22
                        <DocumentAnnotationView />
55 23
                    </div>
56 24
                    <div className={styles.annotations}>
57
                        <AnnotationPanel
58
                            tags={tags}
59
                            onAddOccurrence={addOccurrence}
60
                            onChangeVisibility={changeVisibility}
61
                            onDeleteOccurrence={deleteOccurrence}
62
                            onChangePosition={changePosition}
63
                            onChangeLength={changeLength}
64
                        />
25
                        <AnnotationPanel />
65 26
                    </div>
66 27
                </div>
67 28
            </MainLayout>
webapp/pages/login/index.tsx
1 1
import { Form, Input, Button } from 'antd';
2 2
import { UserOutlined, LockOutlined } from '@ant-design/icons';
3 3
import 'antd/dist/antd.css';
4
import { LoginLayout } from '../../layouts/loginLayout';
4
import { LoginLayout } from '../../layouts/LoginLayout';
5 5

  
6 6
/**
7 7
 * Creates a login screen.
webapp/styles/Annotation.module.scss
1
.layoutWrapper {
2
    display: grid;
3

  
4
    grid:
5
        [main-start] 'tags document annotations' [main-end]
6
        / 1fr 3fr 1fr;
7

  
8
    width:100%;
9
    height:100%;
10
    place-items: stretch;
11
    place-content: stretch;
12
    gap: 3px;
13
}
14

  
15
%annotationContent {
16
    background-color: white;
17
    padding: 10px 0px 10px 10px;
18
    overflow-y: scroll;
19
}
20

  
21
.tags {
22
    @extend %annotationContent;
23
    grid-area: tags;
24
}
25

  
26
.annotations {
27
    @extend %annotationContent;
28
    grid-area: annotations;
29

  
30

  
31
}
32

  
33
.document {
34
    @extend %annotationContent;
35
    grid-area: document;
36
}
webapp/styles/Login.module.scss
1
.title {
2
    font-size: x-large;
3
    font-family:Arial, Helvetica, sans-serif
4
}
webapp/styles/MainLayout.module.scss
1
.layoutWrapper {
2
    background-color: lightgray;
3
    display: grid;
4

  
5
    grid:
6
        [header-start] 'header' 60px [header-end]
7
        [main-start] 'content' [main-end]
8
        [footer-start] 'footer' 30px [footer-end];
9

  
10
    place-items: stretch;
11
    place-content: stretch;
12

  
13
    width: 100vw;
14
    height: 100vh;
15

  
16
    gap: 3px;
17
}
18

  
19
.header {
20
    grid-area: header;
21

  
22
}
23

  
24
.content {
25
    grid-area: content;
26
    overflow-y: hidden;
27
}
28

  
29
.footer {
30
    grid-area: footer;
31
}
webapp/styles/annotation.module.scss
1
%lightBackground {
2
    background-color: white;
3
}
4

  
5
.layoutwrapper {
6
    display: grid;
7

  
8
    grid:
9
        [main-start] 'tags document annotations' [main-end]
10
        / 1fr 3fr 1fr;
11

  
12
    width:100%;
13
    height:100%;
14
    place-items: stretch;
15
    place-content: stretch;
16
    gap: 3px;
17
}
18

  
19

  
20
.tags {
21
    @extend %lightBackground;
22
    grid-area: tags;
23
}
24

  
25
.annotations {
26
    @extend %lightBackground;
27
    grid-area: annotations;
28
}
29

  
30
.document {
31
    @extend %lightBackground;
32
    grid-area: document;
33
}
webapp/styles/login.module.scss
1
.title {
2
    font-size: x-large;
3
    font-family:Arial, Helvetica, sans-serif
4
}
webapp/styles/mainLayout.module.scss
1
.layoutwrapper {
2
    background-color: lightgray;
3
    display: grid;
4

  
5
    grid:
6
        [header-start] 'header' 60px [header-end]
7
        [main-start] 'content' [main-end]
8
        [footer-start] 'footer' 30px [footer-end];
9

  
10
    place-items: stretch;
11
    place-content: stretch;
12

  
13
    width: 100vw;
14
    height: 100vh;
15

  
16
    gap: 3px;
17
}
18

  
19
.header {
20
    grid-area: header;
21
}
22

  
23
.content {
24
    grid-area: content;
25
}
26

  
27
.footer {
28
    grid-area: footer;
29
}

Také k dispozici: Unified diff