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

refactor(resource): improve list of properties in resource viewer (DSP-1663) #453

Merged
merged 10 commits into from May 26, 2021
100 changes: 49 additions & 51 deletions src/app/app.module.ts
Expand Up @@ -21,78 +21,77 @@ import { AngularSplitModule } from 'angular-split';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AccountComponent } from './user/account/account.component';
import { AddGroupComponent } from './project/permission/add-group/add-group.component';
import { AddressTemplateComponent } from './project/board/address-template/address-template.component';
import { AddUserComponent } from './project/collaboration/add-user/add-user.component';
import { AttributionTabViewComponent } from './project/board/attribution-tab-view/attribution-tab-view.component';
import { BoardComponent } from './project/board/board.component';
import { CollaborationComponent } from './project/collaboration/collaboration.component';
import { CollectionListComponent } from './user/collection-list/collection-list.component';
import { ContactsTabViewComponent } from './project/board/contacts-tab-view/contacts-tab-view.component';
import { CookiePolicyComponent } from './main/cookie-policy/cookie-policy.component';
import { DialogHeaderComponent } from './main/dialog/dialog-header/dialog-header.component';
import { DashboardComponent } from './user/dashboard/dashboard.component';
import { DatasetTabViewComponent } from './project/board/dataset-tab-view/dataset-tab-view.component';
import { DialogComponent } from './main/dialog/dialog.component';
import { ExternalLinksDirective } from './main/directive/external-links.directive';
import { InvalidControlScrollDirective } from './main/directive/invalid-control-scroll.directive';
import { DialogHeaderComponent } from './main/dialog/dialog-header/dialog-header.component';
import { EditListItemComponent } from './project/list/list-item-form/edit-list-item/edit-list-item.component';
import { ErrorComponent } from './main/error/error.component';
import { ExternalLinksDirective } from './main/directive/external-links.directive';
import { FooterComponent } from './main/footer/footer.component';
import { GridComponent } from './main/grid/grid.component';
import { GroupsComponent } from './system/groups/groups.component';
import { GroupsListComponent } from './system/groups/groups-list/groups-list.component';
import { HeaderComponent } from './main/header/header.component';
import { HelpComponent } from './main/help/help.component';
import { InvalidControlScrollDirective } from './main/directive/invalid-control-scroll.directive';
import { ListComponent } from './project/list/list.component';
import { ListInfoFormComponent } from './project/list/list-info-form/list-info-form.component';
import { ListItemComponent } from './project/list/list-item/list-item.component';
import { ListItemFormComponent } from './project/list/list-item-form/list-item-form.component';
import { LoginComponent } from './main/login/login.component';
import { MainComponent } from './main/main.component';
import { SelectLanguageComponent } from './main/select-language/select-language.component';
import { MaterialModule } from './material-module';
import { AddressTemplateComponent } from './project/board/address-template/address-template.component';
import { AttributionTabViewComponent } from './project/board/attribution-tab-view/attribution-tab-view.component';
import { BoardComponent } from './project/board/board.component';
import { ContactsTabViewComponent } from './project/board/contacts-tab-view/contacts-tab-view.component';
import { DatasetTabViewComponent } from './project/board/dataset-tab-view/dataset-tab-view.component';
import { MembershipComponent } from './user/membership/membership.component';
import { OntologyComponent } from './project/ontology/ontology.component';
import { OntologyFormComponent } from './project/ontology/ontology-form/ontology-form.component';
import { OntologyVisualizerComponent } from './project/ontology/ontology-visualizer/ontology-visualizer.component';
import { OrganisationTemplateComponent } from './project/board/organisation-template/organisation-template.component';
import { PasswordFormComponent } from './user/user-form/password-form/password-form.component';
import { PermissionComponent } from './project/permission/permission.component';
import { PersonTemplateComponent } from './project/board/person-template/person-template.component';
import { ProfileComponent } from './user/profile/profile.component';
import { ProjectComponent } from './project/project.component';
import { ProjectFormComponent } from './project/project-form/project-form.component';
import { ProjectsComponent } from './system/projects/projects.component';
import { ProjectsListComponent } from './system/projects/projects-list/projects-list.component';
import { ProjectTabViewComponent } from './project/board/project-tab-view/project-tab-view.component';
import { TermsTabViewComponent } from './project/board/terms-tab-view/terms-tab-view.component';
import { UrlTemplateComponent } from './project/board/url-template/url-template.component';
import { AddUserComponent } from './project/collaboration/add-user/add-user.component';
import { CollaborationComponent } from './project/collaboration/collaboration.component';
import { SelectGroupComponent } from './project/collaboration/select-group/select-group.component';
import { ListInfoFormComponent } from './project/list/list-info-form/list-info-form.component';
import { EditListItemComponent } from './project/list/list-item-form/edit-list-item/edit-list-item.component';
import { ListItemFormComponent } from './project/list/list-item-form/list-item-form.component';
import { ListItemComponent } from './project/list/list-item/list-item.component';
import { ListComponent } from './project/list/list.component';
import { OntologyFormComponent } from './project/ontology/ontology-form/ontology-form.component';
import { OntologyVisualizerComponent } from './project/ontology/ontology-visualizer/ontology-visualizer.component';
import { VisualizerComponent } from './project/ontology/ontology-visualizer/visualizer/visualizer.component';
import { OntologyComponent } from './project/ontology/ontology.component';
import { PropertiesComponent } from './workspace/resource/properties/properties.component';
import { PropertyFormComponent } from './project/ontology/property-form/property-form.component';
import { PropertyInfoComponent } from './project/ontology/property-info/property-info.component';
import { ResourceClassFormComponent } from './project/ontology/resource-class-form/resource-class-form.component';
import { ResourceClassInfoComponent } from './project/ontology/resource-class-info/resource-class-info.component';
import { ResourceClassPropertyFormComponent } from './project/ontology/resource-class-property-form/resource-class-property-form.component';
import { AddGroupComponent } from './project/permission/add-group/add-group.component';
import { PermissionComponent } from './project/permission/permission.component';
import { ProjectFormComponent } from './project/project-form/project-form.component';
import { ProjectComponent } from './project/project.component';
import { GroupsListComponent } from './system/groups/groups-list/groups-list.component';
import { GroupsComponent } from './system/groups/groups.component';
import { ProjectsListComponent } from './system/projects/projects-list/projects-list.component';
import { ProjectsComponent } from './system/projects/projects.component';
import { SystemComponent } from './system/system.component';
import { UsersListComponent } from './system/users/users-list/users-list.component';
import { UsersComponent } from './system/users/users.component';
import { AccountComponent } from './user/account/account.component';
import { CollectionListComponent } from './user/collection-list/collection-list.component';
import { DashboardComponent } from './user/dashboard/dashboard.component';
import { MembershipComponent } from './user/membership/membership.component';
import { ProfileComponent } from './user/profile/profile.component';
import { PasswordFormComponent } from './user/user-form/password-form/password-form.component';
import { UserFormComponent } from './user/user-form/user-form.component';
import { UserMenuComponent } from './user/user-menu/user-menu.component';
import { UserComponent } from './user/user.component';
import { ResourceComponent } from './workspace/resource/resource.component';
import { ResourceInstanceFormComponent } from './workspace/resource/resource-instance-form/resource-instance-form.component';
import { ResultsComponent } from './workspace/results/results.component';
import { SelectGroupComponent } from './project/collaboration/select-group/select-group.component';
import { SelectLanguageComponent } from './main/select-language/select-language.component';
import { SelectOntologyComponent } from './workspace/resource/resource-instance-form/select-ontology/select-ontology.component';
import { SelectProjectComponent } from './workspace/resource/resource-instance-form/select-project/select-project.component';
import { SelectPropertiesComponent } from './workspace/resource/resource-instance-form/select-properties/select-properties.component';
import { SwitchPropertiesComponent } from './workspace/resource/resource-instance-form/select-properties/switch-properties/switch-properties.component';
import { SelectResourceClassComponent } from './workspace/resource/resource-instance-form/select-resource-class/select-resource-class.component';
import { ResourceComponent } from './workspace/resource/resource.component';
import { ResultsComponent } from './workspace/results/results.component';
import { ResourceToolbarComponent } from './workspace/resource/resource-toolbar/resource-toolbar.component';
import { ResourcePropertiesComponent } from './workspace/resource/resource-properties/resource-properties.component';
import { StillImageComponent } from './workspace/resource/representation/still-image/still-image.component';
import { SwitchPropertiesComponent } from './workspace/resource/resource-instance-form/select-properties/switch-properties/switch-properties.component';
import { SystemComponent } from './system/system.component';
import { TermsTabViewComponent } from './project/board/terms-tab-view/terms-tab-view.component';
import { UrlTemplateComponent } from './project/board/url-template/url-template.component';
import { UserComponent } from './user/user.component';
import { UserFormComponent } from './user/user-form/user-form.component';
import { UserMenuComponent } from './user/user-menu/user-menu.component';
import { UsersComponent } from './system/users/users.component';
import { UsersListComponent } from './system/users/users-list/users-list.component';
import { VisualizerComponent } from './project/ontology/ontology-visualizer/visualizer/visualizer.component';

