preview.page.ts 7.79 KB
Newer Older
1
/* tslint:disable:no-string-literal */
2
3
4
import {AnnisResponse} from 'src/app/models/annisResponse';
import {ExerciseType, FileType} from 'src/app/models/enum';
import {HelperService} from 'src/app/helper.service';
5
import {NavController, ToastController} from '@ionic/angular';
6
7
import {ExerciseService} from 'src/app/exercise.service';
import {CorpusService} from 'src/app/corpus.service';
8
import {Component, OnDestroy, OnInit} from '@angular/core';
9
10
import {TranslateService} from '@ngx-translate/core';
import {Solution} from 'src/app/models/solution';
11
12
13
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import {XAPIevent} from 'src/app/models/xAPIevent';
import {TestResultMC} from 'src/app/models/testResultMC';
14
15
16
17
18
19
20
21

declare var H5P: any;

@Component({
    selector: 'app-preview',
    templateUrl: './preview.page.html',
    styleUrls: ['./preview.page.scss'],
})
22
export class PreviewPage implements OnDestroy, OnInit {
23
24
25
26
27
    HelperService = HelperService;
    public ExerciseType = ExerciseType;
    public FileType = FileType;
    public currentSolutions: Solution[];
    public maxGapLength = 0;
28
    public shareLink: string;
29
30
    public showInstructions = false;
    public solutionIndicesString: string;
31
    public solutionNodeIdSet: Set<string> = new Set<string>();
32
    public textareaSelector = '#shareLink';
33
    public urlBase: string;
34
35
36
37
38

    constructor(public navCtrl: NavController,
                public http: HttpClient,
                public exerciseService: ExerciseService,
                public translateService: TranslateService,
39
                public corpusService: CorpusService,
40
41
                public helperService: HelperService,
                public toastCtrl: ToastController) {
42
43
44
45
        this.currentSolutions = [];
        if (!HelperService.isVocabularyCheck) {
            this.exerciseService.excludeOOV = false;
        }
46
47
48
49
        HelperService.waitForConfig().then(() => {
            this.corpusService.checkAnnisResponse().then(() => {
                this.processAnnisResponse(this.corpusService.annisResponse);
                this.initH5P();
50
            }, () => {
51
            });
52
        });
53
54
    }

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    async copyLink(): Promise<void> {
        const ta: HTMLTextAreaElement = document.querySelector(this.textareaSelector);
        ta.select();
        document.execCommand('copy');
        ta.setSelectionRange(0, 0);
        const toast = await this.toastCtrl.create({
            message: this.corpusService.shareLinkCopiedString,
            duration: 3000,
            position: 'middle'
        });
        toast.present().then();
    }

