Projekt

Obecné

Profil

Stáhnout (10.6 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { Col, Container, Row, Stack } from 'react-bootstrap';
2
import { Tag } from '../types/tag';
3
import { ChangeEvent, useContext, useState } from 'react';
4
import 'antd/dist/antd.css';
5
import { Button, Input, Select } from 'antd';
6
import {
7
    PlusOutlined,
8
    DownOutlined,
9
    DeleteOutlined,
10
    TagOutlined,
11
    EyeOutlined,
12
} from '@ant-design/icons';
13
import { AnnotationContext } from '../../contexts/AnnotationContext';
14
import { ETagSentiment, TagInstanceInfo } from '../../api';
15

    
16
const { Option } = Select;
17

    
18
/**
19
 * Creates a single item in an annotation panel.
20
 * @param props Properties should contain a tag that will be shown in this annotation.
21
 * @returns The item that represents an annotation.
22
 */
23
export function AnnotationItem(props: { tag: Tag }) {
24
    /**
25
     * Should properties of this annotation be visible?
26
     */
27
    const [visibleProperties, setVisibleProperties] = useState(false);
28

    
29
    /**
30
     * Context that manages annotations.
31
     */
32
    const {
33
        addOccurrence,
34
        deleteOccurrence,
35
        changePosition,
36
        changeNote,
37
        changeSentiment,
38
        changeLength,
39
        selectedOccurrenceId,
40
        selectedInstanceId,
41
        setSelectedOccurrenceId,
42
        setSelectedInstanceId,
43
    } = useContext(AnnotationContext);
44

    
45
    /**
46
     * Adds new occurrence of this annotation to the context.
47
     */
48
    const onAddOccurrence = () => {
49
        addOccurrence(props.tag);
50
    };
51

    
52
    /**
53
     * Removes an occurrence of this annotation from the context.
54
     * @param occurrence The occurrence that should be removed.
55
     */
56
    const onDeleteOccurrence = (occurrence: TagInstanceInfo) => (e: any) => {
57
        deleteOccurrence(occurrence);
58
    };
59

    
60
    /**
61
     * Changes a position of an occurrence of this annotation in the context.
62
     * @param occurrence The occurrence that should be changed.
63
     */
64
    const onChangePosition =
65
        (occurrence: TagInstanceInfo) => (e: ChangeEvent<HTMLInputElement>) => {
66
            changePosition(occurrence, Number(e.currentTarget.value));
67
        };
68

    
69
    /**
70
     * Changes a length of an occurrence of this annotation in the context.
71
     * @param occurrence The occurrence that should be changed.
72
     */
73
    const onChangeLength =
74
        (occurrence: TagInstanceInfo) => (e: ChangeEvent<HTMLInputElement>) => {
75
            changeLength(occurrence, Number(e.currentTarget.value));
76
        };
77

    
78
    const onChangeSentiment = (occurrence: TagInstanceInfo) => (val: ETagSentiment) => {
79
        changeSentiment(occurrence, val);
80
    };
81

    
82
    const onChangeNote =
83
        (occurrence: TagInstanceInfo) => (e: ChangeEvent<HTMLTextAreaElement>) => {
84
            changeNote(occurrence, e.currentTarget.value);
85
        };
86

    
87
    /**
88
     * Changes visibility of properties of this annotation.
89
     */
90
    const changePropertiesVisibility = () => {
91
        setVisibleProperties(!visibleProperties);
92
    };
93

    
94
    return (
95
        <Container>
96
            <Row
97
                className="border rounded"
98
                style={{
99
                    backgroundColor:
100
                        selectedInstanceId === props.tag.instanceId ? '#FCF3CF' : 'white',
101
                }}
102
            >
103
                <Col sm="auto" className="d-flex align-items-center">
104
                    <Button
105
                        icon={<TagOutlined style={{ marginLeft: 0 }} />}
106
                        onClick={() => {
107
                            setSelectedInstanceId(props.tag.instanceId);
108
                            setSelectedOccurrenceId(null);
109
                        }}
110
                        style={{
111
                            border: 'none',
112
                            paddingLeft: 0,
113
                            backgroundColor:
114
                                selectedInstanceId === props.tag.instanceId
115
                                    ? '#FCF3CF'
116
                                    : 'white',
117
                        }}
118
                        title={'Zvýraznit značky'}
119
                    />
120
                </Col>
121
                <Col className="d-flex align-items-center">
122
                    {props.tag.tagName}
123
                    {props.tag.subtagName ? ' (' + props.tag.subtagName + ')' : ''}
124
                </Col>
125
                <Col sm="auto">
126
                    <Button
127
                        type="text"
128
                        shape="circle"
129
                        icon={<PlusOutlined />}
130
                        onClick={onAddOccurrence}
131
                    />
132
                    <Button
133
                        type="text"
134
                        shape="circle"
135
                        icon={<DownOutlined />}
136
                        onClick={changePropertiesVisibility}
137
                    />
138
                </Col>
139
            </Row>
140
            {visibleProperties && (
141
                <Stack gap={1} className="mb-2">
142
                    <div>Kategorie: {props.tag.category}</div>
143
                    <div>Výskyty:</div>
144
                    {props.tag.occurrences.map((occurrence, index) => {
145
                        return (
146
                            <Container
147
                                key={index}
148
                                className="shadow-sm"
149
                                style={{
150
                                    backgroundColor:
151
                                        selectedOccurrenceId === occurrence.occurenceId
152
                                            ? '#D8E1E9'
153
                                            : 'white',
154
                                }}
155
                            >
156
                                <Row className="mb-1 mt-1">
157
                                    <Col>
158
                                        <Row>
159
                                            <Col>Pozice: {occurrence.position}</Col>
160
                                        </Row>
161
                                        <Row>
162
                                            <Col>Délka: {occurrence.length}</Col>
163
                                        </Row>
164
                                        <Row>
165
                                            <Col
166
                                                className="d-flex align-items-center"
167
                                                sm="4"
168
                                            >
169
                                                Poznámka:
170
                                            </Col>
171
                                            <Col>
172
                                                <Input.TextArea
173
                                                    defaultValue={occurrence.note ?? ''}
174
                                                    onBlur={onChangeNote(occurrence)}
175
                                                />
176
                                            </Col>
177
                                        </Row>
178
                                        {occurrence.sentiment && (
179
                                            <Row>
180
                                                <Col
181
                                                    className="d-flex align-items-center"
182
                                                    sm="4"
183
                                                >
184
                                                    Sentiment:
185
                                                </Col>
186
                                                <Col>
187
                                                    <Select
188
                                                        defaultValue={
189
                                                            occurrence.sentiment
190
                                                        }
191
                                                        style={{ width: '100%' }}
192
                                                        onChange={onChangeSentiment(
193
                                                            occurrence
194
                                                        )}
195
                                                    >
196
                                                        <Option
197
                                                            value={ETagSentiment.Positive}
198
                                                        >
199
                                                            Pozitivní
200
                                                        </Option>
201
                                                        <Option
202
                                                            value={ETagSentiment.Neutral}
203
                                                        >
204
                                                            Neutrální
205
                                                        </Option>
206
                                                        <Option
207
                                                            value={ETagSentiment.Negative}
208
                                                        >
209
                                                            Negativní
210
                                                        </Option>
211
                                                    </Select>
212
                                                </Col>
213
                                            </Row>
214
                                        )}
215
                                    </Col>
216
                                    <Col
217
                                        sm="auto"
218
                                        className="d-flex align-items-center flex-column justify-content-sm-evenly"
219
                                    >
220
                                        <Button
221
                                            icon={<EyeOutlined />}
222
                                            onClick={() => {
223
                                                setSelectedOccurrenceId(
224
                                                    occurrence.occurenceId ?? null
225
                                                );
226
                                                setSelectedInstanceId(
227
                                                    props.tag.instanceId
228
                                                );
229
                                            }}
230
                                            title={'Zvýraznit výskyt'}
231
                                        />
232
                                        <Button
233
                                            icon={<DeleteOutlined />}
234
                                            onClick={onDeleteOccurrence(occurrence)}
235
                                            danger
236
                                        />
237
                                    </Col>
238
                                </Row>
239
                            </Container>
240
                        );
241
                    })}
242
                </Stack>
243
            )}
244
        </Container>
245
    );
246
}
(1-1/7)