helper.service.ts 12.9 KB
Newer Older
1
/* tslint:disable:no-string-literal */
2
import {HttpClient, HttpErrorResponse, HttpParams} from '@angular/common/http';
3
import {Injectable} from '@angular/core';
4
import {NavController, ToastController} from '@ionic/angular';
5
import {ApplicationState} from 'src/app/models/applicationState';
6 7 8
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {CaseValue, DependencyValue, PartOfSpeechValue} from 'src/app/models/enum';
import {TranslateService} from '@ngx-translate/core';
9
import {Storage} from '@ionic/storage';
10
import {Language} from 'src/app/models/language';
11 12
import {ReplaySubject} from 'rxjs';
import {TextData} from './models/textData';
13
import {take} from 'rxjs/operators';
14 15 16 17 18 19

@Injectable({
    providedIn: 'root'
})
export class HelperService {

20 21
    public static applicationState: ReplaySubject<ApplicationState> = null;
    private static applicationStateCache: ApplicationState = null;
22 23
    public static baseUrl: string = location.protocol.concat('//').concat(window.location.host) +
        window.location.pathname.split('/').slice(0, -1).join('/');
24
    public static caseMap: { [rawValue: string]: CaseValue } = {
25 26 27 28 29 30 31
        Nom: CaseValue.nominative,
        Gen: CaseValue.genitive,
        Dat: CaseValue.dative,
        Acc: CaseValue.accusative,
        Abl: CaseValue.ablative,
        Voc: CaseValue.vocative,
        Loc: CaseValue.locative,
32
    };
33
    public static config: ReplaySubject<object>;
34
    public static corpusUpdateCompletedString: string;
35
    public static currentError: HttpErrorResponse;
36
    public static currentLanguage: Language;
37
    public static currentPopover: any;
38
    public static dependencyMap: { [rawValue: string]: DependencyValue } = {
39 40 41 42 43 44
        acl: DependencyValue.adjectivalClause,
        advcl: DependencyValue.adverbialClauseModifier,
        advmod: DependencyValue.adverbialModifier,
        amod: DependencyValue.adjectivalModifier,
        appos: DependencyValue.appositionalModifier,
        aux: DependencyValue.auxiliary,
45
        'aux:pass': DependencyValue.auxiliary,
46 47 48 49 50 51 52 53
        case: DependencyValue.caseMarking,
        cc: DependencyValue.coordinatingConjunction,
        ccomp: DependencyValue.clausalComplement,
        clf: DependencyValue.classifier,
        compound: DependencyValue.multiwordExpression,
        conj: DependencyValue.conjunct,
        cop: DependencyValue.copula,
        csubj: DependencyValue.subject,
54
        'csubj:pass': DependencyValue.subject,
55 56 57 58 59 60 61 62 63 64 65
        det: DependencyValue.determiner,
        discourse: DependencyValue.discourseElement,
        dislocated: DependencyValue.dislocated,
        expl: DependencyValue.expletive,
        fixed: DependencyValue.multiwordExpression,
        flat: DependencyValue.multiwordExpression,
        goeswith: DependencyValue.goesWith,
        iobj: DependencyValue.object,
        list: DependencyValue.list,
        mark: DependencyValue.marker,
        nmod: DependencyValue.nominalModifier,
66
        'nmod:poss': DependencyValue.nominalModifier,
67 68
        nummod: DependencyValue.numericModifier,
        nsubj: DependencyValue.subject,
69
        'nsubj:pass': DependencyValue.subject,
70 71 72 73 74 75 76 77
        obj: DependencyValue.object,
        obl: DependencyValue.oblique,
        orphan: DependencyValue.orphan,
        parataxis: DependencyValue.parataxis,
        punct: DependencyValue.punctuation,
        root: DependencyValue.root,
        vocative: DependencyValue.vocative,
        xcomp: DependencyValue.clausalComplement,
78
    };
79
    public static generalErrorAlertMessage: string;
80
    public static isIE11: boolean = !!(window as any).MSInputMethodContext && !!(document as any).documentMode;
81
    public static isLoading = false;
82
    public static isDevMode = ['localhost'].indexOf(window.location.hostname) > -1; // set this to "false" for simulated production mode
83
    public static isVocabularyCheck = false;
84 85 86 87
    public static languages: Language[] = [new Language({
        name: 'English',
        shortcut: 'en'
    }), new Language({name: 'Deutsch', shortcut: 'de'})];
88
    public static menuId = 'menu1';
89
    public static partOfSpeechMap: { [rawValue: string]: PartOfSpeechValue } = {
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
        ADJ: PartOfSpeechValue.adjective,
        ADP: PartOfSpeechValue.preposition,
        ADV: PartOfSpeechValue.adverb,
        AUX: PartOfSpeechValue.auxiliary,
        CCONJ: PartOfSpeechValue.conjunction,
        DET: PartOfSpeechValue.pronoun,
        INTJ: PartOfSpeechValue.interjection,
        NOUN: PartOfSpeechValue.noun,
        NUM: PartOfSpeechValue.numeral,
        PART: PartOfSpeechValue.particle,
        PRON: PartOfSpeechValue.pronoun,
        PROPN: PartOfSpeechValue.properNoun,
        PUNCT: PartOfSpeechValue.punctuation,
        SCONJ: PartOfSpeechValue.conjunction,
        SYM: PartOfSpeechValue.symbol,
        VERB: PartOfSpeechValue.verb,
        X: PartOfSpeechValue.other
107
    };
108

109 110
    constructor(public http: HttpClient,
                private storage: Storage,
111
                public translate: TranslateService,
112
    ) {
113
        this.initConfig();
114
        this.initLanguage();
115 116
    }

117
    // The translate loader needs to know where to load i18n files in Ionic's static asset pipeline.
118 119 120 121
    static createTranslateLoader(http: HttpClient) {
        return new TranslateHttpLoader(http, './assets/i18n/', '.json');
    }

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    static delayedTranslation(translate: TranslateService, key: string) {
        return new Promise(resolve => {
            translate.get(key).subscribe((value: string) => {
                // check if we got the correct translated value
                if (value === value.toUpperCase()) {
                    setTimeout(() => {
                        translate.get(key).subscribe(value2 => resolve(value2));
                    }, 1000);
                } else {
                    resolve(value);
                }
            });
        });
    }

137 138 139 140 141 142
    static getEnumValues(target: any): string[] {
        return Object.keys(target).filter((value, index, array) => {
            return index % 2 !== 0;
        });
    }

143 144 145
    static goToAuthorPage(navCtrl: NavController): Promise<boolean> {
        HelperService.isVocabularyCheck = false;
        return navCtrl.navigateForward('/author');
146 147
    }

148
    static goToAuthorDetailPage(navCtrl: NavController): Promise<boolean> {
149
        return navCtrl.navigateForward('/author-detail');
150 151 152 153 154 155 156 157 158 159 160 161 162 163
    }

