diff --git a/nietzsche-beta-app/src/app/content-view-tab-component/content-view-routes.ts b/nietzsche-beta-app/src/app/content-view-tab-component/content-view-routes.ts index db1c2d2..6feb92b 100644 --- a/nietzsche-beta-app/src/app/content-view-tab-component/content-view-routes.ts +++ b/nietzsche-beta-app/src/app/content-view-tab-component/content-view-routes.ts @@ -1,12 +1,14 @@ import { Routes } from '@angular/router'; import {ManuscriptViewComponentComponent} from "../manuscript-view-component/manuscript-view-component.component"; import {RhizomeViewComponentComponent} from "../rhizome-view-component/rhizome-view-component.component"; import {PageViewWrapperComponent} from "../page-view-wrapper-component/page-view-wrapper.component"; -import { TLN_CROSSREF_ROUTE, TLN_MANUSCRIPT_ROUTE, TLN_VIEWER_ROUTE } from '../tln-edition/constants'; +import { TLN_CROSSREF_ROUTE, TLN_MANUSCRIPT_ROUTE, TLN_SEARCH_ROUTE, TLN_VIEWER_ROUTE } from '../tln-edition/constants'; +import { TlnFulltextComponent } from '../tln-edition/tln-fulltext/tln-fulltext.component'; export const CONTENT_ROUTES: Routes = [ { path: TLN_MANUSCRIPT_ROUTE, component: ManuscriptViewComponentComponent }, { path: TLN_VIEWER_ROUTE, component: PageViewWrapperComponent }, { path: TLN_CROSSREF_ROUTE, component: RhizomeViewComponentComponent }, + { path: TLN_SEARCH_ROUTE, component: TlnFulltextComponent}, { path: '', redirectTo: TLN_VIEWER_ROUTE, pathMatch: 'prefix' } ]; diff --git a/nietzsche-beta-app/src/app/content-view-tab-component/content-view-tab-component.component.ts b/nietzsche-beta-app/src/app/content-view-tab-component/content-view-tab-component.component.ts index 5ed9cac..308df06 100644 --- a/nietzsche-beta-app/src/app/content-view-tab-component/content-view-tab-component.component.ts +++ b/nietzsche-beta-app/src/app/content-view-tab-component/content-view-tab-component.component.ts @@ -1,86 +1,90 @@ import {AfterViewInit, Component, OnInit} from '@angular/core'; import {ActivatedRoute, Params, Router} from '@angular/router'; import {Subscription} from "rxjs/index"; import {NavigationServiceService} from "../services/navigation-service.service"; -import { TLN_CROSSREF_ROUTE, TLN_MANUSCRIPT_ROUTE, TLN_VIEWER_ROUTE } from '../tln-edition/constants'; +import { TLN_CROSSREF_ROUTE, TLN_MANUSCRIPT_ROUTE, TLN_SEARCH_ROUTE, TLN_VIEWER_ROUTE } from '../tln-edition/constants'; @Component({ selector: 'app-content-view-tab-component', templateUrl: './content-view-tab-component.component.html', styleUrls: ['./content-view-tab-component.component.scss'], providers: [ NavigationServiceService ] }) export class ContentViewTabComponentComponent implements OnInit, AfterViewInit { // navigation tabs for the content view (manuscript view, page view, rhizome view) navTabLinks: any[]; // navbar on th left for navigating navBarOpenState = false; fullscreen = false; navBarOpenMode: string; queryParams: Params = {}; queryParamSubscription: Subscription; constructor(private router: Router, private activatedRoute: ActivatedRoute, private naviService: NavigationServiceService) { // The links/tabs for routing the correct view-component this.navTabLinks = [ { label: 'Manuskriptansicht', link: TLN_MANUSCRIPT_ROUTE, index: 0 }, { label: 'Seitenansicht', link: TLN_VIEWER_ROUTE, index: 1 }, { label: 'Querverweise', link: TLN_CROSSREF_ROUTE, index: 2 + },{ + label: 'Suche', + link: TLN_SEARCH_ROUTE, + index: 3 }, ]; } ngOnInit() { // this.mesurePerformance(); this.navBarOpenMode = 'side'; // side || over || push // this.setParamsOnInit(); // If url pasted or page refreshed --> resetting this.queryparams to the query params of the url; // needed for active routing in the nav tabs & for general use in the template this.queryParamSubscription = this.activatedRoute.queryParams.subscribe( (queryParams: Params ) => { console.log('new qParams in contentview', queryParams); this.queryParams = queryParams; this.navBarOpenState = JSON.parse(queryParams.navBarOpenState.toLowerCase()); this.fullscreen = JSON.parse(queryParams.fullscreen.toLowerCase()); }); } ngAfterViewInit() { this.navBarOpenState = JSON.parse(this.activatedRoute.snapshot.queryParamMap.get('navBarOpenState')); } mesurePerformance() { const perfData = window.performance.timing; const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart; console.log('content load performance is: ', pageLoadTime); } setParamsOnInit() { const qParams: Params = {}; // Set the NavBarOpenstate to true if it is not defined explicitely as false in the url query param onInit. if (this.activatedRoute.snapshot.queryParamMap.get('navBarOpenState') !== 'false') { // console.log('setQParamsOnInit', this.activatedRoute.snapshot.queryParamMap.get('navBarOpenState')) this.navBarOpenState = true; qParams.navBarOpenState = 'true'; } // viewMode if (!this.activatedRoute.snapshot.queryParamMap.get('viewMode')) { qParams.viewMode = 'Transkription/Faksimile'; } this.naviService.updateRoute(qParams); } } diff --git a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html index 3792bb8..82e8f18 100644 --- a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html +++ b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html @@ -1,9 +1,8 @@
- +
- +
- +
- diff --git a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts index d45ea58..6c2241d 100644 --- a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts +++ b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts @@ -1,32 +1,33 @@ import {Component, OnInit} from '@angular/core'; import {ActivatedRoute, Params, Router} from '@angular/router'; import { TlnQueryParams} from '../models/models'; @Component({ selector: 'app-page-view-wrapper-component', templateUrl: './page-view-wrapper.component.html', styleUrls: ['./page-view-wrapper.component.scss'] }) export class PageViewWrapperComponent implements OnInit { queryParams: TlnQueryParams; constructor(private router: Router, private activatedRoute: ActivatedRoute) { } ngOnInit() { + this.activatedRoute.queryParams.subscribe( (queryParams: Params ) => { this.queryParams = new TlnQueryParams( queryParams.navBarOpenState, queryParams.NavContext, queryParams.manuscript, queryParams.page, queryParams.selectedLines, queryParams.selectedWords, queryParams.viewMode, queryParams.fullscreen, queryParams.zoom ); }); } } diff --git a/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts b/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts index 472dd20..3b538d2 100644 --- a/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts +++ b/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts @@ -1,194 +1,198 @@ import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { externalAssignStyle, Continuation, Identifier, Line, LineStub, TextField, Word} from '../models'; import { PageViewService } from '../page-view.service'; import { HIGHTLIGHT_CASES } from '../highlight_status'; /** * This component displays an Array of lines. **/ @Component({ selector: 'margin-field', templateUrl: './margin-field.component.html', styleUrls: ['./margin-field.component.css'] }) export class MarginFieldComponent implements OnInit, OnChanges { /** * scrollable HTML-container of this textfield **/ @Input() container: HTMLElement; /** * the hovered status for a line **/ HOVERED_STATUS: string = HIGHTLIGHT_CASES.LINE_HOVERED SELECTED_STATUS: string = HIGHTLIGHT_CASES.SELECTED_LINE /** * the currently hovered line * */ hoveredLine?: Line; /** * the currently hovered reference line * */ hoveredReferenceLine?: LineStub; /** * the currently hovered word * */ hoveredWord?: Word; /** * an Array of lines that will be displayed. **/ @Input() lines: Line[]; /** * the height of a line rect. **/ line_height: number = 8; /** * the length of the line rect. **/ line_length: number = 10; /** * x coordinate of the line rect. **/ line_x: number = 5; /** * the height of the margin field. **/ margin_height: number = 973.91998; /** * geometrical top position of the margin field. **/ margin_top: number = 0; /** * the width of the margin field. **/ margin_width: number = 30; /** * specifies reference type that should be displayed **/ @Input() showReference: string = "to" /** * The area of the image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. * The height of the text_field determines {@link #margin_height|margin_height}, while its top position * determines {@link #margin_top|margin_top}. **/ @Input() text_field: TextField; /** * The viewbox of this svg component. **/ viewBox: string = ''; /** * initial maximum height of margin field. **/ @Input() max_height: number = -1; /** * initial maximum width of margin field. **/ @Input() max_width: number = -1; /** * identifiers of selected lines that should be highlighted. **/ @Input() selectedLines: Identifier[] = []; /** * global zoom factor **/ @Input() zoomFactor: number = 1; /** * An optional function that can be passed to this component in order to return a (svg-)style object * to the line rects. This function allows the user to extend the style of this component. * E.g. by returning { fill: blue } the function overwrites the default behaviour and sets * the default highlight color to blue. **/ @Input('assignStyle') extAssignStyle?: externalAssignStyle; /** * local zoom factor **/ local_zoom: number = 1; /** * @param lineservice an information source about (un-)hovered and clicked Lines/Words. **/ constructor( private lineservice: PageViewService) { } - /** + /** * Initialize geometrical information and subscribe to {@link /injectables/PageViewService.html|PageViewService}. **/ - ngOnInit() { + ngOnInit() { if (this.max_height == -1 && this.max_width == -1){ this.max_height = screen.availHeight; } this.viewBox = 0 + ' ' + this.margin_top + ' ' + this.margin_width + ' ' + this.margin_height; if (this.text_field != null) { this.updateViewBox() } this.lineservice.onHoveredLine.subscribe( (changedLine: Line) => { this.hoveredLine = changedLine;} ); this.lineservice.onHoveredContinuation.subscribe( (changedContinuation: Continuation) => { this.hoveredReferenceLine = changedContinuation.reference.line;} ); this.lineservice.offHoveredContinuation.subscribe( (changedContinuation: Continuation) => { this.hoveredReferenceLine = null} ); this.lineservice.offHoveredLine.subscribe( (changedLine: Line) => { this.hoveredLine = null; } ); this.lineservice.onHoveredWord.subscribe( (changedWord: Word) => { this.hoveredWord = changedWord;} ); this.lineservice.offHoveredWord.subscribe( (changedWord: Word) => { this.hoveredWord = null; } ); - } - /** + } + /** * Update viewBox if there is a change. - **/ - ngOnChanges(changes: SimpleChanges) { + **/ + ngOnChanges(changes: SimpleChanges) { if (this.text_field != null) { this.updateViewBox() } - } - /** + } + /** * Update viewBox: set * {@link #margin_height|margin_height}, * {@link #margin_top|margin_top}, * {@link #viewBox|viewBox} * and {@link #local_zoom|local_zoom} according to * {@link #text_field|text_field}. - **/ - private updateViewBox(){ + **/ + private updateViewBox(){ this.lines.forEach(line =>line.datatype = "Line"); if (this.showReference == 'to'){ this.margin_width = (this.lines.some(line =>line.continuesTo != null || line.continuesTo != undefined)) ? this.line_length*2+30 : 30; } else { let hasReference = this.lines.some(line =>line.continuesFrom != null || line.continuesFrom != undefined) this.margin_width = (this.showReference == 'from' && hasReference) ? this.line_length*2+30 : 30; this.line_x = (this.showReference == 'from' && hasReference) ? 2*this.line_length : 5; } this.margin_height = this.text_field.height; this.margin_top = this.text_field.top; this.viewBox = 0 + ' ' + this.margin_top + ' ' + this.margin_width + ' ' + this.margin_height; this.local_zoom = (this.max_height != -1 && this.max_width == -1) ? this.max_height/this.text_field.height : this.max_width/this.text_field.width; - } - /** + if (this.max_width == -1 && this.text_field.height < this.text_field.width){ + this.local_zoom = (window.innerWidth/2-100)/this.text_field.width; + } + + } + /** * Get the hover status of a line, i.e. whether it is hovered * ({@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.LINE_HOVERED}) * or not ({@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.DEFAULT}). **/ - private getHoverStatus(line: Line): string { + private getHoverStatus(line: Line): string { if ( (this.hoveredLine != undefined && this.hoveredLine != null && line.id == this.hoveredLine.id) || (this.hoveredReferenceLine != undefined && this.hoveredReferenceLine != null && line.id == this.hoveredReferenceLine.id) || (this.hoveredWord != undefined && this.hoveredWord != null && line.id == this.hoveredWord.line)) { return HIGHTLIGHT_CASES.LINE_HOVERED; } else if (this.selectedLines.length > 0 && this.selectedLines.indexOf(line.id) > -1) { return HIGHTLIGHT_CASES.SELECTED_LINE } else { return HIGHTLIGHT_CASES.DEFAULT; } - } + } /** * Assign a style to the rects of a line. **/ private assignStyle(line: Line, hoveredWord: Word, hoveredLine: Line, hoverStatus: string): Object { return (this.extAssignStyle != null) ? this.extAssignStyle(line, hoveredWord, hoveredLine, hoverStatus) : {}; } } diff --git a/nietzsche-beta-app/src/app/page-view/page-view.component.html b/nietzsche-beta-app/src/app/page-view/page-view.component.html index 1bdcd5c..0beeafb 100644 --- a/nietzsche-beta-app/src/app/page-view/page-view.component.html +++ b/nietzsche-beta-app/src/app/page-view/page-view.component.html @@ -1,50 +1,50 @@
diff --git a/nietzsche-beta-app/src/app/page-view/page-view.component.ts b/nietzsche-beta-app/src/app/page-view/page-view.component.ts index 1b02618..9639e50 100644 --- a/nietzsche-beta-app/src/app/page-view/page-view.component.ts +++ b/nietzsche-beta-app/src/app/page-view/page-view.component.ts @@ -1,174 +1,173 @@ import { Component, Input, OnInit, OnChanges} from '@angular/core'; import { externalAssignClass, externalAssignStyle, Configuration, Identifier, Image, Line, TextField, TextByForeignHand, Word} from './models'; /** * This component displays one or two {@link /components/TextFieldComponent.html|TextFieldComponent(s)} * and its or their {@link /components/MarginFieldComponent.html|MarginFieldComponent(s)}. **/ @Component({ selector: 'page-view', templateUrl: './page-view.component.html', styleUrls: ['./page-view.component.css'] }) export class PageViewComponent implements OnInit, OnChanges { @Input() configuration: Configuration; /** * the search text of words that should be highlighted as {@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.SEARCHED_WORD}. **/ @Input() findText: string; /** * first texts written by foreign hand **/ @Input() first_foreign_texts: TextByForeignHand[] = []; /** * the first image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() first_image: Image; /** * the Array of lines of the first image that will be displayed by {@link /components/MarginFieldComponent.html|MarginFieldComponent}. **/ @Input() first_lines: Line[]; /** * Identification of first textfield. **/ first_textfield_id: string = 'first textfield' /** * the Array of words of the first image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() first_words: Word[]; /** * the (initial) maximum height of the image(s). **/ @Input() max_height: number = -1; /** * the (initial) maximum width of the image(s). **/ @Input() max_width: number = -1; /** * should primary Url be used for image. Use secondary Url if false. **/ @Input() preferPrimaryUrl: boolean = true; /** * second texts written by foreign hand **/ @Input() second_foreign_texts: TextByForeignHand[] = []; /** * the second image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() second_image: Image; /** * the Array of lines of the second image that will be displayed by {@link /components/MarginFieldComponent.html|MarginFieldComponent}. **/ @Input() second_lines: Line[]; /** * Identification of second textfield. **/ second_textfield_id: string = 'second textfield' /** * the Array of words of the second image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() second_words: Word[]; /** * An optional function that will be passed to {@link /components/TextFieldComponent.html|TextFieldComponent} * in order to return a further highlight class * to the word rects when the internal function would return 'textfield unhighlighted'. **/ @Input('assignClass') assignClass?: externalAssignClass; /** * An optional function that will be passed to {@link /components/TextFieldComponent.html|TextFieldComponent} * and {@link /components/MarginFieldComponent.html|MarginFieldComponent} * in order to return a (svg-)style object * to the word and line rects. This function allows the user to extend the style of this component. * E.g. by returning { fill: blue } the function overwrites the default behaviour and sets * the default highlight color to blue. **/ @Input('assignStyle') assignStyle?: externalAssignStyle; /** * global zoom factor. **/ @Input() zoomFactor: number = 1; /** * identifiers of selected words that should be highlighted. **/ @Input() selectedWords: Identifier[] = []; /** * identifiers of selected lines that should be highlighted. **/ @Input() selectedLines: Identifier[] = []; @Input('startLine') startLineId: Identifier; @Input('endLine') endLineId: Identifier; @Input() dontShowReference: boolean; showReferenceLeft: string = 'from'; showReferenceRight: string = 'to'; constructor() {} /** * sets {@link /components/PageViewComponent.html#max_height|max_height} if it is unset. **/ ngOnInit() { - if (this.max_height == -1 && this.max_width == -1){ - this.max_height = screen.availHeight - 40; - console.log(this.max_height); - } + if (this.max_height == -1 && this.max_width == -1){ + this.max_height = screen.availHeight; + } this.checkImages(); } ngOnChanges(){ if (this.dontShowReference != undefined && this.dontShowReference != null && this.dontShowReference){ this.showReferenceLeft = ''; this.showReferenceRight = ''; } else { this.showReferenceLeft = 'from'; this.showReferenceRight = 'to'; } this.checkImages(); if (this.first_image != null && this.first_image != undefined && this.first_image.transform != null){ this.updateLines(this.first_words, this.first_lines) } if (this.second_image != null && this.second_image != undefined && this.second_image.transform != null){ this.updateLines(this.second_words, this.second_lines) } } private checkImages(){ if (this.first_image != null && this.first_image != undefined && this.startLineId != null && this.startLineId != undefined){ if(this.first_lines != null && this.first_lines != undefined && this.first_lines.length > 0){ this.first_image = this.updateTextField(this.first_image, this.first_lines); } if(this.second_lines != null && this.second_lines != undefined && this.second_lines.length > 0){ this.second_image = this.updateTextField(this.second_image, this.second_lines); } } } private updateLines(words: Word[], lines: Line[]) { for (var i = 0; i < lines.length; i++){ if (words.filter(word =>word.line == lines[i].id).length > 0){ lines[i].top = words.filter(word =>word.line == lines[i].id).map(word =>Number(word.top)).sort(function(a,b){ return a-b; })[0] lines[i].bottom = words.filter(word =>word.line == lines[i].id).map(word =>Number(word.top)+Number(word.height)).sort(function(a,b){ return b-a; })[0] } } } private updateTextField(image: Image, lines: Line[]): Image { let endLineId = (this.endLineId != null && this.endLineId != undefined) ? this.endLineId : this.startLineId; let startLines = lines.filter(line =>line.id == this.startLineId) let endLines = lines.filter(line =>line.id == endLineId) if (startLines.length > 0 && endLines.length > 0){ let top = (startLines[0].top > 10) ? startLines[0].top-10 : startLines[0].top; let height = (endLines[0].bottom-top)+10; let text_field: TextField = { top: top, left: image.text_field.left, width: image.text_field.width, height: height } return { x: image.x, y: image.y, width: image.width, height: image.height, filename: image.filename, URL: image.URL, secondaryURL: image.secondaryURL, text_field: text_field, transform: image.transform, copyright: image.copyright } } return image; } /** * Returns whether the two images can be displayed as columns. **/ private hasColumnStyle(): boolean { if (this.zoomFactor <= 1 || this.first_image == null || this.second_image == null){ return true } let newLeftWidth = this.max_height/this.first_image.text_field.height*this.zoomFactor*this.first_image.text_field.width; let newRightWidth = this.max_height/this.second_image.text_field.height*this.zoomFactor*this.second_image.text_field.width; return newLeftWidth + newRightWidth < screen.availWidth; } } diff --git a/nietzsche-beta-app/src/app/page-view/page-view.module.ts b/nietzsche-beta-app/src/app/page-view/page-view.module.ts index bfa1335..e13e24d 100644 --- a/nietzsche-beta-app/src/app/page-view/page-view.module.ts +++ b/nietzsche-beta-app/src/app/page-view/page-view.module.ts @@ -1,37 +1,61 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { MatBottomSheetModule,MatButtonModule,MatCheckboxModule,MatDialogModule,MatExpansionModule,MatFormFieldModule,MatInputModule,MatListModule,MatPaginatorModule,MatRadioModule,MatSelectModule,MatSidenavModule,MatSortModule,MatTableModule,MatToolbarModule,MatButtonToggleModule,MatCardModule,MatIconModule,MatMenuModule,MatTabsModule,MatTooltipModule +} from '@angular/material'; +import { NgxMatStandoffMarkupModule } from '../lib/ngx-mat-standoff-markup.module'; import { MarginFieldComponent } from './margin-field/margin-field.component'; import { TextFieldComponent} from './textfield-component/textfield.component'; import { InteractedDirective } from './interacted.directive'; import { PageViewComponent } from './page-view.component'; import { PageViewService } from './page-view.service'; import { CopyrightComponent } from './copyright/copyright.component'; import { LineReferenceComponent } from './margin-field/line-reference/line-reference.component'; import { CopyrightSheetComponent } from './copyright/copyright-sheet/copyright-sheet.component'; @NgModule({ declarations: [ InteractedDirective, MarginFieldComponent, TextFieldComponent, PageViewComponent, CopyrightComponent, LineReferenceComponent, CopyrightSheetComponent ], imports: [ + MatBottomSheetModule, + MatButtonModule, + MatButtonToggleModule, + MatCardModule, + MatCheckboxModule, + MatDialogModule, + MatExpansionModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatListModule, + MatMenuModule, + MatPaginatorModule, + MatRadioModule, + MatSelectModule, + MatSidenavModule, + MatSortModule, + MatTableModule, + MatTabsModule, + MatToolbarModule, + MatTooltipModule, CommonModule ], providers: [ PageViewService ], exports: [ MarginFieldComponent, TextFieldComponent, PageViewComponent, CopyrightComponent ], entryComponents: [CopyrightSheetComponent] }) export class PageViewModule { } diff --git a/nietzsche-beta-app/src/app/page-view/textfield-component/textfield.component.ts b/nietzsche-beta-app/src/app/page-view/textfield-component/textfield.component.ts index 4524a70..d091a4a 100644 --- a/nietzsche-beta-app/src/app/page-view/textfield-component/textfield.component.ts +++ b/nietzsche-beta-app/src/app/page-view/textfield-component/textfield.component.ts @@ -1,344 +1,348 @@ -import { Component, ElementRef, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; +import { Component, ElementRef, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { externalAssignClass, externalAssignStyle, Configuration, Continuation, Identifier, Image, Line, Position, PositionalObject, TextByForeignHand, Word, USE_EXTERNAL_TOOLTIP} from '../models'; import { PageViewService } from '../page-view.service'; import { HIGHTLIGHT_CASES } from '../highlight_status'; import { ConfigurableComponent } from '../configurable-component'; import { Matrix } from './matrix'; /** * This component displays an image with word hovers. **/ @Component({ selector: 'text-field', templateUrl: './textfield.component.html', styleUrls: ['./textfield.component.css'] }) export class TextFieldComponent extends ConfigurableComponent implements OnInit, OnChanges { /** * scrollable HTML-container of this textfield **/ @Input() container: HTMLElement; /** * the currently clicked word * */ clickedWord?: Word; /** * Debug mode. **/ debug: boolean = false; /** * the search text of words that should be highlighted as {@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.SEARCHED_WORD}. **/ @Input() findText: string; /** * texts written by foreign hand **/ @Input() foreign_texts: TextByForeignHand[] = []; /** * the currently hovered line * */ hoveredLine?: Line; /** * the currently hovered text by foreign hand * */ hoveredTextByForeignHand?: TextByForeignHand; /** * the currently hovered word * */ hoveredWord?: Word; /** * the image that will be displayed. **/ @Input() image: Image; /** * textfield's identity. **/ @Input() identity: string = 'first textfield'; /** * The (unzoomed) height of the root svg. * * (The actual height is 'image_height*local_zoom*zoomFactor' * */ image_height: number = 400; /** * image properties for the svg-image. * */ imageSpec = { x: 0, y: 0, height: 973.91998, width: 2038.5601, URL: null, secondaryURL: null, transform: 'matrix(1 0 0 1 0 0)' }; /** * The (unzoomed) width of the root svg. * * (The actual width is 'image_width*local_zoom*zoomFactor' * */ image_width: number = 300; /** * the viewBox of the root svg specifying the area of the svg that will be shown. * */ viewBox: string = ''; /** * the (initial) maximum height of the image. **/ @Input() max_height: number = -1; /** * the (initial) maximum width of the image. **/ @Input() max_width: number = -1; /** * should primary Url be used for image. Use secondary Url if false. **/ @Input() preferPrimaryUrl: boolean = true; /** * Use extended tooltip. **/ @Input() useExtendedTooltip: boolean = false; /** * the words that will be displayed as rects on the image. **/ @Input() words: Word[]; /** * global zoom factor. **/ @Input() zoomFactor: number = 1; /** * local zoom factor that sets the height and width of the image according to {@link #max_height|max_height}. * */ local_zoom: number = 1; /** * An optional function that can be passed to this component in order to return a further highlight class * to the word rects when the internal function would return 'textfield unhighlighted'. **/ @Input('assignClass') externalAssignClassAfter?: externalAssignClass; /** * An optional function that can be passed to this component in order to return a (svg-)style object * to the word rects. This function allows the user to extend the style of this component. * E.g. by returning { fill: blue } the function overwrites the default behaviour and sets * the default highlight color to blue. **/ @Input('assignStyle') extAssignStyle?: externalAssignStyle; /** * identifiers of selected words that should be highlighted. **/ @Input() selectedWords: Identifier[] = []; /** * identifiers of selected lines that should be highlighted. **/ @Input() selectedLines: Identifier[] = []; /** * @param pageViewService an information source about (un-)hovered and clicked Lines/Words. * */ constructor( protected pageViewService: PageViewService) { super() } ngOnInit() { if (this.max_height == -1 && this.max_width == -1){ this.max_height = screen.availHeight; } if (this.image.text_field != null) { this.updateImageProperties(); } else if (this.imageSpec != null) { this.image_width = this.imageSpec.width; this.image_height = this.imageSpec.height; this.viewBox = '0 0 ' + this.image_width + ' ' + this.image_height; } this.pageViewService.onClickedWord.subscribe( (changedWord: Word ) => this.clickedWord = changedWord ); this.pageViewService.onHoveredWord.subscribe( (changedWord: Word) => this.hoveredWord = changedWord ); this.pageViewService.offHoveredWord.subscribe( (changedWord: Word) => { this.hoveredWord = null; } ); this.pageViewService.onHoveredLine.subscribe( (changedLine: Line) => { this.hoveredLine = changedLine} ); this.pageViewService.offHoveredLine.subscribe( (changedLine: Line) => { this.hoveredLine = null; } ); this.pageViewService.onHoveredTextByForeignHand.subscribe( (changedForeignText: TextByForeignHand) => { this.hoveredTextByForeignHand = changedForeignText;} ); this.pageViewService.offHoveredTextByForeignHand.subscribe( (changedForeignText: TextByForeignHand) => { this.hoveredTextByForeignHand = null; } ); } ngOnChanges() { super.ngOnChanges() if (this.image.text_field != null) { this.updateImageProperties(); } if(this.debug && this.findText != null && this.findText != ''){ let words = this.words.filter(word =>word.text == this.findText) if (words.length > 0){ this.pageViewService.onHoverService(words[0], {visible: true, clientX: 100, clientY: 100, layerX: -1, layerY: -1 }) } } } /** * Update image properties: use textfield in order to specify the area of the image that will be shown. * * @param URL set alternative image url. This will be used on image load error (see Template) **/ private updateImageProperties(URL?: string){ let previous_word: Word = null; for (var i = 0; i < this.words.length; i++){ this.words[i].datatype = "Word"; if (previous_word == null || previous_word.id != this.words[i].id){ previous_word = this.words[i] previous_word.is_top_object = true; } else if (previous_word.top > this.words[i].top){ previous_word.is_top_object = false; previous_word = this.words[i] previous_word.is_top_object = true; } else { this.words[i].is_top_object = false; } } this.foreign_texts.forEach(foreignText =>foreignText.datatype = "TextByForeignHand"); let image_left = this.image.text_field.left; let image_top = this.image.text_field.top; this.image_width = this.image.text_field.width; this.image_height = this.image.text_field.height; this.local_zoom = (this.max_height != -1 && this.max_width == -1) ? this.max_height/this.image.text_field.height : this.max_width/this.image.text_field.width; + if (this.max_width == -1 && this.image_height < this.image_width){ + this.local_zoom = (window.innerWidth/2-100)/this.image.text_field.width; + } this.imageSpec.x = this.image.x; this.imageSpec.y = this.image.y; this.imageSpec.height = this.image.height; this.imageSpec.width = this.image.width; this.imageSpec.URL = (this.preferPrimaryUrl) ? this.image.URL : this.image.secondaryURL; this.imageSpec.secondaryURL = (this.preferPrimaryUrl) ? this.image.URL : this.image.URL; if (URL != null){ this.imageSpec.secondaryURL = this.imageSpec.URL this.imageSpec.URL = URL; } if(this.image.transform != null){ this.local_zoom = this.max_height/this.image.text_field.width; let matrix = new Matrix(this.image.transform, this.local_zoom*this.zoomFactor); this.imageSpec.transform = matrix.toString() } this.viewBox = image_left + ' ' + image_top + ' ' + this.image_width + ' ' + this.image_height; } /** * Return the position (i.e. '{ x: x, y: y }') for the copyright symbol. * @param dimension dimension of the copyright symbol. **/ private getCopyrightPosition(dimension: number): Object { if (this.image.text_field != null && this.image.text_field != undefined){ let positions: Position[] = [ { x: Number(this.image.text_field.left) +10/this.zoomFactor, y: Number(this.image.text_field.top) +10/this.zoomFactor }, { x: Number(this.image.text_field.left), y: Number(this.image.text_field.top)}, { x: Number(this.image.text_field.width) + Number(this.image.text_field.left) -15/this.zoomFactor - dimension, y: Number(this.image.text_field.height) + Number(this.image.text_field.top) -15/this.zoomFactor - dimension }, { x: Number(this.image.text_field.width) + Number(this.image.text_field.left) - dimension, y: Number(this.image.text_field.height) + Number(this.image.text_field.top) - dimension }, { x: Number(this.image.text_field.left) +10/this.zoomFactor, y: Number(this.image.text_field.height) + Number(this.image.text_field.top) -10/this.zoomFactor - dimension }, { x: Number(this.image.text_field.width) + Number(this.image.text_field.left) -10/this.zoomFactor - dimension, y: Number(this.image.text_field.top) +10/this.zoomFactor}, { x: Number(this.image.text_field.width) + Number(this.image.text_field.left) - dimension, y: Number(this.image.text_field.top)} ] let default_index = 1 let index = 0; let position_found = false; while (!position_found && index < positions.length){ let left = positions[index].x let top = positions[index].y if(!this.doesPositionConflict(left, top, dimension, this.words) && !this.doesPositionConflict(left, top, dimension, this.foreign_texts)){ position_found = true; } else { index++ } } let left = (index < positions.length) ? positions[index].x : positions[default_index].x; let top = (index < positions.length) ? positions[index].y : positions[default_index].y; return { x: `${left}px`, y: `${top}px` } } else { return { x: '0px', y: '0px' } } } /** * Return whether position specified by left, top and dimension does conflict with one of the positional objects' position. * * @param left left of position * @param top top of position * @param dimension dimension of position * @param positionalObjects Array of positions **/ private doesPositionConflict(left: number, top: number, dimension: number, positionalObjects: PositionalObject[]): boolean { let conflicts = positionalObjects.filter(positionalObject => !(Number(positionalObject.left) + Number(positionalObject.width) < left || Number(positionalObject.left) > left + dimension || Number(positionalObject.top) > top + dimension || Number(positionalObject.top) + Number(positionalObject.height) < top) ) return conflicts.length > 0 } /** * Get the hover status of the word as one of the {@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES}. **/ private getHoverStatus(word: Word, skipFindText: boolean = false): string { if (this.selectedWords.indexOf(word.id) > -1 || this.selectedLines.indexOf(word.line) > -1){ return HIGHTLIGHT_CASES.SELECTED_WORD; } if (!skipFindText && this.findText != null && this.findText != ''){ - return (word.text.match(this.findText) - || (word.edited_text != null && word.edited_text.match(this.findText)) + let findRegex = '^[^\\w]*(' + this.findText.split(' ').join('|') + ')' + return (word.text.match(findRegex) + || (word.edited_text != null && word.edited_text.match(findRegex)) ) ? HIGHTLIGHT_CASES.SEARCHED_WORD : this.getHoverStatus(word, true); } if (typeof this.hoveredLine !== 'undefined' && this.hoveredLine !== null) { return (this.hoveredLine.id == word.line || (this.hoveredLine.continuesTo != undefined && this.hoveredLine.continuesTo != null && this.hoveredLine.continuesTo.line.id == word.line) || (this.hoveredLine.continuesFrom != undefined && this.hoveredLine.continuesFrom != null && this.hoveredLine.continuesFrom.line.id == word.line)) ? HIGHTLIGHT_CASES.LINE_HOVERED : HIGHTLIGHT_CASES.DEFAULT; } else if (typeof this.hoveredWord !== 'undefined' && this.hoveredWord !== null){ return (this.hoveredWord.id == word.id) ? HIGHTLIGHT_CASES.WORD_HOVERED : HIGHTLIGHT_CASES.DEFAULT; } return HIGHTLIGHT_CASES.DEFAULT; } /** * Return a css class for word that will be used with [ngClass] in order to (un-)highlight the word's rect. * * If a function has been passed to Input {@link #assignClass|assignClass}, * this function will call it if {@link #getHoverStatus|getHoverStatus(word)} == {@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.DEFAULT}. **/ private assignClass(positionalObject: PositionalObject, elementName?: string): string { if (positionalObject.datatype == 'TextByForeignHand'){ return (this.hoveredTextByForeignHand != null && this.hoveredTextByForeignHand.id == positionalObject.id) ? 'text_field highlight_foreign_text' : 'text_field unhighlighted' } let word = positionalObject; if (elementName != null) { return (this.getHoverStatus(word) == HIGHTLIGHT_CASES.DEFAULT) ? `text_field unhighlighted_${elementName}` : `text_field highlight_${elementName}`; } switch(this.getHoverStatus(word)) { case HIGHTLIGHT_CASES.SELECTED_WORD: { return 'textfield highlight_magenta'; } case HIGHTLIGHT_CASES.SEARCHED_WORD: { return 'textfield highlight_red'; } case HIGHTLIGHT_CASES.LINE_HOVERED: { return (word.deleted) ? 'textfield deleted' : 'textfield highlight_yellow'; } case HIGHTLIGHT_CASES.WORD_HOVERED: { return (word.deleted) ? 'textfield deleted' : 'textfield highlight_yellow'; } case HIGHTLIGHT_CASES.DEFAULT: { return (this.externalAssignClassAfter != null) ? this.externalAssignClassAfter(word, this.hoveredWord, this.hoveredLine) : 'textfield unhighlighted'; } } } /** * Assign a style to the rects of a line. **/ private assignStyle(word: Word, hoveredWord: Word, hoveredLine: Line, hoverStatus: string): Object { return (this.extAssignStyle != null) ? this.extAssignStyle(word, hoveredWord, hoveredLine, hoverStatus) : {}; } private msg(URL: string){ if(this.preferPrimaryUrl){ console.log(URL + ' TODO: show smaller image during loading'); } } } diff --git a/nietzsche-beta-app/src/app/rhizome-view-component/rhizome-view-component.component.html b/nietzsche-beta-app/src/app/rhizome-view-component/rhizome-view-component.component.html index 8629103..33e8c1b 100644 --- a/nietzsche-beta-app/src/app/rhizome-view-component/rhizome-view-component.component.html +++ b/nietzsche-beta-app/src/app/rhizome-view-component/rhizome-view-component.component.html @@ -1,5 +1,5 @@
- +
diff --git a/nietzsche-beta-app/src/app/tln-edition/constants.ts b/nietzsche-beta-app/src/app/tln-edition/constants.ts index fdc95ae..75d02b6 100644 --- a/nietzsche-beta-app/src/app/tln-edition/constants.ts +++ b/nietzsche-beta-app/src/app/tln-edition/constants.ts @@ -1,66 +1,70 @@ export {HIGHTLIGHT_CASES} from '../page-view/highlight_status'; export enum VIEW_OPTIONS { TRANSKRIPTION = 'Transkription', FAKSIMILE = 'Faksimile', SYNOPSIS = 'Transkription/Faksimile', SYNOPSIS_B = 'Faksimile/Transkription' } export const DEFAULT_VIEW_OPTION: string = VIEW_OPTIONS.SYNOPSIS_B; export const ONTOLOTY_PREFIX: string = 'http://www.nie.org/ontology/nietzsche#' /** * Route for TlnCrossrefComponent **/ export const TLN_CROSSREF_ROUTE: string = 'tln-crossref'; +/** + * Route for TlnFulltextComponent + **/ +export const TLN_SEARCH_ROUTE: string = 'tln-search'; /** * Route for TlnManuscriptViewComponent **/ export const TLN_MANUSCRIPT_ROUTE: string = 'tln-manuscript'; /** * Route for TlnViewerComponent **/ export const TLN_VIEWER_ROUTE: string = 'tln-viewer'; /** * Param that refers to the context that should be shown, i.e. 'page' or 'manuscript'. **/ export const TLN_CONTEXT_VIEW_PARAM: string = 'contextView'; /** * Param that toggles fullscreen, value type: boolean. **/ export const TLN_FULLSCREEN_PARAM: string = 'fullscreen'; /** * Param for find text in page. **/ export const TLN_FIND_PARAM: string = 'find'; /** * Param for page iri. **/ export const TLN_PAGE_PARAM: string = 'page'; /** * Param for manuscript iri. **/ export const TLN_MANUSCRIPT_PARAM: string = 'manuscript'; /** * Param for navigation bar open state. **/ export const TLN_NAV_BAR_OPEN_STATE_PARAM: string = 'navBarOpenState'; /** * Param for selected lines. **/ export const TLN_SELECTED_LINES_PARAM: string = 'selectedLines'; /** * Param for selected lines. **/ export const TLN_SELECTED_WORDS_PARAM: string = 'selectedWords'; /** * Param for iri of a genetic order of text versions. **/ export const TLN_TEXT_GENETIC_ORDER_PARAM: string = 'geneticOrder'; /** * Param for selected view option, e.g. 'Transkription', 'Faksimile', etc. **/ export const TLN_VIEW_OPTION_PARAM: string = 'viewMode'; /** * Param for zoom. **/ export const TLN_ZOOM_PARAM: string = 'zoom'; diff --git a/nietzsche-beta-app/src/app/tln-edition/datatypes/basic_datatype.ts b/nietzsche-beta-app/src/app/tln-edition/datatypes/basic_datatype.ts index c3a6b88..19f16cc 100644 --- a/nietzsche-beta-app/src/app/tln-edition/datatypes/basic_datatype.ts +++ b/nietzsche-beta-app/src/app/tln-edition/datatypes/basic_datatype.ts @@ -1,217 +1,218 @@ import { Parser, Generator } from 'sparqljs'; import { KeyIriMapping } from '../data_handler'; /** * this interface specifies the head of {@link /interfaces/FusekiResults.html|FusekiResults}. **/ interface FusekiVars { vars: string[]; } /** * this interface specifies the bindings of {@link /interfaces/FusekiResults.html|FusekiResults}. **/ interface FusekiBindings { bindings: []; } /** * this interface specifies the results as they are retrieved from an Apache Jena Fuseki server. **/ export interface FusekiResults { results: FusekiBindings; head: FusekiVars } export interface FusekiBoolean { head: any; boolean: boolean; } /** * This is the basic datatype that instantiates an element of {@link /interfaces/FusekiResults.html|FusekiResults}. * * All datatypes can be subclassed from this type in order to create SPARQL-queries, retrieve data and convert it * to the corresponding datatypes. **/ export class BasicResultBindingElement { /** * the internal default key for replacing {@link /classes/BasicResultBindingElement.html#query|query} by "id" * in {@link /classes/BasicResultBindingElement.html#getQuery|getQuery} if "key" is omitted. **/ protected static readonly default_key: string = 'id'; /** * the SPARQL-query of this datatype. **/ static readonly query: string = `SELECT ?id ?p ?o WHERE { ?id ?p ?o. }`; /** * the public key for replacing {@link /classes/BasicResultBindingElement.html#query|query} by "id". **/ public static readonly query_key: string = null; /** * the id of this datatype. **/ public id: string; /** * the raw data of this datatype, i.e. a singular bindings element of {@link /interfaces/FusekiBindings.html|FusekiBindings}. **/ protected data: any; /** * whether or not to pass the id used for the query to the constructor and * use it as the value of the property specified by query_key. **/ public static readonly use_id: boolean = false; /** * a service that this datatype can use in order to communicate with its data holder. **/ protected service: any; /** * The constructor creates a datatype from the data. * * @param id if omitted the id will be retrieved from data **/ constructor(data: any, id?: string, service?: any){ this.data = data; this.service = service; if (id != undefined && id != null && id != ''){ let key = (Object.getPrototypeOf(this).constructor.use_id && Object.getPrototypeOf(this).constructor.query_key != null) ? Object.getPrototypeOf(this).constructor.query_key : 'id'; this[key] = id; } if (this.id == null){ this.id = this.getData4Key('id'); } } /** * This function returns the value of the content specified by "key" from {@link /classes/BasicResultBindingElement.html#data|data}. * * @param key the key that specifies the content * * @returns {any} the value of the content if key exists else null **/ protected getData4Key(key: string): any { if (!this.data.hasOwnProperty(key)) { return null; } if (this.data[key].datatype == 'http://www.w3.org/2001/XMLSchema#boolean'){ return JSON.parse(this.data[key].value); } else if (this.data[key].datatype == 'http://www.w3.org/2001/XMLSchema#integer'){ return Number(this.data[key].value); } return this.data[key].value; } /** * This method returns the SPARQL query of this BasicResultBindingElement. * The query can be modified by providing an "id" and "key" such that every "key" in * the query will be replaced by "id". * * If "key" is omitted {@link /classes/BasicResultBindingElement.html#default_key|default_key} will be used. * * @param id will replace key in query * @param key will be replaced by id. **/ public static getQuery(id?: string, key?: string): string { if (typeof(id) === 'undefined' || id === null || id == ''){ return this.query; } else { if (key == null || key == ''){ key = this.default_key; } let parser = new Parser(); let sparqlGenerator = new Generator({}); let parsedQuery = parser.parse(this.query) - if (parsedQuery.where[0].patterns != undefined){ - for (var j = 0; j < parsedQuery.where[0].patterns.length; j++){ - for (var i = 0; i < parsedQuery.where[0].patterns[j].triples.length; i++){ - if(parsedQuery.where[0].patterns[j].triples[i]['subject']['value'] == key){ - parsedQuery.where[0].patterns[j].triples[i]['subject'] = { termType: "NamedNode", value: id }; - } else if(parsedQuery.where[0].patterns[j].triples[i]['object']['value'] == key){ - parsedQuery.where[0].patterns[j].triples[i]['object'] = { termType: "NamedNode", value: id }; - } else if(parsedQuery.where[0].patterns[j].triples[i]['predicate']['value'] == key){ - parsedQuery.where[0].patterns[j].triples[i]['predicate'] = { termType: "NamedNode", value: id }; + for (var k = 0; k < parsedQuery.where.length; k++){ + if (parsedQuery.where[k].patterns != undefined){ + for (var j = 0; j < parsedQuery.where[k].patterns.length; j++){ + if (parsedQuery.where[k].patterns[j].triples != undefined) { + for (var i = 0; i < parsedQuery.where[k].patterns[j].triples.length; i++){ + if(parsedQuery.where[k].patterns[j].triples[i]['subject']['value'] == key){ + parsedQuery.where[k].patterns[j].triples[i]['subject'] = { termType: "NamedNode", value: id }; + } else if(parsedQuery.where[k].patterns[j].triples[i]['object']['value'] == key){ + parsedQuery.where[k].patterns[j].triples[i]['object'] = { termType: "NamedNode", value: id }; + } else if(parsedQuery.where[k].patterns[j].triples[i]['predicate']['value'] == key){ + parsedQuery.where[k].patterns[j].triples[i]['predicate'] = { termType: "NamedNode", value: id }; + } + } + } + } + } else if (parsedQuery.where[k].triples != undefined){ + for (var i = 0; i < parsedQuery.where[k].triples.length; i++){ + if(parsedQuery.where[k].triples[i]['subject']['value'] == key){ + parsedQuery.where[k].triples[i]['subject'] = { termType: "NamedNode", value: id }; + } else if (parsedQuery.where[k].triples[i]['object']['value'] == key){ + parsedQuery.where[k].triples[i]['object'] = { termType: "NamedNode", value: id }; + } else if (parsedQuery.where[k].triples[i]['predicate']['value'] == key){ + parsedQuery.where[k].triples[i]['predicate'] = { termType: "NamedNode", value: id }; } } - } - return sparqlGenerator.stringify(parsedQuery); - } else if (parsedQuery.where[0].triples == undefined){ - console.log('ERROR', parsedQuery); - return '' - } - for (var i = 0; i < parsedQuery.where[0].triples.length; i++){ - if(parsedQuery.where[0].triples[i]['subject']['value'] == key){ - parsedQuery.where[0].triples[i]['subject'] = { termType: "NamedNode", value: id }; - } else if (parsedQuery.where[0].triples[i]['object']['value'] == key){ - parsedQuery.where[0].triples[i]['object'] = { termType: "NamedNode", value: id }; - } else if (parsedQuery.where[0].triples[i]['predicate']['value'] == key){ - parsedQuery.where[0].triples[i]['predicate'] = { termType: "NamedNode", value: id }; } } return sparqlGenerator.stringify(parsedQuery); } } public static getComplexQuery(keyIriMapping: KeyIriMapping[]): string { let parser = new Parser(); let sparqlGenerator = new Generator({}); let parsedQuery = parser.parse(this.query) for (let mapping of keyIriMapping){ let key = mapping.key; let id = mapping.iri; for (var i = 0; i < parsedQuery.where[0].triples.length; i++){ if(parsedQuery.where[0].triples[i]['subject']['value'] == key){ parsedQuery.where[0].triples[i]['subject'] = { termType: "NamedNode", value: id }; } else if (parsedQuery.where[0].triples[i]['object']['value'] == key){ parsedQuery.where[0].triples[i]['object'] = { termType: "NamedNode", value: id }; } else if (parsedQuery.where[0].triples[i]['predicate']['value'] == key){ parsedQuery.where[0].triples[i]['predicate'] = { termType: "NamedNode", value: id }; } } } return sparqlGenerator.stringify(parsedQuery); } /** * This function returns 'results.bindings' of {@link /interfaces/FusekiResults.html|FusekiResults}. **/ public static getContent(data: FusekiResults): [] { return data['results']['bindings']; } /** * This static function instantiates the subclasses of {@link /classes/BasicResultBindingElement.html|BasicResultBindingElement} from * the data retrieved by executing the query that is provided by {@link /classes/BasicResultBindingElement.html#getQuery|getQuery}. * * @param this a subclass of BasicResultBindingElement * @param data the fuseki result json * @param id the id that has been used in order to retrieve the data and that will identify the instantiation of the subclass. * @param service a means to communicate with the data holder. * * @returns Array of subclass instantiations **/ public static convertData(this: T, data: FusekiResults, id?: string, service?: any): Array> { let elements = []; let content = this.getContent(data); for (var i = 0; i < content.length; i++){ let element = new this(content[i], id, service) as InstanceType; elements.push(element); } return elements; } } export class AskResult extends BasicResultBindingElement { static readonly query: string = ` PREFIX tln: ASK { ?id a ?type. }`; public static getAnswer(answer: FusekiBoolean): boolean { return answer.boolean; } } export class IsReconstructedKonvolut extends AskResult { static readonly query: string = ` PREFIX tln: ASK { ?id a tln:ReconstructedKonvolut. }`; public static readonly query_key: string = 'id'; } diff --git a/nietzsche-beta-app/src/app/tln-edition/datatypes/manuscript.ts b/nietzsche-beta-app/src/app/tln-edition/datatypes/manuscript.ts index fa6224e..bc5f1cf 100644 --- a/nietzsche-beta-app/src/app/tln-edition/datatypes/manuscript.ts +++ b/nietzsche-beta-app/src/app/tln-edition/datatypes/manuscript.ts @@ -1,235 +1,237 @@ import { BasicResultBindingElement, FusekiResults } from './basic_datatype'; import { Manuscript, Page } from '../models'; import { TlnPositionalStyleMarkup } from './positional-markup'; import { PageStub, TlnPage } from './page'; export class ManuscriptStub extends BasicResultBindingElement implements Manuscript { static readonly query: string = ` PREFIX data: PREFIX tln: SELECT ?id ?title ?type WHERE { ?id a tln:ArchivalManuscriptUnity ; tln:hasTitle ?title; tln:hasManuscriptType ?type. }`; title: string; type: string; constructor (data: any, id?: string, service?: any) { super(data, id, service); this.title = this.getData4Key('title'); this.type = this.getData4Key('type'); } } export class TlnExtManuscript extends ManuscriptStub { /** * the internal default key for replacing {@link /classes/TlnLine.html#query|query} by "id" * in {@link /classes/TlnLine.html#getQuery|getQuery} if "key" is omitted. **/ static readonly default_key: string = 'manuscript'; static readonly query: string = ` PREFIX data: PREFIX tln: PREFIX rdf: PREFIX stoff: SELECT DISTINCT ?gsaSignature ?title ?thumbImage ?type ?archivalicSignature WHERE { ?manuscript tln:hasPages/rdf:first/tln:hasFaksimileImage/tln:hasThumburl ?thumbImage; - tln:hasArchivalicSignature ?archivalicSignature; tln:hasGsaSignature ?gsaSignature; tln:hasTitle ?title; tln:hasManuscriptType ?type. + OPTIONAL { + ?manuscript tln:hasArchivalicSignature ?archivalicSignature. + } }`; /** * the public key for replacing {@link /classes/TlnLine.html#query|query} by "id". **/ static readonly query_key: string = 'manuscript'; thumbImage: string; gsaSignature?: string; archivalicSignature?: string; constructor (data: any, id?: string, service?: any) { super(data, id, service); this.thumbImage = this.getData4Key('thumbImage'); this.gsaSignature = this.getData4Key('gsaSignature'); this.archivalicSignature = this.getData4Key('archivalicSignature'); } } export class ReconstructedKonvolut extends ManuscriptStub { /** * the internal default key for replacing {@link /classes/TlnLine.html#query|query} by "id" * in {@link /classes/TlnLine.html#getQuery|getQuery} if "key" is omitted. **/ static readonly default_key: string = 'manuscript'; static readonly query: string = ` PREFIX data: PREFIX tln: PREFIX rdf: PREFIX stoff: SELECT DISTINCT ?id ?manuscriptTitle ?title ?type ?page ?number ?description WHERE { ?manuscript tln:partsBelongToReconstructedKonvolut ?id. ?id tln:hasTitle ?manuscriptTitle; tln:hasDescription/tln:textHasContent ?description; tln:hasManuscriptType ?type; tln:hasPages/rdf:rest*/rdf:first ?page. OPTIONAL { ?page tln:hasNumber ?number.} OPTIONAL { ?archivalicUnity a tln:ArchivalManuscriptUnity; tln:hasPages/rdf:rest*/rdf:first ?page; tln:hasTitle ?title. } }`; /** * the public key for replacing {@link /classes/TlnLine.html#query|query} by "id". **/ static readonly query_key: string = 'manuscript'; pages: Page[] = []; description: string; constructor (data: any, id?: string, service?: any) { super(data, id, service); this.title = this.getData4Key('manuscriptTitle'); this.description = this.getData4Key('description'); } public static convertData(this: T, data: FusekiResults, id?: string, service?: any): Array> { let elements = []; let content = this.getContent(data); for (var i = 0; i < content.length; i++){ let element = new ReconstructedKonvolut(content[i], id, service); let pages = []; if (content[i]['page'] != undefined && content[i]['page'] != null){ pages = (content[i]['title'] != undefined && content[i]['title'] != null) ? TlnPage.convertData({ head: { vars: []}, results: { bindings: [ content[i] ] } }, content[i]['page']['value']) : PageStub.convertData({ head: { vars: []}, results: { bindings: [ content[i] ] } }, content[i]['page']['value']); } if (elements.length > 0 && elements[elements.length-1].id == element.id){ if (pages.length > 0){ elements[elements.length-1].pages.push(pages[0]); } } else { if (pages.length > 0){ element.pages.push(pages[0]); } elements.push(element) } } //console.log(elements) return elements; } } export class ManuscriptDescription extends BasicResultBindingElement { /** * the internal default key for replacing {@link /classes/TlnLine.html#query|query} by "id" * in {@link /classes/TlnLine.html#getQuery|getQuery} if "key" is omitted. **/ static readonly default_key: string = 'manuscript'; static readonly query: string = ` PREFIX data: PREFIX tln: PREFIX rdf: PREFIX stoff: SELECT DISTINCT ?id ?text ?description_markup ?cssStyleTag ?startIndex ?endIndex WHERE { ?manuscript tln:hasDescription ?id. ?id tln:textHasContent ?text. OPTIONAL { ?id tln:textHasMarkup ?description_markup. ?description_markup stoff:hasCSS ?cssStyleTag; stoff:standoffMarkupHasStartIndex ?startIndex; stoff:standoffMarkupHasEndIndex ?endIndex.} }`; /** * the public key for replacing {@link /classes/TlnLine.html#query|query} by "id". **/ static readonly query_key: string = 'manuscript'; text: string; markups: TlnPositionalStyleMarkup[]; constructor (data: any, id?: string, service?: any) { super(data, id, service); this.text = this.getData4Key('text'); this.markups = []; } public static convertData(this: T, data: FusekiResults, id?: string, service?: any): Array> { let elements = []; let content = this.getContent(data); for (var i = 0; i < content.length; i++){ let element = new ManuscriptDescription(content[i], id, service); let markups = (content[i]['description_markup'] != undefined && content[i]['description_markup'] != null) ? TlnPositionalStyleMarkup.convertData({ head: { vars: []}, results: { bindings: [ content[i] ] } }, content[i]['description_markup']['value']) : []; if (elements.length > 0 && elements[elements.length-1].id == element.id){ if (markups.length > 0){ elements[elements.length-1].markups.push(markups[0]); } } else { if (markups.length > 0){ element.markups.push(markups[0]); } elements.push(element) } } //console.log(elements) return elements; } } export class ManuscriptEarlierDescription extends BasicResultBindingElement { /** * the internal default key for replacing {@link /classes/TlnLine.html#query|query} by "id" * in {@link /classes/TlnLine.html#getQuery|getQuery} if "key" is omitted. **/ static readonly default_key: string = 'manuscript'; static readonly query: string = ` PREFIX data: PREFIX tln: PREFIX stoff: SELECT ?id ?text ?author ?citation ?description_markup ?cssStyleTag ?startIndex ?endIndex WHERE { ?manuscript tln:hasEarlierDescriptions ?id. ?id tln:textHasContent ?text; tln:hasAuthor ?author; tln:hasCitation ?citation. OPTIONAL { ?id tln:textHasMarkup ?description_markup. ?description_markup stoff:hasCSS ?cssStyleTag; stoff:standoffMarkupHasStartIndex ?startIndex; stoff:standoffMarkupHasEndIndex ?endIndex.} }`; /** * the public key for replacing {@link /classes/TlnLine.html#query|query} by "id". **/ static readonly query_key: string = 'manuscript'; text: string; author: string; citation: string; markups: TlnPositionalStyleMarkup[]; constructor (data: any, id?: string, service?: any) { super(data, id, service); this.text = this.getData4Key('text'); this.author = this.getData4Key('author'); this.citation = this.getData4Key('citation'); this.markups = []; } public static convertData(this: T, data: FusekiResults, id?: string, service?: any): Array> { let elements = []; let content = this.getContent(data); for (var i = 0; i < content.length; i++){ let element = new ManuscriptEarlierDescription(content[i], id, service); let markups = (content[i]['description_markup'] != undefined && content[i]['description_markup'] != null) ? TlnPositionalStyleMarkup.convertData({ head: { vars: []}, results: { bindings: [ content[i] ] } }, content[i]['description_markup']['value']) : []; if (elements.length > 0 && elements[elements.length-1].id == element.id){ if (markups.length > 0){ elements[elements.length-1].markups.push(markups[0]); } } else { if (markups.length > 0){ element.markups.push(markups[0]); } elements.push(element) } } //console.log(elements) return elements; } } diff --git a/nietzsche-beta-app/src/app/tln-edition/datatypes/search.ts b/nietzsche-beta-app/src/app/tln-edition/datatypes/search.ts new file mode 100644 index 0000000..9210e46 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/datatypes/search.ts @@ -0,0 +1,130 @@ +import { BasicResultBindingElement, FusekiResults} from './basic_datatype'; +import { TlnWord } from './word'; +export class TlnExtWord extends TlnWord { + startLine?: string; + endLine?: string; + + constructor(data: any, id?: string, service?: any){ + super(data, id, service) + this.startLine = this.getData4Key('startLine'); + this.endLine = this.getData4Key('endLine'); + } +} +export class PageResult { + words: TlnExtWord[] = []; + + constructor(words: TlnExtWord[]){ + this.words = words; + } + public getWords(): string[] { + return this.words.map(word =>word.id); + } + public getStartLine(): string { + let sortedWords = this.words.sort((word0, word1) =>word0.line_number - word1.line_number) + if (sortedWords.length == 0){ + return ''; + } + return (sortedWords[0].startLine != undefined && sortedWords[0].startLine != null) ? sortedWords[0].startLine : sortedWords[0].line; + } + public getEndLine(): string { + let sortedWords = this.words.sort((word0, word1) =>word0.line_number - word1.line_number) + if (sortedWords.length == 0){ + return ''; + } + return (sortedWords[sortedWords.length-1].endLine != undefined && sortedWords[sortedWords.length-1].endLine != null) + ? sortedWords[sortedWords.length-1].endLine : sortedWords[sortedWords.length-1].line; + } +} + +export class FoundPage extends BasicResultBindingElement{ + static readonly query: string = ` + PREFIX tln: + PREFIX rdf: + + SELECT DISTINCT ?id ?manuscript ?title ?number ?word ?text ?line ?line_number ?startLine ?endLine WHERE { + ?id a tln:Page; + tln:hasNumber ?number; + tln:hasPseudoText ?fulltext. + FILTER regex(?fulltext, "#find#", "s"). + ?manuscript a tln:ArchivalManuscriptUnity; + tln:hasManuscriptType "Mappe"; + tln:hasPages/rdf:rest*/rdf:first ?id; + tln:hasTitle ?title. + ?id tln:hasWords/rdf:rest*/rdf:first ?word. + ?word tln:hasOutputText ?text; + tln:wordBelongsToLine ?line. + ?line tln:lineHasNumber ?line_number. + OPTIONAL{ ?previouseNode rdf:rest/rdf:first ?line; + rdf:first ?startLine.} + OPTIONAL{ ?myNode rdf:first ?line; + rdf:rest/rdf:first ?endLine.} + #FILTER(). + } order by ?id ?line_number`; + title: string + number: string; + manuscript: string + results: PageResult[] = []; + + + constructor (data: any, id?: string, service?: any) { + super(data, id, service); + this.title = this.getData4Key('title'); + this.number = this.getData4Key('number'); + this.manuscript = this.getData4Key('manuscript'); + } + public removeIncompleteResults(searchTerms: string[]) { + this.results = this.results.filter(result =>searchTerms.every(searchText =>result.words.filter(word =>word.text.match('^[^\w\s]*' + searchText + '.*')).length > 0)) + } + /** + * This method returns the parametrized SPARQL query of this FoundPage + * + * If "key" is omitted {@link /classes/BasicResultBindingElement.html#default_key|default_key} will be used. + * + * @param find the search text + * @param key will be ignored. + **/ + public static getQuery(find?: string, key?: string): string { + if(find == undefined || find == null){ + return this.query; + } + let words = find.split(' ') + let find_regex = words.join('.*') + '.*' + let filter = 'FILTER regex(?text, "^[^\\\\w]?(' + words.join('.*|') + '.*)")'; + let query = this.query.replace('#find#', find_regex).replace('#FILTER()', filter); + //console.log(query); + return query; + } + public static convertData(this: T, data: FusekiResults, id?: string, service?: any): Array> { + let elements = []; + let pages = []; + let searchTerms = service.getSearchTerms(); + let content = this.getContent(data); + let currentResult: PageResult = null; + let currentPage: FoundPage = null; + for (var i = 0; i < content.length; i++){ + let page = new FoundPage(content[i], id, service); + if(content[i]['word'] != undefined && content[i]['word'] != null) { + let words = TlnExtWord.convertData({ head: { vars: []}, results: { bindings: [ content[i] ] } }, content[i]['word']['value']); + if (pages.length == 0 || pages.map(page =>page.id).indexOf(page.id) == -1){ + currentResult = new PageResult(words); + currentPage = page; + currentPage.results.push(currentResult) + pages.push(currentPage) + } else { + if (currentResult.words.indexOf(words[0]) == -1){ + if (currentResult.words.length > 0 + && (Math.abs(Math.min(...currentResult.words.map(word =>word.line_number)) - words[0].line_number) > 4 + || Math.abs(Math.max(...currentResult.words.map(word =>word.line_number)) - words[0].line_number) > 4)){ + currentResult = new PageResult(words); + currentPage.results.push(currentResult); + } else { + currentResult.words.push(words[0]); + } + } + } + } + } + pages.forEach(page =>page.removeIncompleteResults(searchTerms)); + return pages.filter(page =>page.results.length > 0); + } +} diff --git a/nietzsche-beta-app/src/app/tln-edition/debug.pipe.spec.ts b/nietzsche-beta-app/src/app/tln-edition/debug.pipe.spec.ts new file mode 100644 index 0000000..15747c5 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/debug.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DebugPipe } from './debug.pipe'; + +describe('DebugPipe', () => { + it('create an instance', () => { + const pipe = new DebugPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/debug.pipe.ts b/nietzsche-beta-app/src/app/tln-edition/debug.pipe.ts new file mode 100644 index 0000000..9e0c555 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/debug.pipe.ts @@ -0,0 +1,13 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'debug' +}) +export class DebugPipe implements PipeTransform { + + transform(value: any): any { + console.log(value) + return value; + } + +} diff --git a/nietzsche-beta-app/src/app/tln-edition/route-updater.ts b/nietzsche-beta-app/src/app/tln-edition/route-updater.ts index c55f009..859514c 100644 --- a/nietzsche-beta-app/src/app/tln-edition/route-updater.ts +++ b/nietzsche-beta-app/src/app/tln-edition/route-updater.ts @@ -1,50 +1,54 @@ import { Router, ActivatedRoute, Params } from '@angular/router'; import { Mapping, RouteReader } from './route-reader'; export class RouteUpdater extends RouteReader { protected mapping: Mapping; protected routerParams: Params; protected currentRoute: string; parentActivatedRoute: ActivatedRoute; constructor(protected router: Router, protected activatedRoute: ActivatedRoute ) { super(router, activatedRoute); + if(this.currentRoute == undefined || this.currentRoute == null){ + this.currentRoute = (this.activatedRoute.snapshot.routeConfig != null) + ? this.activatedRoute.snapshot.routeConfig.path : null; + } } protected updateParams(launch?: boolean) { let newRouterParam = {}; for(let key of Object.keys(this.mapping)){ let paramsKey = this.mapping[key]['param']; if(this[key] != null){ if (Array.isArray(this[key]) && this[key].length > 0){ newRouterParam[paramsKey] = JSON.stringify(this[key]); } else { newRouterParam[paramsKey] = this[key]; } } } for(let key of Object.keys(this.routerParams)){ if(newRouterParam[key] == null){ newRouterParam[key] = this.routerParams[key]; } } let parentActivatedRoute = (this.activatedRoute.parent != null) ? this.activatedRoute.parent : this.parentActivatedRoute; if(parentActivatedRoute != undefined && parentActivatedRoute != null){ parentActivatedRoute.url.subscribe(url=>{ let parentPath = url[0].path; if (launch != undefined && launch){ let link = this.router.createUrlTree([ parentPath + '/' + this.currentRoute], { queryParams: newRouterParam }); window.open(link.toString(), '_blank') } else { this.router.navigate([ parentPath + '/' + this.currentRoute], { queryParams: newRouterParam }); } }); } else { if (launch != undefined && launch){ let link = this.router.createUrlTree([ this.currentRoute], { queryParams: newRouterParam }); window.open(link.toString(), '_blank') } else { this.router.navigate([ this.currentRoute], { queryParams: newRouterParam }); } } } } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.css b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.css index 90d18aa..9f0f9dd 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.css +++ b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.css @@ -1,26 +1,18 @@ #navi { width: 100%; height: 50px; margin: 0; padding: 0; white-space: nowrap; } .search { margin-left: 8px; } -.zoom { - max-width: 20px; -} -.zoom-in { - cursor: zoom-in; -} -.zoom-out { - cursor: zoom-out; -} + .mat-button.min-width { min-width: 120px; max-width: 120px; } .default-mouse { cursor: default; } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.html index a1af008..2fc987f 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.html +++ b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.html @@ -1,30 +1,18 @@ diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.ts index 9b1b309..b751b6e 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.ts +++ b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/navigation/navigation.component.ts @@ -1,161 +1,107 @@ import { Component, OnInit, Input } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; -import {MatBottomSheet, MatBottomSheetRef} from '@angular/material/bottom-sheet'; import { TlnQueryServiceInterface, Reference, ManuscriptUnity, NavigationPage } from '../../models'; import { TlnManuscriptUnity, TlnNavigationPage} from '../../datatypes/navigation'; import { DEFAULT_VIEW_OPTION, TLN_VIEWER_ROUTE, TLN_CROSSREF_ROUTE, TLN_CONTEXT_VIEW_PARAM, TLN_FULLSCREEN_PARAM, TLN_FIND_PARAM, TLN_PAGE_PARAM, TLN_MANUSCRIPT_PARAM, TLN_SELECTED_LINES_PARAM, TLN_VIEW_OPTION_PARAM, TLN_ZOOM_PARAM, VIEW_OPTIONS, ONTOLOTY_PREFIX } from '../../constants'; import { IsReconstructedKonvolut } from '../../datatypes/basic_datatype'; import { TlnLine} from '../../datatypes/line'; import { TlnTextGeneticOrder} from '../../datatypes/text_version'; import { Mapping } from '../../route-reader'; import { RouteUpdater } from '../../route-updater'; import { ComplexKeyIriMapping, DataHandler, KeyIriMapping } from '../../data_handler'; import { PageViewService, TlnQueryService } from '../../services'; import { TlnInformationComponent, ParentInformation } from '../../tln-information/tln-information.component'; import { PageInformation } from '../../tln-information/page-information'; @Component({ selector: 'crossref-navigation', templateUrl: './navigation.component.html', styleUrls: ['./navigation.component.css'] }) export class NavigationComponent extends RouteUpdater { /** * OPTIONAL pass a queryService with method * {@link /interfaces/TlnQueryServiceInterface.html#getData|getData} * to TlnPageViewComponent. **/ @Input() queryService: TlnQueryServiceInterface; /** * whether or not to show page view in fullscreen mode. **/ fullscreen: boolean = false; - zoomFactor: number = 1; - findText: string; current_iri: string; current_manuscript_iri: string; current_page: NavigationPage; pageInformation: PageInformation; previous_page: NavigationPage; next_page: NavigationPage; showArchivalManuscriptUnity: boolean = false; dataHandler: DataHandler = new DataHandler(this); geneticOrders: TlnTextGeneticOrder[] = []; selectedLines: string[] = []; private readonly PAGE_CONTEXT_VIEW: string = TLN_PAGE_PARAM; private readonly MANUSCRIPT_CONTEXT_VIEW: string = TLN_MANUSCRIPT_PARAM; contextView: string = this.PAGE_CONTEXT_VIEW; private readonly increment: number = 0.333; private readonly decrement: number = this.increment*-1; protected currentRoute: string = TLN_CROSSREF_ROUTE; - protected mapping: Mapping = { findText: { param: TLN_FIND_PARAM, type: "string" }, + protected mapping: Mapping = { contextView: { param: TLN_CONTEXT_VIEW_PARAM, type: "string" }, current_iri: { param: TLN_PAGE_PARAM, type: "string" }, current_manuscript_iri: { param: TLN_MANUSCRIPT_PARAM, type: "string" }, - fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" }, - zoomFactor: { param: TLN_ZOOM_PARAM, type: "number" } + fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" } } routerParams: Params; selectedViewOption: string = DEFAULT_VIEW_OPTION updating: boolean = false; viewOptions: string[] = [ VIEW_OPTIONS.TRANSKRIPTION, VIEW_OPTIONS.FAKSIMILE, VIEW_OPTIONS.SYNOPSIS, VIEW_OPTIONS.SYNOPSIS_B ]; - constructor(private bottomSheet: MatBottomSheet, private pageViewService: PageViewService, private localQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute ) { + constructor(private pageViewService: PageViewService, private localQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute ) { super(router, activatedRoute); } ngOnInit() { let tlnQueryService = (this.queryService != null) ? this.queryService : this.localQueryService; this.dataHandler.addHandler('navigation_page', ['current_page', 'geneticOrders'] ); this.dataHandler.addHandler('current_page', { 'handler': TlnNavigationPage }); this.dataHandler.addHandler('geneticOrders', { 'handler': TlnTextGeneticOrder}); this.dataHandler.setQueryService(tlnQueryService); this.dataHandler.start_processing.subscribe( (started: boolean) =>{ this.updating = true; }); this.dataHandler.processing_finished.subscribe( (finished: boolean) =>{ this.updating = false; }); super.ngOnInit(); - this.pageViewService.reference.subscribe( - (newReference: Reference) => { - this.updatePageToReference(newReference) - }) - this.pageViewService.onClickedLine.subscribe( - (clickedLine: TlnLine) => { - let index = this.selectedLines.indexOf(clickedLine.id) - if (index > -1){ - this.selectedLines.splice(index, 1); - } else { - this.selectedLines.push(clickedLine.id); - } - this.updateParams(); - }); - } - private clearFindText() { - this.findText = ''; - this.updateParams(); } changeContext(){ this.contextView = (this.contextView == this.PAGE_CONTEXT_VIEW) ? this.MANUSCRIPT_CONTEXT_VIEW : this.PAGE_CONTEXT_VIEW; //this.current_genetic_order_iri = 'none'; this.updateParams(); } private getPageTitle(page?: NavigationPage, numPages?: number): string { if (page == null){ return ''; } let indexPrefix = (numPages != null) ? page.index + '/' + numPages : page.index; return indexPrefix + ': ' + page.title + ' ' + page.number; } - private getZoomTitle(changeValue: number): string { - if (this.zoomFactor+changeValue < 0){ - return Math.round(this.zoomFactor*50) + '%'; - } - return Math.round((this.zoomFactor+changeValue)*100) + '%'; - } protected readParams(params: Params){ super.readParams(params); if (this.dataHandler.ready && (this.current_page == null || this.current_page.id != this.current_iri)){ this.dataHandler.resetData('navigation_page') this.dataHandler.getData('current_page', this.current_iri); } } - private setZoomFactor(newZoomFactor: number){ - if (newZoomFactor > 0){ - this.zoomFactor = Math.round(newZoomFactor*100)/100; - } else { - this.zoomFactor = this.zoomFactor/2 - } - this.updateParams(); - } private setCurrentIri(pageIri: string){ this.dataHandler.stop_processing.emit(true); this.current_iri = pageIri; this.currentRoute = TLN_VIEWER_ROUTE; this.updateParams(); } - private showInformation() { - let parentData: ParentInformation = { - geneticOrders: this.geneticOrders, - page: this.current_page, - manuscript_iri: this.current_manuscript_iri - } - this.bottomSheet.open(TlnInformationComponent, { - data: parentData - }); - } - private updatePageToReference(reference: Reference){ - this.current_iri = reference.page.id; - this.selectedLines = [ reference.line.id ] - this.updateParams(); - } private toggleFullscreen(){ this.fullscreen = !this.fullscreen; this.updateParams(); } - public test(iri?: string){ - this.bottomSheet.open(TlnInformationComponent); - //this.dataHandler.isOfType('showArchivalManuscriptUnity', 'http://rdfh.ch/projects/0068#_Mp_XIV', 'http://www.nie.org/ontology/nietzsche#ArchivalManuscriptUnity') - } + } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/page-version-view/page-version-view.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/page-version-view/page-version-view.component.ts index 64f3a5f..51c0218 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/page-version-view/page-version-view.component.ts +++ b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/page-version-view/page-version-view.component.ts @@ -1,60 +1,59 @@ import { Component, Input, OnInit } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; import { MatBottomSheetRef} from '@angular/material/bottom-sheet'; import { ManuscriptUnity, NavigationPage} from '../../models'; import { Mapping, RouteReader } from '../../route-reader'; import { RouteUpdater } from '../../route-updater'; import { TlnTextGeneticOrder} from '../../datatypes/text_version'; import { TLN_CONTEXT_VIEW_PARAM, TLN_PAGE_PARAM, TLN_MANUSCRIPT_PARAM, TLN_TEXT_GENETIC_ORDER_PARAM, TLN_CROSSREF_ROUTE } from '../../constants'; @Component({ selector: 'page-version-view', templateUrl: './page-version-view.component.html', styleUrls: ['./page-version-view.component.css'] }) export class PageVersionViewComponent extends RouteUpdater implements OnInit { /** * IRI of the current page **/ current_iri: string; /** * the current page **/ @Input() current_page_iri: string; /** * the genetic text order that should be displayed. **/ @Input() geneticOrders: TlnTextGeneticOrder[] = []; @Input() filterGeneticOrder: string; @Input() bottomSheetRef: MatBottomSheetRef; @Input() parentActivatedRoute: ActivatedRoute; current_manuscript_iri: string; current_genetic_order: string; contextView: string; protected currentRoute: string = TLN_CROSSREF_ROUTE; protected mapping: Mapping = { current_iri: { param: TLN_PAGE_PARAM, type: "string" }, current_manuscript_iri: { param: TLN_MANUSCRIPT_PARAM, type: "string" }, contextView: { param: TLN_CONTEXT_VIEW_PARAM, type: "string" }, current_genetic_order: { param: TLN_TEXT_GENETIC_ORDER_PARAM, type: "string" } } constructor(protected router: Router, protected activatedRoute: ActivatedRoute ){ super(router, activatedRoute); } ngOnInit() { super.ngOnInit(); - console.log(this.parentActivatedRoute); } private openCrossRef(geneticOrder: TlnTextGeneticOrder){ this.current_genetic_order = geneticOrder.id; this.current_iri = this.current_page_iri this.contextView = TLN_PAGE_PARAM; this.updateParams(); if(this.bottomSheetRef != undefined && this.bottomSheetRef != null){ this.bottomSheetRef.dismiss(); } } } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/tln-crossref.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/tln-crossref.component.html index f922ee4..9f5bfef 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-crossref/tln-crossref.component.html +++ b/nietzsche-beta-app/src/app/tln-edition/tln-crossref/tln-crossref.component.html @@ -1,78 +1,78 @@

Querverweise von {{current_manuscript.title}}

{{current_manuscript.title}} {{page.number}}

Querverweise von {{current_page.title}} {{current_page.number}}

Ausgewählte Querverweise

south
{{version.title}}, {{textUnity.number}}, {{textUnity.startLine}}-{{textUnity.endLine}} - - + +
diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-edition.module.ts b/nietzsche-beta-app/src/app/tln-edition/tln-edition.module.ts index 5ba8e64..759203f 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-edition.module.ts +++ b/nietzsche-beta-app/src/app/tln-edition/tln-edition.module.ts @@ -1,69 +1,83 @@ import { BrowserModule } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { HttpClientModule } from "@angular/common/http"; import { NgModule } from '@angular/core'; -import { MatBottomSheetModule,MatButtonModule,MatCheckboxModule,MatDialogModule,MatExpansionModule,MatFormFieldModule,MatInputModule,MatListModule,MatPaginatorModule,MatRadioModule,MatSelectModule,MatSidenavModule,MatSortModule,MatTableModule,MatToolbarModule,MatButtonToggleModule,MatCardModule,MatIconModule,MatMenuModule,MatTabsModule,MatTooltipModule +import { MatProgressSpinnerModule,MatBottomSheetModule,MatButtonModule,MatCheckboxModule,MatDialogModule,MatExpansionModule,MatFormFieldModule,MatInputModule,MatListModule,MatPaginatorModule,MatRadioModule,MatSelectModule,MatSidenavModule,MatSortModule,MatTableModule,MatToolbarModule,MatButtonToggleModule,MatCardModule,MatIconModule,MatMenuModule,MatTabsModule,MatTooltipModule } from '@angular/material'; import { NgxMatStandoffMarkupModule } from '../lib/ngx-mat-standoff-markup.module'; import { PageViewService } from '../page-view/page-view.service'; import { PageViewModule } from '../page-view/page-view.module'; import { TlnPageViewComponent } from './tln-page-view.component'; import { TlnQueryService } from './tln-query.service'; import { ToolTipComponent } from './tooltip/tool-tip.component'; import { TlnViewerNavigation } from './tln-viewer-navigation/tln-viewer-navigation.component'; import { TlnInformationComponent } from './tln-information/tln-information.component'; import { TlnCrossrefComponent } from './tln-crossref/tln-crossref.component'; import { VersionViewComponent } from './tln-crossref/version-view/version-view.component'; import { PageVersionViewComponent } from './tln-crossref/page-version-view/page-version-view.component'; import { NavigationComponent } from './tln-crossref/navigation/navigation.component'; import { FilterPipe } from './tln-crossref/page-version-view/filter.pipe'; import { TlnPageVersionViewComponent } from './tln-crossref/page-version-view/tln-page-version-view.component'; import { TlnManuscriptViewComponent } from './tln-manuscript-view/tln-manuscript-view.component'; +import { TlnFulltextComponent } from './tln-fulltext/tln-fulltext.component'; +import { FulltextNavigationComponent } from './tln-fulltext/navigation/navigation.component'; +import { ResultPipePipe } from './tln-fulltext/result-pipe.pipe'; +import { SearchComponent } from './tln-navigation-elements/search.component'; +import { ToggleNavigationComponent } from './tln-navigation-elements/toggle-navigation.component'; +import { ZoomComponent } from './tln-navigation-elements/zoom.component'; +import { ZoomPipe } from './tln-navigation-elements/zoom.pipe'; +import { OpenInViewerComponent } from './tln-navigation-elements/open-in-viewer.component'; +import { DebugPipe } from './debug.pipe'; +import { TlnHeightDirective } from './tln-height.directive'; @NgModule({ - declarations: [TlnPageViewComponent, ToolTipComponent, TlnViewerNavigation, TlnInformationComponent, TlnCrossrefComponent, VersionViewComponent, PageVersionViewComponent, NavigationComponent, FilterPipe, TlnPageVersionViewComponent, TlnManuscriptViewComponent], + declarations: [FulltextNavigationComponent, TlnPageViewComponent, ToolTipComponent, TlnViewerNavigation, TlnInformationComponent, TlnCrossrefComponent, VersionViewComponent, PageVersionViewComponent, NavigationComponent, FilterPipe, TlnPageVersionViewComponent, TlnManuscriptViewComponent, TlnFulltextComponent, ResultPipePipe, SearchComponent, ToggleNavigationComponent, ZoomComponent, ZoomPipe, OpenInViewerComponent, DebugPipe, TlnHeightDirective], imports: [ MatBottomSheetModule, MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule, MatDialogModule, MatExpansionModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, + MatProgressSpinnerModule, MatPaginatorModule, MatRadioModule, MatSelectModule, MatSidenavModule, MatSortModule, MatTableModule, MatTabsModule, MatToolbarModule, MatTooltipModule, BrowserModule, CommonModule, FormsModule, NgxMatStandoffMarkupModule, PageViewModule ], exports: [ + DebugPipe, + FulltextNavigationComponent, NavigationComponent, ToolTipComponent, TlnCrossrefComponent, + TlnHeightDirective, TlnManuscriptViewComponent, TlnPageViewComponent, TlnViewerNavigation ], providers: [ PageViewService, TlnQueryService ], entryComponents: [TlnInformationComponent] }) export class TlnEditionModule { } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.css b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.css new file mode 100644 index 0000000..8bf00b9 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.css @@ -0,0 +1,7 @@ +#navi { + width: 100%; + height: 50px; + margin: 0; + padding: 0; + white-space: nowrap; +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.html new file mode 100644 index 0000000..39bc77c --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.html @@ -0,0 +1,4 @@ + diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.spec.ts new file mode 100644 index 0000000..3857718 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NavigationComponent } from './navigation.component'; + +describe('NavigationComponent', () => { + let component: NavigationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ NavigationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(NavigationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.ts new file mode 100644 index 0000000..87479c0 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/navigation/navigation.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'fulltext-navigation', + templateUrl: './navigation.component.html', + styleUrls: ['./navigation.component.css'] +}) +export class FulltextNavigationComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/result-pipe.pipe.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/result-pipe.pipe.spec.ts new file mode 100644 index 0000000..5187909 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/result-pipe.pipe.spec.ts @@ -0,0 +1,8 @@ +import { ResultPipePipe } from './result-pipe.pipe'; + +describe('ResultPipePipe', () => { + it('create an instance', () => { + const pipe = new ResultPipePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/result-pipe.pipe.ts b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/result-pipe.pipe.ts new file mode 100644 index 0000000..2b46957 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/result-pipe.pipe.ts @@ -0,0 +1,18 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { FoundPage} from '../datatypes/search'; +@Pipe({ + name: 'resultPipe' +}) +export class ResultPipePipe implements PipeTransform { + + transform(pages: FoundPage[]): string { + if (pages.length == 0){ + return 'Keine Treffer' + } + let pageResult = (pages.length > 1) ? pages.length + ' Seiten' : pages[0].title + ' ' + pages[0].number; + let numFoundWords = 0; + pages.forEach(page =>page.results.forEach(result =>numFoundWords++)); + return numFoundWords + ' Treffer auf ' + pageResult; + } + +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.css b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.css new file mode 100644 index 0000000..ebe194c --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.css @@ -0,0 +1,53 @@ +#page { + width: 100%; + position: relative; + top: 0px; + left: 0px; +} +.icon-button { + width: 15px; + margin-left: 3px; +} +.page-navi { + float: left; + margin-top: -3px; + margin-bottom: 1px; + height: 38px; + background-color: lightblue; + z-index: 2; +} +.default-mouse { + cursor: default; +} +.small-grey { + color: lightgrey; + font-size: 80%; +} +.text { + position: absolute; + top: 10px; + left: 500px; +} +.search { + position: relative; + top: 60px; + width: 500px; + height: 100%; + text-align: center; + margin-right: 20px; +} +.extra-space { + margin-top: 45px; +} +.title { + text-align: left; + margin-left: 20px; +} +.form { + width: 95%; +} +.full-width { + min-width: 150px; + max-width: 500px; + width: 80%; +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.html new file mode 100644 index 0000000..0970987 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.html @@ -0,0 +1,44 @@ +
+ + +
+
+ + {{page.title}}, {{page.number}} + + + + +
+
+ +
diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.spec.ts new file mode 100644 index 0000000..8c6e41f --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TlnFulltextComponent } from './tln-fulltext.component'; + +describe('TlnFulltextComponent', () => { + let component: TlnFulltextComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TlnFulltextComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TlnFulltextComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.ts new file mode 100644 index 0000000..b544caf --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-fulltext/tln-fulltext.component.ts @@ -0,0 +1,84 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { TLN_CROSSREF_ROUTE, TLN_SEARCH_ROUTE, TLN_MANUSCRIPT_ROUTE, TLN_VIEWER_ROUTE, TLN_CONTEXT_VIEW_PARAM, TLN_FULLSCREEN_PARAM, TLN_FIND_PARAM, TLN_PAGE_PARAM, TLN_MANUSCRIPT_PARAM, +TLN_SELECTED_LINES_PARAM, TLN_TEXT_GENETIC_ORDER_PARAM, TLN_VIEW_OPTION_PARAM, TLN_ZOOM_PARAM, VIEW_OPTIONS, ONTOLOTY_PREFIX } from '../constants'; +import { DataHandler } from '../data_handler'; +import { FoundPage} from '../datatypes/search'; +import { Mapping } from '../route-reader'; +import { RouteUpdater } from '../route-updater'; +import { TlnQueryService } from '../services'; +@Component({ + selector: 'tln-fulltext', + templateUrl: './tln-fulltext.component.html', + styleUrls: ['./tln-fulltext.component.css'] +}) +export class TlnFulltextComponent extends RouteUpdater implements OnInit { + protected currentRoute: string = TLN_SEARCH_ROUTE; + current_page_iri: string; + current_manuscript_unity: string; + dataHandler: DataHandler = new DataHandler(this); + fullscreen: boolean; + max_width: number = -1; + max_height: number = -1; + searchTerm: string; + resultsReceived: boolean = false; + selectedViewOption: string = VIEW_OPTIONS.TRANSKRIPTION + startSearch: boolean = false; + protected mapping: Mapping = { + current_page_iri: { param: TLN_PAGE_PARAM, type: "string" }, + searchTerm: { param: TLN_FIND_PARAM, type: "string" }, + current_manuscript_unity: { param: TLN_MANUSCRIPT_PARAM, type: "string" }, + fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" }, + } + pages: FoundPage[] = []; + private readonly margin_width: number = 280; + private readonly initialPreviewWidth : number = 300; + previewWidth: number = this.initialPreviewWidth; + + constructor(private tlnQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute ) { + super(router, activatedRoute); + } + + ngOnInit() { + if (screen.availWidth - this.initialPreviewWidth - this.margin_width > 1000){ + this.previewWidth = screen.availWidth - this.initialPreviewWidth - 1000; + } + this.max_width = screen.availWidth - this.previewWidth - this.margin_width; + this.max_height = screen.availHeight - 200; + this.dataHandler.addHandler('pages', { 'handler': FoundPage}); + this.dataHandler['pages']['service'] = this + this.dataHandler.setQueryService(this.tlnQueryService); + this.dataHandler.start_processing.subscribe( + (started: boolean) =>{ + this.resultsReceived = false; + this.startSearch = true; + }); + this.dataHandler.processing_finished.subscribe( + (finished: boolean) =>{ + this.resultsReceived = true; + this.startSearch = false; + }); + super.ngOnInit(); + } + private clearFindText() { + this.searchTerm = ''; + this.pages = []; + super.updateParams(); + } + private search(){ + super.updateParams(); + if (this.searchTerm != undefined && this.searchTerm != null && this.searchTerm != ''){ + this.dataHandler.getData('pages', this.searchTerm); + } + } + protected readParams(params: Params){ + let oldSearchTerm = this.searchTerm; + super.readParams(params); + if (this.searchTerm != undefined && this.searchTerm != null && this.searchTerm != '' && this.searchTerm != oldSearchTerm){ + this.dataHandler.getData('pages', this.searchTerm); + } + } + getSearchTerms(): string[] { + return this.searchTerm.split(' '); + } +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-height.directive.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-height.directive.spec.ts new file mode 100644 index 0000000..1752d4b --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-height.directive.spec.ts @@ -0,0 +1,8 @@ +import { TlnHeightDirective } from './tln-height.directive'; + +describe('TlnHeightDirective', () => { + it('should create an instance', () => { + const directive = new TlnHeightDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-height.directive.ts b/nietzsche-beta-app/src/app/tln-edition/tln-height.directive.ts new file mode 100644 index 0000000..f43e4ff --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-height.directive.ts @@ -0,0 +1,16 @@ +import { Directive, ElementRef, OnInit, Input } from '@angular/core'; +import { TlnPageViewComponent } from './tln-page-view.component'; + +@Directive({ + selector: '[setMaxHeightTo]' +}) +export class TlnHeightDirective implements OnInit{ + @Input('setMaxHeightTo') pageView: TlnPageViewComponent; + constructor(public el: ElementRef) { } + + ngOnInit(){ + if (this.pageView != undefined && this.pageView != null){ + this.pageView.max_height = window.innerHeight - this.el.nativeElement.offsetHeight -15; + } + } +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-manuscript-view/tln-manuscript-view.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-manuscript-view/tln-manuscript-view.component.html index 71b84a0..e45677e 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-manuscript-view/tln-manuscript-view.component.html +++ b/nietzsche-beta-app/src/app/tln-edition/tln-manuscript-view/tln-manuscript-view.component.html @@ -1,60 +1,57 @@ {{current_manuscript.archivalicSignature}} {{current_manuscript.title}} GSA-Signatur {{current_manuscript.gsaSignature}}

Frühere Manuskriptbeschreibungen

{{earlierDescription.author}}: {{earlierDescription.text}} {{earlierDescription.citation}}

Beschreibung der Archivmappe

Heftbeschreibung

{{manuscriptDescription.text}}

In {{current_manuscript.title}} wiedergegebene Manuskriptseiten

{{page.number}} - - + + ,

Konvolute, Rekonstruktionen

{{reconstructedKonvolut.description}}

diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/.search.component.html.swp b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/.search.component.html.swp new file mode 100644 index 0000000..8ab496d Binary files /dev/null and b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/.search.component.html.swp differ diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.html new file mode 100644 index 0000000..a7d73b1 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.html @@ -0,0 +1,4 @@ + diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.scss b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.scss new file mode 100644 index 0000000..35e58d5 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.scss @@ -0,0 +1,4 @@ +.icon-button { + width: 15px; + margin-left: 3px; +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.spec.ts new file mode 100644 index 0000000..4430074 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OpenInViewerComponent } from './open-in-viewer.component'; + +describe('OpenInViewerComponent', () => { + let component: OpenInViewerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ OpenInViewerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(OpenInViewerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.ts new file mode 100644 index 0000000..36b9631 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/open-in-viewer.component.ts @@ -0,0 +1,52 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { TLN_VIEWER_ROUTE, TLN_PAGE_PARAM, TLN_MANUSCRIPT_PARAM } from '../constants'; +import { Mapping } from '../route-reader'; +import { RouteUpdater } from '../route-updater'; +import { NavigationPage } from '../models'; + +interface ViewerRouteInformation { + title: string; + number: string; + page: string; + manuscript?: string; + launchExternally?: boolean; +} +@Component({ + selector: 'open-in-viewer', + templateUrl: './open-in-viewer.component.html', + styleUrls: ['./open-in-viewer.component.scss'] +}) +export class OpenInViewerComponent extends RouteUpdater { + @Input() routerInformation: ViewerRouteInformation; + launch: boolean = false; + page: NavigationPage; + protected currentRoute: string = TLN_VIEWER_ROUTE; + current_iri: string; + current_manuscript_unity: string; + protected mapping: Mapping = { current_iri: { param: TLN_PAGE_PARAM, type: "string" }, + current_manuscript_unity: { param: TLN_MANUSCRIPT_PARAM, type: "string" }} + + constructor(protected router: Router, protected activatedRoute: ActivatedRoute ) { + super(router, activatedRoute); + } + ngOnInit(){ + super.ngOnInit(); + this.page = { id: this.routerInformation.page, + number: this.routerInformation.number, + title: this.routerInformation.title }; + this.launch = (this.routerInformation.launchExternally != undefined + && this.routerInformation.launchExternally != null + && this.routerInformation.launchExternally) + } + private openInViewer(){ + if (this.routerInformation != undefined && this.routerInformation != null){ + this.current_iri = this.routerInformation.page; + if (this.routerInformation.manuscript != undefined && this.routerInformation != null){ + this.current_manuscript_unity = this.routerInformation.manuscript; + } + this.updateParams(this.launch); + } + } + +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.css b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.css new file mode 100644 index 0000000..76bc728 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.css @@ -0,0 +1,3 @@ +.search { + margin-left: 8px; +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.html new file mode 100644 index 0000000..fb0ecad --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.html @@ -0,0 +1,11 @@ + + Suche + + + + + diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.spec.ts new file mode 100644 index 0000000..4372919 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.ts new file mode 100644 index 0000000..2aea533 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/search.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { TLN_SEARCH_ROUTE, TLN_FIND_PARAM } from '../constants'; +import { Mapping } from '../route-reader'; +import { RouteUpdater } from '../route-updater'; + +@Component({ + selector: 'search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.css'] +}) +export class SearchComponent extends RouteUpdater { + findText: string; + protected mapping: Mapping = { findText: { param: TLN_FIND_PARAM, type: "string" }} + + constructor(protected router: Router, protected activatedRoute: ActivatedRoute ) { + super(router, activatedRoute); + } + openFulltextSearch(){ + this.currentRoute = TLN_SEARCH_ROUTE + this.updateParams(); + } + private clearFindText() { + this.findText = ''; + this.updateParams(); + } + +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.css b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.css new file mode 100644 index 0000000..e69de29 diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.html new file mode 100644 index 0000000..0cfcac8 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.html @@ -0,0 +1,7 @@ + + + diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.spec.ts new file mode 100644 index 0000000..f2ad817 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToggleNavigationComponent } from './toggle-navigation.component'; + +describe('ToggleNavigationComponent', () => { + let component: ToggleNavigationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ToggleNavigationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ToggleNavigationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.ts new file mode 100644 index 0000000..97e7007 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/toggle-navigation.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { TLN_SEARCH_ROUTE, TLN_FULLSCREEN_PARAM, TLN_NAV_BAR_OPEN_STATE_PARAM} from '../constants'; +import { Mapping } from '../route-reader'; +import { RouteUpdater } from '../route-updater'; + + +@Component({ + selector: 'toggle-navigation', + templateUrl: './toggle-navigation.component.html', + styleUrls: ['./toggle-navigation.component.css'] +}) + +export class ToggleNavigationComponent extends RouteUpdater { + fullscreen: boolean = false; + navBarOpenState: boolean = false; + protected mapping: Mapping = { + navBarOpenState: { param: TLN_NAV_BAR_OPEN_STATE_PARAM, type: "boolean" }, + fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" } + } + + constructor(protected router: Router, protected activatedRoute: ActivatedRoute ) { + super(router, activatedRoute); + } + private toggleFullscreen(){ + this.fullscreen = !this.fullscreen; + this.updateParams(); + } + toggleNavDrawer(){ + this.navBarOpenState = !this.navBarOpenState; + this.updateParams(); + } +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.css b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.css new file mode 100644 index 0000000..a986341 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.css @@ -0,0 +1,9 @@ +.zoom { + max-width: 20px; +} +.zoom-in { + cursor: zoom-in; +} +.zoom-out { + cursor: zoom-out; +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.html new file mode 100644 index 0000000..f70771b --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.html @@ -0,0 +1,7 @@ + + + + diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.spec.ts new file mode 100644 index 0000000..51c7933 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ZoomComponent } from './zoom.component'; + +describe('ZoomComponent', () => { + let component: ZoomComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ZoomComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ZoomComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.ts new file mode 100644 index 0000000..8628812 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { TLN_ZOOM_PARAM } from '../constants'; +import { Mapping } from '../route-reader'; +import { RouteUpdater } from '../route-updater'; + +@Component({ + selector: 'zoom', + templateUrl: './zoom.component.html', + styleUrls: ['./zoom.component.css'] +}) +export class ZoomComponent extends RouteUpdater { + private readonly increment: number = 0.25; + private readonly decrement: number = this.increment*-1; + zoomFactor: number = 1; + protected mapping: Mapping = { zoomFactor: { param: TLN_ZOOM_PARAM, type: "number" }} + + constructor(protected router: Router, protected activatedRoute: ActivatedRoute ) { + super(router, activatedRoute); + } + private setZoomFactor(newZoomFactor: number){ + if (newZoomFactor > 0){ + this.zoomFactor = Math.round(newZoomFactor*100)/100; + } else { + this.zoomFactor = this.zoomFactor/2 + } + this.updateParams(); + } +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.pipe.spec.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.pipe.spec.ts new file mode 100644 index 0000000..2674505 --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.pipe.spec.ts @@ -0,0 +1,8 @@ +import { ZoomPipe } from './zoom.pipe'; + +describe('ZoomPipe', () => { + it('create an instance', () => { + const pipe = new ZoomPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.pipe.ts b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.pipe.ts new file mode 100644 index 0000000..f96252c --- /dev/null +++ b/nietzsche-beta-app/src/app/tln-edition/tln-navigation-elements/zoom.pipe.ts @@ -0,0 +1,17 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +interface ZoomObject { + zoomFactor: number; + changeValue: number; +} + +@Pipe({ + name: 'zoomTitle' +}) +export class ZoomPipe implements PipeTransform { + + transform(zoom: ZoomObject): string { + return (zoom.zoomFactor+zoom.changeValue < 0) ? Math.round(zoom.zoomFactor*50) + '%' : Math.round((zoom.zoomFactor+zoom.changeValue)*100) + '%'; + } + +} diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.html index aa21eee..8b9b7f9 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.html +++ b/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.html @@ -1,55 +1,39 @@ diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts index 495de00..3780341 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts +++ b/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts @@ -1,168 +1,140 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit, Input, ElementRef } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; import {MatBottomSheet, MatBottomSheetRef} from '@angular/material/bottom-sheet'; import { TlnQueryServiceInterface, Reference, ManuscriptUnity, NavigationPage } from '../models'; import { TlnManuscriptUnity, TlnNavigationPage} from '../datatypes/navigation'; import { DEFAULT_VIEW_OPTION, TLN_VIEWER_ROUTE, TLN_FULLSCREEN_PARAM, TLN_FIND_PARAM, TLN_NAV_BAR_OPEN_STATE_PARAM, TLN_PAGE_PARAM, TLN_MANUSCRIPT_PARAM, TLN_SELECTED_LINES_PARAM, TLN_VIEW_OPTION_PARAM, TLN_ZOOM_PARAM, VIEW_OPTIONS, ONTOLOTY_PREFIX } from '../constants'; import { IsReconstructedKonvolut } from '../datatypes/basic_datatype'; import { TlnLine} from '../datatypes/line'; import { TlnTextGeneticOrder} from '../datatypes/text_version'; import { Mapping } from '../route-reader'; import { RouteUpdater } from '../route-updater'; import { ComplexKeyIriMapping, DataHandler, KeyIriMapping } from '../data_handler'; import { PageViewService, TlnQueryService } from '../services'; import { TlnInformationComponent, ParentInformation } from '../tln-information/tln-information.component'; import { PageInformation } from '../tln-information/page-information'; @Component({ selector: 'tln-viewer-navigation', templateUrl: './tln-viewer-navigation.component.html', styleUrls: ['./tln-viewer-navigation.component.css'] }) export class TlnViewerNavigation extends RouteUpdater { /** * OPTIONAL pass a queryService with method * {@link /interfaces/TlnQueryServiceInterface.html#getData|getData} * to TlnPageViewComponent. **/ @Input() queryService: TlnQueryServiceInterface; /** * whether or not to show page view in fullscreen mode. **/ fullscreen: boolean = false; - zoomFactor: number = 1; findText: string; current_iri: string; current_manuscript_iri: string; manuscript_unity: ManuscriptUnity; current_page: NavigationPage; pageInformation: PageInformation; previous_page: NavigationPage; next_page: NavigationPage; navBarOpenState: boolean; showArchivalManuscriptUnity: boolean = false; dataHandler: DataHandler = new DataHandler(this); geneticOrders: TlnTextGeneticOrder[] = []; selectedLines: string[] = []; private readonly increment: number = 0.333; private readonly decrement: number = this.increment*-1; protected currentRoute: string = TLN_VIEWER_ROUTE; protected mapping: Mapping = { findText: { param: TLN_FIND_PARAM, type: "string" }, current_iri: { param: TLN_PAGE_PARAM, type: "string" }, navBarOpenState: { param: TLN_NAV_BAR_OPEN_STATE_PARAM, type: "boolean" }, current_manuscript_iri: { param: TLN_MANUSCRIPT_PARAM, type: "string" }, fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" }, selectedViewOption: { param: TLN_VIEW_OPTION_PARAM, type: "string" }, - selectedLines: { param: TLN_SELECTED_LINES_PARAM, type: "string" }, - zoomFactor: { param: TLN_ZOOM_PARAM, type: "number" } } + selectedLines: { param: TLN_SELECTED_LINES_PARAM, type: "string" } } routerParams: Params; selectedViewOption: string = DEFAULT_VIEW_OPTION updating: boolean = false; viewOptions: string[] = [ VIEW_OPTIONS.TRANSKRIPTION, VIEW_OPTIONS.FAKSIMILE, VIEW_OPTIONS.SYNOPSIS, VIEW_OPTIONS.SYNOPSIS_B ]; - constructor(private bottomSheet: MatBottomSheet, private pageViewService: PageViewService, private localQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute ) { + constructor(el: ElementRef, private bottomSheet: MatBottomSheet, private pageViewService: PageViewService, private localQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute ) { super(router, activatedRoute); } ngOnInit() { let tlnQueryService = (this.queryService != null) ? this.queryService : this.localQueryService; this.dataHandler.addHandler('manuscript_unity', { 'handler': TlnManuscriptUnity, 'next_key': 'navigation_page'}); this.dataHandler.addHandler('navigation_page', ['current_page', 'geneticOrders'] ); this.dataHandler.addHandler('current_page', { 'handler': TlnNavigationPage }); this.dataHandler.addHandler('geneticOrders', { 'handler': TlnTextGeneticOrder}); this.dataHandler.setQueryService(tlnQueryService); this.dataHandler.start_processing.subscribe( (started: boolean) =>{ this.updating = true; }); this.dataHandler.processing_finished.subscribe( (finished: boolean) =>{ this.updating = false; }); super.ngOnInit(); this.pageViewService.reference.subscribe( (newReference: Reference) => { this.updatePageToReference(newReference) }) this.pageViewService.onClickedLine.subscribe( (clickedLine: TlnLine) => { let index = this.selectedLines.indexOf(clickedLine.id) if (index > -1){ this.selectedLines.splice(index, 1); } else { this.selectedLines.push(clickedLine.id); } this.updateParams(); }); } private clearFindText() { this.findText = ''; this.updateParams(); } private getPageTitle(page?: NavigationPage, numPages?: number): string { if (page == null){ return ''; } let indexPrefix = (numPages != null) ? page.index + '/' + numPages : page.index; return indexPrefix + ': ' + page.title + ' ' + page.number; } - private getZoomTitle(changeValue: number): string { - if (this.zoomFactor+changeValue < 0){ - return Math.round(this.zoomFactor*50) + '%'; - } - return Math.round((this.zoomFactor+changeValue)*100) + '%'; - } protected readParams(params: Params){ super.readParams(params); if (this.dataHandler.ready && (this.current_page == null || this.current_page.id != this.current_iri)){ this.dataHandler.resetData('navigation_page') if(this.current_manuscript_iri != null){ //this.dataHandler.debug = true; this.dataHandler.conditionalAddHandler(IsReconstructedKonvolut.getQuery(this.current_manuscript_iri), 'current_page',{ handler: TlnNavigationPage}, { handler: TlnNavigationPage}); this.dataHandler.getData('manuscript_unity', this.current_manuscript_iri, this.current_iri); } else { this.dataHandler.getData('current_page', this.current_iri); } } } - private setZoomFactor(newZoomFactor: number){ - if (newZoomFactor > 0){ - this.zoomFactor = Math.round(newZoomFactor*100)/100; - } else { - this.zoomFactor = this.zoomFactor/2 - } - this.updateParams(); - } private setCurrentIri(pageIri: string, manuscriptIir?: string){ this.dataHandler.stop_processing.emit(true); this.current_iri = pageIri; this.updateParams(); } private showInformation() { let parentData: ParentInformation = { geneticOrders: this.geneticOrders, page: this.current_page, manuscript_iri: this.current_manuscript_iri, parentActivatedRoute: this.activatedRoute.parent } this.bottomSheet.open(TlnInformationComponent, { data: parentData }); } private updatePageToReference(reference: Reference){ this.current_iri = reference.page.id; this.selectedLines = [ reference.line.id ] this.updateParams(); } - private toggleFullscreen(){ - this.fullscreen = !this.fullscreen; - this.updateParams(); - } - public test(iri?: string){ - this.bottomSheet.open(TlnInformationComponent); - //this.dataHandler.isOfType('showArchivalManuscriptUnity', 'http://rdfh.ch/projects/0068#_Mp_XIV', 'http://www.nie.org/ontology/nietzsche#ArchivalManuscriptUnity') - } - toggleNavDrawer(){ - this.navBarOpenState = !this.navBarOpenState; - this.updateParams(); - } }