Projekt

Obecné

Profil

Stáhnout (8.54 KB) Statistiky
| Větev: | Tag: | Revize:
1
import React, { createContext, useEffect, useState } from 'react';
2
import { AnnotationInfo, ETagType, SubTagInfo, TagInfo, TagInstanceInfo } from '../api';
3
import { Tag } from '../components/types/tag';
4
import { annotationController } from '../controllers';
5
import { GetSelectionInfo } from '../utils/selectionUtils';
6

    
7
/**
8
 * Interface of an annotation context provider.
9
 */
10
interface IAnnotationContextProvider {
11
    /**
12
     * Tags managed by the context.
13
     */
14
    tags: TagInstanceInfo[] | null;
15

    
16
    /**
17
     * Sets new tags.
18
     * @param newTags An array of new tags.
19
     */
20
    setTags: (newTags: TagInstanceInfo[] | null) => void;
21

    
22
    /**
23
     * Adds occurrence to an annotation.
24
     * @param tag Tag whose occurrence should be added.
25
     */
26
    addOccurrence: (tag: Tag) => void;
27

    
28
    /**
29
     * Changes visibility of an annotation.
30
     * @param tag Tag whose visibility should be changed.
31
     */
32
    changeVisibility: (tag: Tag) => void;
33

    
34
    /**
35
     * Deletes an occurrence of an annotation.
36
     * @param occurrence Occurrence that should be deleted.
37
     */
38
    deleteOccurrence: (occurrence: TagInstanceInfo) => void;
39

    
40
    /**
41
     * Changes a position of an occurrence of an annotation.
42
     * @param occurrence Occurrence whose position should be changed.
43
     * @param newValue New value of the position.
44
     */
45
    changePosition: (occurrence: TagInstanceInfo, newValue: number) => void;
46

    
47
    /**
48
     * Changes a length of an occurrence of an annotation.
49
     * @param occurrence Occurrence whose length should be changed.
50
     * @param newValue New value of the length.
51
     */
52
    changeLength: (occurrence: TagInstanceInfo, newValue: number) => void;
53

    
54
    annotation: AnnotationInfo | null;
55
    mappedTags: Tag[] | null;
56
    refreshAnnotation: () => void;
57

    
58
    markSelectedText: (
59
        tagId: string,
60
        subtagId: string | null,
61
        instanceID: string | null
62
    ) => void;
63
}
64

    
65
/**
66
 * The annotation context that manages active annotations.
67
 */
68
export const AnnotationContext = createContext<IAnnotationContextProvider>({
69
    /**
70
     * Default tags.
71
     */
72
    tags: null,
73

    
74
    /**
75
     * Default implementation of setTags method.
76
     * @param v Array of new tags.
77
     */
78
    setTags: (v) => {
79
        return;
80
    },
81

    
82
    /**
83
     * Default implementation of addOccurrence method.
84
     * @param tag The tag with new occurrence.
85
     */
86
    addOccurrence: (tag: Tag) => {
87
        return;
88
    },
89

    
90
    /**
91
     * Default implementation of changeVisibility method.
92
     * @param tag The tag whose visibility should be changed.
93
     */
94
    changeVisibility: (tag: Tag) => {
95
        return;
96
    },
97

    
98
    /**
99
     * Default implementation of deleteOccurrence method.
100
     * @param occurrence Occurrence that should be deleted.
101
     */
102
    deleteOccurrence: (occurrence: TagInstanceInfo) => {
103
        return;
104
    },
105

    
106
    /**
107
     * Default implementation of changePosition method.
108
     * @param occurrence Occurrence whose position should be changed.
109
     * @param newValue A new position.
110
     */
111
    changePosition: (occurrence: TagInstanceInfo, newValue: number) => {
112
        return;
113
    },
114

    
115
    /**
116
     * Default implementation of changeLength method.
117
     * @param occurrence Occurrence whose length should be changed.
118
     * @param newValue A new length.
119
     */
120
    changeLength: (occurrence: TagInstanceInfo, newValue: number) => {
121
        return;
122
    },
123

    
124
    annotation: null,
125
    mappedTags: null,
126
    refreshAnnotation: () => {
127
        return;
128
    },
129

    
130
    markSelectedText: () => {
131
        return;
132
    },
133
});
134

    
135
/**
136
 * Provider of the annotation context.
137
 * @param props Children that should have access to the annotation context.
138
 * @returns Prepared html of the provider.
139
 */