    static goToDocExercisesPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/doc-exercises');
    }

    static goToDocSoftwarePage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/doc-software');
    }

    static goToDocVocUnitPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/doc-voc-unit');
    }

164 165
    static goToExerciseListPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/exercise-list');
166 167
    }

168 169
    static goToExerciseParametersPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('exercise-parameters');
170 171
    }

172 173
    static goToHomePage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateRoot('/home');
174 175
    }

176 177
    static goToImprintPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/imprint');
178 179
    }

180 181
    static goToInfoPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/info');
182 183
    }

184 185
    static goToPreviewPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('preview');
186 187
    }

188 189 190 191 192 193
    static goToShowTextPage(navCtrl: NavController, isVocabularyCheck: boolean = false): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            navCtrl.navigateForward('/show-text').then((result: boolean) => {
                HelperService.isVocabularyCheck = isVocabularyCheck;
                return resolve(result);
            });
Konstantin Schulz's avatar
Konstantin Schulz committed
194
        });
195 196
    }

197 198
    static goToSourcesPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/sources');
199 200
    }

201 202
    static goToTestPage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateRoot('/test');
203 204
    }

205 206
    static goToTextRangePage(navCtrl: NavController): Promise<boolean> {
        return navCtrl.navigateForward('/text-range');
207 208
    }

209 210 211 212 213 214
    static goToVocabularyCheckPage(navCtrl: NavController): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            navCtrl.navigateForward('/vocabulary-check').then((result: boolean) => {
                HelperService.isVocabularyCheck = true;
                return resolve(result);
            });
215
        });
216 217
    }

