Merge branch 'Development' of code-repo.d4science.org:MaDgiK-CITE/argos into Development

This commit is contained in:
argirok 2022-02-04 10:05:32 +02:00
commit 938f98100f
24 changed files with 451 additions and 219 deletions

View File

@ -73,7 +73,8 @@ public class Admin extends BaseController {
userDatasetProfile.setRole(0);
getApiContext().getOperationsContext().getDatabaseRepository().getUserDatasetProfileDao().createOrUpdate(userDatasetProfile);
datasetProfileManager.storeDatasetProfileUsers(datasetProfile, profile);
metricsManager.increaseValue(MetricNames.DATASET_TEMPLATE, 1, MetricNames.TOTAL);
metricsManager.increaseValue(MetricNames.DATASET_TEMPLATE, 1, MetricsManager.datasetTemplateStatus.get(datasetProfile.getStatus()) );
return ResponseEntity.status(HttpStatus.OK).body(modelDefinition.getId());
}

View File

@ -1054,14 +1054,10 @@ public class DatasetManager {
if (!value.toString().equals("\"\"")) {
String stringValue = value.toString().replaceAll("=", ":");
JSONArray values = new JSONArray(stringValue);
if (values != null) {
values.iterator().forEachRemaining(element -> {
Map<String, Object> data = ((JSONObject) element).toMap();
this.addTag(tags, wizardModel.getTags(), data.get("id").toString(), data.get("name").toString());
});
} else {
this.addTag(tags, wizardModel.getTags(), "", value.asText());
}
values.iterator().forEachRemaining(element -> {
Map<String, Object> data = ((JSONObject) element).toMap();
this.addTag(tags, wizardModel.getTags(), data.get("id").toString(), data.get("name").toString());
});
}
});
}

View File

