Projekt

Obecné

Profil

Stáhnout (11 KB) Statistiky
| Větev: | Tag: | Revize:
1 acb8a961 Dominik Poch
import React, { createContext, useEffect, useState } from 'react';
2 bcbaa7d3 Dominik Poch
import {
3
    AnnotationInfo,
4
    ETagSentiment,
5
    ETagType,
6
    SubTagInfo,
7
    TagInfo,
8
    TagInstanceInfo,
9
} from '../api';
10 9a41c02f Dominik Poch
import { Tag } from '../components/types/tag';
11 dee53692 Jaroslav Hrubý
import { annotationController, userController } from '../controllers';
12 4bc99591 Lukáš Vlček
import { GetSelectionInfo } from '../utils/selectionUtils';
13 dee53692 Jaroslav Hrubý
import { ShowConfirmDelete, ShowToast } from '../utils/alerts';
14 c057279b Lukáš Vlček
15 acb8a961 Dominik Poch
/**
16
 * Interface of an annotation context provider.
17
 */
18 c057279b Lukáš Vlček
interface IAnnotationContextProvider {
19 acb8a961 Dominik Poch
    /**
20
     * Tags managed by the context.
21
     */
22 c057279b Lukáš Vlček
    tags: TagInstanceInfo[] | null;
23 acb8a961 Dominik Poch
24 dee53692 Jaroslav Hrubý
    /**
25
     * Submitting boolean
26
     */
27
    submitting: boolean;
28
29 acb8a961 Dominik Poch
    /**
30
     * Sets new tags.
31
     * @param newTags An array of new tags.
32
     */
33 c057279b Lukáš Vlček
    setTags: (newTags: TagInstanceInfo[] | null) => void;
34 acb8a961 Dominik Poch
35
    /**
36
     * Adds occurrence to an annotation.
37
     * @param tag Tag whose occurrence should be added.
38
     */
39 c73aecde Dominik Poch
    addOccurrence: (tag: Tag) => void;
40 acb8a961 Dominik Poch
41
    /**
42
     * Deletes an occurrence of an annotation.
43
     * @param occurrence Occurrence that should be deleted.
44
     */
45 9a41c02f Dominik Poch
    deleteOccurrence: (occurrence: TagInstanceInfo) => void;
46 acb8a961 Dominik Poch
47
    /**
48
     * Changes a position of an occurrence of an annotation.
49
     * @param occurrence Occurrence whose position should be changed.
50
     * @param newValue New value of the position.
51
     */
52 9a41c02f Dominik Poch
    changePosition: (occurrence: TagInstanceInfo, newValue: number) => void;
53 acb8a961 Dominik Poch
54
    /**
55
     * Changes a length of an occurrence of an annotation.
56
     * @param occurrence Occurrence whose length should be changed.
57
     * @param newValue New value of the length.
58
     */
59 9a41c02f Dominik Poch
    changeLength: (occurrence: TagInstanceInfo, newValue: number) => void;
60 7652cf88 Lukáš Vlček
61 812ee966 Dominik Poch
    /**
62
     * Changes a note of an occurrence of an annotation.
63
     * @param occurrence Occurrence whose note should be changed.
64
     * @param newValue New value of the note.
65
     */
66
    changeNote: (occurrence: TagInstanceInfo, newValue: string) => void;
67
68 bcbaa7d3 Dominik Poch
    /**
69
     * Changes sentiment of an annotation.
70
     * @param occurrence Occurrence whose sentiment should be changed.
71
     * @param newValue New value of the sentiment.
72
     */
73
    changeSentiment: (occurrence: TagInstanceInfo, newValue: ETagSentiment) => void;
74
75 7652cf88 Lukáš Vlček
    annotation: AnnotationInfo | null;
76 9a41c02f Dominik Poch
    mappedTags: Tag[] | null;
77 7652cf88 Lukáš Vlček
    refreshAnnotation: () => void;
78 4bc99591 Lukáš Vlček
79
    markSelectedText: (
80
        tagId: string,
81
        subtagId: string | null,
82
        instanceID: string | null
83
    ) => void;
84 c057279b Lukáš Vlček
}
85
86 acb8a961 Dominik Poch
/**
87
 * The annotation context that manages active annotations.
88
 */
