diff --git a/browserslist b/browserslist index 8084853..bf9bc75 100644 --- a/browserslist +++ b/browserslist @@ -1,12 +1,12 @@ # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. -# For additional information regarding the format and rule options, please see: +# For additional information regarding the format and rule OptionSettings, please see: # https://github.com/browserslist/browserslist#queries # You can see what browsers were selected by your queries by running: # npx browserslist > 0.5% last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 9-11 # For IE 9-11 support, remove 'not'. diff --git a/src/app/app.component.html b/src/app/app.component.html index c886c26..1df4d14 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,11 +1,9 @@ - -
- -
+
diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 30185a8..876e39a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,90 +1,98 @@ import { AppComponent } from './app.component'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { CdkTableModule } from '@angular/cdk/table'; import { DragDropModule } from '@angular/cdk/drag-drop'; import { FormsModule, ReactiveFormsModule} from '@angular/forms'; import { NgModule } from '@angular/core'; import { MatDialogModule, MatToolbarModule} from '@angular/material'; import { MatExpansionModule } from '@angular/material/expansion'; import {MatIconModule} from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatListModule } from '@angular/material/list'; import {MatMenuModule} from '@angular/material/menu'; import { MatPaginatorModule, MatSortModule, MatSidenavModule, MatCheckboxModule, MatRadioModule } from '@angular/material'; import { MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; import {MatTabsModule} from '@angular/material/tabs'; +import {MatTooltipModule} from '@angular/material'; import { DataListViewComponent } from './data-list-view/data-list-view.component'; import { DataListViewTableComponent, HighlightPipe } from './data-list-view/data-list-view-table/data-list-view-table.component'; import { DialogComponent } from './dialog-component/dialog.component'; import { InfoBoxComponent } from './info-box-component/info-box.component'; import { TextFieldComponent} from './textfield-component/textfield.component'; import { WordPositionDirective } from './textfield-component/word-position.directive'; import { TextfieldOptionsComponentComponent } from './textfield-options-component/textfield-options-component.component'; import { CommonModule } from '@angular/common'; import { HttpClientModule } from '@angular/common/http'; import { RdfDataBrowserComponentComponent } from './rdf-data-browser-component/rdf-data-browser-component.component'; import { QueryService } from './services/query.service'; import {AnnotationService, TextStyleService} from './services/annotation.service'; import { DisplayedCollumnsService } from './data-list-view/data-list-view-services/table-data.service'; import {DataListViewSettings} from './data-list-view/data-list-view-settings/data-list-view-settings.service'; import { MarkupTextComponentComponent } from './markup-text-component/markup-text-component.component'; import { BergwerkeComponent } from './bergwerke/bergwerke.component'; import { SubmenuComponentComponent } from './markup-text-component/submenu-component/submenu-component.component'; import { MarkupTextButtonsComponentComponent } from './markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component'; -import { OptionsComponent } from './options-component/options-component.component'; +import { GenericControlsComponent } from './generic-control-elements-component/generic-control-elements-component.component'; import { MarkupHyperlinkComponentComponent } from './markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component'; +import { MarkupTextIconComponent } from './markup-text-component/markup-text-icon-component/markup-text-icon.component'; +import { UploadRdfDataComponentComponent } from './upload-rdf-data-component/upload-rdf-data-component.component'; +import { CustomizableSearchComponentComponent } from './customizable-search-component/customizable-search-component.component'; @NgModule({ declarations: [ AppComponent, TextFieldComponent, WordPositionDirective, InfoBoxComponent, TextfieldOptionsComponentComponent, DataListViewComponent, DataListViewTableComponent, DialogComponent, HighlightPipe, RdfDataBrowserComponentComponent, MarkupTextComponentComponent, BergwerkeComponent, SubmenuComponentComponent, MarkupTextButtonsComponentComponent, - OptionsComponent, - MarkupHyperlinkComponentComponent + GenericControlsComponent, + MarkupHyperlinkComponentComponent, + MarkupTextIconComponent, + UploadRdfDataComponentComponent, + CustomizableSearchComponentComponent ], imports: [ BrowserModule, BrowserAnimationsModule, CdkTableModule, CommonModule, DragDropModule, HttpClientModule, MatCheckboxModule, MatDialogModule, MatExpansionModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatPaginatorModule, MatRadioModule, MatSelectModule, MatSidenavModule, MatSortModule, MatTableModule, MatTabsModule, MatToolbarModule, + MatTooltipModule, FormsModule, ReactiveFormsModule ], providers: [ QueryService, DisplayedCollumnsService, DataListViewSettings, TextStyleService, AnnotationService ], bootstrap: [AppComponent], entryComponents: [DialogComponent] }) export class AppModule { } diff --git a/src/app/bergwerke/bergwerke.component.html b/src/app/bergwerke/bergwerke.component.html index d85a029..5eb0e58 100644 --- a/src/app/bergwerke/bergwerke.component.html +++ b/src/app/bergwerke/bergwerke.component.html @@ -1,5 +1,11 @@ -

This is a Text app styled with markup component

-

Please take your time to also read this gorgeous text. It is one of the most beautiful texts of all time: The "Unverhofftes Wiedersehen" of Johann Peter Hebel

- + +

This is a Text app styled with markup component

+ + + + +

Unverhofftes Wiedersehen

-
+
diff --git a/src/app/bergwerke/bergwerke.component.scss b/src/app/bergwerke/bergwerke.component.scss index e69de29..69abdac 100644 --- a/src/app/bergwerke/bergwerke.component.scss +++ b/src/app/bergwerke/bergwerke.component.scss @@ -0,0 +1,12 @@ + +.menu_button{ + height:40px; + width:40px; + background-color: Transparent; + background-repeat:no-repeat; + cursor:pointer; + overflow: hidden; + outline:none; +} +.menu-icon { +} diff --git a/src/app/bergwerke/bergwerke.component.ts b/src/app/bergwerke/bergwerke.component.ts index 7673dc8..aecd5c4 100644 --- a/src/app/bergwerke/bergwerke.component.ts +++ b/src/app/bergwerke/bergwerke.component.ts @@ -1,50 +1,64 @@ import { Component, OnInit } from '@angular/core'; import markupDefaultSettings from '../markup-text-component/markup-text-settings.json'; -import {MarkupOptionsService, MarkupSetting} from '../markup-text-component/markup-options.service'; +import {DialogComponent} from '../dialog-component/dialog.component'; +import {MatDialog} from '@angular/material'; @Component({ selector: 'app-bergwerke', templateUrl: './bergwerke.component.html', styleUrls: ['./bergwerke.component.scss'] }) export class BergwerkeComponent implements OnInit { myText = 'In Falun in Schweden küßte vor guten fünfzig Jahren und mehr ein junger Bergmann seine junge hübsche Braut und sagte zu ihr: »Auf Sankt Luciä wird unsere Liebe von des Priesters Hand gesegnet. Dann sind wir Mann und Weib, und bauen uns ein eigenes Nestlein.« – »Und Friede und Liebe soll darin wohnen«, sagte die schöne Braut mit holdem Lächeln, »denn du bist mein einziges und alles, und ohne dich möchte ich lieber im Grab sein, als an einem andern Ort.« Als sie aber vor St. Luciä der Pfarrer zum zweitenmal in der Kirche ausgerufen hatte: »So nun jemand Hindernis wüßte anzuzeigen, warum diese Personen nicht möchten ehelich zusammenkommen« – da meldete sich der Tod. Denn als der Jüngling den andern Morgen in seiner schwarzen Bergmannskleidung an ihrem Haus vorbeiging, der Bergmann hat sein Totenkleid immer an, da klopfte er zwar noch einmal an ihrem Fenster, und sagte ihr guten Morgen, aber keinen guten Abend mehr. Er kam nimmer aus dem Bergwerk zurück, und sie saumte vergeblich selbigen Morgen ein schwarzes Halstuch mit rotem Rand für ihn zum Hochzeittag, sondern als er nimmer kam, legte sie es weg, und weinte um ihn und vergaß ihn nie. Unterdessen wurde die Stadt Lissabon in Portugal durch ein Erdbeben zerstört, und der Siebenjährige Krieg ging vorüber, und Kaiser Franz der Erste starb, und der Jesuitenorden wurde aufgehoben und Polen geteilt, und die Kaiserin Maria Theresia starb, und der Struensee wurde hingerichtet, Amerika wurde frei, und die vereinigte französische und spanische Macht konnte Gibraltar nicht erobern. Die Türken schlossen den General Stein in der Veteraner Höhle in Ungarn ein, und der Kaiser Joseph starb auch. Der König Gustav von Schweden eroberte russisch Finnland, und die Französische Revolution und der lange Krieg fing an, und der Kaiser Leopold der Zweite ging auch ins Grab. Napoleon eroberte Preußen, und die Engländer bombardierten Kopenhagen, und die Ackerleute säeten und schnitten. Der Müller mahlte, und die Schmiede hämmerten, und die Bergleute gruben nach den Metalladern in ihrer unterirdischen Werkstatt. Als aber die Bergleute in Falun im Jahr 1809 etwas vor oder nach Johannis zwischen zwei Schachten eine Öffnung durchgraben wollten, gute dreihundert Ellen tief unter dem Boden gruben sie aus dem Schutt und Vitriolwasser den Leichnam eines Jünglings heraus, der ganz mit Eisenvitriol durchdrungen, sonst aber unverwest und unverändert war; also daß man seine Gesichtszüge und sein Alter noch völlig erkennen konnte, als wenn er erst vor einer Stunde gestorben, oder ein wenig eingeschlafen wäre, an der Arbeit. Als man ihn aber zu Tag ausgefördert hatte, Vater und Mutter, Gefreundte und Bekannte waren schon lange tot, kein Mensch wollte den schlafenden Jüngling kennen oder etwas von seinem Unglück wissen, bis die ehemalige Verlobte des Bergmanns kam, der eines Tages auf die Schicht gegangen war und nimmer zurückkehrte. Grau und zusammengeschrumpft kam sie an einer Krücke an den Platz und erkannte ihren Bräutigam; und mehr mit freudigem Entzücken als mit Schmerz sank sie auf die geliebte Leiche nieder, und erst als sie sich von einer langen heftigen Bewegung des Gemüts erholt hatte, »es ist mein Verlobter«, sagte sie endlich, »um den ich fünfzig Jahre lang getrauert hatte, und den mich Gott noch einmal sehen läßt vor meinem Ende. Acht Tage vor der Hochzeit ist er unter die Erde gegangen und nimmer heraufgekommen.« Da wurden die Gemüter aller Umstehenden von Wehmut und Tränen ergriffen, als sie sahen die ehemalige Braut jetzt in der Gestalt des hingewelkten kraftlosen Alters und den Bräutigam noch in seiner jugendlichen Schöne, und wie in ihrer Brust nach 50 Jahren die Flamme der jugendlichen Liebe noch einmal erwachte; aber er öffnete den Mund nimmer zum Lächeln oder die Augen zum Wiedererkennen; und wie sie ihn endlich von den Bergleuten in ihr Stüblein tragen ließ, als die einzige, die ihm angehöre, und ein Recht an ihn habe, bis sein Grab gerüstet sei auf dem Kirchhof. Den andern Tag, als das Grab gerüstet war auf dem Kirchhof und ihn die Bergleute holten, schloß sie ein Kästlein auf, legte sie ihm das schwarzseidene Halstuch mit roten Streifen um, und begleitete ihn alsdann in ihrem Sonntagsgewand, als wenn es ihr Hochzeittag und nicht der Tag seiner Beerdigung wäre. Denn als man ihn auf dem Kirchhof ins Grab legte, sagte sie: »Schlafe nun wohl, noch einen Tag oder zehen im kühlen Hochzeitbett, und laß dir die Zeit nicht lange werden. Ich habe nur noch wenig zu tun, und komme bald, und bald wird\'s wieder Tag. – Was die Erde einmal wiedergegeben hat, wird sie zum zweitenmal auch nicht behalten«, sagte sie, als sie fortging, und noch einmal umschaute.'; - defaultSettings = JSON.parse(JSON.stringify(markupDefaultSettings)); + mySettings = JSON.parse(JSON.stringify(markupDefaultSettings)); myStandoffData: Array> = [ - [ "stoff:SemanticAnnotation", 3, 8, 'humgeo:City', "https://www.wikidata.org/wiki/Q26509"], + [ "stoff:SemanticAnnotation", 3, 7, 'humgeo:City', "https://www.wikidata.org/wiki/Q26509"], + [ "stoff:CssStyle", 0, 19, "font-style: italic;"], [ "stoff:SemanticAnnotation", 12, 19, 'humgeo:State', "https://www.wikidata.org/wiki/Q34"], [ "stoff:SemanticAnnotation", 1662, 1666, 'human:Organization', "https://de.wikipedia.org/wiki/K%C3%B6nig"], [ "stoff:SemanticAnnotation", 1679, 1686, 'humgeo:State', "https://de.wikipedia.org/wiki/Schweden"], [ "stoff:SemanticAnnotation", 1662, 1686, 'human:Person', "https://de.wikipedia.org/wiki/Karl_X._Gustav"], - [ "stoff:CssStyle", 125, 301, "font-style: italic;"], + [ "stoff:CssStyle", 110, 301, "font-style: italic;"], [ "stoff:CssStyle", 346, 457, "font-style: italic;"], [ "stoff:CssStyle", 544, 645, "font-style: italic;"], [ "stoff:CssStyle", 3163, 3186, "font-style: italic;"], [ "stoff:CssStyle", 3207, 3398, "font-style: italic;"], [ "stoff:CssStyle", 4334, 4605, "font-style: italic;"], - [ "stoff:CssStyle", 2097, 2102, "font-weight: bold;"], - [ "stoff:CssStyle", 2097, 2102, "color: blue;"], - [ "stoff:CssStyle", 2097, 2102, "text-decoration: underline;"], + [ "stoff:CssStyle", 2097, 2101, "font-weight: bold;"], + [ "stoff:CssStyle", 2097, 2101, "color: blue;"], + [ "stoff:CssStyle", 2097, 2101, "text-decoration: underline;"], [ "stoff:CssStyle", 1182, 1190, "text-decoration: underline;"], [ "stoff:CssStyle", 1182, 1190, "font-weight: bold;"], [ "stoff:CssStyle", 1182, 1190, "color: blue;"], - [ "stoff:CssStyle", 1443, 1450, "text-decoration: underline;"], - [ "stoff:CssStyle", 1443, 1450, "font-weight: bold;"], - [ "stoff:CssStyle", 1443, 1450, "color: blue;"], + [ "stoff:CssStyle", 1443, 1449, "text-decoration: underline;"], + [ "stoff:CssStyle", 1443, 1449, "font-weight: bold;"], + [ "stoff:CssStyle", 1443, 1449, "color: blue;"], [ "stoff:CssStyle", 1285, 1300, "text-decoration: underline;"], [ "stoff:CssStyle", 1285, 1300, "font-weight: bold;"], [ "stoff:CssStyle", 1285, 1300, "color: red;"], - [ "stoff:CssStyle", 1316, 1329, "text-decoration: underline;"], - [ "stoff:CssStyle", 1316, 1329, "color: green;"], - [ "stoff:CssStyle", 1383, 1397, "text-decoration: underline;"], - [ "stoff:CssStyle", 1383, 1397, "font-weight: bold;"], - [ "stoff:CssStyle", 1383, 1397, "color: red;"], - [ "stoff:CssStyle", 1639, 1645, "text-decoration: underline;"], - [ "stoff:CssStyle", 1639, 1645, "font-weight: bold;"], - [ "stoff:CssStyle", 1639, 1645, "color: red;"] + [ "stoff:CssStyle", 1316, 1328, "text-decoration: underline;"], + [ "stoff:CssStyle", 1316, 1328, "color: green;"], + [ "stoff:CssStyle", 1383, 1396, "text-decoration: underline;"], + [ "stoff:CssStyle", 1383, 1396, "font-weight: bold;"], + [ "stoff:CssStyle", 1383, 1396, "color: red;"], + [ "stoff:CssStyle", 1639, 1644, "text-decoration: underline;"], + [ "stoff:CssStyle", 1639, 1644, "font-weight: bold;"], + [ "stoff:CssStyle", 1639, 1644, "color: red;"] ]; + + constructor( private dialog: MatDialog ) { + + } ngOnInit() { } + + private openOptionsDialog() { + this.dialog.open(DialogComponent, { + data: { + message: this.mySettings, buttonText: {cancel: 'close'}, title: 'Options', contentType: 0 + }, + }); + } } diff --git a/src/app/customizable-search-component/customizable-search-component.component.html b/src/app/customizable-search-component/customizable-search-component.component.html new file mode 100644 index 0000000..3841c0a --- /dev/null +++ b/src/app/customizable-search-component/customizable-search-component.component.html @@ -0,0 +1,2 @@ +

Customizable search

+ diff --git a/src/app/markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component.scss b/src/app/customizable-search-component/customizable-search-component.component.scss similarity index 100% rename from src/app/markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component.scss rename to src/app/customizable-search-component/customizable-search-component.component.scss diff --git a/src/app/customizable-search-component/customizable-search-component.component.ts b/src/app/customizable-search-component/customizable-search-component.component.ts new file mode 100644 index 0000000..68e87d4 --- /dev/null +++ b/src/app/customizable-search-component/customizable-search-component.component.ts @@ -0,0 +1,24 @@ +import { Component, OnInit } from '@angular/core'; +import mySearchSettings from './my_search_mask.json'; + +@Component({ + selector: 'app-customizable-search-component', + templateUrl: './customizable-search-component.component.html', + styleUrls: ['./customizable-search-component.component.scss'] +}) +export class CustomizableSearchComponentComponent implements OnInit { + + constructor() { } + + searchMaskDefinitions = JSON.parse(JSON.stringify(mySearchSettings)); + + ngOnInit() { + } + // Todo: Load from JSON + + // create Control --> + + // Save to JSON + + +} diff --git a/src/app/markup-text-component/markup-text-settings.json b/src/app/customizable-search-component/my_search_mask.json similarity index 56% copy from src/app/markup-text-component/markup-text-settings.json copy to src/app/customizable-search-component/my_search_mask.json index 37ead40..bde739f 100644 --- a/src/app/markup-text-component/markup-text-settings.json +++ b/src/app/customizable-search-component/my_search_mask.json @@ -1,85 +1,105 @@ -{ +{ "displaySettings": true, + "multiToggle": true, + "queryLanguage": "SPARQL", "settings":[ + { + "label": "styles", + "pannelOpenState": true, + "description": "Styles (non semantic markup only)", + "entries": [ + { + "label":"style", + "description":"render styles", + "value":false, + "type":"checkbox" + } + ] + }, { "label":"semanticMarkup", - "description":"display semantic annotations as", + "pannelOpenState": true, + "condition": [ + {"option":"markup.renderMarkup", "value":"all"}, + {"option":"markup.renderMarkup", "value":"semanticAnnotation"} + ], + "description":"Authors", "entries":[ { - "label":"styleType", - "description":"render semantic annotations as", + "label":"authors", + "description":"select author", + "query": "SELECT ?S from {?s a lombardus:author}", + "options":[ + + ], + "value":"icon", + "type":"select" + }, + { + "label":"renderIcons", + "description":"render semantic overlaps", "options":[ { - "id":"button", - "description":"buttons" - }, - { - "id":"icon", - "description":"icons" - }, - { - "id":"hyperlink", - "description":"text with hyperlinks" - }, - { - "id":"markup", - "description":"styled text/markup only" + "id":"split", + "description":"split up in multiple icons" }, { - "id":"none", - "description":"plane unstyled text" + "id":"group", + "description":"group polysemantics in one icon" } ], - "value":"button", - "type":"select" + "value":"after", + "type":"radio", + "condition": [{"option":"semanticMarkup.styleType", "value":"icon"}] }, { "label":"position", "description":"position them", "options":[ { "id":"before", "description":"before the text" }, { "id":"after", "description":"after the text" } ], "value":"after", "type":"radio", "condition": [{"option":"semanticMarkup.styleType", "value":"icon"}] }, { "label":"actions", "description":"action to take place on click at a semantic annotation", "options":[ { "id":"external", "description":"open external link" }, { "id":"pannel", "description":"display resource in pannel" }, { "id":"menu", "description":"open menu" } ], "value":"menu", "type":"select", "condition": [ {"option": "semanticMarkup.styleType", "value": "icon"}, {"option": "semanticMarkup.styleType", "value": "button"}, {"option": "semanticMarkup.styleType", "value": "hyperlink"} ] }, { "label":"tooltip", + "description":"show tooltip", "value":true, "type":"checkbox" } ] } ] } diff --git a/src/app/data-list-view/data-list-view-table/data-list-view-table.component.html b/src/app/data-list-view/data-list-view-table/data-list-view-table.component.html index 9977822..93ddcd9 100644 --- a/src/app/data-list-view/data-list-view-table/data-list-view-table.component.html +++ b/src/app/data-list-view/data-list-view-table/data-list-view-table.component.html @@ -1,52 +1,52 @@
Displaying {{getSumOfDisplayedEntries()}} of {{dataSource.data.length}} entries in total
{{col}}
- Export options + Export OptionSettings Displayed data only Complete export
diff --git a/src/app/dialog-component/dialog.component.html b/src/app/dialog-component/dialog.component.html index e18d379..47a903b 100644 --- a/src/app/dialog-component/dialog.component.html +++ b/src/app/dialog-component/dialog.component.html @@ -1,12 +1,17 @@

{{this.title}}

-
+ +
+ +
+ +
diff --git a/src/app/dialog-component/dialog.component.ts b/src/app/dialog-component/dialog.component.ts index dc9a9c6..a05b13d 100644 --- a/src/app/dialog-component/dialog.component.ts +++ b/src/app/dialog-component/dialog.component.ts @@ -1,39 +1,39 @@ import {Component, Inject, Injectable} from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import {QueryService} from '../services/query.service'; @Component({ selector: 'dialog-component', templateUrl: './dialog.component.html', styleUrls: ['./dialog.component.css'] }) @Injectable() export class DialogComponent { // DEFAULT values in case there is no initialContent or button text passed from app initialContent = 'loading resource'; cancelButtonText = 'close'; title: string; + contentType: number; // 0 === OptionSettings, 1 === data browser + constructor( @Inject(MAT_DIALOG_DATA) private data: any, - private dialogRef: MatDialogRef, - private dataService: QueryService ) { + private dialogRef: MatDialogRef ) { this.dialogRef.updateSize('1200vw', '800vw'); - if (this.dataService.shrink_iri(data.message)) { this.title = this.dataService.shrink_iri(data.message); - } else { this.title = data.message; } + this.title = data.message; // in case there is no data/initialContent passed the default this.initialContent will be displayed- Same for button text. // if (data) { this.initialContent = data.message || this.initialContent; this.title = data.title; + this.contentType = data.contentType; if (data.buttonText) { this.cancelButtonText = data.buttonText.cancel || this.cancelButtonText; } - } + } else { console.log('no data passed to dialog.'); } } onConfirmClick(): void { this.dialogRef.close(true); } } diff --git a/src/app/generic-control-elements-component/generic-control-elements-component.component.html b/src/app/generic-control-elements-component/generic-control-elements-component.component.html new file mode 100644 index 0000000..8ccfff7 --- /dev/null +++ b/src/app/generic-control-elements-component/generic-control-elements-component.component.html @@ -0,0 +1,61 @@ +
+

+ + + + +

{{group.description}}

+
+
+
+
+ +
+

+
{{controlElement.description}}
+ + + {{option.description}} + + +
+ +
+

+
{{controlElement.description}}
+ +
+ {{option.description}} +
+
+
+ +
+

+ + {{controlElement.description}} + +
+
+

+ + {{controlElement.description}} + +
+
+
+
+
+
+ diff --git a/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.scss b/src/app/generic-control-elements-component/generic-control-elements-component.component.scss similarity index 100% rename from src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.scss rename to src/app/generic-control-elements-component/generic-control-elements-component.component.scss diff --git a/src/app/generic-control-elements-component/generic-control-elements-component.component.ts b/src/app/generic-control-elements-component/generic-control-elements-component.component.ts new file mode 100644 index 0000000..b79fb0a --- /dev/null +++ b/src/app/generic-control-elements-component/generic-control-elements-component.component.ts @@ -0,0 +1,42 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {GenericOptionsService, SelectionBundle} from './generic-control-elements-service.service'; + +@Component({ + selector: 'app-generic-control-elements-component', + templateUrl: './generic-control-elements-component.component.html', + styleUrls: ['./generic-control-elements-component.component.scss'] +}) +export class GenericControlsComponent implements OnInit { + @Input() initialSettings?: any; + selection: SelectionBundle; // the selected values in one object + + constructor(private optionService: GenericOptionsService) { } + + ngOnInit() { + if (this.initialSettings) { + console.log('ControlSettings loaded by input: ', this.initialSettings); + this.selection = this.optionService.getSelectionFromJson(this.initialSettings); + console.log(this.selection); + this.optionService.getOptionsFromJson(this.initialSettings); + } else {console.log('no ControlSettings passed to display'); } + } + + onSelectValueChange(settingGroup, changedSetting) { + this.selection[settingGroup][changedSetting.label] = changedSetting.value; + this.optionService.setSelection(this.selection); + console.log('selections set: ', this.selection); + } + // evaluates conditions on one control field + private evaluateDisplayOption(conditions) { + if (conditions) { + let evaluator = false; + for (const condition of conditions) { + for (const val of condition.values) { + if (val === this.selection[condition.group][condition.option]) { + evaluator = true; + } + } + } + return evaluator; } else {return true; } + } +} diff --git a/src/app/generic-control-elements-component/generic-control-elements-service.service.ts b/src/app/generic-control-elements-component/generic-control-elements-service.service.ts new file mode 100644 index 0000000..006b9ce --- /dev/null +++ b/src/app/generic-control-elements-component/generic-control-elements-service.service.ts @@ -0,0 +1,159 @@ +import {EventEmitter, Injectable} from '@angular/core'; + +@Injectable({ + providedIn: 'root' + // Todo: 1 service instance per component + +}) +export class GenericOptionsService { + selection: SelectionBundle; // collection of all selected values + selectionEvent: EventEmitter = new EventEmitter(); + // Settings of the control interface + optionSettings: OptionSettings; // overall options to render/change + controlElementGroups: Array; // thematic groups of controlElements + controlElements: Array; + controlElementOptions: Array; // selections available for a control like a drop down box or radiobuttons + + + constructor() { + this.selection = new SelectionBundle(); + } + + public getSelectionFromJson(initialSettings: any) { + for (const group of initialSettings.controlElementGroups) { + const controlSettingGroup = new SelectionGroup(); + for (const entry of group.controlElements) { + controlSettingGroup[entry.label] = entry.value; + } + this.selection[group.label] = controlSettingGroup ; + } + return this.selection; + } + + public setSelection(newSelection: SelectionBundle) { + this.selection = newSelection; + this.selectionEvent.emit(this.selection); + } + + public createOptionsBundle( ) { + } + + public getOptionsFromJson(settings) { + console.log('settings', settings); + this.controlElementGroups = []; + for (const settingGroup of settings.controlElementGroups) { + for (const control of settingGroup.controlElements) { + this.controlElements = []; + if (control.type !== 'checkbox') { + this.controlElementOptions = []; + for (const option of control.options ) { + const o = new ControlElementOption(option.id, option.description); + this.controlElementOptions.push(o); + } + } + const c = new ControlElement(control.label, control.pannelOpenState, control.description, this.controlElementOptions, control.condition); + this.controlElements.push(c); + } + const oGroup = new ControlElementGroup(settingGroup.label, + settingGroup.pannelOpenState, settingGroup.description, this.controlElements, settingGroup.condition); + console.log('oGroup', oGroup); + this.controlElementGroups.push(oGroup); + } + this.optionSettings = new OptionSettings(settings.displaySettings, settings.multiToggle, this.controlElementGroups); + console.log('optionSettings', this.optionSettings); + } +} + +export class OptionSettings { + displaySettings: boolean; + multiToggle: boolean; + controlElementGroups: Array; + + constructor(displaySettings: boolean, multiToggle: boolean, controlElementGroups: Array ) { + this.displaySettings = displaySettings; + this.multiToggle = multiToggle; + this.controlElementGroups = controlElementGroups; + } +} + +export class ControlElementGroup { + label: string; + pannelOpenState: boolean; + description: string; + controlElements: Array; + condition?: Array; + + constructor( label: string, + pannelOpenState: boolean, + description: string, + controlElements: Array, + condition?: Array) { + + this.label = label; + this.pannelOpenState = pannelOpenState; + this.description = description; + this.controlElements = controlElements; + this.condition = condition; + } +} + +export class ControlElement { + label: string; + description: string; + type: string; + value: any; + options?: Array; + genericOptions?: Array; + + constructor( label: string, + description: string, + type: string, + value: any, + options?: Array, + genericOptions?: Array) { + + this.label = label; + this.description = description; + this.type = type; + this.value = value; + this.options = options; + this.genericOptions = genericOptions; + } +} + +export class DisplayCondition { + group: string; + control: string; + values: Array; +} + +export class ControlElementOption { + id: string; + description: string; + + constructor(id: string, description: string) { + this.description = description; + this.id = id; + } +} + +export class GenericOptionsData { + iri: string; + stringValue: string; + xsdType: string; + + constructor(iri: string, stringValue: string, xsdType: string) { + this.iri = iri; + this.stringValue = stringValue; + this.xsdType = xsdType; + } +} + +export class SelectionBundle { + [prop: string]: SelectionGroup; +} + +export class SelectionGroup { + [prop: string]: any; +} + diff --git a/src/app/info-box-component/info-box.component.html b/src/app/info-box-component/info-box.component.html index c595291..8dcee39 100644 --- a/src/app/info-box-component/info-box.component.html +++ b/src/app/info-box-component/info-box.component.html @@ -1,52 +1,52 @@
{{word.text}} - - + (click)="openInBrowser(word, this.queryService.shrink_iri(word.text))">in development: open resource in data browser + +
{{manuscript.title}}
{{word.text}}
{{word.id}}
Informationen zu Seite {{page.number}} {{metadata.head.description}}
{{content.reference}}:
{{content.quote}}]
{{content.text}}
diff --git a/src/app/info-box-component/info-box.component.ts b/src/app/info-box-component/info-box.component.ts index 0d474d7..b3d0f2b 100644 --- a/src/app/info-box-component/info-box.component.ts +++ b/src/app/info-box-component/info-box.component.ts @@ -1,81 +1,81 @@ import {Component, Input, OnChanges, Output} from '@angular/core'; import { MatExpansionModule } from '@angular/material/expansion'; import { Subscription} from 'rxjs'; import { WordService} from '../services/field-interaction.service'; import { Word } from '../models/models'; import {AnnotationService, TextStyleService} from '../services/annotation.service'; import { QueryService } from '../services/query.service'; import {DialogComponent} from '../dialog-component/dialog.component'; import {MatDialog} from '@angular/material'; @Component({ selector: 'app-info-box', templateUrl: './info-box.component.html', styleUrls: ['./info-box.component.css'] }) export class InfoBoxComponent implements OnChanges { @Input() manuscript: any; @Output() queryResponse: any; @Output() markupData; @Output() wordToMarkUp; query: string; word: Word; wordSubscription: Subscription; showInfo: boolean = false; expansion: boolean = true; constructor(private wordService: WordService, private matExpansionModule: MatExpansionModule, private textStyleService: TextStyleService, private queryService: QueryService, private annotationService: AnnotationService, private dialog: MatDialog ) { } ngOnChanges() { this.wordSubscription = this.wordService.wordChange$.subscribe( word => { if (this.word === word) { this.toggleShowInfo(); } else { this.word = word; this.wordToMarkUp = word.text; this.updateRDFData(word); if (!this.showInfo) { this.toggleShowInfo(); } } }); } private toggleShowInfo() { this.showInfo = !this.showInfo; } public updateRDFData(word) { this.query = this.queryService.getQueryforResourceData( encodeURI('http://rdfh.ch/projects/0068#_W_II_1_Page131_Word206'), 'subject'); this.queryService.getData(this.query).subscribe(data => { this.queryResponse = data; }); this.markupData = null; // maybe not needed this.markupData = this.annotationService.getAnnotationMarkup2(word); console.log('this.markupData for', word , ': ', this.markupData); // TODO: parse the annotations and apply them // const fuu = 'PREFIX c: <' + decodeURI( 'http://example.org/cartoons#' ) + '> c:Tom a c:Cat. c:Jerry a c:Mouse; c:smarterThan c:Tom.' // this.textStyleService.parseStyles(fuu); } private openInBrowser(word, shrunkTitle) { // TODO: Change this to actual word.iri word = encodeURI('http://rdfh.ch/projects/0068#_W_II_1_Page131_Word206'); this.dialog.open(DialogComponent, { data: { - message: word, buttonText: {cancel: 'close'}, title: shrunkTitle + message: word, buttonText: {cancel: 'close'}, title: shrunkTitle, contentType: 1 }, }); } } diff --git a/src/app/markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component.html b/src/app/markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component.html index 738d596..8627a58 100644 --- a/src/app/markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component.html +++ b/src/app/markup-text-component/markup-hyperlink-component/markup-hyperlink-component.component.html @@ -1,17 +1,34 @@ -{{segment[1]}} + + + {{segment[1]}} + + + + + {{segment[1]}} + - - - {{segment[1]}} + + + {{segment[1]}} - + + + +
open resource in data browser
+
edit text
+
edit semantic annotation "{{segment[3][0].cssClass}}"
+
delete semantic annotation "{{segment[3][0].cssClass}}"
+
+ + - + + {{item.linkText}} + diff --git a/src/app/markup-text-component/markup-options.service.ts b/src/app/markup-text-component/markup-options.service.ts deleted file mode 100644 index bd7cd8f..0000000 --- a/src/app/markup-text-component/markup-options.service.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {EventEmitter, Injectable} from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class MarkupOptionsService { - initialSettings: MarkupSetting; - optionsChange: EventEmitter = new EventEmitter(); - - constructor() { - this.initialSettings = new MarkupSetting(); - } - - public loadDefaultSettings(defaultSettings) { - for (const settingGroup of defaultSettings.settings) { - for (const entry of settingGroup.entries) { - this.initialSettings[settingGroup.label + '.' + entry.label] = entry.value; - } - } - return this.initialSettings; - } - - public setSettings(newSettings: MarkupSetting) { - this.optionsChange.emit(newSettings); - } -} - -export class MarkupSetting { - [prop: string]: string; -} diff --git a/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.html b/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.html index 1fab462..3e6548f 100644 --- a/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.html +++ b/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.html @@ -1,29 +1,38 @@ - + + + + + + + style is defined by class "polysemantic" and onClick opens always a menu with a submenues -->
open resource in data browser
edit text
edit semantic annotation "{{segment[3][0].cssClass}}"
delete semantic annotation "{{segment[3][0].cssClass}}"
diff --git a/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.ts b/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.ts index a35decb..32131d3 100644 --- a/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.ts +++ b/src/app/markup-text-component/markup-text-buttons-component/markup-text-buttons-component.component.ts @@ -1,16 +1,20 @@ import {Component, Input, OnInit} from '@angular/core'; @Component({ selector: 'app-markup-text-buttons-component', templateUrl: './markup-text-buttons-component.component.html', styleUrls: ['../markup-text-component.component.scss'] }) export class MarkupTextButtonsComponentComponent implements OnInit { @Input() segment: any; @Input() action: string; constructor() { } ngOnInit() { } + openLink(iri) { + window.open(iri, '_blank'); + } + } diff --git a/src/app/markup-text-component/markup-text-component.component.html b/src/app/markup-text-component/markup-text-component.component.html index c29513f..f032622 100644 --- a/src/app/markup-text-component/markup-text-component.component.html +++ b/src/app/markup-text-component/markup-text-component.component.html @@ -1,18 +1,48 @@
- - {{segment[1]}} - - {{segment[1]}} - - + + {{segment[1]}} + + + {{segment[1]}} + + + {{segment[1]}} + + + + {{segment[1]}} + + + + {{segment[1]}} + + + + [action]="actualSettings.semanticMarkup.actions" + [matTooltip]="actualSettings.semanticMarkup.tooltip ? this.getToolTip(segment[3]) : ''" + [matTooltipClass]="'semantic-tooltip'"> - + [action]="actualSettings.semanticMarkup.actions" + [matTooltip]="actualSettings.semanticMarkup.tooltip ? this.getToolTip(segment[3]) : ''" + [matTooltipClass]="'semantic-tooltip'"> + +
diff --git a/src/app/markup-text-component/markup-text-component.component.scss b/src/app/markup-text-component/markup-text-component.component.scss index 70bdfd4..9a5b22c 100644 --- a/src/app/markup-text-component/markup-text-component.component.scss +++ b/src/app/markup-text-component/markup-text-component.component.scss @@ -1,62 +1,86 @@ body { } a { + cursor: pointer; color: inherit; /* no colors for links. Color will be defined by semantic classes */ text-decoration: inherit; /* no underline */ } ::ng-deep .poly-menu { width: 400px; } +.semantic-tooltip { + white-space: pre-line; +} + .annotation-button { padding: 0; - margin-right: 0.25em; // needed as a text with white spaces within a button does not make the button have white spaces around ... + margin-right: 0.25em; // needed in case of semantic overlaps, i.e. when a button follows a button and the white space within a button does not make the button have white spaces around ... border: 2px; border-color: transparent; background-color: transparent; white-space: normal; } .annotation-button:hover { + cursor: pointer; + background-color: rgba(10, 104, 24, 0.21); + border-color: rgba(10, 104, 24, 0.21); +} + +.annotation-button-icon { + padding: 0; + margin: 0.25em; // needed in case of semantic overlaps, i.e. when a button follows a button and the white space within a button does not make the button have white spaces around ... + border: 2px; + border-color: transparent; + background-color: transparent; + white-space: normal; +} + +.annotation-button-icon:hover { + cursor: pointer; background-color: rgba(10, 104, 24, 0.21); border-color: rgba(10, 104, 24, 0.21); } +.annotation-icon { + +} + .style-markup { } .semantic-markup { } .semantic-markup.polysemantic { text-decoration: underline; - cursor: pointer; color: #0c5593; font-weight: bold; } .semantic-markup.humgeo { font-weight: bold; } .humgeo.city { color: blue; } .humgeo.state { color: #a4a4a4; } .semantic-markup.human { } .human.organization { color: #fa1cbc; } .human.person{ color: #ffbb5c; } diff --git a/src/app/markup-text-component/markup-text-component.component.ts b/src/app/markup-text-component/markup-text-component.component.ts index 1efd59b..867bfa3 100644 --- a/src/app/markup-text-component/markup-text-component.component.ts +++ b/src/app/markup-text-component/markup-text-component.component.ts @@ -1,168 +1,205 @@ import {Component, Input, OnChanges} from '@angular/core'; -import {MarkupOptionsService, MarkupSetting} from './markup-options.service'; +import {GenericOptionsService, SelectionBundle} from '../generic-control-elements-component/generic-control-elements-service.service'; import markupDefaultSettings from './markup-text-settings.json'; @Component({ selector: 'app-markup-text-component', templateUrl: './markup-text-component.component.html', styleUrls: ['./markup-text-component.component.scss'] // TODO: implement dynamic css from files/assets/server or somewhere }) /** TODO: change documentation * Simple and leightweight component marking up/styling a text input textToStyle with standoff markupData. * @param StandoffData: markup data. * @param textToStyle: the word for which the markup information should be applied as styles in the template. * @param startIndices: the startindices of all final text segments to style * @param styleSegments: the resulting style segments with their css styles which are then applied by ngStyle in the template */ export class MarkupTextComponentComponent implements OnChanges { @Input() standoffData: Array>; // [[rdfs:type, startIndex:number, endIndex:number, cssStyle:string], [...], ...] @Input() textToStyle: string; - @Input() markupSettings?: MarkupSetting; + @Input() inputSettings: string; + // the actual settings + actualSettings?: SelectionBundle; + // in case there is no settings input defaultSettings = JSON.parse(JSON.stringify(markupDefaultSettings)); + // Options on how to render + renderSemanticAnnotations: boolean; + renderStyleMarkup: boolean; + markupData: Array>; - // temporary mockup data - markupData: Array> = [ - ["stoff:CssStyle", 0, 1, "font-weight: bold;"], - ["stoff:CssStyle", 1, 4, "font-style: italic;"], - ["stoff:CssStyle", 0, 6, "text-decoration: underline;"], - ["stoff:CssStyle", 4, 4, "color: blue;"], - ["stoff:CssStyle", 4, 5, "text-decoration: line-through;"] - ]; - - startIndices: Array = []; // the startindices of all style segments + startIndices: Array = []; // the start indices of all style segments templateSegments: Array = []; // the resulting style segments with their css styles - constructor( private optionService: MarkupOptionsService) { - if (!this.markupSettings ) { - this.markupSettings = this.optionService.loadDefaultSettings(this.defaultSettings); - } + constructor( private optionService: GenericOptionsService) { + if (!this.inputSettings ) { + this.actualSettings = this.optionService.getSelectionFromJson(this.defaultSettings); + console.log('No markup settings passed by input. Loading default settings'); + console.log('Settings: ', this.actualSettings); + } else { + this.actualSettings = this.optionService.getSelectionFromJson(this.inputSettings); + console.log('markup settings loaded by input.'); + console.log('Settings: ', this.actualSettings); } } ngOnChanges() { - this.optionService.optionsChange.subscribe( - options => { this.markupSettings = options; console.log('new markup settings coming in: ' + this.markupSettings); } - ); - // TODO: maybe go for data stream as an observable/promise + // subscribing to OptionSettings changes + this.optionService.selectionEvent.subscribe(newSettings => { + this.actualSettings = newSettings; + this.setRenderType(newSettings.markup.renderMarkup); + }); + // TODO: go for data stream as an observable/promise if (this.standoffData && this.standoffData.length > 0 ) { this.markupData = this.standoffData; } - - this.templateSegments = []; // needed reset, if not ngOnChanges appends the new spans to the old ones in the template instead of replacing! + console.log('this.markupData:', this.markupData); + // initial settings for markup rendering + this.setRenderType(this.actualSettings.markup.renderMarkup); this.startIndices = this.getStartIndices(this.markupData); - this.createSegments(); } /** * Creates the final text segments and styles (this.templateSegments) which will * be *ngFored as and styled with *ngStyle in the template. * Iterates through all startindices defined, pushes the corresponding substring * of our text to style together with its matching styles to this.templateSegments * */ private createSegments() { + this.templateSegments = []; // needs reset, let c = 1; // counter for getting the end index of the substring() via this.startIndices[c] for (const startIndex of this.startIndices) { const textSegment = this.textToStyle.substring(startIndex, this.startIndices[c]); const markupDef = this.getMarkupDef(startIndex); if (markupDef) { this.templateSegments.push([markupDef[0], textSegment, markupDef[1], markupDef[2]]); } c += 1; } console.log('this.templateSegments: ', this.templateSegments); } /** * Gets the styles that apply for a passed start index. Hence the styles of a segment * apply to every character within that segment equally, we only need to get the styles * for the startindex, so all those styles apply to the whole segment correctly. * Iterates through all defined styles/ranges ranges of this.markupData. * For every range covering the startIndex, its style is added as property to the styles object. * * @param startIndex: The startindex of a new range to style * @return styles: An object with all matching css styles as properties */ private getMarkupDef(startIndex) { const markup = {}; const resource = []; // more than one linked resource possible at overlaps let markuptype = ''; for (const entry of this.markupData) { // if our startIndex is within a given range, the style of that range will be added to styles. if (entry[1] <= startIndex && startIndex <= entry[2]) { - if (entry[0] === 'stoff:CssStyle') { - markuptype = entry[0].split(':')[1]; // CssStyle + if (entry[0] === 'stoff:CssStyle' && this.renderStyleMarkup) { + if (markuptype === '') { // markuptype = CssStyle only if not yet set. CssStyle should not overwrite Semanticannotation. + markuptype = entry[0].split(':')[1]; + } // Adds css property/value as an object: Splits the style string at ':', // removes leading and ending spaces, deletes ";" and assigns it as an object as css property:"value" markup[entry[3].split(':')[0].trim()] = entry[3].split(':')[1].trim().replace(';', ''); } - if (entry[0] === 'stoff:SemanticAnnotation') { + if (entry[0] === 'stoff:SemanticAnnotation' && this.renderSemanticAnnotations) { markuptype = entry[0].split(':')[1]; // SemanticAnnotation // adds css class markup[(entry[3].trim().replace(':', ' ' ).toLowerCase())] = true; resource.push( { linkText: this.textToStyle.substring(entry[1], entry[2] + 1), link: entry[4], cssClass: entry[3].trim().replace(':', ' ' ).toLowerCase(), oClass: entry[3].trim().split(':')[1] }); // links } } } if (Object.keys(markup).length === 0 && markup.constructor === Object) { // If there is no range applying, e.g. no style at all defined for a startindex we simply define font-style: normal. return ['CssStyle', {'font-style': 'normal'}, '']; } else { return [markuptype, markup, resource ]; } } /** * Creates an array of startindices defining the final text/style segments. * Hence every end index can be described as a startindex minus one (an end * index equals a start index of sth. new -1), end indices are also covered implicitly. * So every endIndex +1 is also pushed to the startIndices array if not yet existing. * If a defined range is ending at the very last character, there is obviously not a new * style starting and an additive startIndex is wrong. Therefore the last startIndex * is simply popped from the array if its value exceeds textToStyle.length. * * @return startIndices: Array of all distinct startIndices of the final text segments. */ private getStartIndices(standoffData) { const startIndices: Array = []; // Push every startindex to startIndices if not yet there (distinct). // Hence every endIndex is itself equals a (startIndex -1), we simply add also every endIndex +1 to // the Array of startIndices if there is not yet a start defined for that character. standoffData.forEach(range => { if (startIndices.indexOf(range[1]) === -1) { startIndices.push(range[1]); } if (startIndices.indexOf(range[2] + 1) === -1) { startIndices.push(range[2] + 1); } }); // if there is no startindex of 0, we have to add it to define the first text segment. if (startIndices.indexOf(0) === -1) { startIndices.push(0); } // sort it startIndices.sort((n1, n2) => n1 - n2); // If the last endIndex is the very last character of the string to style, we must not generate a startIndex at endIndex+1. // In any other case we have to start a new style. // If the last generated startIndex is bigger than this.textToStyle.length // we have to pop that last startIndex (from the right) from our startIndices. // If the textToStyle.length is bigger or equals the last startIndex, that last startIndex simply means the end of the style - // one character before. In theese cases a last style range with font style undefined (style:normal) has to start, + // one character before. In these cases a last style range with font style undefined (style:normal) has to start, // so the last end ist also defined. if (this.textToStyle.length < startIndices[startIndices.length - 1]) { console.log('popping last startIndex: ', startIndices[startIndices.length - 1]); startIndices.pop(); } return startIndices; } // runs some action // TODO: Add actions private getHRef(action, target) { console.log('action = ', action); if (action === 'external') { return target; } } + + private getToolTip(segment) { + let toolTip = ''; + for (const thing of segment) { + if (toolTip === '') { + toolTip = thing.linkText + ': ' + thing.link + ' a ' + thing.cssClass.split(' ')[0] + ':' + thing.cssClass.split(' ')[1]; + } else { + toolTip = toolTip + '; ' + thing.linkText + ': ' + thing.link + ' a ' + thing.cssClass.split(' ')[0] + ':' + thing.cssClass.split(' ')[1]; + } + } + return toolTip; + } + + public setRenderType(renderMarkup: string) { + if (renderMarkup === 'style') { + this.renderSemanticAnnotations = false; + this.renderStyleMarkup = true; + } + if (renderMarkup === 'semanticAnnotation') { + this.renderSemanticAnnotations = true; + this.renderStyleMarkup = false; + } + if (renderMarkup === 'all') { + this.renderSemanticAnnotations = true; + this.renderStyleMarkup = true; } + + // run segmentation again with new renderSettings + this.createSegments(); + } } diff --git a/src/app/markup-text-component/markup-text-settings.json b/src/app/markup-text-component/markup-text-settings.json index 37ead40..18d239c 100644 --- a/src/app/markup-text-component/markup-text-settings.json +++ b/src/app/markup-text-component/markup-text-settings.json @@ -1,85 +1,152 @@ -{ - "settings":[ +{ "displaySettings": true, + "multiToggle": true, + "controlElementGroups":[ + { + "label": "markup", + "pannelOpenState": true, + "description": "Markup options", + "controlElements": [ + { + "label":"renderMarkup", + "description":"render markup", + "type":"radio", + "options":[ + { + "id":"semanticAnnotation", + "description":"semantic annotations only" + }, + { + "id":"style", + "description":"styles markup only" + }, + { + "id":"all", + "description":"both combined" + } + ], + "value":"semanticAnnotation" + } + ] + }, + { + "label": "styles", + "pannelOpenState": true, + "description": "Styles (non semantic markup only)", + "controlElements": [ + { + "label":"style", + "description":"render styles", + "value":true, + "type":"checkbox" + } + ] + }, { "label":"semanticMarkup", - "description":"display semantic annotations as", - "entries":[ + "pannelOpenState": true, + "condition": [ + {"group": "markup", "option":"renderMarkup", "values": ["all", "semanticAnnotation"] } + ], + "description":"Semantic annotations", + "controlElements":[ { "label":"styleType", "description":"render semantic annotations as", "options":[ { "id":"button", "description":"buttons" }, { "id":"icon", "description":"icons" }, { "id":"hyperlink", "description":"text with hyperlinks" }, { "id":"markup", "description":"styled text/markup only" }, { "id":"none", "description":"plane unstyled text" } ], - "value":"button", + "value":"icon", "type":"select" }, + { + "label":"renderIcons", + "description":"render semantic overlaps", + "options":[ + { + "id":"split", + "description":"split up in multiple icons" + }, + { + "id":"group", + "description":"group polysemantics in one icon" + } + ], + "value":"after", + "type":"radio", + "condition": [ + {"group": "semanticMarkup", "option": "styleType", "values": ["icon"]} + ] + }, { "label":"position", "description":"position them", "options":[ { "id":"before", "description":"before the text" }, { "id":"after", "description":"after the text" } ], "value":"after", "type":"radio", - "condition": [{"option":"semanticMarkup.styleType", "value":"icon"}] + "condition": [ + {"group": "semanticMarkup", "option": "styleType", "values": ["icon"]} + ] }, { "label":"actions", "description":"action to take place on click at a semantic annotation", "options":[ { "id":"external", "description":"open external link" }, { "id":"pannel", "description":"display resource in pannel" }, { "id":"menu", "description":"open menu" } ], "value":"menu", "type":"select", - "condition": [ - {"option": "semanticMarkup.styleType", "value": "icon"}, - {"option": "semanticMarkup.styleType", "value": "button"}, - {"option": "semanticMarkup.styleType", "value": "hyperlink"} + "condition": [{ + "group": "semanticMarkup", + "option": "styleType", + "values": ["icon", "button", "hyperlink"]} ] }, { "label":"tooltip", + "description":"show tooltip", "value":true, "type":"checkbox" } ] } ] } diff --git a/src/app/markup-text-component/submenu-component/submenu-component.component.html b/src/app/markup-text-component/submenu-component/submenu-component.component.html index 75fadeb..23390b0 100644 --- a/src/app/markup-text-component/submenu-component/submenu-component.component.html +++ b/src/app/markup-text-component/submenu-component/submenu-component.component.html @@ -1,10 +1,16 @@ - -
- {{item.oClass}}: {{item.linkText}} + +
+ {{item.oClass}}: {{item.linkText}}
+
+ {{item.oClass}}: {{item.linkText}} +
open resource in data browser
edit text
edit semantic annotation
delete semantic annotation
diff --git a/src/app/markup-text-component/submenu-component/submenu-component.component.ts b/src/app/markup-text-component/submenu-component/submenu-component.component.ts index 50c1d6d..bbd83e2 100644 --- a/src/app/markup-text-component/submenu-component/submenu-component.component.ts +++ b/src/app/markup-text-component/submenu-component/submenu-component.component.ts @@ -1,16 +1,17 @@ import {Component, Input, OnInit} from '@angular/core'; @Component({ selector: 'app-submenu-component', templateUrl: './submenu-component.component.html', styleUrls: ['../markup-text-component.component.scss'] }) export class SubmenuComponentComponent implements OnInit { constructor() { } @Input() item: any; + @Input() action: any; ngOnInit() { } } diff --git a/src/app/options-component/options-component.component.html b/src/app/options-component/options-component.component.html deleted file mode 100644 index 0e844bc..0000000 --- a/src/app/options-component/options-component.component.html +++ /dev/null @@ -1,33 +0,0 @@ -

Options

- - - - - {{settingsGroup.label}} - - -
- -
-
{{setting.description}}
- - - {{option.description}} - - -
- -
-
{{setting.description}}
- -
- {{option.description}} -
-
-
-
-
-
- diff --git a/src/app/options-component/options-component.component.scss b/src/app/options-component/options-component.component.scss deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/options-component/options-component.component.ts b/src/app/options-component/options-component.component.ts deleted file mode 100644 index aeafbd1..0000000 --- a/src/app/options-component/options-component.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {Component, Input, OnInit} from '@angular/core'; -import {MarkupOptionsService, MarkupSetting} from '../markup-text-component/markup-options.service'; - -@Component({ - selector: 'app-options-component', - templateUrl: './options-component.component.html', - styleUrls: ['./options-component.component.scss'] -}) -export class OptionsComponent implements OnInit { - @Input() initialSettings?: any; - actualSettings: MarkupSetting; - - constructor(private optionService: MarkupOptionsService) { } - - ngOnInit() { - if (this.initialSettings) { - this.actualSettings = this.optionService.loadDefaultSettings(this.initialSettings); - console.log('this.actualSettings loaded: ', this.actualSettings); - } - } - - onSelectValueChange(settingGroup, changedSetting) { - console.log('new selection => ', changedSetting.label , ': ', changedSetting.value); - this.actualSettings[settingGroup + '.' + changedSetting.label] = changedSetting.value; - - this.optionService.setSettings(this.actualSettings); - console.log('new displaySettings: ', this.actualSettings); - } - - private evaluateDisplayOption(conditions) { - if (conditions) { - let evaluator = false; - for (const condition of conditions) { - if (this.actualSettings[condition.option] === condition.value) { - evaluator = true; - } - } - return evaluator; } else {return true; } - } -}