Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ontology): ontology editor read mode (DEV-1183) #799

Merged
merged 6 commits into from Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/app/project/beta/settings/settings.component.ts
Expand Up @@ -16,11 +16,8 @@ export class SettingsComponent implements OnInit {
constructor() { }

ngOnInit(): void {
// we need only two items from the old project navigation
// collaboration
this.navigation.push(AppGlobal.projectNav[1]);
// permissions
this.navigation.push(AppGlobal.projectNav[2]);
}

}
20 changes: 12 additions & 8 deletions src/app/project/ontology/ontology.component.html
@@ -1,4 +1,4 @@
<div *ngIf="projectAdmin && !disableContent">
<div *ngIf="(projectMember || projectAdmin) && !disableContent">

<app-progress-indicator *ngIf="loading"></app-progress-indicator>

Expand Down Expand Up @@ -41,7 +41,8 @@ <h2 class="mat-title">

<span class="fill-remaining-space"></span>

<span class="app-toolbar-action" [class.select-form]="ontologies.length" *ngIf="project.status">
<span class="app-toolbar-action" [class.select-form]="ontologies.length"
*ngIf="project.status && projectAdmin">
<button mat-raised-button color="primary" class="create-data-model-btn"
(click)="openOntologyForm('createOntology')">
{{ontologies.length ? 'New data model' : 'Create your first data model'}}
Expand Down Expand Up @@ -101,16 +102,17 @@ <h2 class="mat-title">
<span class="ontology-actions project-actions" *ngIf="project.status">
<p class="mat-caption space-reducer">Data model configuration</p>
<span
[matTooltip]="(ontology.lastModificationDate ? 'Edit data model info' : 'This data model can\'t be edited because of missing lastModificationDate!')">
<button mat-button [disabled]="!ontology.lastModificationDate"
[matTooltip]="(projectAdmin ? (ontology.lastModificationDate ? 'Edit data model info' : 'This data model can\'t be edited because of missing lastModificationDate!') : null)">
<button mat-button [disabled]="!ontology.lastModificationDate || !projectAdmin"
(click)="$event.stopPropagation(); openOntologyForm('editOntology', ontology.id)">
<mat-icon>edit</mat-icon>
Edit
</button>
</span>
<span
[matTooltip]="(ontology.lastModificationDate ? (ontologyCanBeDeleted ? 'Delete data model' : 'This data model can\'t be deleted because it is in use!') : 'This data model can\'t be deleted because of missing lastModificationDate!')">
<button mat-button [disabled]="!ontology.lastModificationDate || !ontologyCanBeDeleted"
[matTooltip]="(projectAdmin ? (ontology.lastModificationDate ? (ontologyCanBeDeleted ? 'Delete data model' : 'This data model can\'t be deleted because it is in use!') : 'This data model can\'t be deleted because of missing lastModificationDate!') : null)">
<button mat-button
[disabled]="(!ontology.lastModificationDate || !ontologyCanBeDeleted) || (!projectAdmin || !sysAdmin)"
(click)="$event.stopPropagation(); delete('Ontology', {iri: ontologyIri, label: ontology.label})">
<mat-icon>delete</mat-icon>
Delete
Expand Down Expand Up @@ -182,6 +184,7 @@ <h2 class="mat-title">
<app-resource-class-info *ngFor="let resClass of ontoClasses" [resourceClass]="resClass"
[projectCode]="projectCode" [projectStatus]="project.status" [ontologies]="ontologies"
[expanded]="expandClasses" [(lastModificationDate)]="lastModificationDate"
[userCanEdit]="(projectAdmin || sysAdmin)"
(editResourceClass)="openResourceClassForm('editResourceClass', $event)"
(deleteResourceClass)="delete('ResourceClass', $event)"
(updateCardinality)="initOntology($event)">
Expand All @@ -196,6 +199,7 @@ <h2 class="mat-title">
if objectType is a linkValue hide it (otherwise we have the property twice) -->
<app-property-info [propDef]="ontology?.properties[prop.id]" [projectCode]="projectCode"
[projectStatus]="project.status" [(lastModificationDate)]="lastModificationDate"
[userCanEdit]="(projectAdmin || sysAdmin)"
(editResourceProperty)="openPropertyForm('editProperty', $event)"
(deleteResourceProperty)="delete('Property', $event)">
</app-property-info>
Expand All @@ -210,8 +214,8 @@ <h2 class="mat-title">