@ -97,7 +97,6 @@ public class DatasetProfileManager {
DatasetProfile profile = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(id));
apiContext.getOperationsContext().getDatabaseRepository().detachEntity(profile);
profile.setId(null);
metricsManager.increaseValue(MetricNames.DATASET_TEMPLATE, 1, MetricNames.TOTAL);
return profile;
}
@ -253,7 +252,7 @@ public class DatasetProfileManager {
File localFile = convert(multiPartFile);
eu.eudat.logic.utilities.documents.xml.datasetProfileXml.datasetProfileModel.DatasetProfile profile = xmlBuilder.build(localFile);
Files.deleteIfExists(localFile.toPath());
metricsManager.increaseValue(MetricNames.DATASET_TEMPLATE, 1, MetricNames.TOTAL);
metricsManager.increaseValue(MetricNames.DATASET_TEMPLATE, 1, MetricNames.DRAFT);
return profile;
} catch (IOException e) {
logger.error(e.getMessage(), e);

View File

@ -32,6 +32,11 @@ public class MetricsManager {
private final static Logger logger = LoggerFactory.getLogger(MetricsManager.class);
private final Map<String, Gauge> gauges;
public static final Map<Short, String> datasetTemplateStatus = Stream.of(new Object[][] {
{ DatasetProfile.Status.SAVED.getValue(), MetricNames.DRAFT },
{ DatasetProfile.Status.FINALIZED.getValue(), MetricNames.ACTIVE },
}).collect(Collectors.toMap(data -> (Short) data[0], data -> (String) data[1]));
public void increaseValue(String name, int amount, String label) {
if(label != null) {

View File

@ -18,6 +18,7 @@ public class Section {
private String extendedDescription;
private String title;
private List<Section> section;
private Boolean multiplicity;
@XmlAttribute(name = "id")
public String getId() {
@ -134,4 +135,13 @@ public class Section {
public void setSection(List<Section> section) {
this.section = section;
}
@XmlAttribute(name = "multiplicity")
public Boolean getMultiplicity() {
return multiplicity;
}
public void setMultiplicity(Boolean multiplicity) {
this.multiplicity = multiplicity;
}
}

View File

@ -18,6 +18,7 @@ public class Sections {
private String title;
private List<Section> section;
private FieldSets fieldSets;
private Boolean multiplicity;
@XmlAttribute(name = "id")
public String getId() {
@ -100,6 +101,15 @@ public class Sections {
this.fieldSets = fieldSets;
}
@XmlAttribute(name = "multiplicity")
public Boolean getMultiplicity() {
return multiplicity;
}
public void setMultiplicity(Boolean multiplicity) {
this.multiplicity = multiplicity;
}
public eu.eudat.models.data.admin.components.datasetprofile.Section toAdminCompositeModelSection() {
eu.eudat.models.data.admin.components.datasetprofile.Section sectionEntity = new eu.eudat.models.data.admin.components.datasetprofile.Section();
List<eu.eudat.models.data.admin.components.datasetprofile.Section> sectionsListEntity = new LinkedList<>();
@ -118,6 +128,7 @@ public class Sections {
sectionEntity.setDescription(description);
sectionEntity.setPage(this.page);
sectionEntity.setFieldSets(toAdminCompositeModelSectionFieldSets());
sectionEntity.setMultiplicity(this.multiplicity);
sectionEntity.setSections(sectionsListEntity);

View File

@ -16,6 +16,7 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
private String id;
private String title;
private String description;
private Boolean multiplicity;
public List<Section> getSections() {
return sections;
@ -81,11 +82,20 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
this.ordinal = ordinal;
}
public Boolean getMultiplicity() {
return multiplicity;
}
public void setMultiplicity(Boolean multiplicity) {
this.multiplicity = multiplicity;
}
@Override
public eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Section toDatabaseDefinition(eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Section item) {
if (this.id == null || this.id.isEmpty()) this.id = "section_" + RandomStringUtils.random(5, true, true);
item.setDefaultVisibility(this.defaultVisibility);
item.setDescription(this.description);
item.setMultiplicity(this.multiplicity);
if (this.fieldSets != null)
item.setFieldSets(new ModelBuilder().toViewStyleDefinition(this.fieldSets, eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.FieldSet.class));
item.setId(this.id);
@ -108,6 +118,7 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
this.page = item.getPage();
this.sections = new ModelBuilder().fromViewStyleDefinition(item.getSections(), Section.class);
this.title = item.getTitle();
this.multiplicity = item.getMultiplicity();
}
@Override
@ -134,6 +145,7 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
shortenSection.setId(this.id);
shortenSection.setTitle(this.title);
shortenSection.setDescription(this.description);
shortenSection.setMultiplicity(this.multiplicity);
return shortenSection;
}

View File

@ -20,11 +20,21 @@ import eu.eudat.models.data.dmp.DataManagementPlan;
import eu.eudat.models.data.externaldataset.ExternalDatasetListingModel;
import eu.eudat.models.data.user.composite.PagedDatasetProfile;
import net.minidev.json.JSONValue;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DatasetWizardModel implements DataModel<Dataset, DatasetWizardModel> {
@ -346,7 +356,7 @@ public class DatasetWizardModel implements DataModel<Dataset, DatasetWizardModel
Class<?>[] params = setterMethod.getParameterTypes();
ObjectMapper mapper = new ObjectMapper();
//GK: Tags Special logic
if (prefillingMapping.getTarget().equals("tags")) {
if (!value.equals("null") && prefillingMapping.getTarget().equals("tags")) {
List<Object> rawTags = (List<Object>) mapper.readValue(value, params[0]);
if (rawTags.get(0) instanceof String) {
List<Tag> parsedTags = rawTags.stream().map(rawTag -> new Tag((String) rawTag, (String) rawTag)).collect(Collectors.toList());
@ -359,9 +369,73 @@ public class DatasetWizardModel implements DataModel<Dataset, DatasetWizardModel
}
} else {
List<JsonNode> nodes = JsonSearcher.findNodes(parentNode, "rdaProperty", prefillingMapping.getMaDmpTarget());
if(prefillingMapping.getMaDmpTarget().equals("dataset.distribution.available_until") && !value.equals("null")){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd");
LocalDate date = LocalDate.parse(value.replace("\"", ""), formatter);
date = date.plusYears(20);
value = date.toString();
}
for (JsonNode node: nodes) {
String id = node.get(0) != null ? node.get(0).get("id").asText() : node.get("id").asText();
properties.put(id, value);
if(prefillingMapping.getMaDmpTarget().equals("dataset.distribution.format") && !value.equals("null")){
JSONArray jsonArr = new JSONArray(value);
List<String> formats = new ArrayList<>();
String extension;
for(int i = 0; i < jsonArr.length(); i++){
JSONObject jsonObj = jsonArr.getJSONObject(i);
String filename = (String) jsonObj.get("filename");
int index = filename.lastIndexOf('.');
extension = (index > 0) ? filename.substring(index+1) : filename;
formats.add(extension);
}
formats = formats.stream().distinct().collect(Collectors.toList());
List<Object> standardFormats = new ArrayList<>();
for(String format: formats) {
RestTemplate restTemplate = new RestTemplate();
String parsedUrl = "https://eestore.paas2.uninett.no/api/fileformat/?search=" + format;
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(new MediaType("application", "vnd.api+json")));
HttpEntity<String> entity = new HttpEntity("", headers);
Map<String, Object> data = restTemplate.exchange(parsedUrl, HttpMethod.GET, entity, LinkedHashMap.class).getBody();
jsonArr = new JSONArray(new ObjectMapper().writeValueAsString(data.get("data")));
for(int i = 0; i < jsonArr.length(); i++){
JSONObject jsonObj = jsonArr.getJSONObject(i);
jsonObj = jsonObj.getJSONObject("attributes");
JSONArray extensions = jsonObj.getJSONArray("extensions");
Object formatName = jsonObj.get("name");
boolean found = false;
for(int j = 0; j < extensions.length(); j++){
if(extensions.getString(j).equals(format)){
JSONObject cur = new JSONObject();
cur.put("label", formatName.toString());
standardFormats.add(cur.toString());
found = true;
break;
}
}
if(found){
break;
}
}
}
properties.put(id, standardFormats);
}
else if(prefillingMapping.getMaDmpTarget().equals("dataset.distribution.data_access")){
value = value.replace("\"", "");
if(value.equals("open")){
properties.put(id, value);
}
else if(value.equals("restricted")){
properties.put(id, "shared");
}
else{
properties.put(id, "closed");
}
}
else{
properties.put(id, value.replace("\"", ""));
}
}
}
}

View File

@ -21,6 +21,7 @@ public class Section implements DatabaseViewStyleDefinition, XmlSerializable<Sec
private String extendedDescription;
private List<Section> sections;
private List<FieldSet> fieldSets;
private Boolean multiplicity;
public String getId() {
return id;
@ -102,6 +103,14 @@ public class Section implements DatabaseViewStyleDefinition, XmlSerializable<Sec
this.numbering = numbering;
}
public Boolean getMultiplicity() {
return multiplicity;
}
public void setMultiplicity(Boolean multiplicity) {
this.multiplicity = multiplicity;
}
@Override
public Element toXml(Document doc) {
Element rootElement = doc.createElement("section");
@ -109,6 +118,7 @@ public class Section implements DatabaseViewStyleDefinition, XmlSerializable<Sec
rootElement.setAttribute("ordinal", "" + this.ordinal);
rootElement.setAttribute("defaultVisibility", "" + this.defaultVisibility);
rootElement.setAttribute("page", "" + this.page);
rootElement.setAttribute("multiplicity", (this.multiplicity != null ? "" + this.multiplicity : "false"));
Element description = doc.createElement("description");
description.setTextContent(this.description);
@ -155,6 +165,7 @@ public class Section implements DatabaseViewStyleDefinition, XmlSerializable<Sec
this.ordinal = Integer.parseInt(element.getAttribute("ordinal"));
this.defaultVisibility = Boolean.valueOf(element.getAttribute("defaultVisibility"));
this.page = element.getAttribute("page");
this.multiplicity = element.hasAttribute("multiplicity") ? Boolean.valueOf(element.getAttribute("multiplicity")) : false;
Element description = XmlBuilder.getNodeFromListByTagName(element.getChildNodes(), "description");
if (description != null) this.description = description.getTextContent();

View File

@ -19,6 +19,7 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
private String id;
private String title;
private String description;
private Boolean multiplicity;
public List<Section> getSections() {
Collections.sort(sections);
@ -94,6 +95,14 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
this.numbering = numbering;
}
public Boolean getMultiplicity() {
return multiplicity;
}
public void setMultiplicity(Boolean multiplicity) {
this.multiplicity = multiplicity;
}
@Override
public eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Section toDatabaseDefinition(eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Section item) {
item.setDefaultVisibility(this.defaultVisibility);
@ -106,6 +115,7 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
if (this.sections != null)
item.setSections(new ModelBuilder().toViewStyleDefinition(this.sections, eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Section.class));
item.setTitle(this.title);
item.setMultiplicity(this.multiplicity);
return item;
}
@ -120,6 +130,7 @@ public class Section implements Comparable, ViewStyleDefinition<eu.eudat.models.
this.page = item.getPage();
this.sections = new ModelBuilder().fromViewStyleDefinition(item.getSections(), Section.class);
this.title = item.getTitle();
this.multiplicity = item.getMultiplicity();
}
@Override

View File

@ -1,13 +1,13 @@
package eu.eudat.models.rda.mapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.DatasetProfile;
import eu.eudat.elastic.criteria.DatasetCriteria;
import eu.eudat.elastic.entities.Tag;
import eu.eudat.logic.managers.DatasetManager;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.utilities.json.JavaToJson;
import eu.eudat.logic.utilities.helpers.StreamDistinctBy;
import eu.eudat.logic.utilities.json.JsonSearcher;
import eu.eudat.models.data.datasetprofile.DatasetProfileOverviewModel;
import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.transaction.Transactional;
import java.net.URI;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@ -131,7 +130,7 @@ public class DatasetRDAMapper {
rda.setKeyword(keywordNodes.stream().map(keywordNode -> {
JsonNode value = keywordNode.get("value");
if (value.isArray()) {
return StreamSupport.stream(value.spliterator(), false).map(node -> KeywordRDAMapper.toRDA(node.asText())).flatMap(Collection::stream).collect(Collectors.toList());
return StreamSupport.stream(value.spliterator(), false).map(node -> KeywordRDAMapper.toRDA(node.toString())).flatMap(Collection::stream).collect(Collectors.toList());
} else {
return KeywordRDAMapper.toRDA(keywordNode.get("value").asText());
}
@ -331,9 +330,14 @@ public class DatasetRDAMapper {
// if (keywordIds.size() < rda.getKeyword().size()) {
// takeAll = true;
// }
DatasetCriteria criteria = new DatasetCriteria();
criteria.setHasTags(true);
List<Tag> tags = this.apiContext.getOperationsContext().getElasticRepository().getDatasetRepository().query(criteria).stream().map(eu.eudat.elastic.entities.Dataset::getTags).flatMap(Collection::stream).filter(StreamDistinctBy.distinctByKey(Tag::getId)).collect(Collectors.toList());
if(!rda.getKeyword().isEmpty()){
for (int i = 0; i < keywordIds.size(); i++) {
// if (takeAll) {
List<Tag> templateTags = tags.stream().filter(tag -> rda.getKeyword().contains(tag.getName())).collect(Collectors.toList());
properties.put(keywordIds.get(0), mapper.writeValueAsString(templateTags));
// for (int i = 0; i < keywordIds.size(); i++) {
// //if (takeAll) {
// List<String> tags = new ArrayList<>();
// for (String keyword : rda.getKeyword()) {
// tags.add(mapper.writeValueAsString(toTagEntity(keyword)));
@ -342,8 +346,8 @@ public class DatasetRDAMapper {
// } else {
// properties.put(keywordIds.get(i), mapper.writeValueAsString(toTagEntity(rda.getKeyword().get(i))));
// }
properties.put(keywordIds.get(i), rda.getKeyword().get(i));
}
// properties.put(keywordIds.get(i), rda.getKeyword().get(i));
// }
}
}

View File

@ -2,7 +2,9 @@ package eu.eudat.models.rda.mapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.elastic.entities.Dataset;
import eu.eudat.elastic.entities.Tag;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.utilities.json.JavaToJson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -15,15 +17,15 @@ public class KeywordRDAMapper {
private static final Logger logger = LoggerFactory.getLogger(KeywordRDAMapper.class);
public static List<String> toRDA(String value) {
if (!value.isEmpty()) {
if (!value.isEmpty() && !value.equals("null")) {
try {
ObjectMapper mapper = new ObjectMapper();
String valueJson = JavaToJson.objectStringToJson(value);
List<Tag> tags = Arrays.asList(mapper.readValue(valueJson, Tag[].class));
return tags.stream().map(Tag::getName).collect(Collectors.toList());
Tag tag = mapper.readValue(valueJson, Tag.class);
return new ArrayList<>(Collections.singletonList(tag.getName()));
} catch (JsonProcessingException e) {
logger.warn(e.getMessage() + ". Attempting to parse it as a String list.");
return new ArrayList<>(Arrays.asList(value.replace(" ", "").split(",")));
logger.warn(e.getMessage() + ". Attempting to parse it as a String since its a new tag.");
return new ArrayList<>(Collections.singletonList(value));
}
}

View File

@ -1,7 +1,7 @@
package eu.eudat.types;
public class MetricNames {
public static final String DATASET_TEMPLATE = "argos_dataset_templates";
public static final String DATASET_TEMPLATE = "argos_dmp_templates";
public static final String INSTALLATIONS = "installations";
public static final String USERS = "argos_users";
public static final String DMP = "argos_managed_dmps";

View File

@ -1189,11 +1189,20 @@ but not
<mapping source="metadata.dates.valid" maDmpTarget="dataset.distribution.available_until"/>
<mapping source="metadata.access_right" maDmpTarget="dataset.distribution.data_access"/>
<mapping source="metadata.publication_date" maDmpTarget="dataset.issued"/>
<mapping source="metadata.license.id" maDmpTarget="dataset.distribution.license.license_ref"/>
<mapping source="metadata.license.created" maDmpTarget="dataset.distribution.license.start_date"/>
<mapping source="metadata.embargo_date" maDmpTarget="dataset.distribution.license.start_date"/>
<mapping source="files" maDmpTarget="dataset.distribution.format"/>
</mappings>
<fixedMappings>
<fixedMapping maDmpTarget="dataset.distribution.host.title" value="Zenodo" />
<fixedMapping maDmpTarget="dataset.metadata.metadata_standard_id.identifier" value="https://schema.datacite.org/meta/kernel-4.4/" />
<fixedMapping maDmpTarget="dataset.metadata.metadata_standard_id.type" value="url" />
<fixedMapping maDmpTarget="dataset.distribution.host.description" value="Repository hosted by Zenodo" />
<fixedMapping maDmpTarget="dataset.distribution.host.url" value="https://zenodo.org" />
<fixedMapping maDmpTarget="dataset.distribution.host.pid_system" value="doi" />
<fixedMapping maDmpTarget="dataset.security_and_privacy.title" value="TBD" />
<fixedMapping maDmpTarget="dataset.security_and_privacy.description" value="TBD" />
<fixedMapping maDmpTarget="dataset.preservation_statement" value="TBD" />
</fixedMappings>
</prefillingGet>
</config>

View File

@ -1,15 +1,17 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormArray, FormGroup, AbstractControl, FormArrayName } from '@angular/forms';
import { DatasetDescriptionCompositeFieldEditorModel, DatasetDescriptionFieldEditorModel } from '../../dataset-description-form.model';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';
import { ToCEntry } from '../../dataset-description.component';
import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service';
@Component({
selector: 'app-form-composite-field',
templateUrl: './form-composite-field.component.html',
styleUrls: ['./form-composite-field.component.scss']
styleUrls: ['./form-composite-field.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormCompositeFieldComponent {
export class FormCompositeFieldComponent extends BaseComponent {
@Input() datasetProfileId: String;
@Input() form: FormGroup;
@ -19,13 +21,18 @@ export class FormCompositeFieldComponent {
constructor(
public visibilityRulesService: VisibilityRulesService,
private changeDetector: ChangeDetectorRef
//private markForConsiderationService: MarkForConsiderationService,
) {
super();
this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
this.changeDetector.markForCheck();
});
}
ngOnInit() {
if(this.tocentry){
if (this.tocentry) {
this.form = this.tocentry.form as FormGroup;
}
}
@ -50,7 +57,7 @@ export class FormCompositeFieldComponent {
deleteCompositeFieldFormGroup() {
const compositeFieldId = ((this.form.get('multiplicityItems') as FormArray).get(''+0) as FormGroup).getRawValue().id;
const compositeFieldId = ((this.form.get('multiplicityItems') as FormArray).get('' + 0) as FormGroup).getRawValue().id;
const fieldIds = (this.form.get('fields') as FormArray).controls.map(control => control.get('id').value) as string[];
const numberOfItems = this.form.get('multiplicityItems').get('' + 0).get('fields').value.length;
@ -62,7 +69,7 @@ export class FormCompositeFieldComponent {
this.visibilityRulesService.removeAllIdReferences(compositeFieldId);
fieldIds.forEach( x => this.visibilityRulesService.removeAllIdReferences(x));
fieldIds.forEach(x => this.visibilityRulesService.removeAllIdReferences(x));
}
deleteMultipeFieldFromCompositeFormGroup() {
@ -77,10 +84,10 @@ export class FormCompositeFieldComponent {
fieldIds.forEach(x => this.visibilityRulesService.removeAllIdReferences(x));
(parent as FormArray).removeAt(index);
(parent as FormArray).controls.forEach((control, i)=>{
try{
(parent as FormArray).controls.forEach((control, i) => {
try {
control.get('ordinal').setValue(i);
}catch{
} catch {
throw 'Could not find ordinal';
}
});

View File

@ -1,5 +1,5 @@
<div *ngIf="form && this.visibilityRulesService.checkElementVisibility(this.form.get('id').value)" [id]="this.form.get('id').value"
[formGroup]="form" [ngSwitch]="this.form.get('viewStyle').value.renderStyle" class="dynamic-form-field row">
<div *ngIf="form && visible" [id]="this.form.get('id').value"
[formGroup]="form" [ngSwitch]="renderStyle" class="dynamic-form-field row">
<h5 *ngIf="this.form.get('title').value && !isChild">{{this.form.get('title').value}}</h5>
<mat-icon *ngIf="this.form.get('additionalInformation').value && !isChild" matTooltip="{{this.form.get('additionalInformation').value}}">info</mat-icon>

View File

@ -1,5 +1,5 @@
import { Component, Input, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, OnInit, SimpleChanges } from '@angular/core';
import { FormGroup, FormArray, FormControl } from '@angular/forms';
import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type';
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
@ -19,7 +19,7 @@ import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/sing
import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service';
import { BaseComponent } from '@common/base/base.component';
import { TranslateService } from '@ngx-translate/core';
import { map, takeUntil } from 'rxjs/operators';
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item';
import { ExternalDatasetCriteria } from '@app/core/query/external-dataset/external-dataset-criteria';
@ -42,7 +42,8 @@ import {PublicationCriteria} from "@app/core/query/publication/publication-crite
@Component({
selector: 'app-form-field',
templateUrl: './form-field.component.html',
styleUrls: ['./form-field.component.scss']
styleUrls: ['./form-field.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormFieldComponent extends BaseComponent implements OnInit {
@ -52,6 +53,14 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
@Input() isChild: Boolean = false;
@Input() autocompleteOptions: AutoCompleteSingleData;
visible: boolean = true;
_renderStyle: DatasetProfileFieldViewStyle = null;
get renderStyle() {
//console.log('renderStyle');
return this._renderStyle;
}
// change: Subscription;
// trackByFn = (index, item) => item ? item['id'] : null;
@ -103,9 +112,22 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
private datasetService: DatasetService,
private dmpService: DmpService,
private currencyService: CurrencyService
) { super(); }
) {
super();
this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
this.visible = this.visibilityRulesService.checkElementVisibility(this.form?.get('id')?.value);
});
}
ngOnChanges(changes: SimpleChanges) {
if (changes['form']) {
this._renderStyle = this.form.get('viewStyle')?.value?.renderStyle;
}
}
ngOnInit() {
if (this.form.get('value').value) {
this.visibilityRulesService.updateValueAndVisibility(this.form.get('id').value, this.form.get('value').value);
}
@ -135,20 +157,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
this.singleAutoCompleteConfiguration = {
filterFn: this.searchFromAutocomplete.bind(this),
initialItems: () => this.searchFromAutocomplete(''),
displayFn: (item) => {try{return (item != null && item.length > 1) ? JSON.parse(item).label : item['label']}catch{return ''}},
titleFn: (item) => {try{return item['label'] }catch{return''}},
valueAssign: (item) => {try{return JSON.stringify(item)}catch{return''}},
subtitleFn: (item) => {try{return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE')}catch{return''}}
displayFn: (item) => { try { return (item != null && item.length > 1) ? JSON.parse(item).label : item['label'] } catch { return '' } },
titleFn: (item) => { try { return item['label'] } catch { return '' } },
valueAssign: (item) => { try { return JSON.stringify(item) } catch { return '' } },
subtitleFn: (item) => { try { return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE') } catch { return '' } }
};
}
else {
this.multipleAutoCompleteConfiguration = {
filterFn: this.searchFromAutocomplete.bind(this),
initialItems: () => this.searchFromAutocomplete(''),
displayFn: (item) =>{try{return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label']}catch{return''}},
titleFn: (item) =>{ try{return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label']}catch{return''}},
valueAssign: (item) =>{ try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}},
subtitleFn: (item) => { try{return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE')}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label'] } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['label'] : item['label'] } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } },
subtitleFn: (item) => { try { return item['source'] ? this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-SUBTITLE') + item['source'] : this.language.instant('DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-AUTOCOMPLETE-NO-SOURCE') } catch { return '' } }
}
}
}
@ -158,20 +180,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
this.externalDatasetAutoCompleteConfiguration = {
filterFn: this.searchDatasetExternalDatasets.bind(this),
initialItems: () => this.searchDatasetExternalDatasets(''),//.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.DataRepositories:
this.dataRepositoriesAutoCompleteConfiguration = {
filterFn: this.searchDatasetExternalDataRepositories.bind(this),
initialItems: () => this.searchDatasetExternalDataRepositories(''),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.PubRepositories:
@ -228,29 +250,29 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
this.registriesAutoCompleteConfiguration = {
filterFn: this.searchDatasetExternalRegistries.bind(this),
initialItems: () => this.searchDatasetExternalRegistries(''),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.Services:
this.servicesAutoCompleteConfiguration = {
filterFn: this.searchDatasetExternalServices.bind(this),
initialItems: () => this.searchDatasetExternalServices(''),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return ''}},
titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
subtitleFn: (item) => { try{return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
subtitleFn: (item) => { try { return item.source ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.source : item.tag ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item.tag : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.Tags:
this.tagsAutoCompleteConfiguration = {
filterFn: this.filterTags.bind(this),
initialItems: (excludedItems: any[]) => this.filterTags('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
displayFn: (item) => { try{return this.showTag(item)}catch{return''}},
titleFn: (item) => { try{return item['name']}catch{return''}},
valueAssign: (item) => { try{return this.addTag(item)}catch{return''}}
displayFn: (item) => { try { return this.showTag(item) } catch { return '' } },
titleFn: (item) => { try { return item['name'] } catch { return '' } },
valueAssign: (item) => { try { return this.addTag(item) } catch { return '' } }
};
this.parseTags();
break;
@ -258,20 +280,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
this.researchersAutoCompleteConfiguration = {
filterFn: this.filterResearchers.bind(this),
initialItems: (excludedItems: any[]) => this.filterResearchers('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
titleFn: (item) =>{ try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
subtitleFn: (item) => { try{return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE'))}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
subtitleFn: (item) => { try { return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.Organizations:
this.organisationsAutoCompleteConfiguration = {
filterFn: this.filterOrganisations.bind(this),
initialItems: (excludedItems: any[]) => this.filterOrganisations('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
displayFn:(item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
titleFn: (item) =>{ try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
subtitleFn: (item) =>{ try{return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE'))}catch{return''}},
valueAssign: (item) =>{ try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
subtitleFn: (item) => { try { return item['tag'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.DatasetIdentifier:
@ -284,9 +306,9 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
this.currencyAutoCompleteConfiguration = {
filterFn: this.searchCurrency.bind(this),
initialItems: () => this.searchCurrency(''),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } }
};
break;
case DatasetProfileFieldViewStyle.Validation:
@ -311,7 +333,10 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
// this.form = this.visibilityRulesService.getFormGroup(this.field.id);
this.form.get('value').valueChanges
.pipe(takeUntil(this._destroyed))
.pipe(
takeUntil(this._destroyed),
distinctUntilChanged()
)
.subscribe(item => {
// if (this.form.get('viewStyle').value.renderStyle === DatasetProfileFieldViewStyle.ComboBox && this.form.get('data').value.type === DatasetProfileComboBoxType.WordList && this.form.get('data').value.multiList) {
// item.forEach(element => {
@ -319,7 +344,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
// });
// } else {
this.visibilityRulesService.updateValueAndVisibility(this.form.get('id').value, item);
this.visibilityRulesService.updateValueAndVisibility(this.form.get('id').value, item);
// }
});
}
@ -351,7 +376,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
}
autocompleteRequestItem.criteria.like = query;
if(this.autocompleteOptions){
if (this.autocompleteOptions) {
return this.datasetExternalAutocompleteService.queryApi(autocompleteRequestItem);
}
return this.datasetExternalAutocompleteService.queryAutocomplete(autocompleteRequestItem);
@ -385,20 +410,20 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
this.singleAutoCompleteConfiguration = {
filterFn: myfunc.bind(this),
initialItems: (extraData) => myfunc(''),
displayFn: (item) => { try{return (item != null && item.length > 1) ? JSON.parse(item)[title] : item[title]}catch{return''}},
titleFn: (item) => { try{return item[title]}catch{return''}},
displayFn: (item) => { try { return (item != null && item.length > 1) ? JSON.parse(item)[title] : item[title] } catch { return '' } },
titleFn: (item) => { try { return item[title] } catch { return '' } },
valueAssign: (item) => JSON.stringify(item),
subtitleFn: (item) => { try{return item[subtitle]}catch{return''}}
subtitleFn: (item) => { try { return item[subtitle] } catch { return '' } }
};
}
else {
this.multipleAutoCompleteConfiguration = {
filterFn: myfunc.bind(this),
initialItems: (extraData) => myfunc(''),
displayFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title]}catch{return''}},
titleFn: (item) => { try{return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title]}catch{return''}},
valueAssign: (item) => { try{return typeof (item) == 'string' ? item : JSON.stringify(item)}catch{return''}},
subtitleFn: (item) => { try{return item[subtitle]}catch{return''}}
displayFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title] } catch { return '' } },
titleFn: (item) => { try { return typeof (item) == 'string' ? JSON.parse(item)[title] : item[title] } catch { return '' } },
valueAssign: (item) => { try { return typeof (item) == 'string' ? item : JSON.stringify(item) } catch { return '' } },
subtitleFn: (item) => { try { return item[subtitle] } catch { return '' } }
}
}
}
@ -479,23 +504,23 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
}
parseTags() {
try{
try {
let stringValue = this.form.get('value').value;
if (typeof stringValue === 'string') {
stringValue = (<string>stringValue).replace(new RegExp('{', 'g'), '{"').replace(new RegExp('=', 'g'), '":"').replace(new RegExp(',', 'g'), '",').replace(new RegExp(', ', 'g'), ', "').replace(new RegExp('}', 'g'), '"}');
stringValue = stringValue.replace(new RegExp('}"', 'g'), '}').replace(new RegExp('"{', 'g'), '{');
} else if (stringValue instanceof Array) {
const tempArray = new Array();
for (let stringTag of stringValue) {
tempArray.push(JSON.parse(stringTag));
let stringValue = this.form.get('value').value;
if (typeof stringValue === 'string') {
stringValue = (<string>stringValue).replace(new RegExp('{', 'g'), '{"').replace(new RegExp('=', 'g'), '":"').replace(new RegExp(',', 'g'), '",').replace(new RegExp(', ', 'g'), ', "').replace(new RegExp('}', 'g'), '"}');
stringValue = stringValue.replace(new RegExp('}"', 'g'), '}').replace(new RegExp('"{', 'g'), '{');
} else if (stringValue instanceof Array) {
const tempArray = new Array();
for (let stringTag of stringValue) {
tempArray.push(JSON.parse(stringTag));
}
stringValue = JSON.stringify(tempArray);
}
stringValue = JSON.stringify(tempArray);
}
const tagArray = JSON.parse(stringValue);
this.form.patchValue({'value': tagArray});
}catch(e){
const tagArray = JSON.parse(stringValue);
this.form.patchValue({ 'value': tagArray });
} catch (e) {
console.warn('Could not parse tags');
}
}
@ -524,7 +549,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
} else {
item = ev;
}
if (item.name !== '' ) {
if (item.name !== '') {
return item;
}
}
@ -548,7 +573,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
validateId() {
const identifier = this.getDatasetIdControl('identifier').value;
const type = this.getDatasetIdControl('type').value;
this.validationIcon= 'loading';
this.validationIcon = 'loading';
this.externalSourcesService.validateIdentifier(identifier, type).pipe(takeUntil(this._destroyed)).subscribe(result => {
this.validationIcon = result === true ? 'done' : 'clear';
});

View File

@ -1,22 +1,24 @@
import { AfterViewInit, Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { FormGroup, FormArray, AbstractControl } from '@angular/forms';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';
import { DatasetDescriptionCompositeFieldEditorModel } from '../../../dataset-description-form.model';
import { FormFocusService } from '../../../form-focus/form-focus.service';
import { VisibilityRulesService } from '../../../visibility-rules/visibility-rules.service';
import { DatasetDescriptionSectionEditorModel, DatasetDescriptionCompositeFieldEditorModel } from '../../../dataset-description-form.model';
import { FormCompositeFieldComponent } from '../../form-composite-field/form-composite-field.component';
import { LinkToScroll } from '../../../tableOfContentsMaterial/table-of-contents';
import { VisibilityRulesService } from '../../../visibility-rules/visibility-rules.service';
@Component({
selector: 'app-form-section-inner',
templateUrl: './form-section-inner.component.html',
styleUrls: ['./form-section-inner.component.scss']
styleUrls: ['./form-section-inner.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormSectionInnerComponent implements OnInit, OnChanges {
export class FormSectionInnerComponent extends BaseComponent implements OnInit, OnChanges {
//@Input() section: DatasetDescriptionSectionEditorModel;
@Input() datasetProfileId: String;
// @Input() compositeFieldFormGroup: FormGroup;
@Input() form:FormGroup;
@Input() form: FormGroup;
@Input() pathName: string;
@Input() path: string;
// @Input() i: number;
@ -28,8 +30,14 @@ export class FormSectionInnerComponent implements OnInit, OnChanges {
constructor(
public visibilityRulesService: VisibilityRulesService,
private changeDetector: ChangeDetectorRef,
private formFocusService: FormFocusService
) { }
) {
super();
this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
this.changeDetector.markForCheck();
});
}
ngOnInit() {
// if (this.section) {
@ -75,10 +83,10 @@ export class FormSectionInnerComponent implements OnInit, OnChanges {
deleteMultipeFieldFromCompositeFormGroup(compositeFildIndex: number, fildIndex: number) {
const multiplicityItemsArray = (<FormArray>(this.form.get('compositeFields').get('' + compositeFildIndex).get('multiplicityItems')))
multiplicityItemsArray.removeAt(fildIndex);
multiplicityItemsArray.controls.forEach((control, i)=>{
try{
multiplicityItemsArray.controls.forEach((control, i) => {
try {
control.get('ordinal').setValue(i);
}catch{
} catch {
throw 'Could not find ordinal';
}
});

View File

@ -1,22 +1,23 @@
import { AfterViewInit, Component, Input, OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormArray, AbstractControl } from '@angular/forms';
import { FormFocusService } from '../../form-focus/form-focus.service';
import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service';
import { DatasetDescriptionSectionEditorModel, DatasetDescriptionCompositeFieldEditorModel } from '../../dataset-description-form.model';
import { FormCompositeFieldComponent } from '../form-composite-field/form-composite-field.component';
import { LinkToScroll } from '../../tableOfContentsMaterial/table-of-contents';
import { ToCEntry, ToCEntryType } from '../../dataset-description.component';
import { VisibilityRuleSource } from '../../visibility-rules/models/visibility-rule-source';
import { VisibilityRule } from '../../visibility-rules/models/visibility-rule';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';
import { DatasetDescriptionCompositeFieldEditorModel } from '../../dataset-description-form.model';
import { ToCEntry, ToCEntryType } from '../../dataset-description.component';
import { FormFocusService } from '../../form-focus/form-focus.service';
import { LinkToScroll } from '../../tableOfContentsMaterial/table-of-contents';
import { VisibilityRuleSource } from '../../visibility-rules/models/visibility-rule-source';
import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service';
@Component({
selector: 'app-form-section',
templateUrl: './form-section.component.html',
styleUrls: ['./form-section.component.scss']
styleUrls: ['./form-section.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormSectionComponent implements OnInit, OnChanges {
export class FormSectionComponent extends BaseComponent implements OnInit, OnChanges {
//@Input() section: DatasetDescriptionSectionEditorModel;
@Input() datasetProfileId: String;
@ -33,21 +34,27 @@ export class FormSectionComponent implements OnInit, OnChanges {
@Output() askedToScroll = new EventEmitter<string>();
tocentriesType = ToCEntryType;
@Input() TOCENTRY_ID_PREFIX="";
@Input() TOCENTRY_ID_PREFIX = "";
constructor(
public visibilityRulesService: VisibilityRulesService,
private formFocusService: FormFocusService
) { }
private formFocusService: FormFocusService,
private changeDetector: ChangeDetectorRef
) {
super();
this.visibilityRulesService.getElementVisibilityMapObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
this.changeDetector.markForCheck();
});
}
ngOnInit() {
// if (this.section) {
// this.form = this.visibilityRulesService.getFormGroup(this.section.id);
// }
if(this.tocentry){//maybe not needed as well
if (this.tocentry) {//maybe not needed as well
this.form = this.tocentry.form as FormGroup;
}
}
@ -75,30 +82,30 @@ export class FormSectionComponent implements OnInit, OnChanges {
const compositeFieldToBeCloned = (this.form.get('compositeFields').get('' + fieldsetIndex) as FormGroup).getRawValue();
const multiplicityItemsArray = (<FormArray>(this.form.get('compositeFields').get('' + fieldsetIndex).get('multiplicityItems')));
const ordinal = multiplicityItemsArray.length? multiplicityItemsArray.controls.reduce((ordinal, currentControl)=>{
const ordinal = multiplicityItemsArray.length ? multiplicityItemsArray.controls.reduce((ordinal, currentControl) => {
const currentOrdinal = currentControl.get('ordinal').value as number;
if(currentOrdinal>= ordinal){
return currentOrdinal +1;
if (currentOrdinal >= ordinal) {
return currentOrdinal + 1;
}
return ordinal as number;
},0) : 0;
const idMappings = [] as {old: string, new: string}[];
const compositeField: DatasetDescriptionCompositeFieldEditorModel = new DatasetDescriptionCompositeFieldEditorModel().cloneForMultiplicity(compositeFieldToBeCloned, ordinal ,idMappings);
}, 0) : 0;
const idMappings = [] as { old: string, new: string }[];
const compositeField: DatasetDescriptionCompositeFieldEditorModel = new DatasetDescriptionCompositeFieldEditorModel().cloneForMultiplicity(compositeFieldToBeCloned, ordinal, idMappings);
// ** COMPOSITE FIELD IS SHOWN OR HIDDEN FROM ANOTHER ELEMENT
const compositeFieldVisibilityDependencies = this.visibilityRulesService.getVisibilityDependency(compositeFieldToBeCloned);
if(compositeFieldVisibilityDependencies && compositeFieldVisibilityDependencies.length){
if (compositeFieldVisibilityDependencies && compositeFieldVisibilityDependencies.length) {
compositeFieldVisibilityDependencies.forEach(x =>{
compositeFieldVisibilityDependencies.forEach(x => {
const visRule: Rule = {
targetField: compositeField.id,
sourceField: x.sourceControlId,
requiredValue: x.sourceControlValue,
type: ''
type: ''
}
this.visibilityRulesService.addNewRule(visRule);
});
@ -111,24 +118,24 @@ export class FormSectionComponent implements OnInit, OnChanges {
try{
if(dependency && dependency.length){
try {
if (dependency && dependency.length) {
// * INNER VISIBILITY DEPENDENCIES
// * IF INNER INPUT HIDES ANOTHER INNER INPUT
const innerDependency = compositeFieldToBeCloned.fields.reduce((innerD, currentElement )=>{
const innerDependecies = dependency.filter(d => d.sourceControlId === currentElement.id);
return[...innerD, ...innerDependecies];
},[]) as VisibilityRuleSource[];
if(innerDependency.length){
const innerDependency = compositeFieldToBeCloned.fields.reduce((innerD, currentElement) => {
const innerDependecies = dependency.filter(d => d.sourceControlId === currentElement.id);
return [...innerD, ...innerDependecies];
}, []) as VisibilityRuleSource[];
if (innerDependency.length) {
//Build visibility source
const updatedRules = innerDependency.map(x => {
const newId = idMappings.find(y=> y.old === x.sourceControlId);
return {...x, sourceControlId: newId.new};
const updatedRules = innerDependency.map(x => {
const newId = idMappings.find(y => y.old === x.sourceControlId);
return { ...x, sourceControlId: newId.new };
});
// const visRule: VisibilityRule = {
// targetControlId: idMappings.find(x => x.old === element.id).new,
@ -140,33 +147,33 @@ export class FormSectionComponent implements OnInit, OnChanges {
return {
requiredValue: x.sourceControlValue,
sourceField: x.sourceControlId,
targetField: idMappings.find(l=> l.old === element.id).new,
targetField: idMappings.find(l => l.old === element.id).new,
type: ''
} as Rule;
});
rules.forEach(rule =>{
rules.forEach(rule => {
this.visibilityRulesService.addNewRule(rule);
})
// this.visibilityRulesService.appendVisibilityRule(visRule);
}
}
// * OUTER DEPENDENCIES
// * IF INNER INPUT HIDES OUTER INPUTS
const innerIds = idMappings.map(x => x.old) as string[];
const outerTargets = this.visibilityRulesService.getVisibilityTargets(element.id).filter( x=> !innerIds.includes(x));
const outerTargets = this.visibilityRulesService.getVisibilityTargets(element.id).filter(x => !innerIds.includes(x));
outerTargets.forEach(target =>{
outerTargets.forEach(target => {
const outerRules = (this.visibilityRulesService.getVisibilityDependency(target) as VisibilityRuleSource[]).filter(x => x.sourceControlId === element.id);
const updatedRules = outerRules.map(x => {
return {...x ,sourceControlId: idMappings.find(y => y.old === element.id).new};
return { ...x, sourceControlId: idMappings.find(y => y.old === element.id).new };
});
// const visRule: VisibilityRule = {
@ -175,7 +182,7 @@ export class FormSectionComponent implements OnInit, OnChanges {
// }
const rules = updatedRules.map(x =>{
const rules = updatedRules.map(x => {
return {
requiredValue: x.sourceControlValue,
sourceField: x.sourceControlId,
@ -184,12 +191,12 @@ export class FormSectionComponent implements OnInit, OnChanges {
} as Rule;
})
rules.forEach(rule =>{
rules.forEach(rule => {
this.visibilityRulesService.addNewRule(rule);
})
// this.visibilityRulesService.appendVisibilityRule(visRule);
});
@ -198,16 +205,16 @@ export class FormSectionComponent implements OnInit, OnChanges {
// * IF INNER INPUT IS HIDDEN BY OUTER INPUT
if(dependency && dependency.length){
if (dependency && dependency.length) {
const fieldsThatHideInnerElement = dependency.filter(x => !innerIds.includes(x.sourceControlId));
if( fieldsThatHideInnerElement.length){
fieldsThatHideInnerElement.forEach(x =>{
if (fieldsThatHideInnerElement.length) {
fieldsThatHideInnerElement.forEach(x => {
const visRule: Rule = {
targetField: idMappings.find(l => l.old === element.id).new,
sourceField: x.sourceControlId,
requiredValue: x.sourceControlValue,
type: ''
type: ''
}
const shouldBeVisibile = this.visibilityRulesService.checkTargetVisibilityProvidedBySource(x.sourceControlId, element.id);
this.visibilityRulesService.addNewRule(visRule, shouldBeVisibile);
@ -239,10 +246,10 @@ export class FormSectionComponent implements OnInit, OnChanges {
deleteMultipeFieldFromCompositeFormGroup(compositeFildIndex: number, fildIndex: number) {
const multiplicityItemsArray = (<FormArray>(this.form.get('compositeFields').get('' + compositeFildIndex).get('multiplicityItems')));
multiplicityItemsArray.removeAt(fildIndex);
multiplicityItemsArray.controls.forEach((control, i)=>{
try{
multiplicityItemsArray.controls.forEach((control, i) => {
try {
control.get('ordinal').setValue(i);
}catch{
} catch {
throw 'Could not find ordinal';
}
});
@ -258,7 +265,7 @@ export class FormSectionComponent implements OnInit, OnChanges {
onAskedToScroll(id:string){
onAskedToScroll(id: string) {
this.panelExpanded = true;
this.askedToScroll.emit(id);
}

View File

@ -2,7 +2,7 @@ import { ApplicationRef, Injectable, NgZone } from '@angular/core';
import { AbstractControl, FormArray, FormGroup } from '@angular/forms';
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
import { isNumeric } from '@app/utilities/enhancers/utils';
import { Subject } from 'rxjs';
import { Observable, Subject } from 'rxjs';
import { Rule } from '../../../../core/model/dataset-profile-definition/rule';
import { VisibilityRule } from './models/visibility-rule';
import { VisibilityRuleSource } from './models/visibility-rule-source';
@ -16,7 +16,8 @@ export class VisibilityRulesService {
private visibilityRuleContext: VisibilityRulesContext;
private form: AbstractControl;
private elementVisibilityMap = new Map<String, boolean>();
public elementVisibilityMap = new Map<String, boolean>();
private elementVisibilityMapSubject = new Subject<Map<String, boolean>>();
private elementComputationalMap = new Map<String, Map<String, boolean>>(); /// keep saved the values of each form control validity value
private _changeMade$ = new Subject<void>();
@ -28,6 +29,10 @@ export class VisibilityRulesService {
}
getElementVisibilityMapObservable(): Observable<Map<String, boolean>> {
return this.elementVisibilityMapSubject.asObservable();
}
public checkElementVisibility(id: string): boolean {
if (this.visibilityRuleContext.rules.filter(item => item.targetControlId === id).length === 0) { return true; }
return this.elementVisibilityMap.has(id) ? this.elementVisibilityMap.get(id) : false;
@ -41,8 +46,12 @@ export class VisibilityRulesService {
}
public updateValueAndVisibility(id: string, value: any) {
console.log('updateValueAndVisibility');
const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0);
visibilityRules.forEach(item => this.evaluateVisibility(item, value, id));
if (visibilityRules.length > 0) {
visibilityRules.forEach(item => this.evaluateVisibility(item, value, id));
this.elementVisibilityMapSubject.next(this.elementVisibilityMap);
}
}
private evaluateVisibility(visibilityRule: VisibilityRule, value: any, sourceId: string) {// source controlId is the same
@ -72,7 +81,7 @@ export class VisibilityRulesService {
const shouldBeVisible = visibilityDependencySource.reduce((isVisible, x) => {
const shouldBeHidden = value !== null && (this.parseValue(value) !== this.parseValue(x.sourceControlValue));
return this.VISIBILITY_RULE_LOGIC === 'OR'? (isVisible || !shouldBeHidden) : (isVisible && !shouldBeHidden);
return this.VISIBILITY_RULE_LOGIC === 'OR' ? (isVisible || !shouldBeHidden) : (isVisible && !shouldBeHidden);
// if(value !== null && )
}, this.VISIBILITY_RULE_LOGIC === 'AND');
visibilityMap.set(sourceId, shouldBeVisible);
@ -84,8 +93,10 @@ export class VisibilityRulesService {
const isVisible = this._computeVisibility(targetId);
this._emitChangesIfNeeded(targetId, isVisible);
const previousVisibility = this.elementVisibilityMap.get(targetId);
this.elementVisibilityMap.set(targetId, isVisible);
if (!isVisible) {
if (!isVisible && previousVisibility !== isVisible) {
this.resetControlWithId(this.form, targetId);
}
@ -220,11 +231,18 @@ export class VisibilityRulesService {
private resetFieldFormGroup(formGroup: FormGroup) {
const renderStyle = formGroup.getRawValue().viewStyle.renderStyle;
if (renderStyle === DatasetProfileFieldViewStyle.Validation || renderStyle === DatasetProfileFieldViewStyle.DatasetIdentifier) {
formGroup.get('value').setValue({ identifier: '', type: '' });
const value = { identifier: '', type: '' };
if (formGroup.get('value').value != value) {
formGroup.get('value').setValue(value, { emitEvent: false });
this.updateValueAndVisibility(formGroup.get('id').value, value);
}
} else {
formGroup.get('value').setValue(formGroup.get('defaultValue').value ? this.parseValue(formGroup.get('defaultValue').value.value) : undefined);
const value = formGroup.get('defaultValue').value ? this.parseValue(formGroup.get('defaultValue').value.value) : undefined;
if (formGroup.get('value').value != value) {
formGroup.get('value').setValue(value, { emitEvent: false });
this.updateValueAndVisibility(formGroup.get('id').value, value);
}
}
}
private resetCompositeFieldFormGroup(formGroup: FormGroup) {
@ -342,8 +360,8 @@ export class VisibilityRulesService {
let visibilityMap = this.elementComputationalMap.get(targetId);
if(!visibilityMap){
visibilityMap = new Map<String, boolean>();
if (!visibilityMap) {
visibilityMap = new Map<String, boolean>();
this.elementComputationalMap.set(targetId, visibilityMap);
}
@ -352,6 +370,7 @@ export class VisibilityRulesService {
this._emitChangesIfNeeded(targetId, isVisible);
this.elementVisibilityMap.set(targetId, isVisible);
this.elementVisibilityMapSubject.next(this.elementVisibilityMap);
}
@ -359,10 +378,10 @@ export class VisibilityRulesService {
* Check what sourceId hides or shows the target field
* return true if no rule found
*/
public checkTargetVisibilityProvidedBySource(sourceId: string, targetId: string): boolean{
public checkTargetVisibilityProvidedBySource(sourceId: string, targetId: string): boolean {
const computationalMap = this.elementComputationalMap.get(targetId);
if(computationalMap){
if (computationalMap) {
return !!computationalMap.get(sourceId);
}

View File

@ -89,12 +89,6 @@
features of Argos in a concise
way.
</li>
<li>
<a href="../assets/media-kit/Factsheet.pdf">
Factsheet
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a> containing the basics of Argos and explaining its key features in an adequate level of
</li>
<li>
<a href="https://www.openaire.eu/argos/">Useful Resources
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>

View File

@ -70,31 +70,58 @@
<section class="page-section user-guide" id="user-guide">
<div class="container">
<div class="col">
<div class="page-title">Resources</div>
<div class="page-title">User Guide</div>
</div>
<div class="col pt-5 pb-3">
<div class="title-3">User Guide</div>
<div class="row pt-5 pb-3">
<div class="col">
<div class="title-3 text-center">User</div>
</div>
<div class="col">
<div class="title-3 text-center">Admin</div>
</div>
</div>
<div class="col">
<p>
Become proficient in using Argos by following the User Guide. Check presentation for additional
<div class="row d-flex justify-content-center">
<p class="text-center">
Become proficient in using Argos by following the User Guide. <br/> Check presentation for additional
hints and leave your thoughts for improvements in the feedback form.
</p>
<ul class="list mb-5">
<li><a href="/user-guide">User Guide</a></li>
<li><a href="../assets/presentations/argos.pdf">
Presentations
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a></li>
<li><a href="https://docs.google.com/forms/d/12RSCrUjdSDp2LZLpjDKOi44cN1fLDD2q1-F66SqZIis/viewform?edit_requested=true">
Feedback Form
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a></li>
</ul>
</div>
<div class="col d-flex justify-content-center mb-5 pb-5">
<a href="/user-guide"><button class="normal-btn">View User Guide Online</button></a>
<div class="row mb-5 pb-5">
<div class="col d-flex justify-content-center">
<ul class="list mb-5">
<li><a href="/user-guide">User Guide</a></li>
<li>
<a href="../assets/media-kit/Factsheet.pdf">
Factsheet
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a>
</li>
<li><a href="../assets/presentations/argos.pdf">
Presentations
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a></li>
<li><a href="https://docs.google.com/forms/d/12RSCrUjdSDp2LZLpjDKOi44cN1fLDD2q1-F66SqZIis/viewform?edit_requested=true">
Feedback Form
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a></li>
</ul>
</div>
<div class="col d-flex justify-content-center">
<ul class="list mb-5">
<li><a href="../assets/media-kit/Argos-Admin-Handbook_14_01_2022.pdf">
Handbook
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a></li>
<li><a href="../assets/media-kit/OpenAIRE_ARGOS_Administrators.pdf">
Factsheet
<i class="fas fa-external-link-alt ext-link-icon fa-xs"></i>
</a></li>
</ul>
</div>
</div>
<!-- <div class="col d-flex justify-content-center mb-5 pb-5">-->
<!-- <a href="/user-guide"><button class="normal-btn">View User Guide Online</button></a>-->
<!-- </div>-->
</div>
</section>
<!-- Footer-->