218 219 220 221 222 223 224 225 226 227
    static loadTranslations(translate: TranslateService) {
        // dirty hack to wait until the translation loader is initialized in IE11
        HelperService.delayedTranslation(translate, 'CORPUS_UPDATE_COMPLETED').then((value: string) => {
            HelperService.corpusUpdateCompletedString = value;
        });
        HelperService.delayedTranslation(translate, 'ERROR_GENERAL_ALERT').then((value: string) => {
            HelperService.generalErrorAlertMessage = value;
        });
    }

228
    static makeGetRequest(http: HttpClient, toastCtrl: ToastController, url: string, params: HttpParams): Promise<any> {
229
        HelperService.currentError = null;
230 231 232 233
        // dirty hack to avoid ExpressionChangedAfterItHasBeenCheckedError
        setTimeout(() => {
            HelperService.isLoading = true;
        }, 0);
234 235
        return new Promise(((resolve, reject) => {
            http.get(url, {params}).subscribe((result: any) => {
236 237 238 239
                // dirty hack to avoid ExpressionChangedAfterItHasBeenCheckedError
                setTimeout(() => {
                    HelperService.isLoading = false;
                }, 0);
240 241
                return resolve(result);
            }, async (error: HttpErrorResponse) => {
242 243 244 245
                // dirty hack to avoid ExpressionChangedAfterItHasBeenCheckedError
                setTimeout(() => {
                    HelperService.isLoading = false;
                }, 0);
246 247 248 249 250 251 252 253 254 255 256 257
                HelperService.currentError = error;
                const toast = await toastCtrl.create({
                    message: HelperService.generalErrorAlertMessage,
                    duration: 3000,
                    position: 'top'
                });
                toast.present().then();
                return reject(error);
            });
        }));
    }

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    /**
     * Shuffles array in place.
     * @param array items An array containing the items.
     */
    static shuffle(array: Array<any>) {
        let j, x, i;
        for (i = array.length - 1; i > 0; i--) {
            j = Math.floor(Math.random() * (i + 1));
            x = array[i];
            array[i] = array[j];
            array[j] = x;
        }
        return array;
    }

273 274 275
    initApplicationState(): void {
        HelperService.applicationState = new ReplaySubject<ApplicationState>(1);
        if (!HelperService.applicationStateCache) {
276 277 278 279 280 281 282 283 284 285
            HelperService.config.pipe(take(1)).subscribe((config: object) => {
                this.storage.get(config['localStorageKeyApplicationState']).then((jsonString: string) => {
                    HelperService.applicationStateCache = new ApplicationState({
                        currentSetup: new TextData()
                    });
                    if (jsonString) {
                        const parsedJson: object = JSON.parse(jsonString);
                        HelperService.applicationStateCache = parsedJson as ApplicationState;
                    }
                    HelperService.applicationState.next(HelperService.applicationStateCache);
286 287 288 289 290 291 292
                });
            });
        } else {
            HelperService.applicationState.next(HelperService.applicationStateCache);
        }
    }

293
    initConfig() {
294 295 296 297 298 299 300
        HelperService.config = new ReplaySubject<object>(1);
        this.http.get('assets/config.json').subscribe((config: object) => {
            if (!config['backendBaseUrl']) {
                const part1: string = location.protocol.concat('//').concat(window.location.host);
                config['backendBaseUrl'] = part1.concat(config['backendBaseApiPath']).concat('/');
            }
            HelperService.config.next(config);
301 302 303
        });
    }

304 305 306 307 308 309 310 311
    initLanguage(): void {
        // dirty hack to wait for the translateService intializing
        setTimeout(() => {
            HelperService.currentLanguage = HelperService.languages.find(x => x.shortcut === this.translate.currentLang);
            HelperService.loadTranslations(this.translate);
        });
    }

312
    saveApplicationState(mrs: ApplicationState) {
313
        return new Promise((resolve) => {
314 315
            HelperService.applicationStateCache = mrs;
            HelperService.applicationState.next(HelperService.applicationStateCache);
316 317 318 319
            HelperService.config.pipe(take(1)).subscribe((config: object) => {
                this.storage.set(config['localStorageKeyApplicationState'], JSON.stringify(mrs)).then(() => {
                    return resolve();
                });
320
            });
321 322 323
        });
    }
}