</div>

<div *ngIf="!projectAdmin && !disableContent" class="content large middle">
<div *ngIf="!projectMember && !disableContent && !loading" class="content large middle">
<app-status [status]="403"></app-status>
</div>

<app-status *ngIf="disableContent" [status]="204"></app-status>
<app-status *ngIf="disableContent" [status]="204"></app-status>
15 changes: 11 additions & 4 deletions src/app/project/ontology/ontology.component.ts
Expand Up @@ -19,7 +19,8 @@ import {
PropertyDefinition,
ReadOntology,
ReadProject,
UpdateOntology
UpdateOntology,
UserResponse
} from '@dasch-swiss/dsp-js';
import { CacheService } from 'src/app/main/cache/cache.service';
import { DspApiConnectionToken } from 'src/app/main/declarations/dsp-api-tokens';
Expand Down Expand Up @@ -58,9 +59,10 @@ export class OntologyComponent implements OnInit {

// permissions of logged-in user
session: Session;
// system admin or project admin is by default false
// system admin, project admin, and project member are by default false
sysAdmin = false;
projectAdmin = false;
projectMember = false;

// project shortcode; as identifier in project cache service
projectCode: string;
Expand Down Expand Up @@ -194,8 +196,13 @@ export class OntologyComponent implements OnInit {
// is logged-in user projectAdmin?
this.projectAdmin = this.sysAdmin ? this.sysAdmin : this.session.user.projectAdmin.some(e => e === this.project.id);

// get the ontologies for this project
this.initOntologiesList();
this._dspApiConnection.admin.usersEndpoint.getUserByUsername(this.session.user.name).subscribe(
(userResponse: ApiResponseData<UserResponse>) => {
this.projectMember = userResponse.body.user.projects.some(p => p.shortcode === this.project.shortcode);

// get the ontologies for this project
this.initOntologiesList();
});

this.ontologyForm = this._fb.group({
ontology: new FormControl({
Expand Down
Expand Up @@ -102,6 +102,8 @@ export class PropertyInfoComponent implements OnChanges, AfterContentInit {

@Input() lastModificationDate?: string;

@Input() userCanEdit: boolean; // is user a project admin or sys admin?

// event emitter when the lastModificationDate changed; bidirectional binding with lastModificationDate parameter
@Output() lastModificationDateChange: EventEmitter<string> = new EventEmitter<string>();

Expand Down Expand Up @@ -315,8 +317,10 @@ export class PropertyInfoComponent implements OnChanges, AfterContentInit {
* show action bubble with various CRUD buttons when hovered over.
*/
mouseEnter() {
this.canBeDeleted();
this.showActionBubble = true;
if (this.userCanEdit) {
this.canBeDeleted();
this.showActionBubble = true;
}
}

/**
Expand Down
Expand Up @@ -18,7 +18,8 @@
<span class="resource-class-header-action">
<span class="resource-class-more" *ngIf="projectStatus"
[matTooltip]="(ontology.lastModificationDate ? 'more' : 'This data model can\'t be edited because of missing lastModificationDate!')">
<button mat-icon-button [matMenuTriggerFor]="resClassMenu" class="res-class-menu" [disabled]="!ontology.lastModificationDate" (click)="canBeDeleted()">
<button mat-icon-button [matMenuTriggerFor]="resClassMenu" class="res-class-menu"
[disabled]="!ontology.lastModificationDate" (click)="canBeDeleted()">
<mat-icon>more_horiz</mat-icon>
</button>
</span>
Expand All @@ -29,22 +30,28 @@
</span>
</span>
<mat-menu #resClassMenu="matMenu" xPosition="before">
<button mat-menu-item class="res-class-edit"
(click)="editResourceClass.emit({iri: resourceClass.id, label: resourceClass.label})">
Edit resource class info
</button>
<span *ngIf="userCanEdit">
<button mat-menu-item class="res-class-edit"
(click)="editResourceClass.emit({iri: resourceClass.id, label: resourceClass.label})">
Edit resource class info
</button>
</span>
<span [matTooltip]="'This opens the resource instance form'" matTooltipPosition="before">
<button mat-menu-item (click)="createResourceInstance(resourceClass.id, resourceClass.label + ' (' + subClassOfLabel + ')')">
<button mat-menu-item
(click)="createResourceInstance(resourceClass.id, resourceClass.label + ' (' + subClassOfLabel + ')')">
Create new resource instance
</button>
</span>
<span [matTooltip]="(classCanBeDeleted ? 'This class doesn\'t have any instances yet' : null)" matTooltipPosition="before">
<span [matTooltip]="(classCanBeDeleted ? 'This class doesn\'t have any instances yet' : null)"
matTooltipPosition="before">
<button mat-menu-item (click)="openResourceInstances(resourceClass.id)" [disabled]="classCanBeDeleted">
Open resource instances
</button>
</span>
<span [matTooltip]="(classCanBeDeleted ? null : 'This class can\'t be deleted because it is in use')" matTooltipPosition="before">
<button mat-menu-item [disabled]="!classCanBeDeleted" class="res-class-delete"
<span *ngIf="userCanEdit"
[matTooltip]="classCanBeDeleted ? null : 'This class can\'t be deleted because it is in use'"
matTooltipPosition="before">
<button mat-menu-item [disabled]="!classCanBeDeleted || !userCanEdit" class="res-class-delete"
(click)="deleteResourceClass.emit({iri: resourceClass.id, label: resourceClass.label})">
Delete resource class
</button>
Expand All @@ -56,40 +63,40 @@
<mat-card-content *ngIf="expanded">
<mat-list cdkDropList class="resource-class-properties" (cdkDropListDropped)="drop($event)"
*ngIf="propsToDisplay.length; else noProperties">
<div cdkDrag [cdkDragDisabled]="!ontology.lastModificationDate || !cardinalityUpdateEnabled"
<div cdkDrag
[cdkDragDisabled]="(!ontology.lastModificationDate || !cardinalityUpdateEnabled) || !userCanEdit"
*ngFor="let prop of propsToDisplay; let i = index;">
<div class="drag-n-drop-placeholder" *cdkDragPlaceholder></div>
<mat-list-item class="property" [disabled]="loadProperty">
<span cdkDragHandle mat-list-icon class="list-icon gui-order">
<span [class.hide-on-hover]="cardinalityUpdateEnabled && lastModificationDate">{{i + 1}})</span>
<span *ngIf="lastModificationDate && cardinalityUpdateEnabled"
<span [class.hide-on-hover]="cardinalityUpdateEnabled && lastModificationDate && userCanEdit">
{{i + 1}})
</span>
<span *ngIf="cardinalityUpdateEnabled && lastModificationDate && userCanEdit"
class="display-on-hover drag-n-drop-handle">
<mat-icon>drag_indicator</mat-icon>
</span>
</span>
<!-- display only properties if they exist in list of properties;
objectType is not a linkValue (otherwise we have the property twice) -->
<app-property-info class="property-info"
[propDef]="propsToDisplay[i].propDef"
[propCard]="propsToDisplay[i]"
[projectCode]="projectCode"
[projectStatus]="projectStatus"
[resourceIri]="resourceClass.id"
[(lastModificationDate)]="lastModificationDate"
(removePropertyFromClass)="removeProperty($event)">
<app-property-info class="property-info" [propDef]="propsToDisplay[i].propDef"
[propCard]="propsToDisplay[i]" [projectCode]="projectCode" [projectStatus]="projectStatus"
[resourceIri]="resourceClass.id" [(lastModificationDate)]="lastModificationDate"
[userCanEdit]="userCanEdit" (removePropertyFromClass)="removeProperty($event)">
</app-property-info>
</mat-list-item>
</div>
</mat-list>
<!-- message if the class doesn't have any property -->
<!-- message if the class doesn't have any properties -->
<ng-template #noProperties>
<p>There is no property assigned to this class yet.</p>
<p>There are no properties assigned to this class yet.</p>
</ng-template>
<!-- button to assign new property to class -->
<mat-list>
<!-- here we have to know if the class has values or not;
this information is important to handle the cardinality (1 resp. 1-n); we get this information from the canReplaceCardinality method -->
<mat-list-item *ngIf="lastModificationDate && projectStatus" class="property link" [matMenuTriggerFor]="addPropertyMenu" (click)="canReplaceCardinality()">
<mat-list-item *ngIf="lastModificationDate && projectStatus && userCanEdit" class="property link"
[matMenuTriggerFor]="addPropertyMenu" (click)="canReplaceCardinality()">
<span mat-list-icon class="list-icon">
<mat-icon>add</mat-icon>
</span>
Expand All @@ -105,25 +112,25 @@
<ng-container *ngFor="let type of defaultProperties">
<button mat-menu-item [matMenuTriggerFor]="sub_menu">{{type.group}}</button>
<mat-menu #sub_menu="matMenu" class="default-nested-sub-menu">
<button mat-menu-item *ngFor="let ele of type.elements" [value]="ele"
[matTooltip]="ele.description" matTooltipPosition="after"
(click)="addNewProperty(ele)">
<button mat-menu-item *ngFor="let ele of type.elements" [value]="ele" [matTooltip]="ele.description"
matTooltipPosition="after" (click)="addNewProperty(ele)">
<mat-icon>{{ele.icon}}</mat-icon> {{ele.label}}
</button>
</mat-menu>
</ng-container>
</mat-menu>
<mat-menu #addExistingProp="matMenu" class="default-nested-sub-menu">
<ng-container *ngFor="let onto of existingProperties">
<button mat-menu-item [disabled]="!onto.properties.length" [matMenuTriggerFor]="sub_menu">{{ onto.ontologyLabel }}</button>
<button mat-menu-item [disabled]="!onto.properties.length" [matMenuTriggerFor]="sub_menu">{{
onto.ontologyLabel }}</button>
<mat-menu #sub_menu="matMenu" class="default-nested-sub-menu">
<button mat-menu-item *ngFor="let prop of onto.properties" [matTooltip]="prop.propDef.comment" matTooltipPosition="after"
(click)="addExistingProperty(prop)">
<button mat-menu-item *ngFor="let prop of onto.properties" [matTooltip]="prop.propDef.comment"
matTooltipPosition="after" (click)="addExistingProperty(prop)">
<mat-icon>{{prop.propType?.icon}}</mat-icon> {{prop.propDef.label}}
</button>
</mat-menu>
</ng-container>

</mat-menu>
</mat-card-content>
</mat-card>
</mat-card>
Expand Up @@ -30,7 +30,7 @@ import { ResourceClassInfoComponent } from './resource-class-info.component';
* Property is of type simple text
*/
@Component({
template: '<app-resource-class-info #resClassInfo [resourceClass]="resourceClass" [projectStatus]="true"></app-resource-class-info>'
template: '<app-resource-class-info #resClassInfo [resourceClass]="resourceClass" [projectStatus]="true" [userCanEdit]="userCanEdit"></app-resource-class-info>'
})
class HostComponent implements OnInit {

Expand All @@ -41,6 +41,8 @@ class HostComponent implements OnInit {

resourceClass: ClassDefinition;

userCanEdit: boolean;

constructor(
private _cache: CacheService,
private _sortingService: SortingService
Expand Down Expand Up @@ -72,6 +74,8 @@ class HostComponent implements OnInit {
}
);

this.userCanEdit = true;

}

}
Expand Down
Expand Up @@ -57,6 +57,8 @@ export class ResourceClassInfoComponent implements OnInit {

@Input() lastModificationDate?: string;

@Input() userCanEdit: boolean; // is user a project admin or sys admin?

// event emitter when the lastModificationDate changed; bidirectional binding with lastModificationDate parameter
@Output() lastModificationDateChange: EventEmitter<string> = new EventEmitter<string>();

Expand Down