diff --git a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java index eb382a81e..e79e91a34 100644 --- a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java +++ b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java @@ -13,6 +13,14 @@ public class Tag implements ElasticEntity { private String id; private String name; + public Tag() { + } + + public Tag(String id, String name) { + this.id = id; + this.name = name; + } + public String getId() { return id; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 2a9060acb..9430fa269 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -220,7 +220,11 @@ public class DataManagementPlanManager { datasetEnities.stream() .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED) && !dataset.getStatus().equals(Dataset.Status.CANCELED)) .forEach(dataset -> { - dataManagementPlan.getDatasets().stream().filter(datasetWizardModel -> datasetWizardModel.getId().equals(dataset.getId())).forEach(datasetWizardModel -> datasetWizardModel.setDatasetProfileDefinition(datasetManager.getPagedProfile(datasetWizardModel, dataset))); + dataManagementPlan.getDatasets().stream().filter(datasetWizardModel -> datasetWizardModel.getId().equals(dataset.getId())).forEach(datasetWizardModel -> { + DatasetWizardModel wizardModel = datasetManager.getSingle(datasetWizardModel.getId().toString(), principal); + datasetWizardModel.setDatasetProfileDefinition(wizardModel.getDatasetProfileDefinition()); + datasetWizardModel.setTags(wizardModel.getTags()); + }); }); if (isPublic) { dataManagementPlan.setDatasets(dataManagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java index 6e39738fa..46d4f632b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java @@ -37,6 +37,9 @@ public class DatasetMapper { tags.forEach(tag -> tag.setId(UUID.randomUUID().toString())); elastic.setTags(tags); } else { + if (tags1.size() < tags.size()) { + tags.stream().filter(tag -> tag.getId() == null || tag.getId().equals("")).forEach(tag -> tags1.add(new Tag(UUID.randomUUID().toString(), tag.getName()))); + } elastic.setTags(tags1); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java index 41f42281c..9428c8255 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java @@ -278,11 +278,28 @@ public class RemoteFetcher { + "," + jsonDataPath.getFieldsUrlConfiguration().getId() + "]"), new HashMap<>(1, 1)); List> fixedResults = results.getResults().stream().map(item -> { - String id = jsonDataPath.getFieldsUrlConfiguration().getId().replace("'", ""); - if (! (item.get(id) instanceof String)) { - Object obj = item.get(id); - JSONArray jarr = (JSONArray) obj; - item.put(id, jarr.get(0).toString()); + for (int i = 0; i < 2; i++) { + String id; + if (i == 0) { + id = jsonDataPath.getFieldsUrlConfiguration().getId().replace("'", ""); + } else { + id = jsonDataPath.getFieldsUrlConfiguration().getName().replace("'", ""); + } + if (!(item.get(id) instanceof String)) { + Object obj = item.get(id); + if (obj instanceof JSONArray) { + JSONArray jarr = (JSONArray) obj; + if (jarr.get(0) instanceof String) { + item.put(id, jarr.get(0).toString()); + } else { + for (int j = 0; j < jarr.size(); j++) { + mapToMap(id, (Map)jarr.get(j), item, i == 1); + } + } + } else { + mapToMap(id, (Map)obj, item, i == 1); + } + } } return item; }).collect(Collectors.toList()); @@ -472,4 +489,16 @@ public class RemoteFetcher { this.pagination = pagination; } } + + private void mapToMap(String key, Map source, Map destination, boolean isTitle) { + String content = source.get("content"); + if (isTitle) { + String classId = source.get("classid"); + if (classId.equals("main title")) { + destination.put(key, content); + } + } else { + destination.put(key, content); + } + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ResearchersExternalSourcesModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ResearchersExternalSourcesModel.java index 63a5529d4..29898fb03 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ResearchersExternalSourcesModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ResearchersExternalSourcesModel.java @@ -11,7 +11,13 @@ public class ResearchersExternalSourcesModel extends ExternalListingItem $['meta']['pagination']['page','pages','count'] + + openaire + + 2 + External + https://services.openaire.eu/search/v2/api/datasets/?q={like}&page={page}&size={pageSize}&format=json + 0 + application/json; charset=utf-8 + + $['results'][*]['result']['metadata']['oaf:entity']['oaf:result'] + + 'originalId' + 'title' + 'count' + + + $['meta']['pagination']['page','pages','count'] + - - -
-
-

- {{i+1}}) {{suggestion.get('name').value}} -

-
-
- -
-
-
+ -
+ -
+ -
+ -
+ +
+
+
4.1 {{'DMP-EDITOR.FIELDS.LANGUAGE' | translate}}
+
{{'DMP-EDITOR.LICENSE-INFO.HINT' | translate}}
+
+ + + + {{ lang.name }} + + + + {{formGroup.get('extraProperties').get('language').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+ +
+
+
4.2 {{'DMP-EDITOR.FIELDS.LICENSE' | translate}}
+
{{'DMP-EDITOR.LICENSE-INFO.HINT' | translate}}
+
+ + + + + {{formGroup.get('extraProperties').get('license').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+ +
+
+
4.3 {{'DMP-EDITOR.FIELDS.VISIBILITY' | translate}}
+
{{'DMP-EDITOR.LICENSE-INFO.HINT' | translate}}
+
+ + + + {{vis.name | translate}} + + + + {{formGroup.get('extraProperties').get('visible').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+ +
+
+
4.4 {{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}
+
{{'DMP-EDITOR.LICENSE-INFO.HINT' | translate}}
+
+ + + + + + {{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+
+
+
4.5 {{'DMP-EDITOR.FIELDS.CONTACT' | translate}}
+
{{'DMP-EDITOR.LICENSE-INFO.HINT' | translate}}
+
+ + + + {{vis.name | translate}} + + + + {{formGroup.get('extraProperties').get('contact').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+
+
+
4.6 {{'DMP-EDITOR.FIELDS.COST' | translate}}
+
{{'DMP-EDITOR.LICENSE-INFO.HINT' | translate}}
+
+ + +
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/dmp/editor/license-info/license-info.component.scss b/dmp-frontend/src/app/ui/dmp/editor/license-info/license-info.component.scss new file mode 100644 index 000000000..51514d57e --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/license-info/license-info.component.scss @@ -0,0 +1,105 @@ +.main-info { + // position: relative; + // left: 362px; + // width: calc(100% - 366px); + + .intro { + text-align: left; + font-weight: 400; + letter-spacing: 0px; + color: #212121; + opacity: 1; + margin: 3rem 0rem 3rem 0rem; + } + + .heading { + text-align: left; + font-weight: 700; + font-size: 18px; + letter-spacing: 0px; + color: #212121; + opacity: 0.81; + margin-top: 1.625rem; + margin-bottom: 0.625rem; + } + + .hint { + text-align: left; + font-weight: 400; + font-size: 16px; + letter-spacing: 0px; + color: #212121; + opacity: 0.81; + margin-bottom: 2.125rem; + } + + .title-form, + .description-form { + text-align: left; + font-weight: 400; + font-size: 16px; + letter-spacing: 0.15px; + color: #7d7d7d; + opacity: 1; + margin-bottom: 1rem; + } + + // textarea::placeholder { + // font-style: oblique; + // } + + .input-btn { + border: none; + color: #aaaaaa; + background-color: #ffffff00; + cursor: pointer; + } + + .input-btn :hover { + color: #00b29f !important; + } +} + +::ng-deep .title-form .mat-form-field-appearance-outline .mat-form-field-outline { + background: #fafafa !important; +} + +::ng-deep .description-form .mat-form-field-appearance-outline .mat-form-field-outline { + background: #fafafa !important; +} + +::ng-deep .organizations-form .mat-form-field-appearance-outline .mat-form-field-outline { + background: #fafafa !important; +} + +::ng-deep .author-form .mat-form-field-appearance-outline .mat-form-field-outline { + background: #fafafa !important; +} + +::ng-deep .title-form .mat-form-field-appearance-outline .mat-form-field-infix { + font-size: 1rem; + padding: 0.6em 0 1em 0 !important; +} + +::ng-deep .description-form .mat-form-field-appearance-outline .mat-form-field-infix { + font-size: 1rem; + padding: 0.6em 0 1em 0 !important; +} + +::ng-deep .organizations-form .mat-form-field-appearance-outline .mat-form-field-infix { + font-size: 1rem; + padding: 0.6em 0 1em 0 !important; +} + +::ng-deep .author-form .mat-form-field-appearance-outline .mat-form-field-infix { + font-size: 1rem; + padding: 0.6em 0 1em 0 !important; +} + +.cost-placeholder { + text-decoration: underline; +} + +.cost-add { + margin-top: 1em; +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/license-info/license-info.component.ts b/dmp-frontend/src/app/ui/dmp/editor/license-info/license-info.component.ts new file mode 100644 index 000000000..60f2fa2d7 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/license-info/license-info.component.ts @@ -0,0 +1,115 @@ +import { BaseComponent } from '@common/base/base.component'; +import { OnInit, Component, Input, Output, EventEmitter } from '@angular/core'; +import { FormGroup, FormControl, FormArray } from '@angular/forms'; +import { map, takeUntil } from 'rxjs/operators'; +import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; +import { Observable } from 'rxjs'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; +import { isNullOrUndefined } from 'util'; +import { MatDialog } from '@angular/material'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { LanguageInfo } from '@app/core/model/language-info'; +import { LanguageInfoService } from '@app/core/services/culture/language-info-service'; +import { RequestItem } from '@app/core/query/request-item'; +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; + name: string; +} + +@Component({ + selector: 'license-info', + templateUrl: './license-info.component.html', + styleUrls: ['./license-info.component.scss'] +}) +export class LicenseInfoComponent extends BaseComponent implements OnInit { + + @Input() formGroup: FormGroup = null; + // @Input() datasetFormGroup: FormGroup; + @Input() isNewVersion: boolean; + @Input() isNewDataset: boolean; + @Input() isUserOwner: boolean; + @Input() isClone: boolean; + @Output() onFormChanged: EventEmitter = new EventEmitter(); + + visibles: Visible[] = [ + { value: true, name: 'DMP-EDITOR.VISIBILITY.PUBLIC' }, + { value: false, name: 'DMP-EDITOR.VISIBILITY.RESTRICTED' } + ] + + public formControl = new FormControl(); + + licenseAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { + filterFn: this.licenseSearch.bind(this), + initialItems: (excludedItems: any[]) => this.licenseSearch('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), + displayFn: (item) => item['name'], + titleFn: (item) => item['name'] + }; + + constructor( + private externalSourcesService: ExternalSourcesService, + private dialog: MatDialog, + private languageInfoService: LanguageInfoService + ) { + super(); + } + + ngOnInit() { + // if (this.formGroup.get('definition')) { this.selectedDmpProfileDefinition = this.formGroup.get('definition').value; } + // this.registerFormEventsForDmpProfile(); + + if (this.isNewVersion) { + this.formGroup.get('label').disable(); + } + + if (!this.isUserOwner && !this.isClone) { + this.formGroup.disable(); + } + if (isNullOrUndefined(this.formGroup.get('extraProperties').get('publicDate').value)) { + this.formGroup.get('extraProperties').get('publicDate').patchValue(new Date()); + } + + this.formGroup.valueChanges.pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.onFormChanged.emit(); + }); + } + + getLanguageInfos(): LanguageInfo[] { + return this.languageInfoService.getLanguageInfoValues(); + } + + licenseSearch(query: string): Observable { + const request = new RequestItem(); + request.criteria = new LicenseCriteria(); + request.criteria.like = query; + request.criteria.type = ''; + return this.externalSourcesService.searchLicense(request); + } + + 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); + (this.formGroup.get('extraProperties').get('costs')).push(costeditModel.buildForm(null, true)); + } + }); + } +} diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 835adea18..cbe090e2d 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -794,6 +794,7 @@ "VISIBILITY": "Visibility", "PUBLICATION": "Publication Date", "CONTACT": "Contact", + "COST": "Costs", "DATASETS": "Datasets" }, "ACTIONS": { @@ -837,6 +838,7 @@ "FUNDING-INFO": "Funding info", "DATASET-SELECTION": "Dataset selection", "DATASET-INFO": "Dataset info", + "LICENSE-INFO": "License info", "DATASET": "Dataset", "PREVIOUS": "Previous", "NEXT": "Next" @@ -855,6 +857,11 @@ "SECOND-INTRO": "Datasets are documented following pre-defined templates which set the content of dataset descriptions. In Argos, a DMP can contain as many dataset descriptions as the datasets it documents.", "FIND": "Couldn't find a suitable one?" }, + "LICENSE-INFO": { + "INTRO": "Each DMP can contain specific license informatation over how much open and available it is, that way you can determine who can see your dataset and for how long that data will be private", + "HINT": "A brief description of what license the DMP is using, it’s type and when it will open.", + "TYPING": "Type more letters of the name so its more possible to find the correct one." + }, "CHANGES": "unsaved changes", "CLONE-DIALOG": { "CLONE": "Clone",