140
const AnnotationProvider = (props: {
141
    children: React.ReactNode;
142
    annotationId: string;
143
}) => {
144
    const [annotation, setAnnotation] = useState<AnnotationInfo | null>(null);
145

    
146
    /**
147
     * Tags managed by the context.
148
     */
149
    const [tags, setTags] = useState<TagInstanceInfo[] | null>(null);
150

    
151
    const [mappedTags, setMappedTags] = useState<Tag[] | null>(null);
152

    
153
    async function markSelectedText(
154
        tagId: string,
155
        subtagId: string | null,
156
        instanceId: string | null
157
    ) {
158
        if (!annotation) {
159
            console.log('annotation not found');
160
            return;
161
        }
162

    
163
        const selectionInfo = GetSelectionInfo(annotation);
164
        if (!selectionInfo) {
165
            console.log(
166
                'not able to continue, selection processing not completed successfully'
167
            );
168
            return;
169
        }
170

    
171
        const id = subtagId ?? tagId;
172
        const type: ETagType = subtagId == null ? ETagType.Tag : ETagType.Subtag;
173

    
174
        const res = await annotationController.annotationAnnotationIdPost(
175
            props.annotationId,
176
            {
177
                id: id,
178
                instanceId,
179
                type,
180
                position: selectionInfo.startPositionOriginalDocument,
181
                length: selectionInfo.selectionLengthOriginalDocument,
182
            }
183
        );
184

    
185
        await refreshAnnotation();
186
    }
187

    
188
    /**
189
     * Default implementation of addOccurrence method.
190
     * @param tag The tag with new occurrence.
191
     */
192
    const addOccurrence = async (tag: Tag) => {
193
        await markSelectedText(tag.tagId, tag.subtagId ?? null, tag.instanceId);
194
    };
195

    
196
    /**
197
     * Changes visibility of an annotation.
198
     * @param tag Tag whose visibility should be changed.
199
     */
200
    const changeVisibility = (tag: Tag) => {
201
        //TODO: Implement method (should use objects from server API)
202
    };
203

    
204
    /**
205
     * Deletes an occurrence of an annotation.
206
     * @param occurrence Occurrence that should be deleted.
207
     */
208
    const deleteOccurrence = async (occurrence: TagInstanceInfo) => {
209
        if (!occurrence.occurenceId) {
210
            console.log('invalid occurrence');
211
            return;
212
        }
213

    
214
        const deleteRes =
215
            await annotationController.annotationAnnotationIdOccurenceIdDelete(
216
                props.annotationId,
217
                occurrence.occurenceId
218
            );
219

    
220
        await refreshAnnotation();
221
    };
222

    
223
    /**
224
     * Changes a position of an occurrence of an annotation.
225
     * @param occurrence Occurrence whose position should be changed.
226
     * @param newValue New value of the position.
227
     */
228
    const changePosition = (occurrence: TagInstanceInfo, newValue: number) => {
229
        //TODO: Implement method (should use objects from server API)
230
    };
231

    
232
    /**
233
     * Changes a length of an occurrence of an annotation.
234
     * @param occurrence Occurrence whose length should be changed.
235
     * @param newValue New value of the length.
236
     */
237
    const changeLength = (occurrence: TagInstanceInfo, newValue: number) => {
238
        //TODO: Implement method (should use objects from server API)
239
    };
240

    
241
    const remapAnnotations = (data: AnnotationInfo) => {
242
        let map = new Map<string, Tag>();
243
        data.tagInstances?.forEach((tagInstance) => {
244
            if (map.has(tagInstance.instance ?? '-')) {
245
                let tag = map.get(tagInstance.instance ?? '-');
246
                tag!.occurrences = [...tag!.occurrences, tagInstance];
247
            } else {
248
                map.set(tagInstance.instance ?? '-', {
249
                    tagName: tagInstance.tagName ?? '',
250
                    subtagName: tagInstance.subTagName ?? null,
251
                    category: tagInstance.tagCategoryName ?? '',
252
                    visible: true,
253
                    occurrences: [tagInstance],
254
                    tagId: tagInstance.tagId ?? '',
255
                    instanceId: tagInstance.instance ?? '',
256
                    subtagId: tagInstance.subTagId ?? null,
257
                });
258
            }
259
        });
260

    
261
        setMappedTags(Array.from(map.values()));
262
    };
263

    
264
    async function refreshAnnotation() {
265
        const data = await annotationController.annotationAnnotationIdGet(
266
            props.annotationId
267
        );
268

    
269
        remapAnnotations(data.data);
270
        setAnnotation(data.data ?? null);
271
    }
272

    
273
    /**
274
     * Initializes the context.
275
     */
276
    useEffect(() => {
277
        refreshAnnotation();
278
    }, [props.annotationId]);
279

    
280
    return (
281
        <AnnotationContext.Provider
282
            value={{
283
                tags,
284
                setTags,
285
                addOccurrence,
286
                changeVisibility,
287
                deleteOccurrence,
288
                changeLength,
289
                changePosition,
290
                refreshAnnotation,
291
                annotation,
292
                mappedTags,
293
                markSelectedText,
294
            }}
295
        >
296
            {props.children}
297
        </AnnotationContext.Provider>
298
    );
299
};
300

    
301
export default AnnotationProvider;
(1-1/3)