diff --git a/frontends/dnet-is-application/src/app/app.module.ts b/frontends/dnet-is-application/src/app/app.module.ts index 82830491..f73db797 100644 --- a/frontends/dnet-is-application/src/app/app.module.ts +++ b/frontends/dnet-is-application/src/app/app.module.ts @@ -29,7 +29,7 @@ import { MatSortModule } from '@angular/material/sort'; import { ResourcesComponent, ResContentDialog, ResCreateNewDialog, ResMetadataDialog } from './resources/resources.component' import { MatSnackBarModule } from '@angular/material/snack-bar'; import { ContextsComponent, ContextViewerComponent, ContextParamsDialog } from './contexts/contexts.component'; -import { VocabulariesComponent, VocabularyEditorComponent, VocDialog } from './vocabularies/vocabularies.component'; +import { VocabulariesComponent, VocabularyEditorComponent, VocDialog, VocTermDialog } from './vocabularies/vocabularies.component'; @NgModule({ declarations: [ @@ -50,7 +50,8 @@ import { VocabulariesComponent, VocabularyEditorComponent, VocDialog } from './v ContextParamsDialog, VocabulariesComponent, VocabularyEditorComponent, - VocDialog + VocDialog, + VocTermDialog ], imports: [ BrowserModule, diff --git a/frontends/dnet-is-application/src/app/is.service.ts b/frontends/dnet-is-application/src/app/is.service.ts index 7a57a86b..4164d44b 100644 --- a/frontends/dnet-is-application/src/app/is.service.ts +++ b/frontends/dnet-is-application/src/app/is.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { ResourceType, Protocol, WfHistoryEntry, SimpleResource, Context, ContextNode, Vocabulary } from './model/controller.model'; +import { ResourceType, Protocol, WfHistoryEntry, SimpleResource, Context, ContextNode, Vocabulary, VocabularyTerm } from './model/controller.model'; import { Observable, Observer } from 'rxjs'; import { FormGroup } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -140,13 +140,34 @@ export class ISService { }); } + loadVocabulary(vocId:string, onSuccess: Function): void { + this.client.get('./ajax/vocs/' + encodeURIComponent(vocId)).subscribe({ + next: data => onSuccess(data), + error: error => this.showError(error) + }); + } + + loadVocabularyTerms(vocId:string, onSuccess: Function): void { + this.client.get('./ajax/vocs/' + encodeURIComponent(vocId) + '/terms').subscribe({ + next: data => onSuccess(data), + error: error => this.showError(error) + }); + } + saveVocabulary(voc:Vocabulary, onSuccess: Function, relatedForm?: FormGroup): void { this.client.post('./ajax/vocs/', voc).subscribe({ next: data => onSuccess(data), error: error => this.showError(error, relatedForm) }); } - + + saveVocabularyTerm(vocId:string, term:VocabularyTerm, onSuccess: Function, relatedForm?: FormGroup): void { + this.client.post('./ajax/vocs/' + encodeURIComponent(vocId) + '/terms', term).subscribe({ + next: data => onSuccess(data), + error: error => this.showError(error, relatedForm) + }); + } + deleteVocabulary(vocId:string, onSuccess: Function): void { this.client.delete('./ajax/vocs/' + encodeURIComponent(vocId)).subscribe({ next: data => onSuccess(data), @@ -154,6 +175,17 @@ export class ISService { }); } + deleteVocabularyTerm(vocId:string, termCode:string, onSuccess: Function): void { + this.client.delete('./ajax/vocs/' + + encodeURIComponent(vocId) + + '/terms/' + + encodeURIComponent(termCode) + ).subscribe({ + next: data => onSuccess(data), + error: error => this.showError(error) + }); + } + private showError(error: any, form?: FormGroup) { const msg = this.errorMessage(error); if (form) { diff --git a/frontends/dnet-is-application/src/app/model/controller.model.ts b/frontends/dnet-is-application/src/app/model/controller.model.ts index f3b78183..d1cbeb29 100644 --- a/frontends/dnet-is-application/src/app/model/controller.model.ts +++ b/frontends/dnet-is-application/src/app/model/controller.model.ts @@ -1,9 +1,9 @@ export interface ResourceType { - id:string - name:string - contentType:string - count:number - simple:boolean + id: string + name: string + contentType: string + count: number + simple: boolean } export interface KeyValue { @@ -19,11 +19,11 @@ export interface Module { } export interface ProtocolParams { - name:string - label:string - type:string - optional:boolean - hasSelFunction:boolean + name: string + label: string + type: string + optional: boolean + hasSelFunction: boolean } export interface Protocol { @@ -41,7 +41,7 @@ export interface WfHistoryEntry { dsId?: string, dsName?: string, dsApi?: string, - details: Map + details: Map } export interface SimpleResource { @@ -81,4 +81,17 @@ export interface Vocabulary { id: string, name: string, description?: string -} \ No newline at end of file +} + +export interface VocabularyTermSynonym { + term: string, + encoding: string +} + +export interface VocabularyTerm { + code: string, + vocabulary: string, + name: string, + encoding: string, + synonyms: VocabularyTermSynonym[] +} diff --git a/frontends/dnet-is-application/src/app/vocabularies/voc-term-dialog.html b/frontends/dnet-is-application/src/app/vocabularies/voc-term-dialog.html new file mode 100644 index 00000000..fc06c97f --- /dev/null +++ b/frontends/dnet-is-application/src/app/vocabularies/voc-term-dialog.html @@ -0,0 +1 @@ +XXXXXX diff --git a/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.html b/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.html index 0817c813..7b5b855d 100644 --- a/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.html +++ b/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.html @@ -30,7 +30,7 @@ - + diff --git a/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.ts b/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.ts index 1d2076d3..ee4410fc 100644 --- a/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.ts +++ b/frontends/dnet-is-application/src/app/vocabularies/vocabularies.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject,AfterViewInit, OnInit, ViewChild } from '@angular/core'; +import { Component, Inject, AfterViewInit, OnInit, ViewChild } from '@angular/core'; import { ISService } from '../is.service'; import { MatTableDataSource } from '@angular/material/table'; import { MatSort, Sort } from '@angular/material/sort'; @@ -7,22 +7,23 @@ import { ActivatedRoute, Params } from '@angular/router'; import { Observable, combineLatest } from 'rxjs'; import { map } from 'rxjs/operators'; import { MatDialog, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { KeyValue, ContextParam } from '../model/controller.model'; +import { VocabularyTerm } from '../model/controller.model'; import { FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; +import { EmitterVisitorContext } from '@angular/compiler'; @Component({ selector: 'app-vocabularies', templateUrl: './vocabularies.component.html', styleUrls: ['./vocabularies.component.css'] }) -export class VocabulariesComponent { +export class VocabulariesComponent implements OnInit, AfterViewInit { vocsDatasource: MatTableDataSource = new MatTableDataSource([]); colums: string[] = ['id', 'name', 'description', 'buttons']; @ViewChild(MatSort) sort: MatSort | undefined - constructor(public service: ISService, public route: ActivatedRoute, public dialog: MatDialog) { + constructor(public service: ISService, public route: ActivatedRoute, public dialog: MatDialog) { } ngOnInit() { @@ -30,7 +31,7 @@ export class VocabulariesComponent { } ngAfterViewInit() { - if(this.sort) this.vocsDatasource.sort = this.sort; + if (this.sort) this.vocsDatasource.sort = this.sort; } reload() { @@ -41,11 +42,11 @@ export class VocabulariesComponent { const filterValue = (event.target as HTMLInputElement).value.trim().toLowerCase(); this.vocsDatasource.filter = filterValue; } - + newVocabularyDialog(): void { - const dialogRef = this.dialog.open(VocDialog, { - data: { id: '', name: '', description: '' }, - width: '80%' + const dialogRef = this.dialog.open(VocDialog, { + data: { id: '', name: '', description: '' }, + width: '80%' }); dialogRef.afterClosed().subscribe(result => { @@ -64,12 +65,11 @@ export class VocabulariesComponent { }); } - deleteVocabularyDialog(vocabulary: Vocabulary): void { + deleteVocabulary(vocabulary: Vocabulary): void { if (confirm("Are you sure?")) { - this.service.deleteVocabulary(vocabulary.id , (data:void) => this.reload()); + this.service.deleteVocabulary(vocabulary.id, (data: void) => this.reload()); } } - } @@ -78,7 +78,71 @@ export class VocabulariesComponent { templateUrl: './vocabulary-editor.component.html', styleUrls: ['./vocabularies.component.css'] }) -export class VocabularyEditorComponent { +export class VocabularyEditorComponent implements OnInit, AfterViewInit { + + voc?: Vocabulary + + termsDatasource: MatTableDataSource = new MatTableDataSource([]); + colums: string[] = ['code', 'name', 'encoding', 'synonyms', 'buttons']; + + @ViewChild(MatSort) sort: MatSort | undefined + + constructor(public service: ISService, public route: ActivatedRoute, public dialog: MatDialog) { + } + + ngOnInit() { + this.reload(); + } + + ngAfterViewInit() { + if (this.sort) this.termsDatasource.sort = this.sort; + } + + reload() { + this.route.queryParams.subscribe((params) => { + this.service.loadVocabulary(params['id'], (data: Vocabulary) => this.voc = data); + this.service.loadVocabularyTerms(params['id'], (data: VocabularyTerm[]) => this.termsDatasource.data = data); + }); + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value.trim().toLowerCase(); + this.termsDatasource.filter = filterValue; + } + + newVocabularyTermDialog(): void { + if (this.voc?.id) { + const dialogRef = this.dialog.open(VocTermDialog, { + data: { vocabulary: this.voc.id, code: '', name: '', encoding: '', synonyms: []}, + width: '80%' + }); + + dialogRef.afterClosed().subscribe(result => { + if (result) this.reload(); + }); + } + + } + + editVocabularyTermDialog(term: VocabularyTerm): void { + const dialogRef = this.dialog.open(VocTermDialog, { + data: term, + width: '80%' + }); + + dialogRef.afterClosed().subscribe(result => { + if (result) this.reload(); + }); + } + + deleteVocabularyTerm(term: VocabularyTerm): void { + if (confirm("Are you sure?") && this.voc?.id && term.code) { + this.service.deleteVocabularyTerm(this.voc.id, term.code, (data: void) => this.reload()); + } + } + + + } @Component({ @@ -88,22 +152,50 @@ export class VocabularyEditorComponent { }) export class VocDialog { vocForm = new FormGroup({ - id: new FormControl(''), - name: new FormControl(''), - description : new FormControl('') + id: new FormControl(''), + name: new FormControl(''), + description: new FormControl('') }); - constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, public service: ISService) { + constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, public service: ISService) { this.vocForm.get('id')?.setValue(data.id); this.vocForm.get('name')?.setValue(data.name); this.vocForm.get('description')?.setValue(data.description); } - - onSubmit():void { + + onSubmit(): void { const voc = Object.assign({}, this.data, this.vocForm.value); this.service.saveVocabulary(voc, (data: void) => this.dialogRef.close(1), this.vocForm); } + onNoClick(): void { + this.dialogRef.close(); + } +} + +@Component({ + selector: 'voc-term-dialog', + templateUrl: 'voc-term-dialog.html', + styleUrls: ['vocabularies.component.css'] +}) +export class VocTermDialog { + termForm = new FormGroup({ + code: new FormControl(''), + name: new FormControl(''), + encoding: new FormControl('') + }); + + constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, public service: ISService) { + this.termForm.get('code')?.setValue(data.id); + this.termForm.get('name')?.setValue(data.name); + this.termForm.get('encoding')?.setValue(data.encoding); + } + + onSubmit(): void { + const term = Object.assign({}, this.data, this.termForm.value); + this.service.saveVocabularyTerm(term.vocabulary, term, (data: void) => this.dialogRef.close(1), this.termForm); + } + onNoClick(): void { this.dialogRef.close(); } diff --git a/frontends/dnet-is-application/src/app/vocabularies/vocabulary-editor.component.html b/frontends/dnet-is-application/src/app/vocabularies/vocabulary-editor.component.html index dd0279ba..918b70dc 100644 --- a/frontends/dnet-is-application/src/app/vocabularies/vocabulary-editor.component.html +++ b/frontends/dnet-is-application/src/app/vocabularies/vocabulary-editor.component.html @@ -1 +1,61 @@ -VOC EDITOR \ No newline at end of file +

Vocabulary Editor

+ +

+ Vocabulary ID: {{voc?.id}}
+ Vocabulary Name: {{voc?.name}}
+ Description: {{voc?.description}} +

+ +

+ return to vocabulary list + + Download +

+ + + Filter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Code {{element.code}} Name {{element.name}} Encoding {{element.encoding}} Description + + {{s.term}} + + + + +
No data matching the filter "{{input.value}}"