Projekt

Obecné

Profil

Stáhnout (9.03 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, userController } from '../controllers';
5
import { GetSelectionInfo } from '../utils/selectionUtils';
6
import { ShowConfirmDelete, ShowToast } from '../utils/alerts';
7

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

    
17
    /**
18
     * Submitting boolean
19
     */
20
    submitting: boolean;
21

    
22
    /**
23
     * Sets new tags.
24
     * @param newTags An array of new tags.
25
     */
26
    setTags: (newTags: TagInstanceInfo[] | null) => void;
27

    
28
    /**
29
     * Adds occurrence to an annotation.
30
     * @param tag Tag whose occurrence should be added.
31
     */
32
    addOccurrence: (tag: Tag) => void;
33

    
34
    /**
35
     * Changes visibility of an annotation.
36
     * @param tag Tag whose visibility should be changed.
37
     */
38
    changeVisibility: (tag: Tag) => void;
39

    
40
    /**
41
     * Deletes an occurrence of an annotation.
42
     * @param occurrence Occurrence that should be deleted.
43
     */
44
    deleteOccurrence: (occurrence: TagInstanceInfo) => void;
45

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

    
53
    /**
54
     * Changes a length of an occurrence of an annotation.
55
     * @param occurrence Occurrence whose length should be changed.
56
     * @param newValue New value of the length.
57
     */
58
    changeLength: (occurrence: TagInstanceInfo, newValue: number) => void;
59

    
60
    annotation: AnnotationInfo | null;
61
    mappedTags: Tag[] | null;
62
    refreshAnnotation: () => void;
63

    
64
    markSelectedText: (
65
        tagId: string,
66
        subtagId: string | null,
67
        instanceID: string | null
68
    ) => void;
69
}
70

    
71
/**
72
 * The annotation context that manages active annotations.
73
 */
74
export const AnnotationContext = createContext<IAnnotationContextProvider>({
75
    /**
76
     * Default tags.
77
     */
78
    tags: null,
79

    
80
    /**
81
     * Submitting boolean
82
     */
83
    submitting: false,
84

    
85
    /**
86
     * Default implementation of setTags method.
87
     * @param v Array of new tags.
88
     */
89
    setTags: (v) => {
90
        return;
91
    },
92

    
93
    /**
94
     * Default implementation of addOccurrence method.
95
     * @param tag The tag with new occurrence.
96
     */
97
    addOccurrence: (tag: Tag) => {
98
        return;
99
    },
100

    
101
    /**
102
     * Default implementation of changeVisibility method.
103
     * @param tag The tag whose visibility should be changed.
104
     */
105
    changeVisibility: (tag: Tag) => {
106
        return;
107
    },
108

    
109
    /**
110
     * Default implementation of deleteOccurrence method.
111
     * @param occurrence Occurrence that should be deleted.
112
     */
113
    deleteOccurrence: (occurrence: TagInstanceInfo) => {
114
        return;
115
    },
116

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

    
126
    /**
127
     * Default implementation of changeLength method.
128
     * @param occurrence Occurrence whose length should be changed.
129
     * @param newValue A new length.
130
     */
131
    changeLength: (occurrence: TagInstanceInfo, newValue: number) => {
132
        return;
133
    },
134

    
135
    annotation: null,
136
    mappedTags: null,
137
    refreshAnnotation: () => {
138
        return;
139
    },
140

    
141
    markSelectedText: () => {
142
        return;
143
    },
144
});
145

    
146
/**
147
 * Provider of the annotation context.
148
 * @param props Children that should have access to the annotation context.
149
 * @returns Prepared html of the provider.
150
 */
