diff --git a/package-lock.json b/package-lock.json index dbef9443ab..45d0ee84e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "dsp-app", - "version": "4.1.0", + "version": "4.2.1", "dependencies": { "@angular/animations": "^9.1.12", "@angular/cdk": "^9.2.4", @@ -19,7 +19,7 @@ "@angular/platform-browser-dynamic": "~9.1.12", "@angular/router": "~9.1.12", "@ckeditor/ckeditor5-angular": "^1.2.3", - "@dasch-swiss/dsp-js": "^2.0.2", + "@dasch-swiss/dsp-js": "^2.1.0", "@dasch-swiss/dsp-ui": "^1.2.2", "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", @@ -2109,7 +2109,9 @@ } }, "node_modules/@dasch-swiss/dsp-js": { - "version": "2.0.2", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@dasch-swiss/dsp-js/-/dsp-js-2.1.0.tgz", + "integrity": "sha512-jz4Umltxz5WK9CL9gUYyy9dntuFP6hYIBXODDcoD4Jr9iqBKQTS584XxFg3ZZmktiYt0Iu9j2BeKFlxUk2uAkQ==", "license": "AGPL-3.0", "dependencies": { "@types/jsonld": "^1.5.0", @@ -20863,7 +20865,9 @@ } }, "@dasch-swiss/dsp-js": { - "version": "2.0.2", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@dasch-swiss/dsp-js/-/dsp-js-2.1.0.tgz", + "integrity": "sha512-jz4Umltxz5WK9CL9gUYyy9dntuFP6hYIBXODDcoD4Jr9iqBKQTS584XxFg3ZZmktiYt0Iu9j2BeKFlxUk2uAkQ==", "requires": { "@types/jsonld": "^1.5.0", "json2typescript": "1.4.1", diff --git a/package.json b/package.json index c543533294..da7cbf615b 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@angular/platform-browser-dynamic": "~9.1.12", "@angular/router": "~9.1.12", "@ckeditor/ckeditor5-angular": "^1.2.3", - "@dasch-swiss/dsp-js": "^2.0.2", + "@dasch-swiss/dsp-js": "^2.1.0", "@dasch-swiss/dsp-ui": "^1.2.2", "@ngx-translate/core": "^13.0.0", "@ngx-translate/http-loader": "^6.0.0", diff --git a/src/app/main/dialog/dialog.component.html b/src/app/main/dialog/dialog.component.html index 6e45243c48..3ab7821379 100644 --- a/src/app/main/dialog/dialog.component.html +++ b/src/app/main/dialog/dialog.component.html @@ -145,6 +145,13 @@ (updateParent)="replaceTitle($event)"> + +
+ + + +
+
@@ -157,7 +164,7 @@
- +
diff --git a/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.html b/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.html index 84fd1bd958..88deb051b1 100644 --- a/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.html +++ b/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.html @@ -37,8 +37,8 @@ type="submit" color="primary" [disabled]="saveButtonDisabled" - (click)="updateChildNode()"> - {{ 'appLabels.form.action.update' | translate }} + (click)=" mode === 'editListNode' ? updateChildNode() : insertChildNode()"> + {{ mode === 'editListNode' ? 'appLabels.form.action.update' : 'appLabels.form.action.submit' | translate }}
diff --git a/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.spec.ts b/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.spec.ts index 6f0da3155f..7996a3a0b4 100644 --- a/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.spec.ts +++ b/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.spec.ts @@ -2,7 +2,7 @@ import { Component, DebugElement, OnInit, ViewChild } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { ApiResponseData, ListNodeInfoResponse, ListsEndpointAdmin, UpdateChildNodeRequest } from '@dasch-swiss/dsp-js'; +import { ApiResponseData, CreateChildNodeRequest, ListNodeInfoResponse, ListsEndpointAdmin, UpdateChildNodeRequest } from '@dasch-swiss/dsp-js'; import { DspActionModule, DspApiConnectionToken, ProgressIndicatorComponent } from '@dasch-swiss/dsp-ui'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; @@ -10,29 +10,52 @@ import { AjaxResponse } from 'rxjs/ajax'; import { EditListItemComponent } from './edit-list-item.component'; /** - * Test host component to simulate parent component. + * Test host component to simulate parent component for updating an existing child node. */ @Component({ - template: `` + template: `` }) -class TestHostComponent implements OnInit { +class TestHostUpdateChildNodeComponent { @ViewChild('editListItem') editListItem: EditListItemComponent; iri = 'http://rdfh.ch/lists/0001/otherTreeList01'; + mode = 'update'; + projectIri = 'http://rdfh.ch/projects/0001'; constructor() {} +} + +/** + * Test host component to simulate parent component for inserting a new child node. + */ +@Component({ + template: `` +}) +class TestHostInsertChildNodeComponent { + + @ViewChild('editListItem') editListItem: EditListItemComponent; + + iri = 'http://rdfh.ch/lists/0001/otherTreeList01'; + + mode = 'insert'; - ngOnInit() { - } + parentIri = 'http://rdfh.ch/lists/0001/otherTreeList'; + + position = 0; + + projectCode = '0001'; + + projectIri = 'http://rdfh.ch/projects/0001'; + constructor() {} } describe('EditListItemComponent', () => { - let testHostComponent: TestHostComponent; - let testHostFixture: ComponentFixture; + let testHostComponent: TestHostUpdateChildNodeComponent; + let testHostFixture: ComponentFixture; let editListItemComponentDe: DebugElement; let formInvalidMessageDe: DebugElement; @@ -40,14 +63,15 @@ describe('EditListItemComponent', () => { const listsEndpointSpyObj = { admin: { - listsEndpoint: jasmine.createSpyObj('listsEndpoint', ['getListNodeInfo', 'updateChildNode']) + listsEndpoint: jasmine.createSpyObj('listsEndpoint', ['getListNodeInfo', 'updateChildNode', 'createChildNode']) } }; TestBed.configureTestingModule({ declarations: [ EditListItemComponent, - TestHostComponent, + TestHostUpdateChildNodeComponent, + TestHostInsertChildNodeComponent, ProgressIndicatorComponent, ], imports: [ @@ -65,88 +89,142 @@ describe('EditListItemComponent', () => { .compileComponents(); })); - beforeEach(() => { - const dspConnSpy = TestBed.inject(DspApiConnectionToken); - - (dspConnSpy.admin.listsEndpoint as jasmine.SpyObj).getListNodeInfo.and.callFake( - () => { - const response = new ListNodeInfoResponse(); - response.nodeinfo.id = 'http://rdfh.ch/lists/0001/otherTreeList01'; - response.nodeinfo.labels = [{'value': 'Tree list node 01', 'language': 'en'}]; - response.nodeinfo.comments = [{'value': 'My comment', 'language': 'en'}]; - return of(ApiResponseData.fromAjaxResponse({response} as AjaxResponse)); - } - ); - - testHostFixture = TestBed.createComponent(TestHostComponent); - testHostComponent = testHostFixture.componentInstance; - testHostFixture.detectChanges(); - - expect(testHostComponent).toBeTruthy(); - - const hostCompDe = testHostFixture.debugElement; - editListItemComponentDe = hostCompDe.query(By.directive(EditListItemComponent)); - expect(editListItemComponentDe).toBeTruthy(); - }); - - it('should assign labels and comments', () => { - const dspConnSpy = TestBed.inject(DspApiConnectionToken); - expect(testHostComponent.editListItem.labels).toEqual([{'value': 'Tree list node 01', 'language': 'en'}]); - expect(testHostComponent.editListItem.comments).toEqual([{'value': 'My comment', 'language': 'en'}]); - expect(dspConnSpy.admin.listsEndpoint.getListNodeInfo).toHaveBeenCalledTimes(1); - expect(dspConnSpy.admin.listsEndpoint.getListNodeInfo).toHaveBeenCalledWith('http://rdfh.ch/lists/0001/otherTreeList01'); - + describe('update list child node', () => { + beforeEach(() => { + const dspConnSpy = TestBed.inject(DspApiConnectionToken); + + (dspConnSpy.admin.listsEndpoint as jasmine.SpyObj).getListNodeInfo.and.callFake( + () => { + const response = new ListNodeInfoResponse(); + response.nodeinfo.id = 'http://rdfh.ch/lists/0001/otherTreeList01'; + response.nodeinfo.labels = [{'value': 'Tree list node 01', 'language': 'en'}]; + response.nodeinfo.comments = [{'value': 'My comment', 'language': 'en'}]; + return of(ApiResponseData.fromAjaxResponse({response} as AjaxResponse)); + } + ); + + testHostFixture = TestBed.createComponent(TestHostUpdateChildNodeComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + + expect(testHostComponent).toBeTruthy(); + + const hostCompDe = testHostFixture.debugElement; + editListItemComponentDe = hostCompDe.query(By.directive(EditListItemComponent)); + expect(editListItemComponentDe).toBeTruthy(); + }); + + it('should assign labels and comments', () => { + const dspConnSpy = TestBed.inject(DspApiConnectionToken); + expect(testHostComponent.editListItem.labels).toEqual([{'value': 'Tree list node 01', 'language': 'en'}]); + expect(testHostComponent.editListItem.comments).toEqual([{'value': 'My comment', 'language': 'en'}]); + expect(dspConnSpy.admin.listsEndpoint.getListNodeInfo).toHaveBeenCalledTimes(1); + expect(dspConnSpy.admin.listsEndpoint.getListNodeInfo).toHaveBeenCalledWith('http://rdfh.ch/lists/0001/otherTreeList01'); + }); + + it('should update labels when the value changes', () => { + expect(testHostComponent.editListItem.labels).toEqual([{'value': 'Tree list node 01', 'language': 'en'}]); + testHostComponent.editListItem.handleData([{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}], 'labels'); + expect(testHostComponent.editListItem.labels).toEqual([{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}]); + expect(testHostComponent.editListItem.saveButtonDisabled).toBeFalsy(); + testHostComponent.editListItem.handleData([], 'labels'); + expect(testHostComponent.editListItem.saveButtonDisabled).toBeTruthy(); + testHostFixture.detectChanges(); + formInvalidMessageDe = editListItemComponentDe.query(By.css('span.invalid-form')); + expect(formInvalidMessageDe.nativeElement.innerText).toEqual('A label is required.'); + }); + + it('should update comments when the value changes', () => { + expect(testHostComponent.editListItem.comments).toEqual([{'value': 'My comment', 'language': 'en'}]); + testHostComponent.editListItem.handleData([{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}], 'comments'); + expect(testHostComponent.editListItem.comments).toEqual([{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}]); + expect(testHostComponent.editListItem.saveButtonDisabled).toBeFalsy(); + testHostComponent.editListItem.handleData([], 'comments'); + expect(testHostComponent.editListItem.saveButtonDisabled).toBeFalsy(); + }); + + it('should update the child node info', () => { + const dspConnSpy = TestBed.inject(DspApiConnectionToken); + + testHostComponent.editListItem.handleData([{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}], 'labels'); + testHostComponent.editListItem.handleData([{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}], 'comments'); + + (dspConnSpy.admin.listsEndpoint as jasmine.SpyObj).updateChildNode.and.callFake( + () => { + const response = new ListNodeInfoResponse(); + response.nodeinfo.id = 'http://rdfh.ch/lists/0001/otherTreeList01'; + response.nodeinfo.labels = [{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}]; + response.nodeinfo.comments = [{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}]; + + expect(testHostComponent.editListItem.labels).toEqual(response.nodeinfo.labels); + expect(testHostComponent.editListItem.comments).toEqual(response.nodeinfo.comments); + + return of(ApiResponseData.fromAjaxResponse({response} as AjaxResponse)); + } + ); + + const updateChildNodeRequest: UpdateChildNodeRequest = new UpdateChildNodeRequest(); + updateChildNodeRequest.projectIri = testHostComponent.editListItem.projectIri; + updateChildNodeRequest.listIri = testHostComponent.editListItem.iri; + updateChildNodeRequest.labels = testHostComponent.editListItem.labels; + updateChildNodeRequest.comments = testHostComponent.editListItem.comments; + + testHostComponent.editListItem.updateChildNode(); + expect(dspConnSpy.admin.listsEndpoint.updateChildNode).toHaveBeenCalledTimes(1); + expect(dspConnSpy.admin.listsEndpoint.updateChildNode).toHaveBeenCalledWith(updateChildNodeRequest); + }); }); - it('should update labels when the value changes', () => { - expect(testHostComponent.editListItem.labels).toEqual([{'value': 'Tree list node 01', 'language': 'en'}]); - testHostComponent.editListItem.handleData([{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}], 'labels'); - expect(testHostComponent.editListItem.labels).toEqual([{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}]); - expect(testHostComponent.editListItem.saveButtonDisabled).toBeFalsy(); - testHostComponent.editListItem.handleData([], 'labels'); - expect(testHostComponent.editListItem.saveButtonDisabled).toBeTruthy(); - testHostFixture.detectChanges(); - formInvalidMessageDe = editListItemComponentDe.query(By.css('span.invalid-form')); - expect(formInvalidMessageDe.nativeElement.innerText).toEqual('A label is required.'); - }); + describe('insert list child node', () => { + beforeEach(() => { + testHostFixture = TestBed.createComponent(TestHostInsertChildNodeComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); - it('should update comments when the value changes', () => { - expect(testHostComponent.editListItem.comments).toEqual([{'value': 'My comment', 'language': 'en'}]); - testHostComponent.editListItem.handleData([{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}], 'comments'); - expect(testHostComponent.editListItem.comments).toEqual([{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}]); - expect(testHostComponent.editListItem.saveButtonDisabled).toBeFalsy(); - testHostComponent.editListItem.handleData([], 'comments'); - expect(testHostComponent.editListItem.saveButtonDisabled).toBeFalsy(); - }); + expect(testHostComponent).toBeTruthy(); - it('should update the child node info', () => { - const dspConnSpy = TestBed.inject(DspApiConnectionToken); + const hostCompDe = testHostFixture.debugElement; + editListItemComponentDe = hostCompDe.query(By.directive(EditListItemComponent)); + expect(editListItemComponentDe).toBeTruthy(); + }); - testHostComponent.editListItem.handleData([{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}], 'labels'); - testHostComponent.editListItem.handleData([{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}], 'comments'); + it('should instantiate empty arrays for labels and comments', () => { + expect(testHostComponent.editListItem.labels).toEqual([]); + expect(testHostComponent.editListItem.comments).toEqual([]); + }); - (dspConnSpy.admin.listsEndpoint as jasmine.SpyObj).updateChildNode.and.callFake( - () => { - const response = new ListNodeInfoResponse(); - response.nodeinfo.id = 'http://rdfh.ch/lists/0001/otherTreeList01'; - response.nodeinfo.labels = [{'value': 'Tree list node 01', 'language': 'en'}, {'value': 'Baumlistenknoten 01', 'language': 'de'}]; - response.nodeinfo.comments = [{'value': 'My comment', 'language': 'en'}, {'value': 'Mein Kommentar', 'language': 'de'}]; + it('should create (insert) a new child node', () => { + const dspConnSpy = TestBed.inject(DspApiConnectionToken); - expect(testHostComponent.editListItem.labels).toEqual(response.nodeinfo.labels); - expect(testHostComponent.editListItem.comments).toEqual(response.nodeinfo.comments); + testHostComponent.editListItem.handleData([{'value': 'My new child node value', 'language': 'en'}], 'labels'); + testHostComponent.editListItem.handleData([{'value': 'My new child node comment', 'language': 'en'}], 'comments'); - return of(ApiResponseData.fromAjaxResponse({response} as AjaxResponse)); - } - ); + (dspConnSpy.admin.listsEndpoint as jasmine.SpyObj).createChildNode.and.callFake( + () => { + const response = new ListNodeInfoResponse(); + response.nodeinfo.name = 'My new child node'; + response.nodeinfo.id = 'http://rdfh.ch/lists/0001/otherTreeList0123'; + response.nodeinfo.labels = [{'value': 'My new child node value', 'language': 'en'}]; + response.nodeinfo.comments = [{'value': 'My new child node comment', 'language': 'en'}]; + response.nodeinfo.position = 0; - const childNodeUpdateData: UpdateChildNodeRequest = new UpdateChildNodeRequest(); - childNodeUpdateData.projectIri = testHostComponent.editListItem.projectIri; - childNodeUpdateData.listIri = testHostComponent.editListItem.iri; - childNodeUpdateData.labels = testHostComponent.editListItem.labels; - childNodeUpdateData.comments = testHostComponent.editListItem.comments; + expect(testHostComponent.editListItem.labels).toEqual(response.nodeinfo.labels); + expect(testHostComponent.editListItem.comments).toEqual(response.nodeinfo.comments); + expect(testHostComponent.editListItem.position).toEqual(response.nodeinfo.position); - testHostComponent.editListItem.updateChildNode(); - expect(dspConnSpy.admin.listsEndpoint.updateChildNode).toHaveBeenCalledTimes(1); - expect(dspConnSpy.admin.listsEndpoint.updateChildNode).toHaveBeenCalledWith(childNodeUpdateData); + return of(ApiResponseData.fromAjaxResponse({response} as AjaxResponse)); + } + ); + + const createChildNodeRequest: CreateChildNodeRequest = new CreateChildNodeRequest(); + createChildNodeRequest.projectIri = testHostComponent.editListItem.projectIri; + createChildNodeRequest.labels = testHostComponent.editListItem.labels; + createChildNodeRequest.comments = testHostComponent.editListItem.comments; + createChildNodeRequest.position = testHostComponent.editListItem.position; + createChildNodeRequest.parentNodeIri = testHostComponent.editListItem.parentIri; + + testHostComponent.editListItem.insertChildNode(); + expect(dspConnSpy.admin.listsEndpoint.createChildNode).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts b/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts index 31abe3ab52..541fc9405c 100644 --- a/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts +++ b/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts @@ -1,5 +1,16 @@ import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core'; -import { ApiResponseData, ApiResponseError, ChildNodeInfoResponse, KnoraApiConnection, List, ListNodeInfo, ListNodeInfoResponse, StringLiteral, UpdateChildNodeRequest } from '@dasch-swiss/dsp-js'; +import { + ApiResponseData, + ApiResponseError, + ChildNodeInfoResponse, + CreateChildNodeRequest, + KnoraApiConnection, + List, + ListNodeInfo, + ListNodeInfoResponse, + StringLiteral, + UpdateChildNodeRequest +} from '@dasch-swiss/dsp-js'; import { DspApiConnectionToken } from '@dasch-swiss/dsp-ui'; @Component({ @@ -12,6 +23,14 @@ export class EditListItemComponent implements OnInit { @Input() iri: string; + @Input() mode: 'insert' | 'update'; + + @Input() parentIri?: string; + + @Input() position?: number; + + @Input() projectCode?: string; + @Input() projectIri: string; @Output() closeDialog: EventEmitter = new EventEmitter(); @@ -46,16 +65,23 @@ export class EditListItemComponent implements OnInit { ngOnInit(): void { this.loading = true; - // get list - this._dspApiConnection.admin.listsEndpoint.getListNodeInfo(this.iri).subscribe( - (response: ApiResponseData) => { - this.listNode = response.body.nodeinfo; - this.buildForm(response.body.nodeinfo); - }, - (error: ApiResponseError) => { - console.error(error); - } - ); + // if updating a node, get the existing node info + if (this.mode === 'update') { + this._dspApiConnection.admin.listsEndpoint.getListNodeInfo(this.iri).subscribe( + (response: ApiResponseData) => { + this.listNode = response.body.nodeinfo; + this.buildForm(response.body.nodeinfo); + }, + (error: ApiResponseError) => { + console.error(error); + } + ); + } else { + this.labels = []; + this.comments = []; + + this.loading = false; + } } /** @@ -105,8 +131,8 @@ export class EditListItemComponent implements OnInit { } /** - * Called from the template when the 'update' button is clicked. - * Sends a request to DSP-API to update the list node with the data inside the two local arrays. + * Called from the template when the 'submit' button is clicked in update mode. + * Sends a request to DSP-API to update the list child node with the data inside the two local arrays. */ updateChildNode() { const childNodeUpdateData: UpdateChildNodeRequest = new UpdateChildNodeRequest(); @@ -127,4 +153,30 @@ export class EditListItemComponent implements OnInit { ); } + /** + * Called from the template when the 'submit' button is clicked in insert mode. + * Sends a request to DSP-API to insert a new list child node in the provided position. + */ + insertChildNode() { + const createChildNodeRequest: CreateChildNodeRequest = new CreateChildNodeRequest(); + + createChildNodeRequest.name = this.projectCode + '-' + Math.random().toString(36).substr(2) + Math.random().toString(36).substr(2); + createChildNodeRequest.parentNodeIri = this.parentIri; + createChildNodeRequest.labels = this.labels; + createChildNodeRequest.comments = this.comments.length > 0 ? this.comments : []; + createChildNodeRequest.projectIri = this.projectIri; + createChildNodeRequest.position = this.position; + + this._dspApiConnection.admin.listsEndpoint.createChildNode(createChildNodeRequest).subscribe( + (response: ApiResponseData) => { + this.loading = false; + this.closeDialog.emit(response.body.nodeinfo); + }, + (error: ApiResponseError) => { + this.errorMessage = error; + this.loading = false; + } + ); + } + } diff --git a/src/app/project/list/list-item-form/list-item-form.component.html b/src/app/project/list/list-item-form/list-item-form.component.html index 67e7b030a2..04f6bdaa95 100644 --- a/src/app/project/list/list-item-form/list-item-form.component.html +++ b/src/app/project/list/list-item-form/list-item-form.component.html @@ -1,5 +1,5 @@ -
+
@@ -14,7 +14,7 @@
arrow_downward +
diff --git a/src/app/project/list/list-item/list-item.component.spec.ts b/src/app/project/list/list-item/list-item.component.spec.ts index e625843e8a..f25538defe 100644 --- a/src/app/project/list/list-item/list-item.component.spec.ts +++ b/src/app/project/list/list-item/list-item.component.spec.ts @@ -172,6 +172,70 @@ describe('ListItemComponent', () => { expect(testHostComponent.listItem.list[0].labels).toEqual([{value: 'Tree List Node 0123', language: 'en'}]); }); + it('should update the view to show an inserted node', () => { + const dspConnSpy = TestBed.inject(DspApiConnectionToken); + + (dspConnSpy.admin.listsEndpoint as jasmine.SpyObj).getList.and.callFake( + () => { + const response = new ListResponse(); + response.list.listinfo.id = 'http://rdfh.ch/lists/0001/otherTreeList'; + response.list.listinfo.isRootNode = true; + response.list.listinfo.labels = [{value: 'Tree List Node Root', language: 'en'}]; + response.list.children = [ + { + comments: [], + labels: [{value: 'Tree List Node 01', language: 'en'}], + id: 'http://rdfh.ch/lists/0001/otherTreeList01', + children: [ + { + comments: [], + labels: [{value: 'Tree List Node 03', language: 'en'}], + id: 'http://rdfh.ch/lists/0001/otherTreeList03', + children: [] + } + ] + }, + { + comments: [], + labels: [{value: 'Tree List Node 04 between node 01 and node 02', language: 'en'}], + id: 'http://rdfh.ch/lists/0001/otherTreeList04', + children: [] + }, + { + comments: [], + labels: [{value: 'Tree List Node 02', language: 'en'}], + id: 'http://rdfh.ch/lists/0001/otherTreeList02', + children: [] + } + ]; + return of(ApiResponseData.fromAjaxResponse({response} as AjaxResponse)); + } + ); + + const listNodeOperation: ListNodeOperation = new ListNodeOperation(); + listNodeOperation.listNode = { + children: undefined, + comments: [], + hasRootNode: 'http://rdfh.ch/lists/0001/otherTreeList', + id: 'http://rdfh.ch/lists/0001/otherTreeList04', + labels: [{value: 'Tree List Node 04 between node 01 and node 02', language: 'en'}], + position: 1 + }; + + listNodeOperation.operation = 'insert'; + + testHostComponent.listItem.updateView(listNodeOperation); + + expect(testHostComponent.listItem.list.length).toEqual(3); + + expect(testHostComponent.listItem.list[1].labels).toEqual([{value: 'Tree List Node 04 between node 01 and node 02', language: 'en'}]); + + expect(dspConnSpy.admin.listsEndpoint.getList).toHaveBeenCalledWith(testHostComponent.parentIri); + + // getList is called twice because it is also called in ngOnInit + expect(dspConnSpy.admin.listsEndpoint.getList).toHaveBeenCalledTimes(2); + }); + it('should update the view to remove a deleted node', () => { const listNodeOperation: ListNodeOperation = new ListNodeOperation(); listNodeOperation.listNode = { diff --git a/src/app/project/list/list-item/list-item.component.ts b/src/app/project/list/list-item/list-item.component.ts index 2f8b0dc56f..e3a82d3812 100644 --- a/src/app/project/list/list-item/list-item.component.ts +++ b/src/app/project/list/list-item/list-item.component.ts @@ -3,6 +3,7 @@ import { ApiResponseData, ApiResponseError, KnoraApiConnection, + ListChildNodeResponse, ListNode, ListResponse, RepositionChildNodeRequest, @@ -97,6 +98,25 @@ export class ListItemComponent implements OnInit { } break; } + case 'insert': { + // get the corresponding list from the API again and reassign the local list with its response + this._dspApiConnection.admin.listsEndpoint.getList(this.parentIri).subscribe( + (result: ApiResponseData) => { + if (result.body instanceof ListResponse) { + this.list = result.body.list.children; // root node + } else { + this.list = result.body.node.children; // child node + } + + // emit the updated list of children to the parent node + this.refreshChildren.emit(this.list); + }, + (error: ApiResponseError) => { + this._errorHandler.showMessage(error); + } + ); + break; + } case 'update': { // use the position from the response from DSP-API to find the correct node to update this.list[data.listNode.position].labels = data.listNode.labels; @@ -118,6 +138,7 @@ export class ListItemComponent implements OnInit { repositionRequest.position = data.listNode.position; // since we don't have any way to know the parent IRI from the ListItemForm component, we need to do the API call here + // --> TODO now we have the parent IRI within the ListItemForm component so we can move this logic there this._dspApiConnection.admin.listsEndpoint.repositionChildNode(data.listNode.id, repositionRequest).subscribe( (res: ApiResponseData) => { this.list = res.body.node.children;