Projekt

Obecné

Profil

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