diff --git a/apps/dsp-app/src/app/project/collaboration/add-user/add-user.component.ts b/apps/dsp-app/src/app/project/collaboration/add-user/add-user.component.ts index 570ce5e8cb..ecc2f16197 100644 --- a/apps/dsp-app/src/app/project/collaboration/add-user/add-user.component.ts +++ b/apps/dsp-app/src/app/project/collaboration/add-user/add-user.component.ts @@ -1,4 +1,6 @@ import { + ChangeDetectionStrategy, + ChangeDetectorRef, Component, EventEmitter, Inject, @@ -29,8 +31,11 @@ import { existingNamesValidator } from '@dsp-app/src/app/main/directive/existing import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { ProjectService } from '@dsp-app/src/app/workspace/resource/services/project.service'; import { AutocompleteItem } from '@dsp-app/src/app/workspace/search/operator'; +import { Store } from '@ngxs/store'; +import { ProjectsSelectors } from '@dasch-swiss/vre/shared/app-state'; @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-add-user', templateUrl: './add-user.component.html', styleUrls: ['./add-user.component.scss'], @@ -132,7 +137,9 @@ export class AddUserComponent implements OnInit { private _dialog: MatDialog, private _errorHandler: AppErrorHandler, private _formBuilder: UntypedFormBuilder, - private _projectService: ProjectService + private _projectService: ProjectService, + private _store: Store, + private _cd: ChangeDetectorRef, ) {} ngOnInit() { @@ -152,91 +159,72 @@ export class AddUserComponent implements OnInit { const members: string[] = []; // get all members of this project - this._dspApiConnection.admin.projectsEndpoint.getProjectMembersByIri(this.projectIri).subscribe( - (res: ApiResponseData) => { - for (const m of res.body.members) { - members.push(m.id); - - // if the user is already member of the project - // add the email to the list of existing - this.existingEmailInProject.push( - new RegExp( - '(?:^|W)' + - m.email.toLowerCase() + - '(?:$|W)' - ) - ); - // add username to the list of existing - this.existingUsernameInProject.push( - new RegExp( - '(?:^|W)' + - m.username.toLowerCase() + - '(?:$|W)' - ) - ); - } - - let i = 0; - for (const u of response.body.users) { - // if the user is already member of the project - // add the email to the list of existing - this.existingEmails.push( - new RegExp( - '(?:^|W)' + - u.email.toLowerCase() + - '(?:$|W)' - ) - ); - // add username to the list of existing - this.existingUsernames.push( - new RegExp( - '(?:^|W)' + - u.username.toLowerCase() + - '(?:$|W)' - ) - ); + const projectMembers = this._store.selectSnapshot(ProjectsSelectors.projectMembers); + if (projectMembers[this.projectIri]) { + for (const m of projectMembers[this.projectIri].value) { + members.push(m.id); + + // if the user is already member of the project + // add the email to the list of existing + this.existingEmailInProject.push( + new RegExp('(?:^|W)' + m.email.toLowerCase() + '(?:$|W)') + ); + // add username to the list of existing + this.existingUsernameInProject.push( + new RegExp('(?:^|W)' + m.username.toLowerCase() + '(?:$|W)') + ); + } + } - let existsInProject = ''; - - if (members && members.indexOf(u.id) > -1) { - existsInProject = '* '; - } - - this.users[i] = { - iri: u.id, - name: u.username, - label: - existsInProject + - u.username + - ' | ' + - u.email + - ' | ' + - u.givenName + - ' ' + - u.familyName, - }; - i++; - } - - this.users.sort(function ( - u1: AutocompleteItem, - u2: AutocompleteItem - ) { - if (u1.label < u2.label) { - return -1; - } else if (u1.label > u2.label) { - return 1; - } else { - return 0; - } - }); - }, - (error: ApiResponseError) => { - this._errorHandler.showMessage(error); + let i = 0; + for (const u of response.body.users) { + // if the user is already member of the project + // add the email to the list of existing + this.existingEmails.push( + new RegExp('(?:^|W)' + u.email.toLowerCase() + '(?:$|W)') + ); + // add username to the list of existing + this.existingUsernames.push( + new RegExp('(?:^|W)' + u.username.toLowerCase() + '(?:$|W)') + ); + + let existsInProject = ''; + + if (members && members.indexOf(u.id) > -1) { + existsInProject = '* '; + } + + this.users[i] = { + iri: u.id, + name: u.username, + label: + existsInProject + + u.username + + ' | ' + + u.email + + ' | ' + + u.givenName + + ' ' + + u.familyName, + }; + i++; + } + + this.users.sort(function ( + u1: AutocompleteItem, + u2: AutocompleteItem + ) { + if (u1.label < u2.label) { + return -1; + } else if (u1.label > u2.label) { + return 1; + } else { + return 0; } - ); + }); this.loading = false; + this._cd.markForCheck(); }, (error: ApiResponseError) => { this._errorHandler.showMessage(error); @@ -384,7 +372,6 @@ export class AddUserComponent implements OnInit { }; const dialogRef = this._dialog.open(DialogComponent, dialogConfig); - dialogRef.afterClosed().subscribe(() => { // update the view this.refreshParent.emit(); diff --git a/apps/dsp-app/src/app/project/collaboration/collaboration.component.html b/apps/dsp-app/src/app/project/collaboration/collaboration.component.html index dbb69e541a..13fbddc744 100644 --- a/apps/dsp-app/src/app/project/collaboration/collaboration.component.html +++ b/apps/dsp-app/src/app/project/collaboration/collaboration.component.html @@ -1,10 +1,10 @@ - + -
-
+
+
-
+
diff --git a/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts b/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts index c8421af3e7..b133b6938a 100644 --- a/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts +++ b/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts @@ -1,16 +1,17 @@ -import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { Title } from '@angular/platform-browser'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { ReadProject, ReadUser, } from '@dasch-swiss/dsp-js'; import { ProjectService } from '@dsp-app/src/app/workspace/resource/services/project.service'; import { AddUserComponent } from './add-user/add-user.component'; -import { Select, Store } from '@ngxs/store'; +import { Actions, Select, Store } from '@ngxs/store'; import { CurrentProjectSelectors, LoadProjectMembersAction, ProjectsSelectors, UserSelectors } from '@dasch-swiss/vre/shared/app-state'; import { Observable, Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; +import { ProjectBase } from '../project-base'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -18,26 +19,21 @@ import { map, takeUntil } from 'rxjs/operators'; templateUrl: './collaboration.component.html', styleUrls: ['./collaboration.component.scss'], }) -export class CollaborationComponent implements OnInit, OnDestroy { +export class CollaborationComponent extends ProjectBase implements OnInit, OnDestroy { private ngUnsubscribe: Subject = new Subject(); @ViewChild('addUserComponent') addUser: AddUserComponent; - // loading for progess indicator - loading: boolean; - - isProjectAdmin = false; - - // project uuid; as identifier in project application state service - projectUuid: string; - get activeProjectMembers$(): Observable { return this.projectMembers$ .pipe( takeUntil(this.ngUnsubscribe), map((projectMembers) => { - const members = projectMembers[this._projectService.uuidToIri(this.projectUuid)].value; - return members.filter(member => member.status === true); + if (!projectMembers[this.projectIri]) { + return []; + } + + return projectMembers[this.projectIri].value.filter(member => member.status === true); }) ); } @@ -47,7 +43,11 @@ export class CollaborationComponent implements OnInit, OnDestroy { .pipe( takeUntil(this.ngUnsubscribe), map((projectMembers) => { - return projectMembers[this._projectService.uuidToIri(this.projectUuid)].value.filter(member => !member.status); + if (!projectMembers[this.projectIri]) { + return []; + } + + return projectMembers[this.projectIri].value.filter(member => !member.status); }) ); } @@ -59,11 +59,15 @@ export class CollaborationComponent implements OnInit, OnDestroy { @Select(CurrentProjectSelectors.project) project$: Observable; constructor( - private _route: ActivatedRoute, - private _projectService: ProjectService, - private _titleService: Title, - private _store: Store, + protected _route: ActivatedRoute, + protected _projectService: ProjectService, + protected _titleService: Title, + protected _store: Store, + protected _cd: ChangeDetectorRef, + protected _actions$: Actions, + protected _router: Router, ) { + super(_store, _route, _projectService, _titleService, _router, _cd, _actions$); // get the uuid of the current project if (this._route.parent.parent.snapshot.url.length) { this._route.parent.parent.paramMap.subscribe((params: Params) => { @@ -73,17 +77,9 @@ export class CollaborationComponent implements OnInit, OnDestroy { } ngOnInit() { - const userProjectGroups = this._store.selectSnapshot(UserSelectors.userProjectAdminGroups); - const user = this._store.selectSnapshot(UserSelectors.user) as ReadUser; + super.ngOnInit(); const project = this._store.selectSnapshot(CurrentProjectSelectors.project) as ReadProject; this._titleService.setTitle(`Project ${project.shortname} | Collaboration`); - // is logged-in user projectAdmin? - this.isProjectAdmin = this._projectService.isProjectAdminOrSysAdmin(user, userProjectGroups, project.id); - - // get list of project members and groups - if (this.isProjectAdmin) { - this.refresh(); - } } ngOnDestroy() { @@ -95,8 +91,7 @@ export class CollaborationComponent implements OnInit, OnDestroy { * refresh list of members after adding a new user to the team */ refresh(): void { - const projectIri = this._projectService.uuidToIri(this.projectUuid); - this._store.dispatch(new LoadProjectMembersAction(projectIri)); + this._store.dispatch(new LoadProjectMembersAction(this.projectUuid)); // refresh child component: add user if (this.addUser) { diff --git a/apps/dsp-app/src/app/project/data-models/data-models.component.html b/apps/dsp-app/src/app/project/data-models/data-models.component.html index 01ff28b551..ac5ff240ac 100644 --- a/apps/dsp-app/src/app/project/data-models/data-models.component.html +++ b/apps/dsp-app/src/app/project/data-models/data-models.component.html @@ -21,24 +21,39 @@
- -
+ +
bubble_chart

+ [matTooltipDisabled]="true"> {{onto.label}}

chevron_right
+ +
+ bubble_chart +

+ {{onto.label}} +

+ + chevron_right +
+
@@ -57,9 +72,9 @@ Create New
-
+
-
+
list

{{list.labels | appStringifyStringLiteral}}

diff --git a/apps/dsp-app/src/app/project/data-models/data-models.component.ts b/apps/dsp-app/src/app/project/data-models/data-models.component.ts index caf5ee8a78..36be77cdfb 100644 --- a/apps/dsp-app/src/app/project/data-models/data-models.component.ts +++ b/apps/dsp-app/src/app/project/data-models/data-models.component.ts @@ -1,21 +1,15 @@ import { ProjectService } from '@dsp-app/src/app/workspace/resource/services/project.service'; -import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { - ApiResponseData, - ApiResponseError, - KnoraApiConnection, ListNodeInfo, - ListsResponse, OntologyMetadata, ReadUser, } from '@dasch-swiss/dsp-js'; import {AppConfigService, RouteConstants} from '@dasch-swiss/vre/shared/app-config'; -import { DspApiConnectionToken } from '@dasch-swiss/vre/shared/app-config'; -import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { OntologyService } from '../ontology/ontology.service'; import { Select, Store } from '@ngxs/store'; -import { OntologiesSelectors, UserSelectors } from '@dasch-swiss/vre/shared/app-state'; +import { ListsSelectors, OntologiesSelectors, UserSelectors } from '@dasch-swiss/vre/shared/app-state'; import { Observable, Subject, combineLatest, of } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; @@ -36,8 +30,6 @@ type DataModelRoute = export class DataModelsComponent implements OnInit, OnDestroy { private ngUnsubscribe: Subject = new Subject(); - projectLists: ListNodeInfo[]; - // permissions of logged-in user get isAdmin$(): Observable { return combineLatest([this.user$, this.userProjectAdminGroups$, this._route.parent.params]) @@ -72,11 +64,9 @@ export class DataModelsComponent implements OnInit, OnDestroy { @Select(UserSelectors.userProjectAdminGroups) userProjectAdminGroups$: Observable; @Select(UserSelectors.isLoggedIn) isLoggedIn$: Observable; @Select(OntologiesSelectors.isLoading) isLoading$: Observable; + @Select(ListsSelectors.listsInProject) listsInProject$: Observable; constructor( - @Inject(DspApiConnectionToken) - private _dspApiConnection: KnoraApiConnection, - private _errorHandler: AppErrorHandler, private _route: ActivatedRoute, private _router: Router, private _appInit: AppConfigService, @@ -87,25 +77,18 @@ export class DataModelsComponent implements OnInit, OnDestroy { ngOnInit(): void { const uuid = this._route.parent.snapshot.params.uuid; - const iri = `${this._appInit.dspAppConfig.iriBase}/projects/${uuid}`; - - // get all project lists - this._dspApiConnection.admin.listsEndpoint - .getListsInProject(iri) - .subscribe( - (lists: ApiResponseData) => { - this.projectLists = lists.body.lists; - }, - (error: ApiResponseError) => { - this._errorHandler.showMessage(error); - } - ); + //TODO Soft or Hard loading? + //this._store.dispatch(new LoadListsInProjectAction(uuid)); } ngOnDestroy() { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); } + + trackByFn = (index: number, item: ListNodeInfo) => `${index}-${item.id}`; + + trackByOntologyMetaFn = (index: number, item: OntologyMetadata) => `${index}-${item.id}`; /** * handles routing to the correct path diff --git a/apps/dsp-app/src/app/project/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts b/apps/dsp-app/src/app/project/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts index a6ad8497a4..a0b93b550c 100644 --- a/apps/dsp-app/src/app/project/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts +++ b/apps/dsp-app/src/app/project/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts @@ -1,22 +1,9 @@ -import { ChangeDetectorRef, Component, Inject, OnChanges } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnChanges, OnInit } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { - ApiResponseData, - ApiResponseError, - KnoraApiConnection, - ProjectResponse, - ReadOntology, ResourceClassDefinition, - UserResponse, } from '@dasch-swiss/dsp-js'; -import {AppConfigService, RouteConstants} from '@dasch-swiss/vre/shared/app-config'; -import { ApplicationStateService } from '@dasch-swiss/vre/shared/app-state-service'; -import { DspApiConnectionToken } from '@dasch-swiss/vre/shared/app-config'; -import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; -import { - Session, - SessionService, -} from '@dasch-swiss/vre/shared/app-session'; +import {AppConfigService, RouteConstants, getAllEntityDefinitionsAsArray} from '@dasch-swiss/vre/shared/app-config'; import { OntologyService } from '@dsp-app/src/app/project/ontology/ontology.service'; import { ProjectService } from '@dsp-app/src/app/workspace/resource/services/project.service'; import { @@ -24,15 +11,19 @@ import { SearchParams, } from '@dsp-app/src/app/workspace/results/list-view/list-view.component'; import { SplitSize } from '@dsp-app/src/app/workspace/results/results.component'; +import { ProjectBase } from '../../project-base'; +import { Actions, Store } from '@ngxs/store'; +import { Title } from '@angular/platform-browser'; +import { CurrentProjectSelectors, OntologiesSelectors, UserSelectors } from '@dasch-swiss/vre/shared/app-state'; +import { AuthService } from '@dasch-swiss/vre/shared/app-session'; @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-ontology-class-instance', templateUrl: './ontology-class-instance.component.html', styleUrls: ['./ontology-class-instance.component.scss'], }) -export class OntologyClassInstanceComponent implements OnChanges { - projectIri: string; - +export class OntologyClassInstanceComponent extends ProjectBase implements OnInit, OnChanges { ontoId: string; // id (iri) of resource class @@ -55,112 +46,35 @@ export class OntologyClassInstanceComponent implements OnChanges { splitSizeChanged: SplitSize; - session: Session; - constructor( - @Inject(DspApiConnectionToken) - private _dspApiConnection: KnoraApiConnection, private _acs: AppConfigService, - private _applicationStateService: ApplicationStateService, - private _route: ActivatedRoute, + private _authService: AuthService, + protected _route: ActivatedRoute, private _ontologyService: OntologyService, - private _projectService: ProjectService, - private _sessionService: SessionService, - private _router: Router, - private _errorHandler: AppErrorHandler, - private _cdr: ChangeDetectorRef + protected _projectService: ProjectService, + protected _router: Router, + private _cdr: ChangeDetectorRef, + protected _store: Store, + protected _title: Title, + protected _actions$: Actions, ) { - // parameters from the url - const uuid = this._route.parent.snapshot.params.uuid; - - this.projectIri = this._projectService.uuidToIri(uuid); - - this.session = this._sessionService.getSession(); + super(_store, _route, _projectService, _title, _router, _cdr, _actions$); + } + ngOnInit() { + super.ngOnInit(); this._route.params.subscribe((params) => { - this._dspApiConnection.admin.projectsEndpoint - .getProjectByIri(this.projectIri) - .subscribe((res: ApiResponseData) => { - const shortcode = res.body.project.shortcode; - const iriBase = this._ontologyService.getIriBaseUrl(); - - const ontologyName = params[RouteConstants.ontoParameter]; - const className = params[RouteConstants.classParameter]; - - // get the resource ids from the route. Do not use the RouteConstants ontology route constant here, - // because the ontology and class ids are not defined within the apps domain. They are defined by - // the api and can not be changed generically via route constants. - this.ontoId = `${iriBase}/ontology/${shortcode}/${ontologyName}/v2`; - this.classId = `${this.ontoId}#${className}`; - - this.instanceId = params[RouteConstants.instanceParameter]; - if (this.instanceId) { - // single instance view - - if (this.instanceId === RouteConstants.addClassInstance) { - if (!this.session) { - // user isn't signed in, redirect to project description - this._router.navigateByUrl(`/${RouteConstants.project}/${uuid}`); - } else { - this._dspApiConnection.admin.usersEndpoint - .getUserByUsername(this.session.user.name) - .subscribe( - ( - res: ApiResponseData - ) => { - const usersProjects = - res.body.user.projects; - if ( - usersProjects?.some( - (p) => - p.id === this.projectIri - ) || // project member - this.session.user.sysAdmin // system admin - ) { - // user has permission, display create resource instance form - this.ngOnChanges(); - } else { - // user is not a member of the project or a systemAdmin, redirect to project description - this._router.navigateByUrl( - `/${RouteConstants.project}/${uuid}` - ); - } - }, - (error: ApiResponseError) => { - this._errorHandler.showMessage( - error - ); - } - ); - } - } else { - // get the single resource instance - this.resourceIri = `${this._acs.dspAppConfig.iriBase}/${shortcode}/${this.instanceId}`; - } - } else { - // display all resource instances of this resource class - this.searchParams = { - query: this._setGravsearch(this.classId), - mode: 'gravsearch' - }; - } - }); + this.initProject(params); }); } ngOnChanges() { - this._applicationStateService.get('currentProjectOntologies').subscribe( - (ontologies: ReadOntology[]) => { - // find ontology of current resource class to get the class label - const classes = - ontologies[ - ontologies.findIndex((onto) => onto.id === this.ontoId) - ].getAllClassDefinitions(); - this.resClass = ( - classes[classes.findIndex((res) => res.id === this.classId)] - ); - }, - () => {} // don't log error to rollbar if 'currentProjectOntologies' does not exist in the application state + const projectOntologies = this._store.selectSnapshot(OntologiesSelectors.projectOntologies)[this.projectIri]; + // find ontology of current resource class to get the class label + const ontology = projectOntologies.readOntologies.find((onto) => onto.id === this.ontoId); + const classes = getAllEntityDefinitionsAsArray(ontology.classes); + this.resClass = ( + classes[classes.findIndex((res) => res.id === this.classId)] ); } @@ -178,6 +92,58 @@ export class OntologyClassInstanceComponent implements OnChanges { this._cdr.detectChanges(); } + private initProject(params: Params): void { + const currentProject = this._store.selectSnapshot(CurrentProjectSelectors.project); + const shortcode = currentProject.shortcode; + const iriBase = this._ontologyService.getIriBaseUrl(); + + const ontologyName = params[RouteConstants.ontoParameter]; + const className = params[RouteConstants.classParameter]; + + // get the resource ids from the route. Do not use the RouteConstants ontology route constant here, + // because the ontology and class ids are not defined within the apps domain. They are defined by + // the api and can not be changed generically via route constants. + this.ontoId = `${iriBase}/ontology/${shortcode}/${ontologyName}/v2`; + this.classId = `${this.ontoId}#${className}`; + + this.instanceId = params[RouteConstants.instanceParameter]; + if (this.instanceId) { + // single instance view + + if (this.instanceId === RouteConstants.addClassInstance) { + if (!this._authService.isLoggedIn) { + // user isn't signed in, redirect to project description + this._router.navigateByUrl(`/${RouteConstants.project}/${this.projectUuid}`); + } else { + const isSysAdmin = this._store.selectSnapshot(UserSelectors.isSysAdmin); + const usersProjects = this._store.selectSnapshot(UserSelectors.userProjects); + if ( + usersProjects?.some((p) => p.id === this.projectIri) || // project member + isSysAdmin // system admin + ) { + // user has permission, display create resource instance form + this.ngOnChanges(); + } else { + // user is not a member of the project or a systemAdmin, redirect to project description + this._router.navigateByUrl( + `/${RouteConstants.project}/${this.projectUuid}` + ); + } + } + } else { + // get the single resource instance + this.resourceIri = `${this._acs.dspAppConfig.iriBase}/${shortcode}/${this.instanceId}`; + } + } else { + // display all resource instances of this resource class + this.searchParams = { + query: this._setGravsearch(this.classId), + mode: 'gravsearch' + }; + this._cdr.markForCheck(); + } + } + private _setGravsearch(iri: string): string { return ` PREFIX knora-api: diff --git a/apps/dsp-app/src/app/project/ontology-classes/ontology-class-item/ontology-class-item.component.ts b/apps/dsp-app/src/app/project/ontology-classes/ontology-class-item/ontology-class-item.component.ts index 46533504ca..243a636d4a 100644 --- a/apps/dsp-app/src/app/project/ontology-classes/ontology-class-item/ontology-class-item.component.ts +++ b/apps/dsp-app/src/app/project/ontology-classes/ontology-class-item/ontology-class-item.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, Input, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, OnDestroy, OnInit } from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import { ClassDefinition, @@ -18,6 +18,7 @@ import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { OntologyService } from '@dsp-app/src/app/project/ontology/ontology.service'; @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-ontology-class-item', templateUrl: './ontology-class-item.component.html', styleUrls: ['./ontology-class-item.component.scss'], @@ -53,7 +54,8 @@ export class OntologyClassItemComponent implements OnInit, OnDestroy { private _dspApiConnection: KnoraApiConnection, private _errorHandler: AppErrorHandler, private _route: ActivatedRoute, - private _componentCommsService: ComponentCommunicationEventService + private _componentCommsService: ComponentCommunicationEventService, + private _cd: ChangeDetectorRef, ) {} ngOnInit(): void { @@ -146,6 +148,7 @@ export class OntologyClassItemComponent implements OnInit, OnDestroy { .subscribe( (res: CountQueryResponse) => { this.results = res.numberOfResults; + this._cd.markForCheck(); }, (error: ApiResponseError) => { this._errorHandler.showMessage(error); diff --git a/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.html b/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.html index 0f8ed90498..572cc6549c 100644 --- a/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.html +++ b/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.ts b/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.ts index 496c9cf18e..8453f5ac4e 100644 --- a/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.ts +++ b/apps/dsp-app/src/app/project/ontology-classes/ontology-classes.component.ts @@ -1,8 +1,9 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; import { ClassDefinition, Constants } from '@dasch-swiss/dsp-js'; import { SortingService } from '@dsp-app/src/app/main/services/sorting.service'; @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-ontology-classes', templateUrl: './ontology-classes.component.html', styleUrls: ['./ontology-classes.component.scss'], @@ -34,4 +35,6 @@ export class OntologyClassesComponent implements OnInit { 'label' ); } + + trackByFn = (index: number, item: ClassDefinition) => `${index}-${item.id}`; } diff --git a/apps/dsp-app/src/app/project/ontology/ontology-form/ontology-form.component.ts b/apps/dsp-app/src/app/project/ontology/ontology-form/ontology-form.component.ts index 2031cf3f0e..36a577f0bb 100644 --- a/apps/dsp-app/src/app/project/ontology/ontology-form/ontology-form.component.ts +++ b/apps/dsp-app/src/app/project/ontology/ontology-form/ontology-form.component.ts @@ -311,7 +311,7 @@ export class OntologyFormComponent implements OnInit, OnDestroy { .createOntology(ontologyData) .subscribe( (response: OntologyMetadata) => { - this._store.dispatch(new LoadProjectAction(this.projectUuid)); + this._store.dispatch(new LoadProjectAction(this.projectUuid, true)); this.updateParent.emit(response.id); this.loading = false; // go to the new ontology page diff --git a/apps/dsp-app/src/app/project/ontology/ontology.component.html b/apps/dsp-app/src/app/project/ontology/ontology.component.html index fca32acb5f..efb549d198 100644 --- a/apps/dsp-app/src/app/project/ontology/ontology.component.html +++ b/apps/dsp-app/src/app/project/ontology/ontology.component.html @@ -74,7 +74,7 @@ Create new class - @@ -93,10 +93,10 @@ Create new property - + -