Projekt

Obecné

Profil

Stáhnout (11.1 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
import { getTextMaxLength } from '../../utils/strings';
16

    
17
const { Option } = Select;
18

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

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

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

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

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

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

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

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

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

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