151
const AnnotationProvider = (props: {
152
    children: React.ReactNode;
153
    annotationId: string;
154
}) => {
155
    const [annotation, setAnnotation] = useState<AnnotationInfo | null>(null);
156

    
157
    /**
158
     * Tags managed by the context.
159
     */
160
    const [tags, setTags] = useState<TagInstanceInfo[] | null>(null);
161

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

    
164
    const [submitting, setSubmitting] = useState(false);
165

    
166
    async function markSelectedText(
167
        tagId: string,
168
        subtagId: string | null,
169
        instanceId: string | null
170
    ) {
171
        setSubmitting(true);
172
        if (!annotation) {
173
            console.log('annotation not found');
174
            return;
175
        }
176

    
177
        const selectionInfo = GetSelectionInfo(annotation);
178
        if (!selectionInfo) {
179
            console.log(
180
                'not able to continue, selection processing not completed successfully'
181
            );
182
            return;
183
        }
184

    
185
        const id = subtagId ?? tagId;
186
        const type: ETagType = subtagId == null ? ETagType.Tag : ETagType.Subtag;
187
        const res = await annotationController
188
            .annotationAnnotationIdPost(props.annotationId, {
189
                id: id,
190
                instanceId,
191
                type,
192
                position: selectionInfo.startPositionOriginalDocument,
193
                length: selectionInfo.selectionLengthOriginalDocument,
194
            })
195
            .catch((e) => ShowToast('Tato značka je textu již přiřazena', 'warning'));
196

    
197
        await refreshAnnotation();
198
    }
199

    
200
    /**
201
     * Default implementation of addOccurrence method.
202
     * @param tag The tag with new occurrence.
203
     */
204
    const addOccurrence = async (tag: Tag) => {
205
        await markSelectedText(tag.tagId, tag.subtagId ?? null, tag.instanceId);
206
    };
207

    
208
    /**
209
     * Changes visibility of an annotation.
210
     * @param tag Tag whose visibility should be changed.
211
     */
212
    const changeVisibility = (tag: Tag) => {
213
        //TODO: Implement method (should use objects from server API)
214
    };
215

    
216
    /**
217
     * Deletes an occurrence of an annotation.
218
     * @param occurrence Occurrence that should be deleted.
219
     */
220
    const deleteOccurrence = async (occurrence: TagInstanceInfo) => {
221
        if (!occurrence.occurenceId) {
222
            console.log('invalid occurrence');
223
            return;
224
        }
225

    
226
        ShowConfirmDelete(() => {
227
            annotationController
228
                .annotationAnnotationIdOccurenceIdDelete(
229
                    props.annotationId,
230
                    occurrence.occurenceId ?? ''
231
                )
232
                .then(() => refreshAnnotation());
233
        }, 'značku');
234
    };
235

    
236
    /**
237
     * Changes a position of an occurrence of an annotation.
238
     * @param occurrence Occurrence whose position should be changed.
239
     * @param newValue New value of the position.
240
     */
241
    const changePosition = (occurrence: TagInstanceInfo, newValue: number) => {
242
        //TODO: Implement method (should use objects from server API)
243
    };
244

    
245
    /**
246
     * Changes a length of an occurrence of an annotation.
247
     * @param occurrence Occurrence whose length should be changed.
248
     * @param newValue New value of the length.
249
     */
250
    const changeLength = (occurrence: TagInstanceInfo, newValue: number) => {
251
        //TODO: Implement method (should use objects from server API)
252
    };
253

    
254
    const remapAnnotations = (data: AnnotationInfo) => {
255
        let map = new Map<string, Tag>();
256
        data.tagInstances?.forEach((tagInstance) => {
257
            if (map.has(tagInstance.instance ?? '-')) {
258
                let tag = map.get(tagInstance.instance ?? '-');
259
                tag!.occurrences = [...tag!.occurrences, tagInstance];
260
            } else {
261
                map.set(tagInstance.instance ?? '-', {
262
                    tagName: tagInstance.tagName ?? '',
263
                    subtagName: tagInstance.subTagName ?? null,
264
                    category: tagInstance.tagCategoryName ?? '',
265
                    visible: true,
266
                    occurrences: [tagInstance],
267
                    tagId: tagInstance.tagId ?? '',
268
                    instanceId: tagInstance.instance ?? '',
269
                    subtagId: tagInstance.subTagId ?? null,
270
                });
271
            }
272
        });
273

    
274
        setMappedTags(Array.from(map.values()));
275
    };
276

    
277
    async function refreshAnnotation() {
278
        const data = await annotationController.annotationAnnotationIdGet(
279
            props.annotationId
280
        );
281

    
282
        remapAnnotations(data.data);
283
        setAnnotation(data.data ?? null);
284
        setSubmitting(false);
285
    }
286

    
287
    /**
288
     * Initializes the context.
289
     */
290
    useEffect(() => {
291
        refreshAnnotation();
292
    }, [props.annotationId]);
293

    
294
    return (
295
        <AnnotationContext.Provider
296
            value={{
297
                tags,
298
                submitting,
299
                setTags,
300
                addOccurrence,
301
                changeVisibility,
302
                deleteOccurrence,
303
                changeLength,
304
                changePosition,
305
                refreshAnnotation,
306
                annotation,
307
                mappedTags,
308
                markSelectedText,
309
            }}
310
        >
311
            {props.children}
312
        </AnnotationContext.Provider>
313
    );
314
};
315

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