/* tslint:disable:no-string-literal */ import {ApplicationState} from 'src/app/models/applicationState'; import {NavController, ToastController} from '@ionic/angular'; import {TextRange} from 'src/app/models/textRange'; import {Citation} from 'src/app/models/citation'; import {HttpErrorResponse} from '@angular/common/http'; import {Component} from '@angular/core'; import {CitationLevel} from 'src/app/models/enum'; import {TranslateService} from '@ngx-translate/core'; import {HelperService} from '../helper.service'; import {CorpusService} from 'src/app/corpus.service'; @Component({ selector: 'app-text-range', templateUrl: './text-range.page.html', styleUrls: ['./text-range.page.scss'], }) export class TextRangePage { public citationsUnavailableString: string; // TODO: rebuild the system so it works for any corpus of arbitrary citation depth public CitationLevel = CitationLevel; public invalidTextRangeString: string; ObjectKeys = Object.keys; public currentlyAvailableCitations: string[] = []; public currentInputId = 0; public citationValuesStart: number[]; public citationValuesEnd: number[]; public isTextRangeCheckRunning = false; HelperService = HelperService; constructor(public navCtrl: NavController, public corpusService: CorpusService, public toastCtrl: ToastController, public translateService: TranslateService, public helperService: HelperService) { this.currentlyAvailableCitations = []; this.corpusService.isTextRangeCorrect = false; this.corpusService.currentTextRange = new TextRange({start: ['', '', ''], end: ['', '', '']}); if (Object.keys(this.corpusService.currentCorpus.citations).length === 0) { this.addReferences(this.corpusService.currentCorpus.citation_level_1).then(() => { this.initPage(); }, () => { }); } else { this.initPage(); } this.translateService.get('INVALID_TEXT_RANGE').subscribe(value => this.invalidTextRangeString = value); this.translateService.get('ERROR_CITATIONS_UNAVAILABLE').subscribe(value => this.citationsUnavailableString = value); } private addMissingCitations(citationLabelsStart: string[], citationLabelsEnd: string[]) { return new Promise((resolve, reject) => { this.mapCitationLabelsToValues(citationLabelsStart[0], 0, citationLabelsStart, this.citationValuesStart).then(() => { this.mapCitationLabelsToValues(citationLabelsEnd[0], 0, citationLabelsEnd, this.citationValuesEnd).then(() => { if (citationLabelsStart.length > 1) { const cls1: string = citationLabelsStart[1]; this.mapCitationLabelsToValues(cls1, 1, citationLabelsStart, this.citationValuesStart).then(() => { this.mapCitationLabelsToValues(citationLabelsEnd[1], 1, citationLabelsEnd, this.citationValuesEnd).then(() => { if (citationLabelsStart.length > 2) { const cls2: string = citationLabelsStart[2]; this.mapCitationLabelsToValues(cls2, 2, citationLabelsStart, this.citationValuesStart).then(() => { const cle2: string = citationLabelsEnd[2]; this.mapCitationLabelsToValues(cle2, 2, citationLabelsEnd, this.citationValuesEnd).then(() => { resolve(); }); }); } else { resolve(); } }); }, () => reject()); } else { resolve(); } }); }, () => reject()); }); } private addReferences(targetCitationLevel: string, relevantCitations: Citation[] = []) { return new Promise((resolve, reject) => { if (relevantCitations.some(x => !x)) { resolve(); } const urnLastPart: string = relevantCitations.map(x => x.isNumeric ? x.value.toString() : x.label).join('.'); const fullUrn: string = this.corpusService.currentCorpus.source_urn + (urnLastPart ? ':' + urnLastPart : ''); HelperService.currentError = null; HelperService.isLoading = true; this.corpusService.getCTSvalidReff(fullUrn).subscribe((result: string[]) => { HelperService.isLoading = false; const newCitations: Citation[] = []; const urnList: string[] = result as string[]; const replaceString: string = fullUrn + (urnLastPart ? '.' : ':'); urnList.forEach((urn) => { const urnModified: string = urn.replace(replaceString, ''); const isNumeric: boolean = !isNaN(+urnModified); newCitations.push(new Citation({ isNumeric, level: targetCitationLevel, label: urnModified, value: (isNumeric ? newCitations.length + 1 : +urnModified) })); }); newCitations.forEach((citation) => { citation.subcitations = {}; if (relevantCitations.length === 0) { this.corpusService.currentCorpus.citations[citation.label] = citation; this.currentlyAvailableCitations.push(citation.label); } else if (relevantCitations.length === 1) { this.corpusService.currentCorpus.citations[relevantCitations[0].label].subcitations[citation.label] = citation; const firstLabel: string = this.corpusService.currentCorpus.citations[relevantCitations[0].label].label; this.currentlyAvailableCitations.push(firstLabel.concat('.', citation.label)); } else if (relevantCitations.length === 2) { const rc0Label: string = relevantCitations[0].label; const rc1Label: string = relevantCitations[1].label; this.corpusService.currentCorpus.citations[rc0Label].subcitations[rc1Label].subcitations[citation.label] = citation; const firstLabel: string = this.corpusService.currentCorpus.citations[rc0Label].label; const secondLabel: string = this.corpusService.currentCorpus.citations[rc0Label].subcitations[rc1Label].label; this.currentlyAvailableCitations.push(firstLabel.concat('.', secondLabel, '.', citation.label)); } resolve(); }); }, async (error: HttpErrorResponse) => { HelperService.isLoading = false; HelperService.currentError = error; const toast = await this.toastCtrl.create({ message: this.citationsUnavailableString, duration: 3000, position: 'top' }); toast.present().then(); reject(); }); }); } applyAutoComplete(isStart: boolean) { this.showFurtherReferences(isStart).then(() => { const newId: string = 'input' + (this.currentInputId + 1).toString(); this.currentInputId = 0; const newEl: HTMLInputElement = document.getElementById(newId) as HTMLInputElement; if (newEl) { // adjust disabled state manually because the focus won't work otherwise and the automatic check comes too late newEl.disabled = false; newEl.focus(); } }); } checkTextRange(citationLabelsStart: string[], citationLabelsEnd: string[]) { return new Promise(resolve => { citationLabelsStart = citationLabelsStart.filter(x => x); citationLabelsEnd = citationLabelsEnd.filter(x => x); if (this.corpusService.currentCorpus.citation_level_2 === CitationLevel[CitationLevel.default]) { if (citationLabelsStart.length !== 1 || citationLabelsEnd.length !== 1) { resolve(false); return; } } else { if (citationLabelsStart.length < 2 || citationLabelsEnd.length < 2) { resolve(false); return; } else { if (this.corpusService.currentCorpus.citation_level_3 === CitationLevel[CitationLevel.default]) { if (citationLabelsStart.length !== 2 || citationLabelsEnd.length !== 2) { resolve(false); return; } } else if (citationLabelsStart.length !== 3 || citationLabelsEnd.length !== 3) { resolve(false); return; } } } this.citationValuesEnd = []; this.citationValuesStart = []; this.addMissingCitations(citationLabelsStart, citationLabelsEnd).then(() => { this.compareCitationValues().then((result: boolean) => resolve(result)); }, () => { // if the citation system does not work, we allow the user to choose the correct citations on his own resolve(true); }); }); } compareCitationValues(): Promise { return new Promise((resolve) => { const citationValuesStart: number[] = this.citationValuesStart; const citationValuesEnd: number[] = this.citationValuesEnd; if (citationValuesStart[0] < citationValuesEnd[0]) { resolve(true); } else if (citationValuesStart.concat(citationValuesEnd).some(x => isNaN(x))) { // there are non-numeric citation values involved, so we cannot easily compare them resolve(true); } else if (citationValuesStart[0] === citationValuesEnd[0]) { if (citationValuesStart.length > 1) { if (citationValuesStart[1] < citationValuesEnd[1]) { resolve(true); } else if (this.citationValuesStart[1] === citationValuesEnd[1]) { if (citationValuesStart.length > 2) { resolve(citationValuesStart[2] <= citationValuesEnd[2]); } else { resolve(true); } } else { resolve(false); } } else { resolve(true); } } else { resolve(false); } }); } private initPage() { if (this.corpusService.currentCorpus.citation_level_2 === CitationLevel[CitationLevel.default]) { const firstKey: string = Object.keys(this.corpusService.currentCorpus.citations)[0]; const randomLabel: string = this.corpusService.currentCorpus.citations[firstKey].label; this.corpusService.currentTextRange.start[0] = this.corpusService.currentTextRange.end[0] = randomLabel; } } isInputDisabled(isStart: boolean) { const baseCits: { [label: string]: Citation } = this.corpusService.currentCorpus.citations; const ctrPart: string[] = isStart ? this.corpusService.currentTextRange.start : this.corpusService.currentTextRange.end; if (!baseCits.hasOwnProperty(ctrPart[0])) { return true; } return !baseCits[ctrPart[0]].subcitations.hasOwnProperty(ctrPart[1]); } public mapCitationLabelsToValues(label: string, index: number, citationLabels: string[], valueList: number[]) { return new Promise((resolve, reject) => { if (index === 0 && this.corpusService.currentCorpus.citations[label]) { valueList.push(this.corpusService.currentCorpus.citations[label].value); resolve(); } else if (index === 1) { if (!this.corpusService.currentCorpus.citations[citationLabels[index - 1]]) { if (!!+label) { valueList.push(+label); resolve(); } else { reject(); } } if (Object.keys(this.corpusService.currentCorpus.citations[citationLabels[index - 1]].subcitations).length === 0) { const relevantCitations: Citation[] = [this.corpusService.currentCorpus.citations[citationLabels[index - 1]]]; this.addReferences(this.corpusService.currentCorpus.citation_level_2, relevantCitations).then(() => { valueList.push(this.corpusService.currentCorpus.citations[citationLabels[index - 1]].subcitations[label].value); resolve(); }, () => reject()); } else { valueList.push(this.corpusService.currentCorpus.citations[citationLabels[index - 1]].subcitations[label].value); resolve(); } } else if (index === 2) { if (!this.corpusService.currentCorpus.citations[citationLabels[index - 2]] || !this.corpusService.currentCorpus.citations[citationLabels[index - 2]].subcitations[citationLabels[index - 1]]) { if (!!+label) { valueList.push(+label); resolve(); } else { reject(); } } const citation: Citation = this.corpusService.currentCorpus.citations[citationLabels[index - 2]]; const subCitation: Citation = citation.subcitations[citationLabels[index - 1]]; if (Object.keys(subCitation.subcitations).length === 0) { this.addReferences(this.corpusService.currentCorpus.citation_level_3, [citation, subCitation]).then(() => { valueList.push(subCitation.subcitations[label].value); resolve(); }, () => reject()); } else { valueList.push(subCitation.subcitations[label].value); resolve(); } } else if (!!+label) { valueList.push(+label); resolve(); } }); } resetCitations() { switch (this.currentInputId) { case 1: if (this.corpusService.currentCorpus.citation_level_2 !== CitationLevel[CitationLevel.default]) { this.corpusService.currentTextRange.start[1] = ''; this.corpusService.currentTextRange.start[2] = ''; } break; case 2: if (this.corpusService.currentCorpus.citation_level_3 !== CitationLevel[CitationLevel.default]) { this.corpusService.currentTextRange.start[2] = ''; } break; case 4: if (this.corpusService.currentCorpus.citation_level_2 !== CitationLevel[CitationLevel.default]) { this.corpusService.currentTextRange.end[1] = ''; this.corpusService.currentTextRange.end[2] = ''; } break; case 5: if (this.corpusService.currentCorpus.citation_level_3 !== CitationLevel[CitationLevel.default]) { this.corpusService.currentTextRange.end[2] = ''; } break; default: break; } } resetCurrentInputId() { const oldId: number = this.currentInputId; // dirty hack to prevent the blur event from triggering before the click event setTimeout(() => { if (oldId === this.currentInputId) { this.currentInputId = 0; } }, 50); } async showFurtherReferences(isStart: boolean) { const relTextRangePart: string[] = isStart ? this.corpusService.currentTextRange.start : this.corpusService.currentTextRange.end; if (!relTextRangePart[0]) { return; } this.resetCitations(); return new Promise(resolve => { const baseCit: Citation = this.corpusService.currentCorpus.citations[relTextRangePart[0]]; if (baseCit && (Object.keys(baseCit.subcitations).length || this.corpusService.currentCorpus.citation_level_2 === CitationLevel[CitationLevel.default])) { resolve(); } else { this.addReferences(this.corpusService.currentCorpus.citation_level_2, [baseCit]).then(() => { resolve(); }); } }).then(() => { if ([2, 3, 5, 6].indexOf(this.currentInputId) > -1) { const baseCit: Citation = this.corpusService.currentCorpus.citations[relTextRangePart[0]]; const relCit: Citation = baseCit.subcitations[relTextRangePart[1]]; const hasLvl3: boolean = this.corpusService.currentCorpus.citation_level_3 !== CitationLevel[CitationLevel.default]; if (relTextRangePart[1] && !(relCit && Object.keys(relCit.subcitations).length) && hasLvl3) { this.addReferences(this.corpusService.currentCorpus.citation_level_3, [baseCit, relCit]).then(); } } }); } showText() { if (this.isTextRangeCheckRunning) { return; } const citationLabelsStart: string[] = this.corpusService.currentTextRange.start; const citationLabelsEnd: string[] = this.corpusService.currentTextRange.end; this.isTextRangeCheckRunning = true; this.checkTextRange(citationLabelsStart, citationLabelsEnd).then(async (isTextRangeCorrect: boolean) => { this.isTextRangeCheckRunning = false; if (!isTextRangeCorrect) { const toast = await this.toastCtrl.create({ message: this.invalidTextRangeString, duration: 3000, position: 'top' }); toast.present().then(); return; } const newUrnBase: string = this.corpusService.currentCorpus.source_urn + ':'; if (this.citationValuesStart.concat(this.citationValuesEnd).some(x => isNaN(x))) { this.corpusService.currentUrn = newUrnBase + this.corpusService.currentTextRange.start.filter(x => x).join('.') + '-' + this.corpusService.currentTextRange.end.filter(x => x).join('.'); } else { this.corpusService.currentUrn = newUrnBase + this.citationValuesStart.join('.') + '-' + this.citationValuesEnd.join('.'); } HelperService.mostRecentSetup = new ApplicationState({ currentUrn: this.corpusService.currentUrn, currentCorpus: this.corpusService.currentCorpus, currentTextRange: this.corpusService.currentTextRange }); this.helperService.saveMostRecentSetup().then(() => { this.corpusService.isTextRangeCorrect = true; this.corpusService.getText().then(() => { if (HelperService.isVocabularyCheck) { HelperService.goToVocabularyCheckPage(this.navCtrl); } else { HelperService.goToShowTextPage(this.navCtrl); } }, () => { }); }); }); } }