Projekt

Obecné

Profil

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