Skip to content

Commit

Permalink
Implemented state interaction in ontology-class-instance, add-user, u…
Browse files Browse the repository at this point in the history
…ser-form components. Refactored project-base. Added SetCurrentProjectByUuidAction
  • Loading branch information
irmastnt committed Oct 30, 2023
1 parent 0fbe455 commit 5c864c6
Show file tree
Hide file tree
Showing 32 changed files with 459 additions and 418 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
Inject,
Expand Down Expand Up @@ -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'],
Expand Down Expand Up @@ -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() {
Expand All @@ -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<MembersResponse>) => {
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);
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<dasch-swiss-app-progress-indicator *ngIf="loading"></dasch-swiss-app-progress-indicator>
<dasch-swiss-app-progress-indicator *ngIf="isProjectsLoading$ | async"></dasch-swiss-app-progress-indicator>

<div *ngIf="!loading">
<div *ngIf="isProjectAdmin" class="content large middle">
<div *ngIf="(isProjectsLoading$ | async) === false">
<div *ngIf="isProjectAdmin$ | async" class="content large middle">
<!-- add user to the project -->
<app-add-user
*ngIf="(project$ | async)?.status && ((isSysAdmin$ | async) === true || isProjectAdmin)"
*ngIf="(project$ | async)?.status && ((isSysAdmin$ | async) === true || (isProjectAdmin$ | async) === true)"
[projectUuid]="projectUuid"
(refreshParent)="refresh()"
#addUserComponent
Expand All @@ -29,7 +29,7 @@
</div>
</div>

<div *ngIf="!isProjectAdmin" class="content large middle">
<div *ngIf="!(isProjectAdmin$ | async)" class="content large middle">
<app-status [status]="403"></app-status>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,39 @@
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,
selector: 'app-collaboration',
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<void> = new Subject<void>();

@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<ReadUser[]> {
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);
})
);
}
Expand All @@ -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);
})
);
}
Expand All @@ -59,11 +59,15 @@ export class CollaborationComponent implements OnInit, OnDestroy {
@Select(CurrentProjectSelectors.project) project$: Observable<ReadProject>;

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) => {
Expand All @@ -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() {
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,39 @@
</div>
<div *ngIf="ontologiesMetadata$ | async" class="projectOntos">
<div class="list" [class.top-padding]="isAdmin$ | async">
<ng-container *ngIf="isLoggedIn$ | async as isLoggedIn">
<div
class="list-item ontos"
[class.no-click]="!isLoggedIn"
*ngFor="let onto of ontologiesMetadata$ | async"
(click)="isLoggedIn === true ? open('ontology', onto.id) : null">
<ng-container *ngIf="(isLoggedIn$ | async) === true">
<div
class="list-item ontos "
*ngFor="let onto of ontologiesMetadata$ | async; trackBy: trackByOntologyMetaFn"
(click)="open('ontology', onto.id)">
<mat-icon class="icon-prefix">bubble_chart</mat-icon>
<p
class="label"
matTooltip="You must be logged in to view data models"
matTooltipPosition="right"
[matTooltipDisabled]="isLoggedIn">
[matTooltipDisabled]="true">
{{onto.label}}
</p>
<span class="fill-remaining-space"></span>
<mat-icon class="icon-suffix">chevron_right</mat-icon>
</div>
</ng-container>
<ng-container *ngIf="(isLoggedIn$ | async) === false">
<div
class="list-item ontos no-click"
*ngFor="let onto of ontologiesMetadata$ | async; trackBy: trackByOntologyMetaFn">
<mat-icon class="icon-prefix">bubble_chart</mat-icon>
<p
class="label"
matTooltip="You must be logged in to view data models"
matTooltipPosition="right"
[matTooltipDisabled]="false">
{{onto.label}}
</p>
<span class="fill-remaining-space"></span>
<mat-icon class="icon-suffix">chevron_right</mat-icon>
</div>
</ng-container>
</div>
</div>
<div class="header">
Expand All @@ -57,9 +72,9 @@
<span class="v-align-middle">Create New</span>
</button>
</div>
<div *ngIf="projectLists" class="projectLists">
<div *ngIf="(listsInProject$ | async)?.length > 0" class="projectLists">
<div class="list" [class.top-padding]="isAdmin$ | async">
<div class="list-item" *ngFor="let list of projectLists" (click)="open('list', list.id)">
<div class="list-item" *ngFor="let list of (listsInProject$ | async); trackBy: trackByFn" (click)="open('list', list.id)">
<mat-icon class="icon-prefix">list</mat-icon>
<p class="label">{{list.labels | appStringifyStringLiteral}}</p>
<span class="fill-remaining-space"></span>
Expand Down
Loading

0 comments on commit 5c864c6

Please sign in to comment.