dmp overview page refactor

This commit is contained in:
Diamantis Tziotzios 2023-12-04 19:37:52 +02:00
parent a72c7001f9
commit ad1539af59
15 changed files with 227 additions and 163 deletions

View File

@ -14,7 +14,8 @@ public class DmpDescriptionTemplateLookup extends Lookup {
private List<UUID> ids;
private List<UUID> dmpIds;
private List<UUID> descriptionTemplateIds;
private List<UUID> descriptionTemplateGroupIds;
private List<UUID> sectionIds;
private List<UUID> excludedIds;
@ -52,19 +53,28 @@ public class DmpDescriptionTemplateLookup extends Lookup {
this.dmpIds = dmpIds;
}
public List<UUID> getDescriptionTemplateIds() {
return descriptionTemplateIds;
public List<UUID> getDescriptionTemplateGroupIds() {
return descriptionTemplateGroupIds;
}
public void setDescriptionTemplateIds(List<UUID> descriptionTemplateIds) {
this.descriptionTemplateIds = descriptionTemplateIds;
public List<UUID> getSectionIds() {
return sectionIds;
}
public void setSectionIds(List<UUID> sectionIds) {
this.sectionIds = sectionIds;
}
public void setDescriptionTemplateGroupIds(List<UUID> descriptionTemplateGroupIds) {
this.descriptionTemplateGroupIds = descriptionTemplateGroupIds;
}
public DmpDescriptionTemplateQuery enrich(QueryFactory queryFactory) {
DmpDescriptionTemplateQuery query = queryFactory.query(DmpDescriptionTemplateQuery.class);
if (this.ids != null) query.ids(this.ids);
if (this.dmpIds != null) query.ids(this.dmpIds);
if (this.descriptionTemplateIds != null) query.ids(this.descriptionTemplateIds);
if (this.descriptionTemplateGroupIds != null) query.descriptionTemplateGroupIds(this.descriptionTemplateGroupIds);
if (this.sectionIds != null) query.sectionIds(this.sectionIds);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
if (this.isActive != null) query.isActive(this.isActive);

View File

@ -0,0 +1,26 @@
import { Lookup } from '@common/model/lookup';
import { Guid } from '@common/types/guid';
import { IsActive } from '../common/enum/is-active.enum';
export class DmpDescriptionTemplateLookup extends Lookup implements DmpDescriptionTemplateFilter {
ids: Guid[];
excludedIds: Guid[];
dmpIds: Guid[];
descriptionTemplateGroupIds: Guid[];
sectionIds: Guid[];
isActive: IsActive[];
constructor() {
super();
}
}
export interface DmpDescriptionTemplateFilter {
ids: Guid[];
excludedIds: Guid[];
dmpIds: Guid[];
descriptionTemplateGroupIds: Guid[];
sectionIds: Guid[];
isActive: IsActive[];
}

View File

@ -1,9 +1,10 @@
import { Lookup } from '@common/model/lookup';
import { Guid } from '@common/types/guid';
import { IsActive } from '../common/enum/is-active.enum';
import { DmpAccessType } from '../common/enum/dmp-access-type';
import { DmpStatus } from '../common/enum/dmp-status';
import { DmpVersionStatus } from '../common/enum/dmp-version-status';
import { DmpAccessType } from '../common/enum/dmp-access-type';
import { IsActive } from '../common/enum/is-active.enum';
import { DmpDescriptionTemplateLookup } from './dmp-description-template.lookup';
export class DmpLookup extends Lookup implements DmpFilter {
ids: Guid[];
@ -14,7 +15,8 @@ export class DmpLookup extends Lookup implements DmpFilter {
statuses: DmpStatus[];
accessTypes: DmpAccessType[];
versions: Number[];
dmpDescriptionTemplateSubQuery: DmpDescriptionTemplateLookup;
constructor() {
super();

View File

@ -33,6 +33,7 @@ import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service';
import { BaseHttpService } from '../http/base-http.service';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { DmpDescriptionTemplateLookup } from '@app/core/query/dmp-description-template.lookup';
@Injectable()
export class DmpServiceNew {
@ -160,7 +161,7 @@ export class DmpServiceNew {
valueAssign: (item: Dmp) => item.id,
};
public buildAutocompleteLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[]): DmpLookup {
public buildAutocompleteLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup {
const lookup: DmpLookup = new DmpLookup();
lookup.page = { size: 100, offset: 0 };
if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; }
@ -173,6 +174,7 @@ export class DmpServiceNew {
nameof<Dmp>(x => x.label)
]
};
if (dmpDescriptionTemplateSubQuery != null) lookup.dmpDescriptionTemplateSubQuery = dmpDescriptionTemplateSubQuery;
lookup.order = { items: [nameof<Dmp>(x => x.label)] };
if (like) { lookup.like = this.filterService.transformLike(like); }
return lookup;

View File

@ -119,6 +119,10 @@ export class ReferenceService {
//
//
hasRerefenceOfTypes(dmpReferences: DmpReference[], referenceTypes: ReferenceType[]): boolean {
return this.getReferencesForTypes(dmpReferences, referenceTypes)?.length > 0;
}
getReferencesForTypes(dmpReferences: DmpReference[], referenceTypes: ReferenceType[]): DmpReference[] {
return dmpReferences?.filter(x => referenceTypes?.includes(x?.reference?.type));
}
@ -126,4 +130,5 @@ export class ReferenceService {
getReferencesForTypesFirstSafe(dmpReferences: DmpReference[], referenceTypes: ReferenceType[]): DmpReference {
return this.getReferencesForTypes(dmpReferences, referenceTypes)?.find(Boolean);
}
}

View File

@ -9,6 +9,8 @@ import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/sing
import { Dmp } from '@app/core/model/dmp/dmp';
import { DmpServiceNew } from '@app/core/services/dmp/dmp.service';
import { DescriptionService } from '@app/core/services/description/description.service';
import { DmpDescriptionTemplateLookup } from '@app/core/query/dmp-description-template.lookup';
import { IsActive } from '@app/core/common/enum/is-active.enum';
@Component({
selector: 'description-copy-dialog-component',
@ -20,14 +22,18 @@ export class DescriptionCopyDialogComponent {
dmpModel: Dmp;
descriptionDescriptionTemplateLabel: String;
dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { //TODO: add filter to only get DMPs that have connection with the same Description Template group.
initialItems: (data?: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup()).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(searchQuery)).pipe(map(x => x.items)),
initialItems: (data?: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(null,null,null,null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(searchQuery, null, null, null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
displayFn: (item: Dmp) => item.label,
titleFn: (item: Dmp) => item.label,
valueAssign: (item: Dmp) => item.id,
};
dmpDescriptionTemplateLookup: DmpDescriptionTemplateLookup = {
descriptionTemplateGroupIds: [this.data.descriptionTemplate.groupId],
isActive: [IsActive.Active]
} as DmpDescriptionTemplateLookup;
constructor(
public dialogRef: MatDialogRef<DescriptionCopyDialogComponent>,

View File

@ -7,7 +7,6 @@ import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DescriptionStatus } from '@app/core/common/enum/description-status';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
@ -107,9 +106,6 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
this.dmpId = queryParams['dmpId'];
this.status = queryParams['status'];
this.lookup.dmpSubQuery = new DmpLookup();
this.lookup.dmpSubQuery.statuses = [DmpStatus.Draft];
this.lookup.page = { size: this.pageSize, offset: 0 };
this.lookup.order = { items: ['-' + nameof<Description>(x => x.updatedAt)] };
this.lookup.metadata = { countAll: true };
@ -191,6 +187,7 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
nameof<Description>(x => x.updatedAt),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.label)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.accessType)].join('.'),

View File

@ -165,7 +165,7 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
data: {
formControl: formControl,
descriptionId: description.id,
descriptionProfileId: description.descriptionTemplate.id,
descriptionTemplate: description.descriptionTemplate,
descriptionProfileExist: false,
confirmButton: this.language.instant('DESCRIPTION-LISTING.COPY-DIALOG.COPY'),
cancelButton: this.language.instant('DESCRIPTION-LISTING.COPY-DIALOG.CANCEL')

View File

@ -59,7 +59,7 @@
</button>
</div>
<div *ngIf="description.grant">
<div *ngIf="referenceService.hasRerefenceOfTypes(description?.dmp?.dmpReferences, [referenceTypeEnum.Grants])">
<div class="row header">{{'DESCRIPTION-OVERVIEW.GRANT' | translate}}</div>
<div class="row description-label">{{referenceService.getReferencesForTypesFirstSafe(description?.dmp?.dmpReferences, [referenceTypeEnum.Grants])?.reference?.label}}</div>
</div>
@ -149,7 +149,7 @@
<p class="authors-role">{{ enumUtils.toDmpUserRoleString(dmpUser.role) }}</p>
</div>
</div>
<button *ngIf="isUserOwner && !description.status && dmpUser.role" (click)="removeUserFromDmp(dmpUser)" class="remove-btn">{{ 'GENERAL.CONFIRMATION-DIALOG.ACTIONS.REMOVE' | translate}}</button>
<button *ngIf="isUserOwner && description.dmp?.status === dmpStatusEnum.Draft && dmpUser.role === dmpUserRoleEnum.Owner" (click)="removeUserFromDmp(dmpUser)" class="remove-btn">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}</button>
</div>
</div>
<div *ngIf="isUserOwner" class="row mt-3 mb-3 d-flex align-items-center justify-content-center">

View File

@ -55,6 +55,8 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
descriptionStatusEnum = DescriptionStatus;
dmpAccessTypeEnum = DmpAccessType;
referenceTypeEnum = ReferenceType;
dmpStatusEnum = DmpStatus;
dmpUserRoleEnum = DmpUserRole;
constructor(
private route: ActivatedRoute,
@ -335,7 +337,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
data: {
formControl: formControl,
descriptionId: this.description.id,
descriptionProfileId: this.description.descriptionTemplate.id,
descriptionTemplate: this.description.descriptionTemplate,
descriptionProfileExist: false,
confirmButton: this.language.instant('DESCRIPTION-OVERVIEW.COPY-DIALOG.COPY'),
cancelButton: this.language.instant('DESCRIPTION-OVERVIEW.COPY-DIALOG.CANCEL')
@ -440,6 +442,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
nameof<Description>(x => x.updatedAt),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.label)].join('.'),
[nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.accessType)].join('.'),

View File

@ -24,7 +24,14 @@ const routes: Routes = [
breadcrumb: true
},
},
{
path: 'overview/:id',
component: DmpOverviewComponent,
data: {
breadcrumb: true,
title: 'GENERAL.TITLES.DMP-OVERVIEW'
},
},
// {
// path: 'edit/:id',
// component: DmpEditorBlueprintComponent,
@ -43,14 +50,7 @@ const routes: Routes = [
// },
// canDeactivate: [CanDeactivateGuard]
// },
// {
// path: 'overview/:id',
// component: DmpOverviewComponent,
// data: {
// breadcrumb: true,
// title: 'GENERAL.TITLES.DMP-OVERVIEW'
// },
// },
// {
// path: 'publicOverview/:publicId',
// component: DmpOverviewComponent,
@ -61,7 +61,7 @@ const routes: Routes = [
// },
// {
// path: 'new',
// component: DmpEditorBlueprintComponent,

View File

@ -3,12 +3,12 @@
<div *ngIf="dmp">
<a class="row mb-2 pl-1" (click)="goBack()" role="button">
<mat-icon class="back-icon pointer">chevron_left</mat-icon>
<p class="label-txt pointer">{{'DMP-WIZARD.ACTIONS.BACK' | translate}}</p>
<p class="label-txt pointer">{{'DMP-OVERVIEW.ACTIONS.BACK' | translate}}</p>
</a>
<div class="row">
<div class="col-md-8 col-lg-8 pl-4">
<div class="row">
<span class="dmp-logo">{{ 'DATASET-LISTING.COLUMNS.DMP' | translate }}</span>
<span class="dmp-logo">{{ 'DMP-OVERVIEW.TITLE' | translate }}</span>
<p class="dmp-label ml-3 mb-0">{{ dmp.label }}</p>
</div>
<div class="row d-flex align-items-center mt-3 mb-4 label-txt">
@ -16,114 +16,114 @@
<p class="ml-0 mb-0 label2-txt">
{{ enumUtils.toDmpUserRolesString(dmpService.getCurrentUserRolesInDmp(dmp?.dmpUsers)) }}
</div>
<span *ngIf="isUserDmpRelated() && (dmp.isPublic || lockStatus)" class="ml-2 mr-2">.</span>
<div *ngIf="dmp.isPublic" class="d-flex flex-row">
<span *ngIf="isUserDmpRelated() && (isPublishedDmp() || lockStatus)" class="ml-2 mr-2">.</span>
<div *ngIf="isPublishedDmp()" class="d-flex flex-row">
<mat-icon class="status-icon">public</mat-icon>
{{'DMP-OVERVIEW.PUBLIC' | translate}}
</div>
<span *ngIf="dmp.isPublic && lockStatus" class="ml-2 mr-2">.</span>
<span *ngIf="isPublishedDmp() && lockStatus" class="ml-2 mr-2">.</span>
<div *ngIf="lockStatus" class="d-flex flex-row">
<mat-icon class="status-icon">lock_outline</mat-icon>
{{'DMP-OVERVIEW.LOCKED' | translate}}
</div>
<mat-form-field appearance="outline" class="versions-select ml-3 mr-3">
<mat-select placeholder="{{'DMP-LISTING.VERSION' | translate}} {{dmp.version}}" [(ngModel)]="version" (ngModelChange)="versionChanged(version.id)">
<mat-option *ngFor="let version of versions" [value]="version">
{{'DMP-LISTING.VERSION' | translate}} {{version.version}}</mat-option>
<mat-select placeholder="{{'DMP-OVERVIEW.VERSION' | translate}} {{dmp.version}}" [(ngModel)]="version" (ngModelChange)="versionChanged(version.id)">
<mat-option *ngFor="let version of pastVersions" [value]="version">
{{'DMP-OVERVIEW.VERSION' | translate}} {{version.version}}</mat-option>
</mat-select>
</mat-form-field>
<div class="d-flex mr-4">{{'GENERAL.STATUSES.EDIT' | translate}} :
{{dmp.modifiedTime | dateTimeCultureFormatter: "d MMMM y"}}
<div class="d-flex mr-4">{{'DMP-OVERVIEW.EDITED' | translate}} :
{{dmp.updatedAt | dateTimeCultureFormatter: "d MMMM y"}}
</div>
<div class="d-flex mr-4">
<div *ngIf="dmp.status" class="d-flex flex-row uppercase">
<mat-icon class="status-icon">check</mat-icon>
{{'TYPES.DMP.FINALISED' | translate}}
{{'DMP-OVERVIEW.FINALISED' | translate}}
</div>
</div>
</div>
<div class="row">
<button *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus" (click)="editClicked(dmp)" mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
<button *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus" (click)="editClicked(dmp)" mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
</button>
<button *ngIf="isAuthenticated()" (click)="cloneOrNewVersionClicked(dmp, false)" mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.CLONE' | translate}}" matTooltipPosition="above">
<button *ngIf="isAuthenticated()" (click)="cloneOrNewVersionClicked(dmp, false)" mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-OVERVIEW.ACTIONS.CLONE' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
</button>
<button *ngIf="isUserOwner && !lockStatus" (click)="deleteClicked()" mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.DELETE' | translate}}" matTooltipPosition="above">
<button *ngIf="isUserOwner && !lockStatus" (click)="deleteClicked()" mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-OVERVIEW.ACTIONS.DELETE' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
</button>
</div>
<div *ngIf="dmp.grant">
<div *ngIf="referenceService.hasRerefenceOfTypes(dmp?.dmpReferences, [referenceTypeEnum.Grants])">
<div class="row header">{{'DMP-OVERVIEW.GRANT' | translate}}</div>
<div class="row dmp-label">{{ dmp.grant.label }}</div>
<div class="row dmp-label">{{referenceService.getReferencesForTypesFirstSafe(dmp?.dmpReferences, [referenceTypeEnum.Grants])?.reference?.label}}</div>
</div>
<div class="row header">{{'DMP-OVERVIEW.RESEARCHERS' | translate}}</div>
<div class="row header">{{'DESCRIPTION-OVERVIEW.RESEARCHERS' | translate}}</div>
<div class="row">
<div *ngFor="let researcher of dmp.researchers; let last = last">
<span *ngIf="isOrcid(researcher.reference)">
<a href="{{ getOrcidPathForResearcher(researcher.reference) }}" target="blank" class="researcher">
<div *ngFor="let dmpReference of researchers let last = last">
<span *ngIf="isOrcid(dmpReference.reference)">
<a href="{{ getOrcidPathForResearcher(dmpReference.reference?.reference) }}" target="blank" class="researcher">
<div class="id-btn">&nbsp;</div>
<div *ngIf="!last">{{ researcher.name }}, </div>
<div *ngIf="last">{{ researcher.name }}</div>
<div *ngIf="!last">{{ dmpReference.reference?.data?.name }}, </div> <!-- TODO: data is missign after refactor -->
<div *ngIf="last">{{ dmpReference.reference?.data?.name }}</div><!-- TODO: data is missign after refactor -->
</a>
</span>
<span *ngIf="!isOrcid(researcher.reference)">
<div *ngIf="!last">{{ researcher.name }}, </div>
<div *ngIf="last">{{ researcher.name }}</div>
<span *ngIf="!isOrcid(dmpReference.reference)">
<div *ngIf="!last">{{ dmpReference.reference?.data?.name }}, </div> <!-- TODO: data is missign after refactor -->
<div *ngIf="last">{{ dmpReference.reference?.data?.name }}</div> <!-- TODO: data is missign after refactor -->
</span>
</div>
<span *ngIf="!dmp.researchers || dmp.researchers.length === 0" class="material-icons">horizontal_rule</span>
<span *ngIf="!researchers || researchers.length === 0" class="material-icons">horizontal_rule</span>
</div>
<div class="row header">{{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}}</div>
<div class="row header">{{'DMP-OVERVIEW.DESCRIPTION' | translate}}</div>
<div class="row" *ngIf="dmp.description">
<p class="desc-txt" [innerHTML]="dmp.description"></p>
</div>
<div class="row" *ngIf="!dmp.description">
<span class="material-icons">horizontal_rule</span>
</div>
<div class="row header">{{'DMP-OVERVIEW.DESCRIPTIONS-USED' | translate}}</div>
<div class="row header">{{'DMP-OVERVIEW.DESCRIPTIONS' | translate}}</div>
<div class="d-flex flex-column">
<div *ngFor="let dataset of dmp.datasets">
<a class="row dataset" [routerLink]="isPublicView ? ['/datasets/publicOverview/' + dataset.id] : ['/datasets/overview/' + dataset.id]" target="_blank">
<div *ngFor="let description of dmp.descriptions">
<a class="row description" [routerLink]="isPublicView ? ['/descriptions/publicOverview/' + description.id] : ['/descriptions/overview/' + description.id]" target="_blank">
<button mat-raised-button class="mb-2 mr-2 pl-0 pr-0">
<div matTooltip="{{ dataset.label }}" class="col-auto" [ngClass]="{'dataset-btn': dataset.status === 0, 'dataset-finalized-btn': dataset.status === 1}">
<div class="dataset-btn-label">{{ dataset.label }}</div>
<div matTooltip="{{ description.label }}" class="col-auto" [ngClass]="{'description-btn': description.status === descriptionStatusEnum.Draft, 'description-finalized-btn': description.status === descriptionStatusEnum.Finalized}">
<div class="description-btn-label">{{ description.label }}</div>
<mat-icon>launch</mat-icon>
</div>
</button>
</a>
</div>
<div class="row" *ngIf="!dmp.datasets || dmp.datasets.length === 0">
<div class="row" *ngIf="!dmp.descriptions || dmp.descriptions.length === 0">
<span class="material-icons">horizontal_rule</span>
</div>
</div>
<div class="row mt-2 add-dataset-txt" *ngIf="!lockStatus">
<a class="add-dataset-btn" *ngIf="isDraftDmp(dmp)" [routerLink]="['/plans/edit/' + dmp.id]" target="_blank">
<div class="row mt-2 add-description-txt" *ngIf="!lockStatus">
<a class="add-description-btn" *ngIf="isDraftDmp(dmp)" [routerLink]="['/plans/edit/' + dmp.id]" target="_blank">
<mat-icon>add</mat-icon>
{{'DMP-LISTING.ACTIONS.ADD-DESCRIPTION-SHORT' | translate}}
{{'DMP-OVERVIEW.ACTIONS.ADD-DESCRIPTION' | translate}}
</a>
</div>
</div>
<div class="col-md-4 col-lg-4 p-0">
<div *ngIf="!hasDoi(dmp)" class="row d-flex flex-column ml-0 mr-0 mb-3">
<div class="d-flex align-items-center doi-label">
<span class="mr-3">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}: </span>
<span class="mr-3">{{'DMP-OVERVIEW.DOI-PROVIDED' | translate}}: </span>
<ng-container *ngIf="selectedModel">
<mat-select class="max-width-80 select-repo" [placeholder]="selectedModel.repositoryId">
<mat-option *ngFor="let doi of dmp.dois" (click)="selectDoi(doi)">
{{doi.repositoryId}}
<mat-option *ngFor="let entityDoi of dmp.entityDois" (click)="selectDoi(entityDoi)">
{{entityDoi.repositoryId}}
</mat-option>
</mat-select>
</ng-container>
</div>
<div *ngIf="dmp.dois && selectedModel" class="doi-panel">
<div *ngIf="dmp.entityDois && selectedModel" class="doi-panel">
<span class="ml-3 mr-3">{{selectedModel.doi}}</span>
<div class="d-flex justify-content-end ml-3">
<button (click)="copyDoi(selectedModel.doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<button (click)="copyDoi(selectedModel.doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-OVERVIEW.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
</button>
<button *ngIf="depositRepos?.length > 0" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<button *ngIf="depositRepos?.length > 0" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-OVERVIEW.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<a [href]="createDoiLink(selectedModel)" class="doi-link" target="_blank">
<mat-icon class="mat-mini-fab-icon">launch</mat-icon>
</a>
@ -137,31 +137,31 @@
<button mat-mini-fab class="finalize-btn">
<mat-icon class="mat-mini-fab-icon">check</mat-icon>
</button>
<p class="mb-0 pl-2 finalize-txt">{{ 'DMP-LISTING.ACTIONS.FINALIZE' | translate }}</p>
<p class="mb-0 pl-2 finalize-txt">{{ 'DMP-OVERVIEW.ACTIONS.FINALIZE' | translate }}</p>
</div>
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center">
<hr class="hr-line">
</div>
</div>
<app-dmp-deposit-dropdown *ngIf="(hasDoi(dmp) || moreDeposit()) && isFinalizedDmp(dmp) && !this.isPublicView && isUserOwner" [inputRepos]="inputRepos" [dmp]="dmp" (outputReposEmitter)="afterDeposit($event)"></app-dmp-deposit-dropdown>
<div *ngIf="isFinalizedDmp(dmp) && hasDoi(dmp) && !isPublishedDMP(dmp) && isUserOwner" (click)="reverseFinalization()" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<div *ngIf="isFinalizedDmp(dmp) && hasDoi(dmp) && !isPublishedDmp(dmp) && isUserOwner" (click)="reverseFinalization()" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
</button>
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.UNFINALIZE' | translate }}</p>
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-OVERVIEW.ACTIONS.REVERSE' | translate }}</p>
</div>
<div class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<button mat-mini-fab class="frame-btn" [matMenuTriggerFor]="exportMenu">
<mat-icon class="mat-mini-fab-icon">open_in_new</mat-icon>
</button>
<p class="mb-0 mr-0 pl-2 frame-txt" [matMenuTriggerFor]="exportMenu">
{{ 'DMP-LISTING.ACTIONS.EXPORT' | translate }}</p>
{{ 'DMP-OVERVIEW.ACTIONS.EXPORT' | translate }}</p>
</div>
<div *ngIf="isUserOwner" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center" (click)="cloneOrNewVersionClicked(dmp, true)">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">add_to_photos</mat-icon>
</button>
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.START-NEW-VERSION' | translate }}
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-OVERVIEW.OVERVIEW.NEW-VERSION' | translate }}
</p>
</div>
<mat-menu #exportMenu="matMenu" xPosition="before">
@ -188,25 +188,26 @@
<p class="header">{{ 'DMP-OVERVIEW.DMP-AUTHORS' | translate }}</p>
</div>
<div class="row ml-0 mr-0 pl-4 ml-2 pb-3 d-flex align-items-center">
<div *ngFor="let user of dmp.users" class="row authors">
<div *ngFor="let dmpUser of dmp.dmpUsers" class="row authors">
<div class="d-flex flex-row">
<button class="account_btn mr-3 pl-0">
<mat-icon class="account-icon">account_circle</mat-icon>
</button>
<div>
<p class="authors-label">{{ user.name }}
<span *ngIf="isUserAuthor(user.id)">({{ 'DMP-OVERVIEW.YOU' | translate }})</span>
<p class="authors-label">{{ dmpUser.user?.name }}
<span *ngIf="isUserAuthor(dmpUser.user?.id)">
({{ 'DMP-OVERVIEW.YOU' | translate }})</span>
</p>
<p class="authors-role">{{ enumUtils.toDmpUserRoleString(dmpUser.role) }}</p>
</div>
</div>
<button *ngIf="isUserOwner && !dmp.status && user.role" (click)="removeUserFromDmp(user)" class="remove-btn">{{ 'GENERAL.CONFIRMATION-DIALOG.ACTIONS.REMOVE' | translate}}</button>
<button *ngIf="isUserOwner && dmp.status === dmpStatusEnum.Draft && dmpUser.role === dmpUserRoleEnum.Owner" (click)="removeUserFromDmp(dmpUser)" class="remove-btn">{{ 'DMP-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}</button>
</div>
</div>
<div *ngIf="isUserOwner" class="row mt-3 mb-3 d-flex align-items-center justify-content-center">
<button mat-raised-button class="invite-btn" (click)="openShareDialog(dmp.id,dmp.label)">
<mat-icon>group_add</mat-icon>
{{'DMP-LISTING.ACTIONS.INVITE-SHORT' | translate}}
{{'DMP-OVERVIEW.ACTIONS.INVITE-SHORT' | translate}}
</button>
</div>
</div>

View File

@ -31,7 +31,9 @@
.account-icon {
font-size: 2.5em;
}
height: auto;
width: auto;
}
// ********BUTTONS********
@ -42,7 +44,7 @@
align-self: center;
}
.dataset-btn {
.description-btn {
width: 36.1em;
padding: 0 1.1em;
background-color: var(--secondary-color);
@ -52,7 +54,7 @@
// opacity: 0.8;
}
.dataset-finalized-btn {
.description-finalized-btn {
width: 36.1em;
padding: 0 1.1em;
background-color: #b2f772;
@ -179,11 +181,11 @@
margin-bottom: 1.875em;
}
.dataset {
.description {
width: fit-content;
}
.dataset-btn-label {
.description-btn-label {
margin-right: 1em;
overflow: hidden;
text-overflow: ellipsis;
@ -291,20 +293,20 @@
}
.dmp-label,
.dataset-btn,
.dataset-finalized-btn,
.add-dataset-btn,
.description-btn,
.description-finalized-btn,
.add-description-btn,
.doi-panel,
.researcher {
display: flex;
align-items: center;
}
.add-dataset-btn {
.add-description-btn {
color: #212121 !important;
}
.add-dataset-btn:hover {
.add-description-btn:hover {
color: var(--primary-color) !important;
}
@ -456,7 +458,7 @@
// color: var(--primary-color-3);
// }
// .dataset-card {
// .description-card {
// display: flex;
// flex-direction: column;
// min-width: 0;
@ -473,7 +475,7 @@
// box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.14);
// }
// .dataset-card h4 {
// .description-card h4 {
// padding-left: 1em;
// margin: 1em 1.5em;
// }
@ -544,12 +546,12 @@
// text-overflow: ellipsis;
// }
// .datasets-counter {
// .descriptions-counter {
// display: flex;
// cursor: pointer;
// }
// .datasets-counter :hover {
// .descriptions-counter :hover {
// color: var(--primary-color-3) !important;
// }

View File

@ -1,61 +1,41 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview';
import { DatasetsToBeFinalized } from '@app/core/model/dataset/datasets-toBeFinalized';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DmpService, DmpServiceNew } from '@app/core/services/dmp/dmp.service';
import { DmpServiceNew } from '@app/core/services/dmp/dmp.service';
import {
SnackBarNotificationLevel,
UiNotificationService
} from '@app/core/services/notification/ui-notification-service';
import {
DmpFinalizeDialogComponent,
DmpFinalizeDialogInput,
DmpFinalizeDialogOutput
} from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
// import {BreadcrumbItem} from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { Location } from '@angular/common';
import { UntypedFormGroup } from '@angular/forms';
import { DmpBlueprintSectionFieldCategory } from '@app/core/common/enum/dmp-blueprint-section-field-category';
import { DmpBlueprintSystemFieldType } from '@app/core/common/enum/dmp-blueprint-system-field-type';
import { Role } from "@app/core/common/enum/role";
import { DescriptionStatus } from '@app/core/common/enum/description-status';
import { DmpAccessType } from '@app/core/common/enum/dmp-access-type';
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
import { ReferenceType } from '@app/core/common/enum/reference-type';
import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration';
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection, FieldInSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
import { Dmp, Dmp, DmpUser } from '@app/core/model/dmp/dmp';
import { Description } from '@app/core/model/description/description';
import { Dmp, DmpUser } from '@app/core/model/dmp/dmp';
import { DoiModel } from '@app/core/model/doi/doi';
import { VersionListingModel } from '@app/core/model/version/version-listing.model';
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
import { DmpReference, Reference } from '@app/core/model/reference/reference';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service';
import { DmpBlueprintService } from '@app/core/services/dmp/dmp-blueprint.service';
import { LockService } from '@app/core/services/lock/lock.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { ReferenceService } from '@app/core/services/reference/reference.service';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { FileUtils } from '@app/core/services/utilities/file-utils.service';
import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component';
import { isNullOrUndefined } from '@app/utilities/enhancers/utils';
import { BaseComponent } from '@common/base/base.component';
import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { Observable } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
import { CloneDialogComponent } from '../clone/clone-dialog/clone-dialog.component';
import { DmpEditorModel } from '../editor/dmp-editor.model';
import { ExtraPropertiesFormModel } from '../editor/general-tab/extra-properties-form.model';
import { FunderFormModel } from '../editor/grant-tab/funder-form-model';
import { GrantTabModel } from '../editor/grant-tab/grant-tab-model';
import { ProjectFormModel } from '../editor/grant-tab/project-form-model';
import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation-dialog.component';
import { StartNewDmpDialogComponent } from '../start-new-dmp-dialogue/start-new-dmp-dialog.component';
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
import { DmpAccessType } from '@app/core/common/enum/dmp-access-type';
import { Description } from '@app/core/model/description/description';
@Component({
selector: 'app-dmp-overview',
@ -65,6 +45,7 @@ import { Description } from '@app/core/model/description/description';
export class DmpOverviewComponent extends BaseComponent implements OnInit {
dmp: Dmp;
researchers: DmpReference[] = [];
isNew = true;
isFinalized = false;
isPublicView = true;
@ -73,8 +54,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
isUserOwner: boolean;
lockStatus: Boolean;
textMessage: any;
versions: VersionListingModel[];
version: VersionListingModel;
pastVersions: Dmp[]; //TODO: get these from the backend
selectedModel: EntityDoi;
@ViewChild('doi')
@ -82,7 +62,11 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
depositRepos: DepositConfigurationModel[] = [];
formGroup: UntypedFormGroup;
descriptionStatusEnum = DescriptionStatus;
dmpAccessTypeEnum = DmpAccessType;
referenceTypeEnum = ReferenceType;
dmpStatusEnum = DmpStatus;
dmpUserRoleEnum = DmpUserRole;
constructor(
private route: ActivatedRoute,
@ -99,7 +83,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
private location: Location,
private lockService: LockService,
private matomoService: MatomoService,
private fileUtils: FileUtils
private fileUtils: FileUtils,
public referenceService: ReferenceService,
public enumUtils: EnumUtils
) {
super();
}
@ -119,6 +105,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
this.researchers = this.referenceService.getReferencesForTypes(this.dmp?.dmpReferences, [ReferenceType.Researcher]);
if (!this.hasDoi()) {
this.selectedModel = this.dmp.entityDois[0];
}
@ -146,6 +133,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
this.researchers = this.referenceService.getReferencesForTypes(this.dmp?.dmpReferences, [ReferenceType.Researcher]);
if (!this.hasDoi()) {
this.selectedModel = this.dmp.entityDois[0];
}
@ -279,7 +267,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
// maxHeight: '80vh',
// data: {
// formGroup: this.formGroup,
// datasets: this.dmp.datasets,
// descriptions: this.dmp.descriptions,
// isNewVersion: isNewVersion,
// confirmButton: this.language.instant('DMP-EDITOR.CLONE-DIALOG.SAVE'),
// cancelButton: this.language.instant('DMP-EDITOR.CLONE-DIALOG.CANCEL'),
@ -426,8 +414,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
return dmp.status == DmpStatus.Finalized;
}
isPublishedDMP(dmp: Dmp) {
return (dmp.status == DmpStatus.Finalized && dmp.accessType === DmpAccessType.Public);
isPublishedDmp() {
return (this.dmp.status == DmpStatus.Finalized && this.dmp.accessType === DmpAccessType.Public);
}
hasDoi() {
@ -471,7 +459,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
// const dialogInputModel: DmpFinalizeDialogInput = {
// dmpLabel: this.dmp.label,
// dmpDescription: this.dmp.description,
// datasets: this.dmp.datasets.map(x => {
// descriptions: this.dmp.descriptions.map(x => {
// return { label: x.label, id: x.id, status: x.status }
// }),
// accessRights: extraProperties.visible
@ -492,10 +480,10 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
// if (result && !result.cancelled) {
// this.checkIfAnyProfileIsUsedLessThanMin(data).subscribe(checked => {
// if (!checked) {
// var datasetsToBeFinalized: DatasetsToBeFinalized = {
// uuids: result.datasetsToBeFinalized
// var descriptionsToBeFinalized: DescriptionsToBeFinalized = {
// uuids: result.descriptionsToBeFinalized
// };
// this.dmpService.finalize(datasetsToBeFinalized, this.dmp.id)
// this.dmpService.finalize(descriptionsToBeFinalized, this.dmp.id)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// complete => {
@ -536,8 +524,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
// if (!(template.minMultiplicity > 0))
// return false;
// let count = 0;
// dmp.datasets.filter(dataset => dataset.dmpSectionIndex === (section.ordinal - 1)).forEach(dataset => {
// if (Guid.parse(dataset.profile.id) === template.descriptionTemplateId) {
// dmp.descriptions.filter(description => description.dmpSectionIndex === (section.ordinal - 1)).forEach(description => {
// if (Guid.parse(description.profile.id) === template.descriptionTemplateId) {
// count++;
// }
// })
@ -693,15 +681,13 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
return this.configurationService.orcidPath;
}
isOrcid(reference: string) {
const head = reference.split(':')[0];
return head === 'orcid';
isOrcid(reference: Reference) {
return reference.source === 'orcid';
}
getOrcidPathForResearcher(reference: string): string {
const path = this.getOrcidPath();
const userId = reference.split(':')[1];
return path + userId;
return path + reference;
}
checkLockStatus(id: Guid) {
@ -727,24 +713,24 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
nameof<Dmp>(x => x.accessType),
nameof<Dmp>(x => x.version),
nameof<Dmp>(x => x.groupId),
nameof<Dmp>(x => x.version),
nameof<Dmp>(x => x.updatedAt),
[nameof<Dmp>(x => x.entityDois), nameof<EntityDoi>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.entityDois), nameof<EntityDoi>(x => x.repositoryId)].join('.'),
[nameof<Dmp>(x => x.entityDois), nameof<EntityDoi>(x => x.doi)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
// [nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.id)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.label)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.accessType)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.id)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.name)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.role)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.id)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.label)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.type)].join('.'),
// [nameof<Description>(x => x.dmp), nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.reference)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.label)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.type)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.source)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.reference)].join('.'),
]
}
}

View File

@ -872,16 +872,39 @@
}
},
"DMP-OVERVIEW": {
"GRANT": "Grant",
"DMP-AUTHORS": "DΜP Authors",
"RESEARCHERS": "Researchers",
"DESCRIPTIONS-USED": "Descriptions used",
"COLLABORATORS": "Collaborators",
"TITLE": "DMP",
"PUBLIC": "Public",
"PRIVATE": "Private",
"LOCKED": "Locked",
"UNLOCKED": "Unlocked",
"VERSION":"Version",
"EDITED": "Edited",
"FINALISED": "Finalized",
"GRANT": "Grant",
"RESEARCHERS": "Researchers",
"DESCRIPTION": "Description",
"DESCRIPTIONS": "Descriptions included",
"DOI-PROVIDED": "DOI provided by",
"DMP-AUTHORS": "DΜP Authors",
"YOU": "you",
"ACTIONS": {
"BACK":"Back",
"EDIT":"Edit",
"CLONE":"Clone",
"DELETE":"Delete",
"ADD-DESCRIPTION": "Add Description",
"COPY":"Copy",
"FINALIZE":"Finalize",
"VISIT-WEBSITE": "Visit Website",
"REVERSE":"Undo Finalization",
"EXPORT":"Export",
"NEW-VERSION":"Start new version",
"INVITE-SHORT": "Invite",
"REMOVE-AUTHOR": "Remove"
},
"COLLABORATORS": "Collaborators",
"PRIVATE": "Private",
"UNLOCKED": "Unlocked",
"LOCK": "Lock",
"TOOLTIP": {
"LEVEL-OF-ACCESS": "Level of Access",
@ -937,7 +960,8 @@
"FINALIZE":"Finalize",
"REVERSE":"Undo Finalization",
"EXPORT":"Export",
"INVITE-SHORT": "Invite"
"INVITE-SHORT": "Invite",
"REMOVE-AUTHOR": "Remove"
},
"COPY-DIALOG": {
"COPY": "Copy",