89 c057279b Lukáš Vlček
export const AnnotationContext = createContext<IAnnotationContextProvider>({
90 acb8a961 Dominik Poch
    /**
91
     * Default tags.
92
     */
93 c057279b Lukáš Vlček
    tags: null,
94 acb8a961 Dominik Poch
95 dee53692 Jaroslav Hrubý
    /**
96
     * Submitting boolean
97
     */
98
    submitting: false,
99
100 acb8a961 Dominik Poch
    /**
101
     * Default implementation of setTags method.
102
     * @param v Array of new tags.
103
     */
104 c057279b Lukáš Vlček
    setTags: (v) => {
105
        return;
106
    },
107 acb8a961 Dominik Poch
108
    /**
109
     * Default implementation of addOccurrence method.
110
     * @param tag The tag with new occurrence.
111
     */
112 c73aecde Dominik Poch
    addOccurrence: (tag: Tag) => {
113 c057279b Lukáš Vlček
        return;
114
    },
115 acb8a961 Dominik Poch
116
    /**
117
     * Default implementation of deleteOccurrence method.
118
     * @param occurrence Occurrence that should be deleted.
119
     */
120 9a41c02f Dominik Poch
    deleteOccurrence: (occurrence: TagInstanceInfo) => {
121 c057279b Lukáš Vlček
        return;
122
    },
123 acb8a961 Dominik Poch
124
    /**
125
     * Default implementation of changePosition method.
126
     * @param occurrence Occurrence whose position should be changed.
127
     * @param newValue A new position.
128
     */
129 9a41c02f Dominik Poch
    changePosition: (occurrence: TagInstanceInfo, newValue: number) => {
130 c057279b Lukáš Vlček
        return;
131
    },
132 acb8a961 Dominik Poch
133
    /**
134
     * Default implementation of changeLength method.
135
     * @param occurrence Occurrence whose length should be changed.
136
     * @param newValue A new length.
137
     */
138 9a41c02f Dominik Poch
    changeLength: (occurrence: TagInstanceInfo, newValue: number) => {
139 c057279b Lukáš Vlček
        return;
140
    },
141 7652cf88 Lukáš Vlček
142 812ee966 Dominik Poch
    /**
143
     * Changes a note of an occurrence of an annotation.
144
     * @param occurrence Occurrence whose note should be changed.
145
     * @param newValue New value of the note.
146
     */
147
    changeNote: (occurrence: TagInstanceInfo, newValue: string) => {
148
        return;
149
    },
150
151 bcbaa7d3 Dominik Poch
    /**
152
     * Changes sentiment of an annotation.
153
     * @param occurrence Occurrence whose sentiment should be changed.
154
     * @param newValue New value of the sentiment.
155
     */
156
    changeSentiment: (occurrence: TagInstanceInfo, newValue: ETagSentiment) => {
157
        return;
158
    },
159
160 7652cf88 Lukáš Vlček
    annotation: null,
161 9a41c02f Dominik Poch
    mappedTags: null,
162 7652cf88 Lukáš Vlček
    refreshAnnotation: () => {
163
        return;
164
    },
165 4bc99591 Lukáš Vlček
166
    markSelectedText: () => {
167
        return;
168
    },
169 c057279b Lukáš Vlček
});
170
171 acb8a961 Dominik Poch
/**
172
 * Provider of the annotation context.
173
 * @param props Children that should have access to the annotation context.
174
 * @returns Prepared html of the provider.
175
 */
