Projekt

Obecné

Profil

Stáhnout (7.05 KB) Statistiky
| Větev: | Tag: | Revize:
1
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
            if (props.occurrence.isFinal) {
68
                return COLOR_OCCURRENCE_ACCEPTED;
69
            }
70
        }
71

    
72
        return 'white';
73
    }
74

    
75
    return (
76
        <Container
77
            className="shadow-sm"
78
            style={{
79
                backgroundColor: getBackgroundColor(),
80
            }}
81
        >
82
            <Row className="mb-1 mt-1">
83
                <Col>
84
                    <Row>
85
                        <Col>Pozice: {props.occurrence.position}</Col>
86
                        <Col>Délka: {props.occurrence.length}</Col>
87
                    </Row>
88
                    <Row>
89
                        <i title={props.occurrence.selectedText ?? ''}>
90
                            {getTextMaxLength(props.occurrence.selectedText ?? '', 35)}
91
                        </i>
92
                    </Row>
93
                    <Row>
94
                        <Col className="d-flex align-items-center" sm="4">
95
                            Poznámka:
96
                        </Col>
97
                        <Col>
98
                            <Input.TextArea
99
                                defaultValue={props.occurrence.note ?? ''}
100
                                onBlur={onChangeNote(props.occurrence)}
101
                                rows={1}
102
                            />
103
                        </Col>
104
                    </Row>
105
                    {props.occurrence.sentiment && (
106
                        <Row>
107
                            <Col className="d-flex align-items-center" sm="4">
108
                                Sentiment:
109
                            </Col>
110
                            <Col>
111
                                <Select
112
                                    defaultValue={props.occurrence.sentiment}
113
                                    style={{ width: '100%' }}
114
                                    onChange={onChangeSentiment(props.occurrence)}
115
                                >
116
                                    <Option value={ETagSentiment.Positive}>
117
                                        <span style={{ color: 'green' }}>Pozitivní</span>
118
                                    </Option>
119
                                    <Option value={ETagSentiment.Neutral}>
120
                                        Neutrální
121
                                    </Option>
122
                                    <Option value={ETagSentiment.Negative}>
123
                                        <span
124
                                            style={{
125
                                                color: '#ff4d4f',
126
                                            }}
127
                                        >
128
                                            Negativní
129
                                        </span>
130
                                    </Option>
131
                                </Select>
132
                            </Col>
133
                        </Row>
134
                    )}
135
                </Col>
136
                <Col
137
                    sm="auto"
138
                    className="d-flex align-items-center flex-column justify-content-sm-evenly"
139
                >
140
                    <Button
141
                        icon={<EyeOutlined />}
142
                        onClick={() => {
143
                            setSelectedOccurrenceId(props.occurrence.occurenceId ?? null);
144
                            setSelectedInstanceId(props.tag.instanceId);
145
                        }}
146
                        title={'Zvýraznit výskyt'}
147
                    />
148
                    <Button
149
                        icon={<DeleteOutlined />}
150
                        onClick={onDeleteOccurrence(props.occurrence)}
151
                        danger
152
                        className={'mt-1'}
153
                    />
154
                    {isFinal && (
155
                        <Button
156
                            icon={<LikeOutlined />}
157
                            title={'Označit jako správné řešení'}
158
                            onClick={() => {
159
                                ShowConfirm(() => {
160
                                    makeOccurrenceFinal(props.occurrence);
161
                                }, 'označit toto řešení jako správné');
162
                            }}
163
                            className={'mt-1'}
164
                        />
165
                    )}
166
                </Col>
167
            </Row>
168
            {isFinal && (
169
                <Row className="mb-1 mt-1">
170
                    <Col>
171
                        Označili:{' '}
172
                        {props.occurrence.users?.map((u) => (
173
                            <span
174
                                title={u.name + ' ' + u.surname + ' (' + u.username + ')'}
175
                                key={props.occurrence.occurenceId + '.' + u.id}
176
                                style={{ marginRight: 10 }}
177
                            >
178
                                {getNameTruncated(u)}
179
                            </span>
180
                        ))}
181
                    </Col>
182
                </Row>
183
            )}
184
        </Container>
185
    );
186
}
(2-2/8)