Projekt

Obecné

Profil

Stáhnout (7.14 KB) Statistiky
| Větev: | Tag: | Revize:
1 b80a6919 Lukáš Vlček
import { Col, Container, Row } from 'react-bootstrap';
2
import { Tag } from '../types/tag';
3
import { ChangeEvent, useContext } from 'react';
4
import 'antd/dist/antd.css';
5
import { Button, Input, Select } from 'antd';
6
import { DeleteOutlined, EyeOutlined, LikeOutlined } from '@ant-design/icons';
7
import { AnnotationContext } from '../../contexts/AnnotationContext';
8
import { ETagSentiment, TagInstanceInfo } from '../../api';
9
import { getNameTruncated, getTextMaxLength } from '../../utils/strings';
10
import {
11
    COLOR_ALL_OCCURRENCES_ACCEPTED,
12
    COLOR_HIGHLIGHTED_OCCURRENCE,
13
    COLOR_HIGHLIGHTED_TAG,
14
    COLOR_OCCURRENCE_ACCEPTED,
15
} from '../../constants';
16
import { ShowConfirm } from '../../utils/alerts';
17
18
const { Option } = Select;
19
20
/**
21
 * Creates a single item in an annotation panel.
22
 * @param props Properties should contain a tag that will be shown in this annotation.
23
 * @returns The item that represents an annotation.
24
 */
25
export function AnnotationOccurrenceItem(props: {
26
    tag: Tag;
27
    occurrence: TagInstanceInfo;
28
}) {
29
    /**
30
     * Context that manages annotations.
31
     */
32
    const {
33
        deleteOccurrence,
34
        changeNote,
35
        changeSentiment,
36
        selectedOccurrenceId,
37
        setSelectedOccurrenceId,
38
        setSelectedInstanceId,
39
        isFinal,
40
        makeOccurrenceFinal,
41
    } = useContext(AnnotationContext);
42
43
    const onChangeSentiment = (occurrence: TagInstanceInfo) => (val: ETagSentiment) => {
44
        changeSentiment(occurrence, val);
45
    };
46
47
    /**
48
     * Removes an occurrence of this annotation from the context.
49
     * @param occurrence The occurrence that should be removed.
50
     */
51
    const onDeleteOccurrence = (occurrence: TagInstanceInfo) => (e: any) => {
52
        deleteOccurrence(occurrence);
53
    };
54
55
    const onChangeNote =
56
        (occurrence: TagInstanceInfo) => (e: ChangeEvent<HTMLTextAreaElement>) => {
57
            changeNote(occurrence, e.currentTarget.value);
58
        };
59
60
    function getBackgroundColor(): string {
61
        if (selectedOccurrenceId === props.occurrence.occurenceId) {
62
            // highlighted occurrence
63
            return COLOR_HIGHLIGHTED_OCCURRENCE;
64
        }
65
66
        if (isFinal) {
67
            const allAccepted =
68
                props.tag.occurrences.filter((o) => !o.isFinal).length === 0;
69
            if (allAccepted) {
70
                return COLOR_OCCURRENCE_ACCEPTED;
71
            }
72
        }
73
74
        return 'white';
75
    }
76
77
    return (
78
        <Container
79
            className="shadow-sm"
80
            style={{
81
                backgroundColor: getBackgroundColor(),
82
            }}
83
        >
84
            <Row className="mb-1 mt-1">
85
                <Col>
86
                    <Row>
87
                        <Col>Pozice: {props.occurrence.position}</Col>
88
                        <Col>Délka: {props.occurrence.length}</Col>
89
                    </Row>
90
                    <Row>
91
                        <i title={props.occurrence.selectedText ?? ''}>
92
                            {getTextMaxLength(props.occurrence.selectedText ?? '', 35)}
93
                        </i>
94
                    </Row>
95
                    <Row>
96
                        <Col className="d-flex align-items-center" sm="4">
97
                            Poznámka:
98
                        </Col>
99
                        <Col>
100
                            <Input.TextArea
101
                                defaultValue={props.occurrence.note ?? ''}
102
                                onBlur={onChangeNote(props.occurrence)}
103
                                rows={1}
104
                            />
105
                        </Col>
106
                    </Row>
107
                    {props.occurrence.sentiment && (
108
                        <Row>
109
                            <Col className="d-flex align-items-center" sm="4">
110
                                Sentiment:
111
                            </Col>
112
                            <Col>
113
                                <Select
114
                                    defaultValue={props.occurrence.sentiment}
115
                                    style={{ width: '100%' }}
116
                                    onChange={onChangeSentiment(props.occurrence)}
117
                                >
118
                                    <Option value={ETagSentiment.Positive}>
119
                                        <span style={{ color: 'green' }}>Pozitivní</span>
120
                                    </Option>
121
                                    <Option value={ETagSentiment.Neutral}>
122
                                        Neutrální
123
                                    </Option>
124
                                    <Option value={ETagSentiment.Negative}>
125
                                        <span
126
                                            style={{
127
                                                color: '#ff4d4f',
128
                                            }}
129
                                        >
130
                                            Negativní
131
                                        </span>
132
                                    </Option>
133
                                </Select>
134
                            </Col>
135
                        </Row>
136
                    )}
137
                </Col>
138
                <Col
139
                    sm="auto"
140
                    className="d-flex align-items-center flex-column justify-content-sm-evenly"
141
                >
142
                    <Button
143
                        icon={<EyeOutlined />}
144
                        onClick={() => {
145
                            setSelectedOccurrenceId(props.occurrence.occurenceId ?? null);
146
                            setSelectedInstanceId(props.tag.instanceId);
147
                        }}
148
                        title={'Zvýraznit výskyt'}
149
                    />
150
                    <Button
151
                        icon={<DeleteOutlined />}
152
                        onClick={onDeleteOccurrence(props.occurrence)}
153
                        danger
154
                        className={'mt-1'}
155
                    />
156 cb6654d2 Lukáš Vlček
                    {isFinal && (
157
                        <Button
158
                            icon={<LikeOutlined />}
159
                            title={'Označit jako správné řešení'}
160
                            onClick={() => {
161
                                ShowConfirm(() => {
162
                                    makeOccurrenceFinal(props.occurrence);
163
                                }, 'označit toto řešení jako správné');
164
                            }}
165
                            className={'mt-1'}
166
                        />
167
                    )}
168 b80a6919 Lukáš Vlček
                </Col>
169
            </Row>
170 cb6654d2 Lukáš Vlček
            {isFinal && (
171
                <Row className="mb-1 mt-1">
172
                    <Col>
173
                        Označili:{' '}
174
                        {props.occurrence.users?.map((u) => (
175
                            <span
176
                                title={u.name + ' ' + u.surname + ' (' + u.username + ')'}
177
                                key={props.occurrence.occurenceId + '.' + u.id}
178
                                style={{ marginRight: 10 }}
179
                            >
180
                                {getNameTruncated(u)}
181
                            </span>
182
                        ))}
183
                    </Col>
184
                </Row>
185
            )}
186 b80a6919 Lukáš Vlček
        </Container>
187
    );
188
}