176 7595035c Lukáš Vlček
const AnnotationProvider = (props: {
177
    children: React.ReactNode;
178
    annotationId: string;
179
}) => {
180 7652cf88 Lukáš Vlček
    const [annotation, setAnnotation] = useState<AnnotationInfo | null>(null);
181
182 acb8a961 Dominik Poch
    /**
183
     * Tags managed by the context.
184
     */
185 c057279b Lukáš Vlček
    const [tags, setTags] = useState<TagInstanceInfo[] | null>(null);
186
187 9a41c02f Dominik Poch
    const [mappedTags, setMappedTags] = useState<Tag[] | null>(null);
188
189 dee53692 Jaroslav Hrubý
    const [submitting, setSubmitting] = useState(false);
190
191 4bc99591 Lukáš Vlček
    async function markSelectedText(
192
        tagId: string,
193
        subtagId: string | null,
194
        instanceId: string | null
195
    ) {
196 dee53692 Jaroslav Hrubý
        setSubmitting(true);
197 4bc99591 Lukáš Vlček
        if (!annotation) {
198
            console.log('annotation not found');
199
            return;
200
        }
201
202
        const selectionInfo = GetSelectionInfo(annotation);
203
        if (!selectionInfo) {
204
            console.log(
205
                'not able to continue, selection processing not completed successfully'
206
            );
207 eb2b4573 Jaroslav Hrubý
            ShowToast('Není označen žádný text pro přidělení značky', 'warning');
208
            setSubmitting(false);
209 4bc99591 Lukáš Vlček
            return;
210
        }
211
212
        const id = subtagId ?? tagId;
213
        const type: ETagType = subtagId == null ? ETagType.Tag : ETagType.Subtag;
214 dee53692 Jaroslav Hrubý
        const res = await annotationController
215
            .annotationAnnotationIdPost(props.annotationId, {
216 4bc99591 Lukáš Vlček
                id: id,
217
                instanceId,
218
                type,
219
                position: selectionInfo.startPositionOriginalDocument,
220
                length: selectionInfo.selectionLengthOriginalDocument,
221 dee53692 Jaroslav Hrubý
            })
222 5ef75299 Lukáš Vlček
            .catch((e) =>
223
                ShowToast('Tato část textu je již touto značkou anotována', 'warning')
224
            );
225 4bc99591 Lukáš Vlček
226
        await refreshAnnotation();
227
    }
228
229 acb8a961 Dominik Poch
    /**
230
     * Default implementation of addOccurrence method.
231
     * @param tag The tag with new occurrence.
232
     */
233 4bc99591 Lukáš Vlček
    const addOccurrence = async (tag: Tag) => {
234
        await markSelectedText(tag.tagId, tag.subtagId ?? null, tag.instanceId);
235 acb8a961 Dominik Poch
    };
236
237
    /**
238
     * Deletes an occurrence of an annotation.
239
     * @param occurrence Occurrence that should be deleted.
240
     */
241 9fdb7d55 Lukáš Vlček
    const deleteOccurrence = async (occurrence: TagInstanceInfo) => {
242
        if (!occurrence.occurenceId) {
243
            console.log('invalid occurrence');
244
            return;
245
        }
246
247 dee53692 Jaroslav Hrubý
        ShowConfirmDelete(() => {
248
            annotationController
249
                .annotationAnnotationIdOccurenceIdDelete(
250
                    props.annotationId,
251
                    occurrence.occurenceId ?? ''
252
                )
253
                .then(() => refreshAnnotation());
254
        }, 'značku');
255 acb8a961 Dominik Poch
    };
256
257
    /**
258
     * Changes a position of an occurrence of an annotation.
259
     * @param occurrence Occurrence whose position should be changed.
260
     * @param newValue New value of the position.
261
     */
262 9a41c02f Dominik Poch
    const changePosition = (occurrence: TagInstanceInfo, newValue: number) => {
263 acb8a961 Dominik Poch
        //TODO: Implement method (should use objects from server API)
264
    };
265
266
    /**
267
     * Changes a length of an occurrence of an annotation.
268
     * @param occurrence Occurrence whose length should be changed.
269
     * @param newValue New value of the length.
270
     */
271 9a41c02f Dominik Poch
    const changeLength = (occurrence: TagInstanceInfo, newValue: number) => {
272 acb8a961 Dominik Poch
        //TODO: Implement method (should use objects from server API)
273
    };
274
275 812ee966 Dominik Poch
    /**
276
     * Changes a note of an occurrence of an annotation.
277
     * @param occurrence Occurrence whose note should be changed.
278
     * @param newValue New value of the note.
279
     */
280
    const changeNote = async (occurrence: TagInstanceInfo, newValue: string) => {
281
        if (!occurrence.occurenceId) {
282
            console.log('invalid occurrence');
283
            return;
284
        }
285
286
        const postRes =
287
            await annotationController.annotationAnnotationIdTagOccurenceIdNotePost(
288
                props.annotationId,
289
                occurrence.occurenceId,
290
                { note: newValue }
291
            );
292
293 89154cb1 Dominik Poch
        occurrence.note = newValue;
294 812ee966 Dominik Poch
    };
295
296 bcbaa7d3 Dominik Poch
    /**
297
     * Changes sentiment of an annotation.
298
     * @param occurrence Occurrence whose sentiment should be changed.
299
     * @param newValue New value of the sentiment.
300
     */
301
    const changeSentiment = async (
302
        occurrence: TagInstanceInfo,
303
        newValue: ETagSentiment
304
    ) => {
305
        if (!occurrence.instance) {
306
            console.log('invalid instance');
307
            return;
308
        }
309
310
        const putRes =
311
            await annotationController.annotationAnnotationIdInstanceIdSentimentPut(
312
                props.annotationId,
313
                occurrence.instance,
314
                { sentiment: newValue }
315
            );
316
317 89154cb1 Dominik Poch
        occurrence.sentiment = newValue;
318 bcbaa7d3 Dominik Poch
    };
319
320 9a41c02f Dominik Poch
    const remapAnnotations = (data: AnnotationInfo) => {
321 4bc99591 Lukáš Vlček
        let map = new Map<string, Tag>();
322 9a41c02f Dominik Poch
        data.tagInstances?.forEach((tagInstance) => {
323 4bc99591 Lukáš Vlček
            if (map.has(tagInstance.instance ?? '-')) {
324
                let tag = map.get(tagInstance.instance ?? '-');
325 9a41c02f Dominik Poch
                tag!.occurrences = [...tag!.occurrences, tagInstance];
326
            } else {
327 4bc99591 Lukáš Vlček
                map.set(tagInstance.instance ?? '-', {
328
                    tagName: tagInstance.tagName ?? '',
329
                    subtagName: tagInstance.subTagName ?? null,
330 9a41c02f Dominik Poch
                    category: tagInstance.tagCategoryName ?? '',
331
                    occurrences: [tagInstance],
332 4bc99591 Lukáš Vlček
                    tagId: tagInstance.tagId ?? '',
333
                    instanceId: tagInstance.instance ?? '',
334
                    subtagId: tagInstance.subTagId ?? null,
335 9a41c02f Dominik Poch
                });
336
            }
337
        });
338
339
        setMappedTags(Array.from(map.values()));
340
    };
341
342 7652cf88 Lukáš Vlček
    async function refreshAnnotation() {
343
        const data = await annotationController.annotationAnnotationIdGet(
344
            props.annotationId
345
        );
346
347 9a41c02f Dominik Poch
        remapAnnotations(data.data);
348 7652cf88 Lukáš Vlček
        setAnnotation(data.data ?? null);
349 dee53692 Jaroslav Hrubý
        setSubmitting(false);
350 7652cf88 Lukáš Vlček
    }
351
352 acb8a961 Dominik Poch
    /**
353
     * Initializes the context.
354
     */
355 c057279b Lukáš Vlček
    useEffect(() => {
356 7652cf88 Lukáš Vlček
        refreshAnnotation();
357 7595035c Lukáš Vlček
    }, [props.annotationId]);
358 c057279b Lukáš Vlček
359
    return (
360
        <AnnotationContext.Provider
361
            value={{
362
                tags,
363 dee53692 Jaroslav Hrubý
                submitting,
364 c057279b Lukáš Vlček
                setTags,
365
                addOccurrence,
366
                deleteOccurrence,
367
                changeLength,
368
                changePosition,
369 812ee966 Dominik Poch
                changeNote,
370 bcbaa7d3 Dominik Poch
                changeSentiment,
371 7652cf88 Lukáš Vlček
                refreshAnnotation,
372
                annotation,
373 9a41c02f Dominik Poch
                mappedTags,
374 4bc99591 Lukáš Vlček
                markSelectedText,
375 c057279b Lukáš Vlček
            }}
376
        >
377
            {props.children}
378
        </AnnotationContext.Provider>
379
    );
380
};
381
382
export default AnnotationProvider;