    initH5P(): void {
        const solutionIndicesString: string = this.exerciseService.excludeOOV ? '&solution_indices=' +
            JSON.stringify(this.currentSolutions.map(x => this.corpusService.annisResponse.solutions.indexOf(x))) : '';
        // this will be called via GET request from the h5p standalone javascript library
        const url: string = `${HelperService.config['backendBaseUrl'] + HelperService.config['backendApiH5pPath']}` +
            `?eid=${this.corpusService.annisResponse.exercise_id}&lang=${this.translateService.currentLang + solutionIndicesString}`;
        window.localStorage.setItem(HelperService.config['localStorageKeyH5P'], url);
        const exerciseTypePath: string = this.corpusService.exercise.type === ExerciseType.markWords ? 'mark_words' : 'drag_text';
        this.exerciseService.initH5P(exerciseTypePath);
77
        this.updateFileUrl();
78
79
    }

80
81
82
83
    ngOnDestroy(): void {
        H5P.externalDispatcher.off('xAPI');
    }

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    ngOnInit(): void {
        H5P.externalDispatcher.on('xAPI', (event: XAPIevent) => {
            // results are only available when a task has been completed/answered, not in the "attempted" or "interacted" stages
            if (event.data.statement.verb.id === HelperService.config['xAPIverbIDanswered'] && event.data.statement.result) {
                const iframe: HTMLIFrameElement = document.querySelector(this.exerciseService.h5pIframeString);
                if (iframe) {
                    const iframeDoc: Document = iframe.contentWindow.document;
                    const inner: string = iframeDoc.documentElement.innerHTML;
                    const result: TestResultMC = new TestResultMC({
                        statement: event.data.statement,
                        innerHTML: inner
                    });
                    this.sendData(result);
                }
            }
        });
    }

102
    processAnnisResponse(ar: AnnisResponse): void {
103
        this.corpusService.annisResponse.solutions = ar.solutions;
104
        this.processSolutions(ar.solutions);
105
        this.corpusService.annisResponse.uri = ar.uri;
106
        const isUrn: boolean = this.corpusService.currentUrn && this.corpusService.currentUrn.startsWith('urn:');
107
108
        this.corpusService.annisResponse.nodes = isUrn ? this.corpusService.annisResponse.nodes : ar.nodes;
        this.corpusService.annisResponse.links = isUrn ? this.corpusService.annisResponse.links : ar.links;
109
110
    }

111
    processSolutions(solutions: Solution[]): void {
112
        const isCloze: boolean = this.corpusService.exercise.type === ExerciseType.cloze;
113
        if (this.exerciseService.excludeOOV) {
114
            const nodeIdSet: Set<string> = new Set(this.corpusService.annisResponse.nodes.filter(
115
                x => !x.is_oov).map(x => x.id));
116
            solutions = this.corpusService.annisResponse.solutions.filter(
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
                x => nodeIdSet.has(x.target.salt_id) && (isCloze || nodeIdSet.has(x.value.salt_id)));
        }
        let newSolutions: Solution[] = [];
        if (isCloze) {
            this.maxGapLength = Math.max.apply(Math, solutions.map(x => x.target.content.length));
            this.solutionNodeIdSet = new Set(solutions.map(x => x.target.salt_id));
            newSolutions = solutions.concat();
        } else {
            newSolutions = solutions.concat().sort((s1, s2) => {
                return s1.target.content < s2.target.content ? -1 : (s1.target.content > s2.target.content ? 1 : 0);
            });
        }
        this.currentSolutions = newSolutions;
    }

132
133
134
135
136
137
    selectLink(): void {
        const ta: HTMLTextAreaElement = document.querySelector(this.textareaSelector);
        ta.select();
    }

    sendData(result: TestResultMC): void {
138
139
140
141
142
143
144
145
146
147
148
149
150
151
        const fileUrl: string = HelperService.config['backendBaseUrl'] + HelperService.config['backendApiFilePath'];
        HelperService.currentError = null;
        HelperService.isLoading = true;
        const formData = new FormData();
        formData.append('learning_result', JSON.stringify(result.statement));
        this.http.post(fileUrl, formData).subscribe(async () => {
            HelperService.isLoading = false;
        }, async (error: HttpErrorResponse) => {
            HelperService.isLoading = false;
            HelperService.currentError = error;
            console.log('ERROR: COULD NOT SEND EXERCISE RESULTS TO SERVER.');
        });
    }

152
    switchOOV(): void {
153
        this.currentSolutions = [];
154
        this.processSolutions(this.corpusService.annisResponse.solutions);
155
156
157
        this.initH5P();
    }

158
159
160
161
162
163
164
165
166
167
    toggleShareLink(): void {
        if (this.shareLink) {
            this.shareLink = '';
        } else {
            this.shareLink = `${HelperService.baseUrl}/${HelperService.config['frontendExercisePage']}?eid=` +
                this.corpusService.annisResponse.exercise_id;
        }
    }

    updateFileUrl(): void {
168
169
170
        const fileId: string = this.corpusService.annisResponse.exercise_id;
        const fileTypeBase = '&type=';
        this.urlBase = HelperService.config['backendBaseUrl'] + HelperService.config['backendApiFilePath'] + '?id=' + fileId + fileTypeBase;
171
        this.solutionIndicesString = this.exerciseService.excludeOOV ? '&solution_indices=' +
172
            JSON.stringify(this.currentSolutions.map(x => this.corpusService.annisResponse.solutions.indexOf(x))) : '';
173
174
    }
}