Merge branch 'ui-redesign' of gitlab.eudat.eu:dmp/OpenAIRE-EUDAT-DMP-service-pilot into ui-redesign
# Conflicts: # dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts
This commit is contained in:
commit
6fa7b4a350
|
@ -28,6 +28,7 @@ import eu.eudat.models.data.helpers.common.DataTableData;
|
|||
import eu.eudat.models.data.helpers.responses.ResponseItem;
|
||||
import eu.eudat.models.data.listingmodels.DataManagementPlanListingModel;
|
||||
import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel;
|
||||
import eu.eudat.models.data.listingmodels.UserInfoListingModel;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
import eu.eudat.query.DMPQuery;
|
||||
import eu.eudat.types.ApiMessageCode;
|
||||
|
@ -277,6 +278,19 @@ public class DMPs extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
@RequestMapping(method = RequestMethod.POST, value = {"/updateusers/{id}"})
|
||||
public ResponseEntity<ResponseItem<DMP>> updateUsers(@PathVariable String id, @RequestBody List<UserInfoListingModel> users, Principal principal) {
|
||||
try {
|
||||
this.dataManagementPlanManager.updateUsers(UUID.fromString(id), users, principal);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DMP>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully Updated Colaborators for Data Datamanagement Plan."));
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<DMP>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to update the users of Data Management Plan."));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DOI Generation
|
||||
* */
|
||||
|
|
|
@ -137,7 +137,7 @@ public class DashBoardManager {
|
|||
|
||||
List<Integer> roles = new LinkedList<>();
|
||||
List<Dmp> finalDmps = dmps;
|
||||
CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated(dmps != null ? dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))) : dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).countAsync()
|
||||
CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated(dmps != null ? dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))) : dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).distinct().countAsync()
|
||||
.whenComplete((dmpsStats, throwable) -> statistics.setTotalDataManagementPlanCount(dmpsStats));
|
||||
List<eu.eudat.elastic.entities.Dataset> finalDatasets = datasets;
|
||||
CompletableFuture datasetFuture = datasetRepository.getAuthenticated(datasets != null ? datasetRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))) : datasetRepository.getWithCriteria(datasetCriteria), user, roles).countAsync()
|
||||
|
|
|
@ -189,7 +189,7 @@ public class DataManagementPlanManager {
|
|||
.whenComplete((resultList, throwable) -> dataTable.setData(resultList));
|
||||
}
|
||||
|
||||
CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count));
|
||||
CompletableFuture countFuture = authItems.distinct().countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count));
|
||||
CompletableFuture.allOf(itemsFuture, countFuture).join();
|
||||
return dataTable;
|
||||
}
|
||||
|
@ -867,6 +867,18 @@ public class DataManagementPlanManager {
|
|||
this.updateIndex(dmp);
|
||||
}
|
||||
|
||||
public void updateUsers(UUID id, List<UserInfoListingModel> users, Principal principal) throws Exception {
|
||||
DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id);
|
||||
if (!isUserOwnerOfDmp(dmp, principal))
|
||||
throw new Exception("User does not have the privilege to do this action.");
|
||||
clearUsers(dmp);
|
||||
for (UserInfoListingModel userListing : users) {
|
||||
UserInfo tempUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userListing.getId());
|
||||
assignUser(dmp, tempUser, UserDMP.UserDMPRoles.fromInteger(userListing.getRole()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Export Data
|
||||
* */
|
||||
|
|
|
@ -3,6 +3,8 @@ package eu.eudat.models.data.dataset;
|
|||
import eu.eudat.data.entities.Dataset;
|
||||
import eu.eudat.models.DataModel;
|
||||
import eu.eudat.models.data.datasetprofile.DatasetProfileOverviewModel;
|
||||
import eu.eudat.models.data.grant.GrantOverviewModel;
|
||||
import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel;
|
||||
import eu.eudat.models.data.listingmodels.UserInfoListingModel;
|
||||
|
||||
import java.util.Date;
|
||||
|
@ -17,8 +19,8 @@ public class DatasetOverviewModel implements DataModel<Dataset, DatasetOverviewM
|
|||
private short status;
|
||||
private DatasetProfileOverviewModel datasetTemplate;
|
||||
private List<UserInfoListingModel> users;
|
||||
private String dmp;
|
||||
private String grant;
|
||||
private DataManagementPlanOverviewModel dmp;
|
||||
private GrantOverviewModel grant;
|
||||
private String description;
|
||||
private Boolean isPublic;
|
||||
private Date modified;
|
||||
|
@ -59,19 +61,19 @@ public class DatasetOverviewModel implements DataModel<Dataset, DatasetOverviewM
|
|||
this.users = users;
|
||||
}
|
||||
|
||||
public String getDmp() {
|
||||
public DataManagementPlanOverviewModel getDmp() {
|
||||
return dmp;
|
||||
}
|
||||
|
||||
public void setDmp(String dmp) {
|
||||
public void setDmp(DataManagementPlanOverviewModel dmp) {
|
||||
this.dmp = dmp;
|
||||
}
|
||||
|
||||
public String getGrant() {
|
||||
public GrantOverviewModel getGrant() {
|
||||
return grant;
|
||||
}
|
||||
|
||||
public void setGrant(String grant) {
|
||||
public void setGrant(GrantOverviewModel grant) {
|
||||
this.grant = grant;
|
||||
}
|
||||
|
||||
|
@ -106,8 +108,8 @@ public class DatasetOverviewModel implements DataModel<Dataset, DatasetOverviewM
|
|||
this.status = entity.getStatus();
|
||||
this.datasetTemplate = new DatasetProfileOverviewModel().fromDataModel(entity.getProfile());
|
||||
this.users = entity.getDmp().getUsers().stream().map(x -> new UserInfoListingModel().fromDataModel(x)).collect(Collectors.toList());
|
||||
this.dmp = entity.getDmp().getLabel();
|
||||
this.grant = entity.getDmp().getGrant().getLabel();
|
||||
this.dmp = new DataManagementPlanOverviewModel().fromDataModel(entity.getDmp());
|
||||
this.grant = new GrantOverviewModel().fromDataModel(entity.getDmp().getGrant());
|
||||
this.description = entity.getDescription();
|
||||
this.isPublic = entity.getDmp().isPublic();
|
||||
this.modified = entity.getModified();
|
||||
|
|
|
@ -3,6 +3,7 @@ package eu.eudat.models.rda.mapper;
|
|||
import eu.eudat.data.entities.*;
|
||||
import eu.eudat.logic.services.ApiContext;
|
||||
import eu.eudat.logic.utilities.helpers.StreamDistinctBy;
|
||||
import eu.eudat.models.rda.Cost;
|
||||
import eu.eudat.models.rda.Dmp;
|
||||
import eu.eudat.models.rda.DmpId;
|
||||
import net.minidev.json.JSONObject;
|
||||
|
@ -43,16 +44,34 @@ public class DmpRDAMapper {
|
|||
|
||||
Map<String, Object> extraProperties = new org.json.JSONObject(dmp.getExtraProperties()).toMap();
|
||||
if (!extraProperties.isEmpty()) {
|
||||
rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(extraProperties.get("language").toString()));
|
||||
if (extraProperties.get("language") != null) {
|
||||
rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(extraProperties.get("language").toString()));
|
||||
}
|
||||
if (extraProperties.get("costs") != null) {
|
||||
rda.setCost(new ArrayList<>());
|
||||
((List) extraProperties.get("costs")).forEach(costl -> {
|
||||
Cost cost = new Cost();
|
||||
Map<String, Object> code = new org.json.JSONObject((String) ((Map) costl).get("code")).toMap();
|
||||
cost.setCurrencyCode(Cost.CurrencyCode.fromValue((String) code.get("value")));
|
||||
cost.setDescription((String) ((Map) costl).get("description"));
|
||||
cost.setTitle((String) ((Map) costl).get("title"));
|
||||
cost.setValue(((Integer) ((Map) costl).get("value")).doubleValue());
|
||||
rda.getCost().add(cost);
|
||||
});
|
||||
}
|
||||
if (extraProperties.get("contact") != null) {
|
||||
UserInfo contact = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(UUID.fromString((String)extraProperties.get("contact")));
|
||||
rda.setContact(ContactRDAMapper.toRDA(contact));
|
||||
}
|
||||
}
|
||||
|
||||
UserInfo creator;
|
||||
/*UserInfo creator;
|
||||
if (dmp.getCreator() != null) {
|
||||
creator = dmp.getCreator();
|
||||
} else {
|
||||
creator = dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).map(UserDMP::getUser).findFirst().orElse(new UserInfo());
|
||||
}
|
||||
rda.setContact(ContactRDAMapper.toRDA(creator));
|
||||
rda.setContact(ContactRDAMapper.toRDA(creator));*/
|
||||
rda.setContributor(new ArrayList<>());
|
||||
if (dmp.getResearchers() != null && !dmp.getResearchers().isEmpty()) {
|
||||
rda.getContributor().addAll(dmp.getResearchers().stream().map(ContributorRDAMapper::toRDA).collect(Collectors.toList()));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { DatasetProfileModel } from "./dataset-profile";
|
||||
import { GrantOverviewModel } from '../grant/grant-overview';
|
||||
import { DmpOverviewModel } from '../dmp/dmp-overview';
|
||||
|
||||
export interface DatasetOverviewModel {
|
||||
id: string;
|
||||
|
@ -8,7 +9,7 @@ export interface DatasetOverviewModel {
|
|||
datasetTemplate: DatasetProfileModel;
|
||||
|
||||
users: any[];
|
||||
dmp: String;
|
||||
dmp: DmpOverviewModel;
|
||||
grant: GrantOverviewModel;
|
||||
description: String;
|
||||
public: boolean;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||
import { ValidationContext } from '@common/forms/validation/validation-context';
|
||||
|
||||
export interface CostModel {
|
||||
code: string;
|
||||
description: string;
|
||||
title: string;
|
||||
value: number;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
export interface ResearcherModel {
|
||||
id: String;
|
||||
id: string;
|
||||
name: String;
|
||||
reference: String;
|
||||
lastName: String;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { BaseHttpService } from '../http/base-http.service';
|
|||
import { DatasetProfileCriteria } from '../../query/dataset-profile/dataset-profile-criteria';
|
||||
import { ConfigurationService } from '../configuration/configuration.service';
|
||||
import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview';
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { HttpHeaders, HttpResponse, HttpClient } from '@angular/common/http';
|
||||
import { DatasetModel } from '@app/core/model/dataset/dataset';
|
||||
|
||||
@Injectable()
|
||||
|
@ -22,7 +22,8 @@ export class DatasetService {
|
|||
|
||||
constructor(
|
||||
private http: BaseHttpService,
|
||||
private configurationSevice: ConfigurationService) {
|
||||
private configurationSevice: ConfigurationService,
|
||||
private httpClient: HttpClient) {
|
||||
this.actionUrl = configurationSevice.server + 'datasets/';
|
||||
}
|
||||
|
||||
|
@ -69,4 +70,27 @@ export class DatasetService {
|
|||
delete(id: String): Observable<DatasetModel> {
|
||||
return this.http.delete<DatasetModel>(this.actionUrl + 'delete/' + id, { headers: this.headers }); // + 'delete/'
|
||||
}
|
||||
|
||||
publish(id: String): Observable<DatasetModel> {
|
||||
return this.http.get<DatasetModel>(this.actionUrl + 'makepublic/' + id, { headers: this.headers });
|
||||
}
|
||||
|
||||
public downloadXML(id: string): Observable<HttpResponse<Blob>> {
|
||||
let headerXml: HttpHeaders = this.headers.set('Content-Type', 'application/xml')
|
||||
return this.httpClient.get(this.actionUrl + id, { responseType: 'blob', observe: 'response', headers: headerXml }); //+ "/getXml/"
|
||||
}
|
||||
|
||||
public downloadDocx(id: string): Observable<HttpResponse<Blob>> {
|
||||
let headerDoc: HttpHeaders = this.headers.set('Content-Type', 'application/msword')
|
||||
return this.httpClient.get(this.actionUrl + id, { responseType: 'blob', observe: 'response', headers: headerDoc });
|
||||
}
|
||||
|
||||
public downloadPDF(id: string): Observable<HttpResponse<Blob>> {
|
||||
let headerPdf: HttpHeaders = this.headers.set('Content-Type', 'application/pdf')
|
||||
return this.httpClient.get(this.actionUrl + 'getPDF/' + id, { responseType: 'blob', observe: 'response', headers: headerPdf });
|
||||
}
|
||||
|
||||
public downloadJson(id: string): Observable<HttpResponse<Blob>> {
|
||||
return this.httpClient.get(this.actionUrl + 'rda/' + id, { responseType: 'blob', observe: 'response' });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import { ExploreDmpCriteriaModel } from '../../query/explore-dmp/explore-dmp-cri
|
|||
import { RequestItem } from '../../query/request-item';
|
||||
import { BaseHttpService } from '../http/base-http.service';
|
||||
import { ConfigurationService } from '../configuration/configuration.service';
|
||||
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
|
||||
|
||||
@Injectable()
|
||||
export class DmpService {
|
||||
|
@ -96,6 +97,10 @@ export class DmpService {
|
|||
return this.http.post<DmpModel>(this.actionUrl + 'unfinalize/' + id, { headers: this.headers });
|
||||
}
|
||||
|
||||
updateUsers(id: string, users: UserInfoListingModel[]): Observable<DmpModel> {
|
||||
return this.http.post<DmpModel>(`${this.actionUrl}updateusers/${id}`, users, {headers: this.headers});
|
||||
}
|
||||
|
||||
getDoi(id: string): Observable<string> {
|
||||
return this.http.post<string>(this.actionUrl + 'createZenodoDoi/' + id, { headers: this.headers });
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
<div class="row">
|
||||
<div class="col-md-8 col-lg-8 pl-4">
|
||||
<div class="row">
|
||||
<span class="dataset-logo">{{ 'NAV-BAR.DATASET' | translate }}</span>
|
||||
<p class="dataset-label ml-2 mb-0">{{ dataset.label }}</p>
|
||||
<span class="col-auto dataset-logo">{{ 'NAV-BAR.DATASET' | translate }}</span>
|
||||
<p class="col dataset-label p-0 ml-3 mb-0">{{ dataset.label }}</p>
|
||||
</div>
|
||||
<div class="row d-flex align-items-center mt-3 mb-4 label-txt">
|
||||
<div *ngIf="isUserDatasetRelated()" class="d-flex">
|
||||
|
@ -27,56 +27,40 @@
|
|||
{{'DMP-OVERVIEW.PRIVATE' | translate}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="d-flex mr-4">
|
||||
<div *ngIf="lockStatus" class="d-flex flex-row">
|
||||
<mat-icon class="status-icon">lock_outline</mat-icon>
|
||||
{{'DMP-OVERVIEW.LOCKED' | translate}}
|
||||
</div>
|
||||
<div *ngIf="!lockStatus" class="d-flex flex-row">
|
||||
<mat-icon class="status-icon">lock_open</mat-icon>
|
||||
{{'DMP-OVERVIEW.UNLOCKED' | translate}}
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- <button class="d-flex mr-4 version-btn label2-txt"
|
||||
(click)="viewVersions(dmp.groupId, dmp.label)">
|
||||
{{'DMP-LISTING.ACTIONS.VIEW-VERSION' | translate}}
|
||||
</button> -->
|
||||
<div class="d-flex mr-4">{{'GENERAL.STATUSES.EDIT' | translate}} :
|
||||
<div *ngIf="lockStatus" class="d-flex flex-row mr-4">
|
||||
<mat-icon class="status-icon">lock_outline</mat-icon>
|
||||
{{'DMP-OVERVIEW.LOCKED' | translate}}
|
||||
</div>
|
||||
<div class="d-flex mr-3">{{'GENERAL.STATUSES.EDIT' | translate}} :
|
||||
{{dataset.modified | date:"longDate"}}
|
||||
</div>
|
||||
<!-- <div class="d-flex mr-4">
|
||||
<div *ngIf="dmp.status" class="d-flex flex-row uppercase">
|
||||
<div class="d-flex mr-4">
|
||||
<div *ngIf="dataset.status" class="d-flex flex-row uppercase">
|
||||
<mat-icon class="status-icon">check</mat-icon>
|
||||
{{'DATASET-LISTING.COLUMNS.FINALIZED' | translate}}
|
||||
{{'TYPES.DATASET-STATUS.FINALISED' | translate}}
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4 pb-3">
|
||||
<button *ngIf="isAuthenticated()" (click)="cloneClicked(dataset)" 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)="openDmpSearchDialogue()" mat-mini-fab
|
||||
class="mr-3 actions-btn" matTooltip="{{'DMP-LISTING.ACTIONS.CLONE' | translate}}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="isDraftDataset(dataset) && isUserOwner" (click)="editClicked(dataset)"
|
||||
mat-mini-fab class="mr-3 d-flex justify-content-center align-items-center"
|
||||
mat-mini-fab class="mr-3 actions-btn"
|
||||
matTooltip="{{'DMP-LISTING.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="isDraftDataset(dataset) && isUserOwner" (click)="deleteClicked()" mat-mini-fab
|
||||
class="mr-3 d-flex justify-content-center align-items-center"
|
||||
matTooltip="{{'DMP-LISTING.ACTIONS.DELETE' | translate}}" matTooltipPosition="above">
|
||||
class="mr-3 actions-btn" matTooltip="{{'DMP-LISTING.ACTIONS.DELETE' | translate}}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
|
||||
</button>
|
||||
<!-- <button *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus" mat-mini-fab (click)="createOrUpdate(dmp.id)"
|
||||
class="mr-3 d-flex justify-content-center align-items-center">
|
||||
<mat-icon class="mat-mini-fab-icon" matTooltip="{{'DMP-OVERVIEW.LOCK' | translate}}"
|
||||
matTooltipPosition="above">lock_outline
|
||||
</mat-icon>
|
||||
</button> -->
|
||||
</div>
|
||||
<div class="row header">{{'DATASET-LISTING.TOOLTIP.PART-OF' | translate}}</div>
|
||||
<div class="row ">
|
||||
<button class="dmp-btn">
|
||||
<button class="dmp-btn" (click)="dmpClicked(dataset.dmp.id)">
|
||||
<div class="dmp-btn-label">
|
||||
{{ 'DATASET-LISTING.TOOLTIP.DMP-FOR' | translate }}: {{ dataset.datasetTemplate.label }}
|
||||
</div>
|
||||
|
@ -85,17 +69,16 @@
|
|||
</div>
|
||||
|
||||
<div class="row header">{{'DMP-OVERVIEW.GRANT' | translate}}</div>
|
||||
<div class="row dmp-label">Grant label</div>
|
||||
<!-- <div class="row dmp-label">{{ dataset.grant.label }}</div> -->
|
||||
<div class="row dataset-label">{{ dataset.grant.label }}</div>
|
||||
<div class="row header">{{'DMP-OVERVIEW.RESEARCHERS' | translate}}</div>
|
||||
<div class="row">
|
||||
<!-- <div *ngFor="let researcher of dataset.dmp.researchers; let last = last">
|
||||
<a href="{{getOrcidPath() + researcher.id }}" target="blank" class="researcher">
|
||||
<div *ngFor="let researcher of researchers; let last = last">
|
||||
<a href="{{ getOrcidPath() + researcher.id }}" target="blank" class="researcher">
|
||||
<div class="id-btn"> </div>
|
||||
<div *ngIf="!last">{{ researcher.name }}, </div>
|
||||
<div *ngIf="last">{{ researcher.name }}</div>
|
||||
</a>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row header">{{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}}</div>
|
||||
|
@ -104,31 +87,9 @@
|
|||
</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">
|
||||
<p class="doi-label">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}</p>
|
||||
<div class="doi-panel">
|
||||
<p *ngIf="!hasDoi(dmp)" class="mb-0 ml-3">
|
||||
<textarea #doi class="doi-txt">{{ dmp.doi }}</textarea>
|
||||
</p>
|
||||
<div class="d-flex justify-content-end">
|
||||
<button (click)="copyDoi(doi)" mat-mini-fab
|
||||
class="mr-2 d-flex justify-content-center align-items-center"
|
||||
matTooltip="{{'DMP-LISTING.ACTIONS.CLONE' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
|
||||
</button>
|
||||
<button mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center"
|
||||
matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}"
|
||||
matTooltipPosition="above">
|
||||
<a [href]="createDoiLink(dmp.doi)" class="doi-link" target="_blank">
|
||||
<mat-icon class="mat-mini-fab-icon">launch</mat-icon>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="frame mb-3 pt-4 pl-3 pr-5 pb-1">
|
||||
<!-- <div *ngIf="!dmp.status && isDraftDmp(dmp) && isUserOwner">
|
||||
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(dmp)">
|
||||
<!-- <div *ngIf="!dataset.status && isDraftDataset(dataset) && isUserOwner">
|
||||
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(dataset)">
|
||||
<button mat-mini-fab class="finalize-btn">
|
||||
<mat-icon class="mat-mini-fab-icon">check</mat-icon>
|
||||
</button>
|
||||
|
@ -138,60 +99,38 @@
|
|||
<hr class="hr-line">
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- <div *ngIf="hasDoi(dmp) && isFinalizedDmp(dmp) && !this.isPublicView && isUserOwner"
|
||||
(click)="getDoi(dmp)" 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">archive</mat-icon>
|
||||
</button>
|
||||
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.DEPOSIT' | translate }}</p>
|
||||
</div> -->
|
||||
<!-- <div class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
|
||||
<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>
|
||||
</div> -->
|
||||
<!-- <div class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center" *ngIf="isUserOwner"
|
||||
(click)="newVersion(dmp.id, dmp.label)">
|
||||
<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>
|
||||
</div> -->
|
||||
<!-- <div *ngIf="!dataset.public && showPublishButton(dmp) && isUserOwner"
|
||||
class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center" (click)="publish(dmp.id)">
|
||||
<button mat-mini-fab class="frame-btn">
|
||||
<mat-icon class="mat-mini-fab-icon">public</mat-icon>
|
||||
</button>
|
||||
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.MAKE-PUBLIC' | translate }}</p>
|
||||
</div>
|
||||
<mat-menu #exportMenu="matMenu" xPosition="before">
|
||||
<button mat-menu-item (click)="downloadPDF(dmp.id)">
|
||||
<button mat-menu-item (click)="downloadPDF(dataset.id)">
|
||||
<i class="fa fa-file-pdf-o pr-2"></i>
|
||||
<span>{{'GENERAL.FILE-TYPES.PDF' | translate}}</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="downloadDocx(dmp.id)">
|
||||
<button mat-menu-item (click)="downloadDocx(dataset.id)">
|
||||
<i class="fa fa-file-word-o pr-2"></i>
|
||||
<span>{{'GENERAL.FILE-TYPES.DOC' | translate}}</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="downloadXml(dmp.id)">
|
||||
<button mat-menu-item (click)="downloadXml(dataset.id)">
|
||||
<i class="fa fa-file-code-o pr-2"></i>
|
||||
<span>{{'GENERAL.FILE-TYPES.XML' | translate}}</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="downloadJson(dmp.id)">
|
||||
<button mat-menu-item (click)="downloadJson(dataset.id)">
|
||||
<i class="fa fa-file-o pr-2"></i>
|
||||
<span>{{'GENERAL.FILE-TYPES.JSON' | translate}}</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div> -->
|
||||
<!-- <div class="frame mb-3 pt-4 pl-3 pr-3 pb-1">
|
||||
</div>
|
||||
<div class="frame mb-3 pt-4 pl-3 pr-3 pb-1">
|
||||
<div class="row ml-0 mr-0 pl-4 pb-3">
|
||||
<p class="header">{{ 'DATASET-OVERVIEW.DATASET-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 user of dataset.users" 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>
|
||||
|
@ -204,19 +143,18 @@
|
|||
<p class="authors-role">{{ roleDisplay(user) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button *ngIf="isUserOwner && !dmp.status && user.role"
|
||||
(click)="removeCollaborator(user.id)"
|
||||
<button *ngIf="isUserOwner && !dataset.status && user.role"
|
||||
class="remove-btn">{{ 'GENERAL.CONFIRMATION-DIALOG.ACTIONS.REMOVE' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="isUserOwner" (click)="openShareDialog(dmp.id,dmp.label)"
|
||||
<div *ngIf="isUserOwner" (click)="openShareDialog(dataset.dmp.id, dataset.dmp.label)"
|
||||
class="row mt-3 mb-3 d-flex align-items-center justify-content-center">
|
||||
<button mat-raised-button class="invite-btn">
|
||||
<mat-icon>group_add</mat-icon>
|
||||
{{'DMP-LISTING.ACTIONS.INVITE-SHORT' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.mat-mini-fab:hover {
|
||||
.actions-btn:hover {
|
||||
background-color: #129D99;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
@ -139,6 +139,7 @@
|
|||
|
||||
.dataset-label {
|
||||
font-weight: bold;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.uppercase {
|
||||
|
@ -149,14 +150,13 @@
|
|||
font-size: 0.875em;
|
||||
color: #008887;
|
||||
padding-right: 0.5em;
|
||||
align-self: center;
|
||||
|
||||
align-self: center;;
|
||||
}
|
||||
|
||||
.header {
|
||||
opacity: 0.6;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.25em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.dataset-label, .header {
|
||||
|
@ -262,7 +262,7 @@
|
|||
|
||||
// ********CENTER ELEMENTS********
|
||||
|
||||
.mat-mini-fab, .mat-mini-fab-icon,
|
||||
.mat-mini-fab, .mat-mini-fab-icon, .actions-btn,
|
||||
.status-icon, .dataset-logo, .frame-btn, .finalize-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
@ -19,6 +19,15 @@ import { Location } from '@angular/common';
|
|||
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
|
||||
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
|
||||
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
|
||||
import * as FileSaver from 'file-saver';
|
||||
import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation.component';
|
||||
import { DatasetWizardEditorModel } from '../dataset-wizard/dataset-wizard-editor.model';
|
||||
import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { DatasetCopyDialogueComponent } from '../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component';
|
||||
import { DmpService } from '@app/core/services/dmp/dmp.service';
|
||||
import { ResearcherModel } from '@app/core/model/researcher/researcher';
|
||||
import { LockService } from '@app/core/services/lock/lock.service';
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -29,6 +38,7 @@ import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog
|
|||
export class DatasetOverviewComponent extends BaseComponent implements OnInit {
|
||||
|
||||
dataset: DatasetOverviewModel;
|
||||
datasetWizardModel: DatasetWizardEditorModel;
|
||||
isNew = true;
|
||||
isFinalized = false;
|
||||
isPublicView = true;
|
||||
|
@ -37,6 +47,8 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
|
|||
isUserOwner: boolean;
|
||||
expand = false;
|
||||
hasDOIToken = false;
|
||||
researchers: ResearcherModel[];
|
||||
lockStatus: Boolean;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
|
@ -50,7 +62,10 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
|
|||
private configurationService: ConfigurationService,
|
||||
private oauth2DialogService: Oauth2DialogService,
|
||||
private userService: UserService,
|
||||
private location: Location
|
||||
private dmpService: DmpService,
|
||||
private location: Location,
|
||||
private datasetWizardService: DatasetWizardService,
|
||||
private lockService: LockService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -69,7 +84,12 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
|
|||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(data => {
|
||||
this.dataset = data;
|
||||
// this.checkLockStatus(this.dataset.id);
|
||||
this.getDmpResearchers();
|
||||
this.datasetWizardService.getSingle(this.dataset.id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(data => {
|
||||
this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data);
|
||||
});
|
||||
this.checkLockStatus(this.dataset.id);
|
||||
this.setIsUserOwner();
|
||||
const breadCrumbs = [];
|
||||
breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DATASET-DESCRIPTIONS'), url: "/datasets" });
|
||||
|
@ -92,7 +112,12 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
|
|||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(data => {
|
||||
this.dataset = data;
|
||||
// this.checkLockStatus(this.dataset.id);
|
||||
this.getDmpResearchers();
|
||||
this.datasetWizardService.getSingle(this.dataset.id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(data => {
|
||||
this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data);
|
||||
});
|
||||
this.checkLockStatus(this.dataset.id);
|
||||
this.setIsUserOwner();
|
||||
const breadCrumbs = [];
|
||||
breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC DATASETS'), url: "/explore" });
|
||||
|
@ -110,112 +135,241 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
onFetchingDeletedCallbackError(redirectRoot: string) {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.DELETED-DATASET'), SnackBarNotificationLevel.Error);
|
||||
this.router.navigate([redirectRoot]);
|
||||
checkLockStatus(id: string){
|
||||
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(lockStatus => this.lockStatus = lockStatus);
|
||||
}
|
||||
|
||||
onFetchingForbiddenCallbackError(redirectRoot: string) {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.FORBIDEN-DATASET'), SnackBarNotificationLevel.Error);
|
||||
this.router.navigate([redirectRoot]);
|
||||
onFetchingDeletedCallbackError(redirectRoot: string) {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.DELETED-DATASET'), SnackBarNotificationLevel.Error);
|
||||
this.router.navigate([redirectRoot]);
|
||||
}
|
||||
|
||||
|
||||
onFetchingForbiddenCallbackError(redirectRoot: string) {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.FORBIDEN-DATASET'), SnackBarNotificationLevel.Error);
|
||||
this.router.navigate([redirectRoot]);
|
||||
}
|
||||
|
||||
goBack(): void {
|
||||
this.location.back();
|
||||
}
|
||||
this.location.back();
|
||||
}
|
||||
|
||||
getDmpResearchers() {
|
||||
this.dmpService.getSingle(this.dataset.dmp.id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(data => {
|
||||
this.researchers = data.researchers;
|
||||
});
|
||||
}
|
||||
|
||||
setIsUserOwner() {
|
||||
if (this.dataset) {
|
||||
const principal: Principal = this.authentication.current();
|
||||
if (principal) this.isUserOwner = principal.id === this.dataset.users.find(x => x.role === Role.Owner).id;
|
||||
}
|
||||
if (this.dataset) {
|
||||
const principal: Principal = this.authentication.current();
|
||||
if (principal) this.isUserOwner = principal.id === this.dataset.users.find(x => x.role === Role.Owner).id;
|
||||
}
|
||||
}
|
||||
|
||||
isUserAuthor(userId: string): boolean {
|
||||
const principal: Principal = this.authentication.current();
|
||||
return userId === principal.id;
|
||||
}
|
||||
|
||||
isUserDatasetRelated() {
|
||||
const principal: Principal = this.authentication.current();
|
||||
let isRelated: boolean = false;
|
||||
if (this.dataset && principal) {
|
||||
this.dataset.users.forEach(element => {
|
||||
if (element.id === principal.id) {
|
||||
isRelated = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
return isRelated;
|
||||
const principal: Principal = this.authentication.current();
|
||||
let isRelated: boolean = false;
|
||||
if (this.dataset && principal) {
|
||||
this.dataset.users.forEach(element => {
|
||||
if (element.id === principal.id) {
|
||||
isRelated = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
return isRelated;
|
||||
}
|
||||
|
||||
roleDisplayFromList(value: UserInfoListingModel[]) {
|
||||
const principal: Principal = this.authentication.current();
|
||||
let role: number;
|
||||
if (principal) {
|
||||
value.forEach(element => {
|
||||
if (principal.id === element.id) {
|
||||
role = element.role;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (role === Role.Owner) {
|
||||
return this.translate.instant('DMP-LISTING.OWNER');
|
||||
} else if (role === Role.Member) {
|
||||
return this.translate.instant('DMP-LISTING.MEMBER');
|
||||
} else {
|
||||
return this.translate.instant('DMP-LISTING.OWNER');
|
||||
}
|
||||
}
|
||||
|
||||
public isAuthenticated(): boolean {
|
||||
return !(!this.authentication.current());
|
||||
}
|
||||
|
||||
cloneClicked(dataset: DatasetOverviewModel) {
|
||||
this.router.navigate(['/datasets/clone/' + dataset.id]);
|
||||
}
|
||||
|
||||
isDraftDataset(dataset: DatasetOverviewModel) {
|
||||
return dataset.status == DatasetStatus.Draft;
|
||||
}
|
||||
|
||||
editClicked(dataset: DatasetOverviewModel) {
|
||||
this.router.navigate(['/datasets/edit/' + dataset.id]);
|
||||
}
|
||||
|
||||
deleteClicked() {
|
||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||
maxWidth: '300px',
|
||||
data: {
|
||||
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
|
||||
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'),
|
||||
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
|
||||
isDeleteConfirmation: true
|
||||
}
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||
if (result) {
|
||||
this.datasetService.delete(this.dataset.id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
complete => { this.onCallbackSuccess() },
|
||||
error => this.onDeleteCallbackError(error)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onCallbackSuccess(): void {
|
||||
this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
|
||||
this.router.navigate(['/datasets']);
|
||||
}
|
||||
|
||||
onDeleteCallbackError(error) {
|
||||
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
|
||||
roleDisplay(value: UserInfoListingModel) {
|
||||
if (value.role === Role.Owner) {
|
||||
return this.translate.instant('DMP-LISTING.OWNER');
|
||||
} else if (value.role === Role.Member) {
|
||||
return this.translate.instant('DMP-LISTING.MEMBER');
|
||||
} else {
|
||||
return this.translate.instant('DMP-LISTING.OWNER');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
roleDisplayFromList(value: UserInfoListingModel[]) {
|
||||
const principal: Principal = this.authentication.current();
|
||||
let role: number;
|
||||
if (principal) {
|
||||
value.forEach(element => {
|
||||
if (principal.id === element.id) {
|
||||
role = element.role;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (role === Role.Owner) {
|
||||
return this.translate.instant('DMP-LISTING.OWNER');
|
||||
} else if (role === Role.Member) {
|
||||
return this.translate.instant('DMP-LISTING.MEMBER');
|
||||
} else {
|
||||
return this.translate.instant('DMP-LISTING.OWNER');
|
||||
}
|
||||
}
|
||||
|
||||
openShareDialog(rowId: any, rowName: any) {
|
||||
const dialogRef = this.dialog.open(DmpInvitationDialogComponent, {
|
||||
restoreFocus: false,
|
||||
data: {
|
||||
dmpId: rowId,
|
||||
dmpName: rowName
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public isAuthenticated(): boolean {
|
||||
return !(!this.authentication.current());
|
||||
}
|
||||
|
||||
isDraftDataset(dataset: DatasetOverviewModel) {
|
||||
return dataset.status == DatasetStatus.Draft;
|
||||
}
|
||||
|
||||
isFinalizedDataset(dataset: DatasetOverviewModel) {
|
||||
return dataset.status == DatasetStatus.Finalized;
|
||||
}
|
||||
|
||||
editClicked(dataset: DatasetOverviewModel) {
|
||||
if (dataset.public) {
|
||||
this.router.navigate(['/datasets/publicEdit/' + dataset.id]);
|
||||
} else {
|
||||
this.router.navigate(['/datasets/edit/' + dataset.id]);
|
||||
}
|
||||
}
|
||||
|
||||
deleteClicked() {
|
||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||
maxWidth: '300px',
|
||||
data: {
|
||||
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
|
||||
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'),
|
||||
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
|
||||
isDeleteConfirmation: true
|
||||
}
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||
if (result) {
|
||||
this.datasetService.delete(this.dataset.id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
complete => { this.onCallbackSuccess() },
|
||||
error => this.onDeleteCallbackError(error)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dmpClicked(dmpId: String) {
|
||||
this.router.navigate(['/plans/overview/' + dmpId]);
|
||||
}
|
||||
|
||||
onCallbackSuccess(): void {
|
||||
this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
|
||||
this.router.navigate(['/datasets']);
|
||||
}
|
||||
|
||||
onDeleteCallbackError(error) {
|
||||
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
|
||||
}
|
||||
|
||||
public getOrcidPath(): string {
|
||||
return this.configurationService.orcidPath;
|
||||
return this.configurationService.orcidPath;
|
||||
}
|
||||
|
||||
// showPublishButton(dataset: DatasetOverviewModel) {
|
||||
// return this.isFinalizedDmp(dmp) && !dmp.isPublic && this.hasPublishButton;
|
||||
// }
|
||||
|
||||
downloadPDF(id: string) {
|
||||
this.datasetService.downloadPDF(id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(response => {
|
||||
const blob = new Blob([response.body], { type: 'application/pdf' });
|
||||
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
|
||||
|
||||
FileSaver.saveAs(blob, filename);
|
||||
});
|
||||
}
|
||||
|
||||
downloadDocx(id: string) {
|
||||
this.datasetService.downloadDocx(id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(response => {
|
||||
const blob = new Blob([response.body], { type: 'application/msword' });
|
||||
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
|
||||
|
||||
FileSaver.saveAs(blob, filename);
|
||||
});
|
||||
}
|
||||
|
||||
downloadXml(id: string) {
|
||||
this.datasetService.downloadXML(id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(response => {
|
||||
const blob = new Blob([response.body], { type: 'application/xml' });
|
||||
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
|
||||
|
||||
FileSaver.saveAs(blob, filename);
|
||||
});
|
||||
}
|
||||
|
||||
downloadJson(id: string) {
|
||||
this.datasetService.downloadJson(id)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(response => {
|
||||
const blob = new Blob([response.body], { type: 'application/json' });
|
||||
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
|
||||
FileSaver.saveAs(blob, filename);
|
||||
})
|
||||
}
|
||||
|
||||
getFilenameFromContentDispositionHeader(header: string): string {
|
||||
const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g);
|
||||
|
||||
const matches = header.match(regex);
|
||||
let filename: string;
|
||||
for (let i = 0; i < matches.length; i++) {
|
||||
const match = matches[i];
|
||||
if (match.includes('filename="')) {
|
||||
filename = match.substring(10, match.length - 1);
|
||||
break;
|
||||
} else if (match.includes('filename=')) {
|
||||
filename = match.substring(9);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
openDmpSearchDialogue() {
|
||||
const formControl = new FormControl();
|
||||
const dialogRef = this.dialog.open(DatasetCopyDialogueComponent, {
|
||||
width: '500px',
|
||||
restoreFocus: false,
|
||||
data: {
|
||||
formControl: formControl,
|
||||
datasetId: this.dataset.id,
|
||||
datasetProfileId: this.datasetWizardModel.profile,
|
||||
datasetProfileExist: false,
|
||||
confirmButton: this.language.instant('DATASET-WIZARD.DIALOGUE.COPY'),
|
||||
cancelButton: this.language.instant('DATASET-WIZARD.DIALOGUE.CANCEL')
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed))
|
||||
.subscribe(result => {
|
||||
if (result && result.datasetProfileExist) {
|
||||
const newDmpId = result.formControl.value.id
|
||||
this.router.navigate(['/datasets/copy/' + result.datasetId], { queryParams: { newDmpId: newDmpId } });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-
|
|||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
|
||||
import { AddOrganizationComponent } from './editor/add-organization/add-organization.component';
|
||||
import { AddCostComponent } from './editor/cost-editor/add-cost/add-cost.component';
|
||||
import { CostListingComponent } from './editor/cost-editor/cost-listing/cost-listing.component';
|
||||
import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
|
@ -71,7 +73,10 @@ import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dial
|
|||
DatasetsTabComponent,
|
||||
DmpCloneComponent,
|
||||
AddOrganizationComponent,
|
||||
DmpCriteriaDialogComponent
|
||||
DmpCriteriaDialogComponent,
|
||||
AddOrganizationComponent,
|
||||
AddCostComponent,
|
||||
CostListingComponent
|
||||
],
|
||||
entryComponents: [
|
||||
DmpInvitationDialogComponent,
|
||||
|
@ -80,7 +85,9 @@ import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dial
|
|||
DmpFinalizeDialogComponent,
|
||||
DmpUploadDialogue,
|
||||
AddOrganizationComponent,
|
||||
DmpCriteriaDialogComponent
|
||||
DmpCriteriaDialogComponent,
|
||||
AddOrganizationComponent,
|
||||
AddCostComponent
|
||||
]
|
||||
})
|
||||
export class DmpModule { }
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<form *ngIf="formGroup" [formGroup]="formGroup">
|
||||
<h1 mat-dialog-title>{{'ADDEDITCOST-EDITOR.ADD-TITLE' | translate}}</h1>
|
||||
<div mat-dialog-content class="row">
|
||||
<mat-form-field class="col-12">
|
||||
<app-single-auto-complete [formControl]="formGroup.get('code')" placeholder="{{'ADDEDITCOST-EDITOR.CODE' | translate}}" [configuration]="currencyAutoCompleteConfiguration">
|
||||
</app-single-auto-complete>
|
||||
<mat-error *ngIf="formGroup.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="col-12">
|
||||
<input matInput formControlName="description" placeholder="{{'ADDEDITCOST-EDITOR.DESCRIPTION' | translate}}">
|
||||
<mat-error *ngIf="formGroup.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="col-12">
|
||||
<input matInput formControlName="title" placeholder="{{'ADDEDITCOST-EDITOR.TITLE' | translate}}" required>
|
||||
<mat-error *ngIf="formGroup.get('title').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="col-12">
|
||||
<input matInput formControlName="value" placeholder="{{'ADDEDITCOST-EDITOR.VALUE' | translate}}" type="number">
|
||||
<mat-error *ngIf="formGroup.get('value').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="ml-auto col-auto"><button mat-raised-button mat-dialog-close type="button">{{'ADDEDITCOST-EDITOR.ACTIONS.CANCEL' | translate}}</button></div>
|
||||
<div class="col-auto"><button mat-raised-button [disabled]="!isFormValid()" color="primary" (click)="addCost()" type="button">{{'ADDEDITCOST-EDITOR.ACTIONS.SAVE' | translate}}</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,60 @@
|
|||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { ExternalResearcherService } from '@app/core/services/external-sources/researcher/external-researcher.service';
|
||||
import { BaseComponent } from '@common/base/base.component';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { CostEditorModel } from './add-cost.model';
|
||||
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LocalFetchModel } from '@app/core/model/local-fetch/local-fetch.model';
|
||||
import { CurrencyService } from '@app/core/services/currency/currency.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-cost-component',
|
||||
templateUrl: 'add-cost.component.html',
|
||||
})
|
||||
export class AddCostComponent extends BaseComponent implements OnInit {
|
||||
|
||||
public formGroup: FormGroup;
|
||||
|
||||
currencyAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
|
||||
filterFn: this.searchCurrency.bind(this),
|
||||
initialItems: () => this.searchCurrency(''),
|
||||
displayFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||
titleFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||
valueAssign: (item) => JSON.stringify(item)
|
||||
};
|
||||
|
||||
constructor(
|
||||
private externalResearcherService: ExternalResearcherService,
|
||||
public dialogRef: MatDialogRef<AddCostComponent>,
|
||||
private currencyService: CurrencyService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any
|
||||
) { super(); }
|
||||
|
||||
ngOnInit(): void {
|
||||
const cost = new CostEditorModel();
|
||||
this.formGroup = cost.buildForm();
|
||||
}
|
||||
|
||||
send(value: any) {
|
||||
this.externalResearcherService.createResearcher(this.formGroup.value)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
null, null, () => this.dialogRef.close()
|
||||
);
|
||||
}
|
||||
|
||||
addCost() {
|
||||
this.dialogRef.close(this.formGroup.value);
|
||||
}
|
||||
|
||||
isFormValid() {
|
||||
return this.formGroup.valid;
|
||||
}
|
||||
|
||||
searchCurrency(like: string): Observable<LocalFetchModel[]> {
|
||||
return this.currencyService.get(like);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { ResearcherModel } from '@app/core/model/researcher/researcher';
|
||||
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
|
||||
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
|
||||
import { ValidationContext } from '@common/forms/validation/validation-context';
|
||||
import { OrganizationModel } from '@app/core/model/organisation/organization';
|
||||
import { CostModel } from '@app/core/model/dmp/cost';
|
||||
|
||||
export class CostEditorModel implements CostModel{
|
||||
public code: string;
|
||||
public description: string;
|
||||
public title: string;
|
||||
public value: number;
|
||||
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
|
||||
|
||||
fromModel(item: CostModel): CostEditorModel {
|
||||
this.code = item.code;
|
||||
this.description = item.description;
|
||||
this.title = item.title;
|
||||
this.value = item.value;
|
||||
return this;
|
||||
}
|
||||
|
||||
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
|
||||
if (context == null) { context = this.createValidationContext(); }
|
||||
const formGroup = new FormBuilder().group({
|
||||
code: [{ value: this.code, disabled: disabled }, context.getValidation('code').validators],
|
||||
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
|
||||
title: [{ value: this.title, disabled: disabled }, context.getValidation('title').validators],
|
||||
value: [{ value: this.value, disabled: disabled }, context.getValidation('value').validators]
|
||||
});
|
||||
|
||||
return formGroup;
|
||||
}
|
||||
|
||||
createValidationContext(): ValidationContext {
|
||||
const baseContext: ValidationContext = new ValidationContext();
|
||||
baseContext.validation.push({ key: 'code', validators: [] });
|
||||
baseContext.validation.push({ key: 'description', validators: [] });
|
||||
baseContext.validation.push({ key: 'title', validators: [BackendErrorValidator(this.validationErrorModel, 'title')] });
|
||||
baseContext.validation.push({ key: 'value', validators: [] });
|
||||
return baseContext;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<mat-card class="row listing-container">
|
||||
|
||||
<ng-template #costTemplate let-cost let-i="index">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<mat-form-field>
|
||||
<app-single-auto-complete [formControl]="cost.get('code')" placeholder="{{'ADDEDITCOST-EDITOR.CODE' | translate}}" [configuration]="currencyAutoCompleteConfiguration"></app-single-auto-complete>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="{{'ADDEDITCOST-EDITOR.DESCRIPTION' | translate}}" type="text" [formControl]="cost.get('description')">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="{{'ADDEDITCOST-EDITOR.TITLE' | translate}}" type="text" [formControl]="cost.get('title')">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="{{'ADDEDITCOST-EDITOR.VALUE' | translate}}" type="text" [formControl]="cost.get('value')">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row"*ngIf="cost.disabled">
|
||||
<div class=" ml-auto col-auto"><button type="button" mat-raised-button color="primary" (click)="switchEditMode(i)">Edit</button></div>
|
||||
<div class="col-auto"><button type="button" mat-raised-button color="red" (click)="removeCost(i)">Delete</button></div>
|
||||
</div>
|
||||
<div class="row"*ngIf="!cost.disabled">
|
||||
<div class=" ml-auto col-auto" *ngIf="!cost.disabled"><button type="button" mat-raised-button color="primary" (click)="switchEditMode(i)">Save</button></div>
|
||||
<div class="col-auto" *ngIf="!cost.disabled"><button type="button" mat-raised-button (click)="revertEdits(i)">Cancel</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<mat-card class="col-12 cost-element" *ngFor="let cost of form['controls']; let i = index">
|
||||
<ng-container *ngTemplateOutlet="costTemplate; context: { $implicit: cost, index: i }">
|
||||
</ng-container>
|
||||
</mat-card>
|
||||
</mat-card>
|
|
@ -0,0 +1,10 @@
|
|||
.listing-container {
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
|
||||
.cost-element {
|
||||
margin-bottom: 1em;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { BaseComponent } from '@common/base/base.component';
|
||||
import { FormArray, FormControl } from '@angular/forms';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { CostModel } from '@app/core/model/dmp/cost';
|
||||
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
||||
import { CurrencyService } from '@app/core/services/currency/currency.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LocalFetchModel } from '@app/core/model/local-fetch/local-fetch.model';
|
||||
import { CostEditorModel } from '../add-cost/add-cost.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cost-listing',
|
||||
templateUrl: './cost-listing.component.html',
|
||||
styleUrls: ['./cost-listing.component.scss']
|
||||
})
|
||||
export class CostListingComponent extends BaseComponent implements OnInit {
|
||||
|
||||
@Input() form: FormArray;
|
||||
|
||||
private cost: CostEditorModel[] = [];
|
||||
|
||||
currencyAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
|
||||
filterFn: this.searchCurrency.bind(this),
|
||||
initialItems: () => this.searchCurrency(''),
|
||||
displayFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||
titleFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||
valueAssign: (item) => JSON.stringify(item)
|
||||
};
|
||||
|
||||
constructor(
|
||||
private currencyService: CurrencyService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
searchCurrency(like: string): Observable<LocalFetchModel[]> {
|
||||
return this.currencyService.get(like);
|
||||
}
|
||||
|
||||
switchEditMode(event: number) {
|
||||
const control = this.form.at(event);
|
||||
if (control.disabled) {
|
||||
this.cost[event] = control.value;
|
||||
control.enable();
|
||||
} else {
|
||||
control.disable();
|
||||
}
|
||||
}
|
||||
|
||||
removeCost(event: number) {
|
||||
this.form.removeAt(event);
|
||||
}
|
||||
|
||||
revertEdits(event: number) {
|
||||
this.form.at(event).setValue(this.cost[event]);
|
||||
this.form.at(event).disable();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +1,53 @@
|
|||
import { ValidationContext } from '@common/forms/validation/validation-context';
|
||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
|
||||
import { CostModel } from '@app/core/model/dmp/cost';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { CostEditorModel } from '../cost-editor/add-cost/add-cost.model';
|
||||
|
||||
export class ExtraPropertiesFormModel {
|
||||
public language: string;
|
||||
public license: string;
|
||||
public visible: boolean;
|
||||
public publicDate: Date;
|
||||
public contact: string;
|
||||
public costs: CostEditorModel[] = [];
|
||||
|
||||
fromModel(item: any): ExtraPropertiesFormModel {
|
||||
this.language = item.language;
|
||||
this.license = item.license;
|
||||
this.visible = item.visible;
|
||||
this.publicDate = item.publicDate;
|
||||
this.contact = item.contact;
|
||||
if (!isNullOrUndefined(item.costs)) {
|
||||
(<any[]>item.costs).forEach(element => {
|
||||
this.costs.push(new CostEditorModel().fromModel(element));
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
|
||||
if (context == null) { context = this.createValidationContext(); }
|
||||
|
||||
const formBuilder = new FormBuilder();
|
||||
const formGroup = new FormBuilder().group({
|
||||
language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators],
|
||||
license: [{ value: this.license, disabled: disabled }, context.getValidation('license').validators],
|
||||
visible: [{ value: this.visible, disabled: disabled }, context.getValidation('visible').validators],
|
||||
publicDate: [{ value: this.publicDate, disabled: disabled }, context.getValidation('publicDate').validators]
|
||||
publicDate: [{ value: this.publicDate, disabled: disabled }, context.getValidation('publicDate').validators],
|
||||
contact: [{ value: this.contact, disabled: disabled }, context.getValidation('contact').validators],
|
||||
// costs: [{ value: this.costs, disabled: disabled }, context.getValidation('costs').validators]
|
||||
});
|
||||
|
||||
const costArray = new Array<FormGroup>();
|
||||
//if (this.externalDatasets && this.externalDatasets.length > 0) {
|
||||
this.costs.forEach(item => {
|
||||
costArray.push(item.buildForm(context.getValidation('costs').descendantValidations, true));
|
||||
});
|
||||
// } else {
|
||||
// //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
|
||||
// }
|
||||
formGroup.addControl('costs', formBuilder.array(costArray));
|
||||
return formGroup;
|
||||
}
|
||||
|
||||
|
@ -34,6 +57,8 @@ export class ExtraPropertiesFormModel {
|
|||
baseContext.validation.push({ key: 'license', validators: [] });
|
||||
baseContext.validation.push({ key: 'visible', validators: [] });
|
||||
baseContext.validation.push({ key: 'publicDate', validators: [] });
|
||||
baseContext.validation.push({ key: 'contact', validators: [] });
|
||||
baseContext.validation.push({ key: 'costs', validators: [] });
|
||||
return baseContext;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
<app-single-auto-complete [formControl]="formGroup.get('extraProperties').get('license')" placeholder="{{'DMP-EDITOR.FIELDS.LICENSE' | translate}}" [configuration]="licenseAutoCompleteConfiguration">
|
||||
</app-single-auto-complete>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('backendError')">
|
||||
{{formGroup.get('extraProperties').get('language').getError('backendError').message}}</mat-error>
|
||||
{{formGroup.get('extraProperties').get('license').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('required')">
|
||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
|
@ -117,13 +117,36 @@
|
|||
<input matInput [matDatepicker]="picker" [formControl]="formGroup.get('extraProperties').get('publicDate')" placeholder="{{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}">
|
||||
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('visible').hasError('backendError')">
|
||||
{{formGroup.get('extraProperties').get('visible').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('visible').hasError('required')">
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('publicDate').hasError('backendError')">
|
||||
{{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('publicDate').hasError('required')">
|
||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
|
||||
</div>
|
||||
<div class="row pt-3">
|
||||
<mat-form-field class="col-sm-12 col-md-8">
|
||||
<!-- <app-multiple-auto-complete [formControl]="formGroup.get('extraProperties').get('language')" placeholder="{{'DMP-EDITOR.FIELDS.RESEARCHERS' | translate}}" [configuration]="researchersAutoCompleteConfiguration">
|
||||
</app-multiple-auto-complete> -->
|
||||
<mat-select [formControl]="formGroup.get('extraProperties').get('contact')" placeholder="{{'DMP-EDITOR.FIELDS.CONTACT' | translate}}">
|
||||
<mat-option *ngFor="let vis of getAssociates()" [value]="vis.id">
|
||||
{{vis.name | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('contact').hasError('backendError')">
|
||||
{{formGroup.get('extraProperties').get('contact').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="formGroup.get('extraProperties').get('contact').hasError('required')">
|
||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
|
||||
</div>
|
||||
<div class="row pt-3">
|
||||
<mat-label class="col-12 cost-placeholder">Costs</mat-label>
|
||||
<app-cost-listing class="col-12" [form] = "formGroup.get('extraProperties').get('costs')"></app-cost-listing>
|
||||
<button class="col-12 cost-add" matSuffix class="input-btn" type="button" (click)="addCost($event)">
|
||||
<mat-icon class="icon-btn">add_circle</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<mat-form-field class="col-sm-12 col-md-8">
|
||||
<app-single-auto-complete [required]="false" [formControl]="formGroup.get('profile')" placeholder="{{'DMP-EDITOR.FIELDS.TEMPLATE' | translate}}" [configuration]="dmpProfileAutoCompleteConfiguration">
|
||||
|
|
|
@ -37,3 +37,11 @@
|
|||
::ng-deep .mat-form-field-appearance-legacy .mat-form-field-wrapper {
|
||||
padding-bottom: 1.25em;
|
||||
}
|
||||
|
||||
.cost-placeholder {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cost-add {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { FormGroup, FormArray } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
|
||||
import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile';
|
||||
|
@ -26,6 +26,8 @@ import { ConfigurationService } from '@app/core/services/configuration/configura
|
|||
import { LanguageInfoService } from '@app/core/services/culture/language-info-service';
|
||||
import { LanguageInfo } from '@app/core/model/language-info';
|
||||
import { LicenseCriteria } from '@app/core/query/license/license-criteria';
|
||||
import { AddCostComponent } from '../cost-editor/add-cost/add-cost.component';
|
||||
import { CostEditorModel } from '../cost-editor/add-cost/add-cost.model';
|
||||
|
||||
interface Visible {
|
||||
value: boolean;
|
||||
|
@ -253,4 +255,27 @@ export class GeneralTabComponent extends BaseComponent implements OnInit {
|
|||
getLanguageInfos(): LanguageInfo[] {
|
||||
return this.languageInfoService.getLanguageInfoValues();
|
||||
}
|
||||
|
||||
getAssociates(): any[] {
|
||||
let associates: any[] = [];
|
||||
//associates = (this.formGroup.get('researchers').value as any[]);
|
||||
associates = associates.concat(this.formGroup.get('associatedUsers').value);
|
||||
return associates;
|
||||
}
|
||||
|
||||
addCost(event: MouseEvent) {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(AddCostComponent, {
|
||||
data: this.formGroup.get('extraProperties').get('costs')
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||
if (result) {
|
||||
const costsArray = this.formGroup.get('extraProperties').get('costs').value || [];
|
||||
costsArray.push(result);
|
||||
let costeditModel: CostEditorModel = new CostEditorModel();
|
||||
costeditModel = costeditModel.fromModel(result);
|
||||
(<FormArray>this.formGroup.get('extraProperties').get('costs')).push(costeditModel.buildForm(null, true));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,15 +26,9 @@
|
|||
{{'DMP-OVERVIEW.PRIVATE' | translate}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex mr-4">
|
||||
<div *ngIf="lockStatus" class="d-flex flex-row">
|
||||
<mat-icon class="status-icon">lock_outline</mat-icon>
|
||||
{{'DMP-OVERVIEW.LOCKED' | translate}}
|
||||
</div>
|
||||
<div *ngIf="!lockStatus" class="d-flex flex-row">
|
||||
<mat-icon class="status-icon">lock_open</mat-icon>
|
||||
{{'DMP-OVERVIEW.UNLOCKED' | translate}}
|
||||
</div>
|
||||
<div *ngIf="lockStatus" class="d-flex flex-row mr-4">
|
||||
<mat-icon class="status-icon">lock_outline</mat-icon>
|
||||
{{'DMP-OVERVIEW.LOCKED' | translate}}
|
||||
</div>
|
||||
<button class="d-flex mr-4 version-btn label2-txt"
|
||||
(click)="viewVersions(dmp.groupId, dmp.label)">
|
||||
|
@ -46,7 +40,7 @@
|
|||
<div class="d-flex mr-4">
|
||||
<div *ngIf="dmp.status" class="d-flex flex-row uppercase">
|
||||
<mat-icon class="status-icon">check</mat-icon>
|
||||
{{'DATASET-LISTING.COLUMNS.FINALIZED' | translate}}
|
||||
{{'TYPES.DMP.FINALISED' | translate}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,22 +50,16 @@
|
|||
matTooltip="{{'DMP-LISTING.ACTIONS.CLONE' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="isDraftDmp(dmp) && isUserOwner" (click)="editClicked(dmp)" mat-mini-fab
|
||||
<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">
|
||||
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="isDraftDmp(dmp) && isUserOwner" (click)="deleteClicked()" mat-mini-fab
|
||||
<button *ngIf="isDraftDmp(dmp) && 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">
|
||||
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus" mat-mini-fab (click)="createOrUpdate(dmp.id)"
|
||||
class="mr-3 d-flex justify-content-center align-items-center">
|
||||
<mat-icon class="mat-mini-fab-icon" matTooltip="{{'DMP-OVERVIEW.LOCK' | translate}}"
|
||||
matTooltipPosition="above">lock_outline
|
||||
</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row header">{{'DMP-OVERVIEW.GRANT' | translate}}</div>
|
||||
<div class="row dmp-label">{{ dmp.grant.label }}</div>
|
||||
|
@ -141,7 +129,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="frame mb-3 pt-4 pl-3 pr-5 pb-1">
|
||||
<div *ngIf="!dmp.status && isDraftDmp(dmp) && isUserOwner">
|
||||
<div *ngIf="!dmp.status && isDraftDmp(dmp) && isUserOwner && !lockStatus">
|
||||
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(dmp)">
|
||||
<button mat-mini-fab class="finalize-btn">
|
||||
<mat-icon class="mat-mini-fab-icon">check</mat-icon>
|
||||
|
|
|
@ -161,7 +161,7 @@
|
|||
.header {
|
||||
opacity: 0.6;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.25em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.dmp-label, .header {
|
||||
|
|
|
@ -52,7 +52,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
isUserOwner: boolean;
|
||||
expand = false;
|
||||
hasDOIToken = false;
|
||||
lock: LockModel;
|
||||
lockStatus: Boolean;
|
||||
textMessage: any;
|
||||
|
||||
|
@ -183,11 +182,12 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
}
|
||||
|
||||
datasetClicked(datasetId: String) {
|
||||
if (this.isPublicView) {
|
||||
this.router.navigate(['/datasets/publicEdit/' + datasetId]);
|
||||
} else {
|
||||
this.router.navigate(['/datasets/edit/' + datasetId]);
|
||||
}
|
||||
// if (this.isPublicView) {
|
||||
// this.router.navigate(['/datasets/publicEdit/' + datasetId]);
|
||||
// } else {
|
||||
// this.router.navigate(['/datasets/edit/' + datasetId]);
|
||||
// }
|
||||
this.router.navigate(['/datasets/overview/' + datasetId]);
|
||||
}
|
||||
|
||||
datasetsClicked(dmpId: String) {
|
||||
|
@ -609,24 +609,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
createOrUpdate(id: string): void {
|
||||
if (!this.lockStatus) {
|
||||
this.lock = new LockModel(id, this.getUserFromDMP());
|
||||
|
||||
this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => {
|
||||
this.lock.id = Guid.parse(result);
|
||||
this.checkLockStatus(id);
|
||||
// interval(this.configurationService.lockInterval).pipe(takeUntil(this._destroyed)).subscribe(() => this.pumpLock());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// private pumpLock() {
|
||||
// this.lock.touchedAt = new Date();
|
||||
// this.lockStatus = true;
|
||||
// this.lockService.createOrUpdate(this.lock).pipe(takeUntil(this._destroyed)).subscribe(async result => this.lock.id = Guid.parse(result));
|
||||
// }
|
||||
|
||||
|
||||
// advancedClicked() {
|
||||
// const dialogRef = this.dialog.open(ExportMethodDialogComponent, {
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
"LOGIN": "Login",
|
||||
"DMP-OVERVIEW": "DMP Overview",
|
||||
"DMP-EDIT": "Edit DMP",
|
||||
"DATASET-OVERVIEW": "Dataset Overview",
|
||||
"DATASET-EDIT": "Dataset View/Edit",
|
||||
"DMP-NEW-VERSION": "DMP New Version",
|
||||
"DMP-CLONE": "Clone DMP",
|
||||
|
@ -567,7 +568,7 @@
|
|||
}
|
||||
},
|
||||
"DATASET-OVERVIEW": {
|
||||
"DATASET-AUTHORS": "Dataset description Authors",
|
||||
"DATASET-AUTHORS": "Dataset description authors",
|
||||
"ERROR": {
|
||||
"DELETED-DATASET": "The requested dataset is deleted",
|
||||
"FORBIDEN-DATASET": "You are not allowed to access this dataset"
|
||||
|
@ -755,7 +756,8 @@
|
|||
"LANGUAGE": "Language",
|
||||
"LICENSE": "License",
|
||||
"VISIBILITY": "Visibility",
|
||||
"PUBLICATION": "Publication Date"
|
||||
"PUBLICATION": "Publication Date",
|
||||
"CONTACT": "Contact"
|
||||
},
|
||||
"ACTIONS": {
|
||||
"GO-TO-GRANT": "Go To DMP Grant",
|
||||
|
@ -1030,6 +1032,18 @@
|
|||
"CANCEL": "Cancel"
|
||||
}
|
||||
},
|
||||
"ADDEDITCOST-EDITOR": {
|
||||
"ADD-TITLE": "Add a Cost",
|
||||
"EDIT-TITLE": "Edit the Cost",
|
||||
"CODE": "Code",
|
||||
"DESCRIPTION": "Description",
|
||||
"TITLE": "Title",
|
||||
"VALUE": "Value",
|
||||
"ACTIONS": {
|
||||
"SAVE": "Save",
|
||||
"CANCEL": "Cancel"
|
||||
}
|
||||
},
|
||||
"DMP-WIZARD": {
|
||||
"FIRST-STEP": {
|
||||
"DMP": "DMP Editor",
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
"LOGIN": "Iniciar sesión",
|
||||
"DMP-OVERVIEW": "Resumen del PGD",
|
||||
"DMP-EDIT": "Editar el PGD",
|
||||
"DATASET-OVERVIEW": "Resumen del Dataset",
|
||||
"DATASET-EDIT": "Ver/Editar el Dataset",
|
||||
"DMP-NEW-VERSION": "Nueva versiónd del PGD",
|
||||
"DMP-CLONE": "Clonar el PGD",
|
||||
|
@ -565,7 +566,7 @@
|
|||
}
|
||||
},
|
||||
"DATASET-OVERVIEW": {
|
||||
"DATASET-AUTHORS": "Descripciones del Dataset Autores",
|
||||
"DATASET-AUTHORS": "Descripciones del dataset autores",
|
||||
"ERROR": {
|
||||
"DELETED-DATASET": "El Dataset solicitado está borrado",
|
||||
"FORBIDEN-DATASET": "No tiene permiso para acceder a esto Dataset"
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
"LOGIN": "Σύνδεση",
|
||||
"DMP-OVERVIEW": "Επισκόπηση Σχεδίου Διαχείρισης Δεδομένων",
|
||||
"DMP-EDIT": "Επεξεργασία Σχεδίου Διαχείρισης Δεδομένων",
|
||||
"DATASET-OVERVIEW": "Επισκόπηση Συνόλου Δεδομένων",
|
||||
"DATASET-EDIT": "Προβολή / Επεξεργασία Συνόλου Δεδομένων",
|
||||
"DMP-NEW-VERSION": "Νέα έκδοση Σχεδίου Διαχείρισης Δεδομένων",
|
||||
"DMP-CLONE": "Κλωνοποίηση Σχεδίου Διαχείρισης Δεδομένων",
|
||||
|
@ -566,7 +567,7 @@
|
|||
}
|
||||
},
|
||||
"DATASET-OVERVIEW": {
|
||||
"DATASET-AUTHORS": "Συγγραφείς Περιγραφής Δεδομένων",
|
||||
"DATASET-AUTHORS": "Συγγραφείς περιγραφής δεδομένων",
|
||||
"ERROR": {
|
||||
"DELETED-DATASET": "H επιλεγμένη Περιγραφή Δεδομένων θα διαγραφεί",
|
||||
"FORBIDEN-DATASET": "Δεν επιτρέπεται η πρόσβαση σε αυτή την Περιγραφή Δεδομένων"
|
||||
|
|
|
@ -51,7 +51,9 @@
|
|||
</div>
|
||||
</li>
|
||||
<li class="nav-item"><a class="nav-link" href="../contact.html">CONTACT</a></li>
|
||||
<li class="nav-item"><li class="nav-item"><a class="nav-link" href="/login">SIGN IN</a></li></li>
|
||||
<li class="nav-item">
|
||||
<li class="nav-item"><a class="nav-link" href="/login">SIGN IN</a></li>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -60,7 +62,7 @@
|
|||
<section class="page-section how-it-works" id="how-it-works">
|
||||
<div class="container-small">
|
||||
<div class="col">
|
||||
<div class="page-title">About</div>
|
||||
<div class="page-title">FAQs</div>
|
||||
</div>
|
||||
<div class="col pt-5 pb-3">
|
||||
<div class="row title-1">FAQs</div>
|
||||
|
@ -108,7 +110,7 @@
|
|||
</div>
|
||||
<div class="collapse show" id="collapseFAQ-3">
|
||||
<div class="faq-content">
|
||||
<p>ARGOS is comprised of two main functionalities: DMP templates and Dataset Descriptions.
|
||||
<div>ARGOS is comprised of two main functionalities: DMP templates and Dataset Descriptions.
|
||||
Additional entities are Projects that link to funders and grants information.<br />ARGOS can
|
||||
be used for:
|
||||
<br /><br /><u style="padding:20px;"> A. viewing/ consulting publicly released DMPs and
|
||||
|
@ -131,7 +133,7 @@
|
|||
Examples may refer to embedding DMP and DMP tools in specific curricula or even utilization
|
||||
of the tool for researchers and students familiarization with the concept and process, as
|
||||
part of library instructions’ sessions.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -206,4 +208,4 @@
|
|||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<section class="page-section how-it-works" id="how-it-works">
|
||||
<div class="container-small">
|
||||
<div class="col">
|
||||
<div class="page-title">About</div>
|
||||
<div class="page-title">How it works</div>
|
||||
</div>
|
||||
<div class="col pt-5 pb-2">
|
||||
<div class="row title-1">How it works</div>
|
||||
|
|
Loading…
Reference in New Issue