// translate: AoT requires an exported function for factories
export function httpLoaderFactory(httpClient: HttpClient) {
Expand Down Expand Up @@ -146,6 +145,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
ProjectsComponent,
ProjectsListComponent,
ProjectTabViewComponent,
PropertiesComponent,
PropertyFormComponent,
PropertyInfoComponent,
ResourceClassFormComponent,
Expand All @@ -160,6 +160,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
SelectProjectComponent,
SelectPropertiesComponent,
SelectResourceClassComponent,
StillImageComponent,
SwitchPropertiesComponent,
SystemComponent,
TermsTabViewComponent,
Expand All @@ -170,9 +171,6 @@ export function httpLoaderFactory(httpClient: HttpClient) {
UsersComponent,
UsersListComponent,
VisualizerComponent,
ResourceToolbarComponent,
ResourcePropertiesComponent,
StillImageComponent,
],
imports: [
AppRoutingModule,
Expand Down
126 changes: 126 additions & 0 deletions src/app/workspace/resource/properties/properties.component.html
@@ -0,0 +1,126 @@

<!-- toolbar -->
<div class="toolbar" *ngIf="project">
<!-- resource info -->
<h3 class="label mat-title">
{{resource.res.label}}
</h3>
<span class="fill-remaining-space"></span>

<!-- tools: share, add to favorites, edit, delete etc. -->
<span>
<!-- TODO: activate favorite action to add resource to collection -->
<!--
<button mat-button class="add-res-to-collection">
<mat-icon>star_border</mat-icon>
</button>
-->

<!-- Toggle list of properties: all or only the ones with value -->
<button mat-button class="toggle-props" matTooltip="Toggle list of properties" matTooltipPosition="above"
(click)="showAllProps = !showAllProps">
<mat-icon>{{showAllProps ? 'unfold_less' : 'unfold_more'}}</mat-icon>
<span class="desktop-only">{{showAllProps ? 'Hide empty' : 'Show all'}} properties</span>
</button>

<!-- TODO: activate delete action to delete the whole resource -->
<!--
<button mat-button class="delete-res">
<mat-icon>delete</mat-icon>
</button>
-->

<!-- Share resource by copying the ark url -->
<button mat-button class="share-res" matTooltip="Share resource by copying ARK url" matTooltipPosition="above"
[matMenuTriggerFor]="share">
<mat-icon>share</mat-icon>
<span class="desktop-only">Citation Link</span>
</button>
<mat-menu #share="matMenu" class="res-share-menu">
<!-- citation link - ARK URL -->
<div class="ark-url-label mat-body">
<label for="clipboard-arkurl">Citation Link (ARK URL)</label>
</div>
<div class="ark-url-input">
<input id="clipboard-arkurl" class="clipboard-arkurl" cols="30" rows="10" readonly
[(ngModel)]="resource.res.versionArkUrl" />
<button mat-button class="btn-copy-arkurl" [cdkCopyToClipboard]="resource.res.versionArkUrl"
matTooltip="Copy ARK url" matTooltipPosition="below" (click)="openSnackBar()">
<mat-icon class="icon-arkurl">content_copy</mat-icon>
</button>
</div>
</mat-menu>
</span>
</div>

<!-- additional line with project and user information -->
<div class="infobar mat-caption" *ngIf="project && user">
<p *ngIf="displayProjectInfo">This resource belongs to the project
<span class="project link" (click)="openProject(project)" (mouseover)="previewProject(project)">
<b>{{project?.shortname}}</b>
<mat-icon inline>open_in_new</mat-icon>
</span>
</p>
<span class="fill-remaining-space"></span>
<p *ngIf="user || resource.res.creationDate">
Created
<span *ngIf="user">by {{(user.username ? user.username : user.givenName + ' ' + user.familyName)}}</span>
<span *ngIf="resource.res.creationDate"> on {{resource.res.creationDate | date}}</span>
</p>
</div>

<!-- list of properties -->
<div class="properties-container">
<div class="properties" *ngIf="resource.resProps.length !== 0; else noProperties">

<!-- list of properties -->
<div *ngFor="let prop of resource.resProps; let last = last">
<!-- show property; all in case of showAll === true or only the ones with prop.values -->
<div *ngIf="!prop.propDef['isLinkProperty'] && showAllProps || ( prop.values && prop.values.length > 0 )"
[class.border-bottom]="prop.values && !last"
class="property">
<div class="property-label">
<!-- label of the property -->
<h3 class="label mat-subheading-1"
[class.label-info]="prop.propDef.comment"
[matTooltip]="prop.propDef.comment"
matTooltipPosition="above">
{{prop.propDef.label}}
</h3>
</div>
<div class="property-value">
<!-- the value(s) of the property -->
<div *ngFor="let val of prop.values">
<dsp-display-edit *ngIf="val"
#displayEdit
[parentResource]="resource.res"
[displayValue]="val"
[propArray]="resource.resProps"
(referredResourceClicked)="openResource($event)"
(referredResourceHovered)="previewResource($event)">
</dsp-display-edit>
</div>
<!-- Add value form -->
<div *ngIf="addValueFormIsVisible && propID === prop.propDef.id">
<dsp-add-value #addValue
class="add-value"
[parentResource]="resource.res"
[resourcePropertyDefinition]="$any(resource.res.entityInfo.properties[prop.propDef.id])"
(operationCancelled)="hideAddValueForm()">
</dsp-add-value>
</div>
<!-- Add button -->
<div *ngIf="addValueIsAllowed(prop)">
<button class="create"
(click)="showAddValueForm(prop)"
title="Add a new value">
<mat-icon>add_box</mat-icon>
</button>
</div>
</div>
</div>
</div>
</div>
<ng-template #noProperties>The resource {{resource?.res.resourceClassLabel}} has no defined
properties.</ng-template>
</div>
@@ -1,27 +1,73 @@
@import "../../../../assets/style/config";

// toolbar
.toolbar,
.infobar {
display: flex;
box-sizing: border-box;
flex-direction: row;
align-items: center;
white-space: nowrap;
padding: 0 16px;
width: 100%;
color: rgba(0, 0, 0, 0.87);
}
.toolbar {
background: whitesmoke;

.label {
margin: 0 !important;
max-width: 48%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

.infobar {
height: 24px;
}

.clipboard-arkurl {
width: 264px;
height: 32px;
border: 1px solid rgba(0, 0, 0, 0.35);
border-radius: 4px 0 0 4px;
}
.ark-url-label {
margin-bottom: 8px;
}
.btn-copy-arkurl {
border-radius: 0 4px 4px 0;
background-color: rgba(0, 0, 0, 0.35);
}

//
// list of properties
.border-bottom {
border-bottom: 1px solid rgba(33,33,33,.1);
border-bottom: 1px solid rgba(33, 33, 33, 0.1);
}

// smaller buttons: add value and value info
.info,
.create {
cursor: pointer;
border: none;
padding: 0em;
outline: none;
background-color: transparent;
color: #000000;
cursor: pointer;
border: none;
padding: 0em;
outline: none;
background-color: transparent;
color: #000000;
}

.info .material-icons,
.create .material-icons {
font-size: 18px;
font-size: 18px;
}

.info .mat-icon,
.create .mat-icon {
width: 18px;
height: 18px;
width: 18px;
height: 18px;
}

// properties container with property item and property value items
Expand Down