diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/converters/DateToUTCConverter.java b/dmp-backend/data/src/main/java/eu/eudat/data/converters/DateToUTCConverter.java index 35fb84dae..e0fd8e070 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/converters/DateToUTCConverter.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/converters/DateToUTCConverter.java @@ -1,5 +1,7 @@ package eu.eudat.data.converters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.format.datetime.DateFormatter; import javax.persistence.AttributeConverter; @@ -15,6 +17,7 @@ import java.util.TimeZone; */ @Converter public class DateToUTCConverter implements AttributeConverter { + private static final Logger logger = LoggerFactory.getLogger(DateToUTCConverter.class); @Override public Date convertToDatabaseColumn(Date attribute) { @@ -25,7 +28,7 @@ public class DateToUTCConverter implements AttributeConverter { String date = formatterIST.format(attribute); return formatterIST.parse(date); } catch (ParseException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return null; } @@ -39,7 +42,7 @@ public class DateToUTCConverter implements AttributeConverter { String date = formatterIST.format(dbData); return formatterIST.parse(date); } catch (ParseException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return null; } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanPublicCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanPublicCriteria.java index edc1ffa9f..cc96186fc 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanPublicCriteria.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanPublicCriteria.java @@ -12,6 +12,8 @@ public class DataManagementPlanPublicCriteria extends Criteria { public List datasetProfile; private List dmpOrganisations; private Integer role; + private boolean allVersions; + private List groupIds; public GrantStateType getGrantStatus() { return grantStatus; @@ -47,4 +49,18 @@ public class DataManagementPlanPublicCriteria extends Criteria { public void setRole(Integer role) { this.role = role; } + + public boolean getAllVersions() { + return allVersions; + } + public void setAllVersions(boolean allVersions) { + this.allVersions = allVersions; + } + + public List getGroupIds() { + return groupIds; + } + public void setGroupIds(List groupIds) { + this.groupIds = groupIds; + } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetCriteria.java index 8dac2b30f..7631c4d76 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetCriteria.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetCriteria.java @@ -21,6 +21,7 @@ public class DatasetCriteria extends Criteria { private List grants; private List collaborators; private List datasetTemplates; + private List groupIds; public boolean getAllVersions() { return allVersions; @@ -105,4 +106,11 @@ public class DatasetCriteria extends Criteria { public void setDatasetTemplates(List datasetTemplates) { this.datasetTemplates = datasetTemplates; } + + public List getGroupIds() { + return groupIds; + } + public void setGroupIds(List groupIds) { + this.groupIds = groupIds; + } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java index 0bf07564c..b8e2c35c4 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DatasetProfileCriteria.java @@ -32,6 +32,7 @@ public class DatasetProfileCriteria extends Criteria { private List groupIds; private Short filter; private UUID userId; + private boolean finalized; public boolean getAllVersions() { return allVersions; } public void setAllVersions(boolean allVersions) { this.allVersions = allVersions; } @@ -52,4 +53,11 @@ public class DatasetProfileCriteria extends Criteria { public void setUserId(UUID userId) { this.userId = userId; } + + public boolean getFinalized() { + return finalized; + } + public void setFinalized(boolean finalized) { + this.finalized = finalized; + } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDao.java index b3e81ec03..bcf5d134f 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDao.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDao.java @@ -6,13 +6,14 @@ import eu.eudat.data.entities.Dataset; import eu.eudat.data.entities.UserInfo; import eu.eudat.queryable.QueryableList; +import java.util.List; import java.util.UUID; public interface DatasetDao extends DatabaseAccessLayer { QueryableList getWithCriteria(DatasetCriteria criteria); - QueryableList getAuthenticated(QueryableList query, UserInfo principal); + QueryableList getAuthenticated(QueryableList query, UserInfo principal, List roles); Dataset isPublicDataset(UUID id); diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java index 1a68dcead..c2e703c7d 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetDaoImpl.java @@ -13,8 +13,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import java.util.Arrays; +import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -41,13 +43,15 @@ public class DatasetDaoImpl extends DatabaseAccess implements DatasetDa query.where((builder, root) -> builder.greaterThan(root.get("created"), criteria.getPeriodStart())); if (!criteria.getAllVersions()) query.initSubQuery(String.class).where((builder, root) -> builder.equal(root.get("dmp").get("version"), query.subQueryMax((builder1, externalRoot, nestedRoot) -> builder1.equal(externalRoot.get("dmp").get("groupId"), nestedRoot.get("dmp").get("groupId")), Arrays.asList(new SelectionField(FieldSelectionType.COMPOSITE_FIELD, "dmp:version")), String.class))); + if (criteria.getGroupIds() != null && !criteria.getGroupIds().isEmpty()) + query.where((builder, root) -> root.get("dmp").get("groupId").in(criteria.getGroupIds())); if (criteria.getDmpIds() != null && !criteria.getDmpIds().isEmpty()) query.where((builder, root) -> root.get("dmp").get("id").in(criteria.getDmpIds())); - if (criteria.getRole() != null) { + /*if (criteria.getRole() != null) { query.where((builder, root) -> builder.equal(root.join("dmp").join("users").get("role"), criteria.getRole())); } else { query.where((builder, root) -> root.join("dmp").join("users").get("role").in(UserDMP.UserDMPRoles.getAllValues())); - } + }*/ if (criteria.getOrganisations() != null && !criteria.getOrganisations().isEmpty()) query.where((builder, root) -> root.join("dmp").join("organisations").get("reference").in(criteria.getOrganisations())); if (criteria.getGrants() != null && !criteria.getGrants().isEmpty()) @@ -87,9 +91,13 @@ public class DatasetDaoImpl extends DatabaseAccess implements DatasetDa } @Override - public QueryableList getAuthenticated(QueryableList query, UserInfo principal) { - if (principal.getId() == null) query.where((builder, root) -> builder.equal(root.get("isPublic"), true)); - else { + public QueryableList getAuthenticated(QueryableList query, UserInfo principal, List roles) { + if (roles != null && !roles.isEmpty()) { + query.where((builder, root) -> { + Join userJoin = root.join("dmp", JoinType.LEFT).join("users", JoinType.LEFT); + return builder.and(builder.equal(userJoin.join("user", JoinType.LEFT).get("id"), principal.getId()), userJoin.get("role").in(roles)); + }); + } else { query.where((builder, root) -> builder.equal(root.join("dmp", JoinType.LEFT).join("users", JoinType.LEFT).join("user", JoinType.LEFT).get("id"), principal.getId())); } return query; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java index 42a7f8082..b06d5d8fd 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DatasetProfileDaoImpl.java @@ -52,7 +52,11 @@ public class DatasetProfileDaoImpl extends DatabaseAccess implem builder.notEqual(root.get("id"), criteria.getUserId()))); } } - query.where(((builder, root) -> builder.notEqual(root.get("status"), DatasetProfile.Status.DELETED.getValue()))); + if (criteria.getFinalized()) { + query.where(((builder, root) -> builder.equal(root.get("status"), DatasetProfile.Status.FINALIZED.getValue()))); + } else { + query.where(((builder, root) -> builder.notEqual(root.get("status"), DatasetProfile.Status.DELETED.getValue()))); + } return query; } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/GrantDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/GrantDaoImpl.java index bb91b39ad..04e14d3b8 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/GrantDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/GrantDaoImpl.java @@ -53,7 +53,7 @@ public class GrantDaoImpl extends DatabaseAccess implements GrantDao { if (criteria.getFunderId() != null && !criteria.getFunderId().trim().isEmpty()) query.where((builder, root) -> builder.equal(root.get("funder").get("id"), UUID.fromString(criteria.getFunderId()))); if (criteria.getFunderReference() != null && !criteria.getFunderReference().isEmpty()) - query.where((builder, root) -> builder.equal(root.join("funder", JoinType.LEFT).get("reference"), criteria.getFunderReference())); + query.where((builder, root) -> builder.or(builder.like(root.join("funder", JoinType.LEFT).get("reference"), "%" + criteria.getFunderReference()))); query.where((builder, root) -> builder.notEqual(root.get("status"), Grant.Status.DELETED.getValue())); return query; } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java index fe38a22cb..521dfb45f 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java @@ -281,20 +281,41 @@ public class Dataset implements DataEntity { this.setLabel(entity.getLabel()); this.setProperties(entity.getProperties()); - this.getDatasetDataRepositories().removeAll(this.getDatasetDataRepositories()); - if (entity.getDatasetDataRepositories() != null) - this.getDatasetDataRepositories().addAll(entity.getDatasetDataRepositories()); + if (entity.getDatasetDataRepositories() == null || entity.getDatasetDataRepositories().size() < 1) { + if (this.getDatasetDataRepositories() != null) this.getDatasetDataRepositories().removeAll(this.getDatasetDataRepositories()); + } else { + if (this.getDatasetDataRepositories() != null) { + this.getDatasetDataRepositories().removeAll(this.getDatasetDataRepositories()); + } else { + this.setDatasetDataRepositories(new HashSet<>()); + } + this.getDatasetDataRepositories().addAll(entity.getDatasetDataRepositories().stream().peek(item -> item.setDataset(this)).collect(Collectors.toList())); + } - this.getDatasetExternalDatasets().removeAll(this.getDatasetExternalDatasets()); - if (entity.getDatasetExternalDatasets() != null) - this.getDatasetExternalDatasets().addAll(entity.getDatasetExternalDatasets()); + if (entity.getDatasetExternalDatasets() == null || entity.getDatasetExternalDatasets().size() < 1) { + if (this.getDatasetExternalDatasets() != null) this.getDatasetExternalDatasets().removeAll(this.getDatasetExternalDatasets()); + } else { + if (this.getDatasetExternalDatasets() != null) { + this.getDatasetExternalDatasets().removeAll(this.getDatasetExternalDatasets()); + } else { + this.setDatasetExternalDatasets(new HashSet<>()); + } + this.getDatasetExternalDatasets().addAll(entity.getDatasetExternalDatasets().stream().peek(item -> item.setDataset(this)).collect(Collectors.toList())); + } + + if (entity.getServices() == null || entity.getServices().size() < 1) { + if (this.getServices() != null) this.getServices().removeAll(this.getServices()); + } else { + if (this.getServices() != null) { + this.getServices().removeAll(this.getServices()); + } else { + this.setServices(new HashSet<>()); + } + this.getServices().addAll(entity.getServices().stream().peek(item -> item.setDataset(this)).collect(Collectors.toList())); + } this.setRegistries(entity.getRegistries()); - this.getServices().removeAll(this.getServices()); - if (entity.getServices() != null) - this.getServices().addAll(entity.getServices()); - this.setDmp(entity.getDmp()); this.setStatus(entity.getStatus()); this.setProfile(entity.getProfile()); diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Funder.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Funder.java index c1a3bb087..d57e91136 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Funder.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Funder.java @@ -66,8 +66,8 @@ public class Funder implements DataEntity { } @Id - @GeneratedValue - @GenericGenerator(name = "uuid2", strategy = "uuid2") + //@GeneratedValue + //@GenericGenerator(name = "uuid2", strategy = "uuid2") @Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)") private UUID id; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Grant.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Grant.java index a7dbfc926..9809f0953 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Grant.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Grant.java @@ -81,8 +81,8 @@ public class Grant implements DataEntity { } @Id - @GeneratedValue - @GenericGenerator(name = "uuid2", strategy = "uuid2") + //@GeneratedValue + //@GenericGenerator(name = "uuid2", strategy = "uuid2") @Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)") private UUID id; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java index 44a5c8804..04c9d662c 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java @@ -67,8 +67,8 @@ public class Project implements DataEntity { } @Id - @GeneratedValue - @GenericGenerator(name = "uuid2", strategy = "uuid2") + //@GeneratedValue + //@GenericGenerator(name = "uuid2", strategy = "uuid2") @Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)") private UUID id; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Researcher.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Researcher.java index 1ede09a23..7777a883f 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Researcher.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Researcher.java @@ -19,8 +19,8 @@ import java.util.UUID; public class Researcher implements DataEntity { @Id - @GeneratedValue - @GenericGenerator(name = "uuid2", strategy = "uuid2") + /*@GeneratedValue + @GenericGenerator(name = "uuid2", strategy = "uuid2")*/ @Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)") private UUID id; diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/query/definition/Query.java b/dmp-backend/data/src/main/java/eu/eudat/data/query/definition/Query.java index aee35ca35..cb808bae6 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/query/definition/Query.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/query/definition/Query.java @@ -3,8 +3,11 @@ package eu.eudat.data.query.definition; import eu.eudat.data.dao.criteria.Criteria; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.queryableentity.DataEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class Query, T extends DataEntity> implements CriteriaQuery { + private static final Logger logger = LoggerFactory.getLogger(Query.class); private C criteria; private QueryableList query; @@ -33,10 +36,8 @@ public abstract class Query, T extends DataEntity> impleme q.setCriteria(criteria); q.setQuery(query); return q; - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + } catch (InstantiationException | IllegalAccessException e) { + logger.error (e.getMessage(), e); } return null; } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/query/items/table/dmp/DataManagmentPlanPublicTableRequest.java b/dmp-backend/data/src/main/java/eu/eudat/data/query/items/table/dmp/DataManagmentPlanPublicTableRequest.java index 78d9dfeb3..f359fcb4b 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/query/items/table/dmp/DataManagmentPlanPublicTableRequest.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/query/items/table/dmp/DataManagmentPlanPublicTableRequest.java @@ -5,8 +5,11 @@ import eu.eudat.data.entities.DMP; import eu.eudat.data.query.PaginationService; import eu.eudat.data.query.definition.TableQuery; import eu.eudat.queryable.QueryableList; +import eu.eudat.queryable.types.FieldSelectionType; +import eu.eudat.queryable.types.SelectionField; import eu.eudat.types.grant.GrantStateType; +import java.util.Arrays; import java.util.Date; import java.util.UUID; @@ -33,6 +36,14 @@ public class DataManagmentPlanPublicTableRequest extends TableQuery root.join("associatedDmps").get("id").in(this.getCriteria().datasetProfile)); if (this.getCriteria().getDmpOrganisations() != null && !this.getCriteria().getDmpOrganisations().isEmpty()) query.where(((builder, root) -> root.join("organisations").get("reference").in(this.getCriteria().getDmpOrganisations()))); + if (!this.getCriteria().getAllVersions()) { + query.initSubQuery(String.class).where((builder, root) -> builder.equal(root.get("version"), + query.subQueryMax((builder1, externalRoot, nestedRoot) -> builder1.and(builder1.equal(externalRoot.get("groupId"), + nestedRoot.get("groupId")), builder1.equal(nestedRoot.get("isPublic"), true)), Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "version")), String.class))); + } + if (this.getCriteria().getGroupIds() != null && !this.getCriteria().getGroupIds().isEmpty()) { + query.where((builder, root) -> root.get("groupId").in(this.getCriteria().getGroupIds())); + } return query; } diff --git a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dataset.java b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dataset.java index 2fca86b57..177417ffd 100644 --- a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dataset.java +++ b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Dataset.java @@ -1,6 +1,8 @@ package eu.eudat.elastic.entities; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.LinkedList; @@ -11,6 +13,7 @@ import java.util.Map; * Created by ikalyvas on 7/5/2018. */ public class Dataset implements ElasticEntity { + private static final Logger logger = LoggerFactory.getLogger(Dataset.class); private String id; private List tags = new LinkedList<>(); @@ -40,7 +43,7 @@ public class Dataset implements ElasticEntity { try { x.toElasticEntity(builder); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } }); builder.endArray(); diff --git a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/repository/ElasticRepository.java b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/repository/ElasticRepository.java index 90b9f3d36..aca4d8dea 100644 --- a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/repository/ElasticRepository.java +++ b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/repository/ElasticRepository.java @@ -6,6 +6,8 @@ import eu.eudat.elastic.entities.ElasticEntity; import org.elasticsearch.client.Client; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; @@ -13,6 +15,7 @@ import java.io.IOException; * Created by ikalyvas on 7/5/2018. */ public abstract class ElasticRepository implements Repository { + private static final Logger logger = LoggerFactory.getLogger(ElasticRepository.class); private RestHighLevelClient client; public RestHighLevelClient getClient() { @@ -29,7 +32,7 @@ public abstract class ElasticRepository implements QueryableList { + private static final Logger logger = LoggerFactory.getLogger(QueryableHibernateList.class); private Collector collector = new Collector(); private EntityManager manager; @@ -264,7 +267,7 @@ public class QueryableHibernateList implements QueryableLi try { return (T) this.tClass.newInstance().buildFromTuple(groupedResults.get(x.get("id")), this.fields, ""); } catch (InstantiationException | IllegalAccessException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return null; }).collect(Collectors.toList())); diff --git a/dmp-backend/web/src/main/java/eu/eudat/cache/ResponsesCache.java b/dmp-backend/web/src/main/java/eu/eudat/cache/ResponsesCache.java index fc1dba6ae..c87d616ab 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/cache/ResponsesCache.java +++ b/dmp-backend/web/src/main/java/eu/eudat/cache/ResponsesCache.java @@ -2,6 +2,8 @@ package eu.eudat.cache; import com.google.common.cache.CacheBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.guava.GuavaCache; @@ -17,6 +19,7 @@ import java.util.concurrent.TimeUnit; @Component @EnableCaching public class ResponsesCache { + private static final Logger logger = LoggerFactory.getLogger(ResponsesCache.class); public static long HOW_MANY = 30; public static TimeUnit TIME_UNIT = TimeUnit.MINUTES; @@ -24,7 +27,7 @@ public class ResponsesCache { @Bean public CacheManager cacheManager() { - System.out.print("Loading ResponsesCache..."); + logger.info("Loading ResponsesCache..."); SimpleCacheManager simpleCacheManager = new SimpleCacheManager(); List caches = new ArrayList(); caches.add(new GuavaCache("repositories", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); @@ -38,7 +41,7 @@ public class ResponsesCache { caches.add(new GuavaCache("researchers", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); caches.add(new GuavaCache("externalDatasets", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); simpleCacheManager.setCaches(caches); - System.out.println("OK"); + logger.info("OK"); return simpleCacheManager; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java index d1136aba9..89a330cd2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java @@ -37,6 +37,6 @@ public class WebMVCConfiguration extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new RequestInterceptor(this.apiContext.getHelpersService().getLoggerService())); +// registry.addInterceptor(new RequestInterceptor(this.apiContext.getHelpersService().getLoggerService())); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java index a1839073d..edad07650 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationDevelImpl.java @@ -4,6 +4,8 @@ import eu.eudat.configurations.dynamicfunder.entities.Configuration; import eu.eudat.configurations.dynamicfunder.entities.Property; import eu.eudat.models.data.dynamicfields.Dependency; import eu.eudat.models.data.dynamicfields.DynamicField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; @@ -19,6 +21,7 @@ import java.util.List; @Service("dynamicFunderConfiguration") @Profile("devel") public class DynamicFunderConfigurationDevelImpl implements DynamicFunderConfiguration { + private static final Logger logger = LoggerFactory.getLogger(DynamicFunderConfigurationDevelImpl.class); private Configuration configuration; private List fields; @@ -32,7 +35,7 @@ public class DynamicFunderConfigurationDevelImpl implements DynamicFunderConfigu public Configuration getConfiguration() { if (this.configuration != null) return this.configuration; String fileUrl = this.environment.getProperty("configuration.dynamicFunderUrl"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { @@ -43,13 +46,12 @@ public class DynamicFunderConfigurationDevelImpl implements DynamicFunderConfigu is = new URL("file:///"+ current + "/web/src/main/resources/FunderConfiguration.xml").openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } return this.configuration; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java index 699ff9580..1e8adbfdc 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicfunder/DynamicFunderConfigurationProdImpl.java @@ -4,6 +4,8 @@ import eu.eudat.configurations.dynamicfunder.entities.Configuration; import eu.eudat.configurations.dynamicfunder.entities.Property; import eu.eudat.models.data.dynamicfields.Dependency; import eu.eudat.models.data.dynamicfields.DynamicField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; @@ -20,6 +22,7 @@ import java.util.List; @Service("dynamicFunderConfiguration") @Profile({ "production", "staging" }) public class DynamicFunderConfigurationProdImpl implements DynamicFunderConfiguration { + private static final Logger logger = LoggerFactory.getLogger(DynamicFunderConfigurationProdImpl.class); private Configuration configuration; private List fields; @@ -33,7 +36,7 @@ public class DynamicFunderConfigurationProdImpl implements DynamicFunderConfigur public Configuration getConfiguration() { if (this.configuration != null) return this.configuration; String fileUrl = this.environment.getProperty("configuration.dynamicFunderUrl"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { @@ -44,13 +47,12 @@ public class DynamicFunderConfigurationProdImpl implements DynamicFunderConfigur is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } return this.configuration; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java index 92acd774a..13128d7d9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationDevelImpl.java @@ -4,6 +4,8 @@ import eu.eudat.configurations.dynamicgrant.entities.Configuration; import eu.eudat.configurations.dynamicgrant.entities.Property; import eu.eudat.models.data.dynamicfields.Dependency; import eu.eudat.models.data.dynamicfields.DynamicField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; @@ -24,6 +26,7 @@ import java.util.List; @Service("dynamicGrantConfiguration") @Profile("devel") public class DynamicGrantConfigurationDevelImpl implements DynamicGrantConfiguration { + private static final Logger logger = LoggerFactory.getLogger(DynamicGrantConfigurationDevelImpl.class); private Configuration configuration; @@ -40,7 +43,7 @@ public class DynamicGrantConfigurationDevelImpl implements DynamicGrantConfigura public Configuration getConfiguration() { if (this.configuration != null) return this.configuration; String fileUrl = this.environment.getProperty("configuration.dynamicGrantUrl"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { @@ -51,13 +54,12 @@ public class DynamicGrantConfigurationDevelImpl implements DynamicGrantConfigura is = new URL("file:///"+ current + "/web/src/main/resources/GrantConfiguration.xml").openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } return this.configuration; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java index 9fc72b985..db6d0c0ec 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicgrant/DynamicGrantConfigurationProdImpl.java @@ -4,6 +4,8 @@ import eu.eudat.configurations.dynamicgrant.entities.Configuration; import eu.eudat.configurations.dynamicgrant.entities.Property; import eu.eudat.models.data.dynamicfields.Dependency; import eu.eudat.models.data.dynamicfields.DynamicField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; @@ -24,6 +26,7 @@ import java.util.List; @Service("dynamicGrantConfiguration") @Profile({ "production", "staging" }) public class DynamicGrantConfigurationProdImpl implements DynamicGrantConfiguration { + private static final Logger logger = LoggerFactory.getLogger(DynamicGrantConfigurationProdImpl.class); private Configuration configuration; @@ -40,7 +43,7 @@ public class DynamicGrantConfigurationProdImpl implements DynamicGrantConfigurat public Configuration getConfiguration() { if (this.configuration != null) return this.configuration; String fileUrl = this.environment.getProperty("configuration.dynamicGrantUrl"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { @@ -51,13 +54,12 @@ public class DynamicGrantConfigurationProdImpl implements DynamicGrantConfigurat is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } return this.configuration; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java index 757990db1..fb1c17787 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java @@ -4,6 +4,8 @@ import eu.eudat.configurations.dynamicproject.entities.Configuration; import eu.eudat.configurations.dynamicproject.entities.Property; import eu.eudat.models.data.dynamicfields.Dependency; import eu.eudat.models.data.dynamicfields.DynamicField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; @@ -20,6 +22,7 @@ import java.util.List; @Service("dynamicProjectConfiguration") @Profile("devel") public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfiguration{ + private static final Logger logger = LoggerFactory.getLogger(DynamicProjectConfigurationDevelImpl.class); private Configuration configuration; private List fields; @@ -34,7 +37,7 @@ public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfi public Configuration getConfiguration() { if (this.configuration != null) return this.configuration; String fileUrl = this.environment.getProperty("configuration.dynamicProjectUrl"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { @@ -45,13 +48,12 @@ public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfi is = new URL("file:///"+ current + "/web/src/main/resources/ProjectConfiguration.xml").openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } return this.configuration; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java index a6627c6d1..f3ad8c010 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationProdImpl.java @@ -4,6 +4,8 @@ import eu.eudat.configurations.dynamicproject.entities.Configuration; import eu.eudat.configurations.dynamicproject.entities.Property; import eu.eudat.models.data.dynamicfields.Dependency; import eu.eudat.models.data.dynamicfields.DynamicField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; @@ -21,6 +23,7 @@ import java.util.List; @Service("dynamicProjectConfiguration") @Profile({ "production", "staging" }) public class DynamicProjectConfigurationProdImpl implements DynamicProjectConfiguration{ + private static final Logger logger = LoggerFactory.getLogger(DynamicProjectConfigurationProdImpl.class); private Configuration configuration; @@ -37,7 +40,7 @@ public class DynamicProjectConfigurationProdImpl implements DynamicProjectConfig public Configuration getConfiguration() { if (this.configuration != null) return this.configuration; String fileUrl = this.environment.getProperty("configuration.dynamicProjectUrl"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { @@ -48,13 +51,12 @@ public class DynamicProjectConfigurationProdImpl implements DynamicProjectConfig is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } return this.configuration; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Admin.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Admin.java index 11760957b..c461906b6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Admin.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Admin.java @@ -42,7 +42,7 @@ public class Admin extends BaseController { private ConfigLoader configLoader; @Autowired - public Admin(ApiContext apiContext, DatasetProfileManager datasetProfileManager, UserManager userManager, Logger logger, ConfigLoader configLoader) { + public Admin(ApiContext apiContext, DatasetProfileManager datasetProfileManager, UserManager userManager/*, Logger logger*/, ConfigLoader configLoader) { super(apiContext); this.datasetProfileManager = datasetProfileManager; this.userManager = userManager; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/BaseController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/BaseController.java index 147f91f22..c9bddab50 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/BaseController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/BaseController.java @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.InitBinder; public abstract class BaseController { - private Logger logger; + /*private Logger logger;*/ private ApiContext apiContext; @@ -17,9 +17,9 @@ public abstract class BaseController { return apiContext; } - public Logger getLoggerService() { + /*public Logger getLoggerService() { return logger; - } + }*/ public BaseController(ApiContext apiContext) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/ContactEmail.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/ContactEmail.java index 5b0054cac..78b53595c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/ContactEmail.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/ContactEmail.java @@ -5,6 +5,8 @@ import eu.eudat.models.data.ContactEmail.ContactEmailModel; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -15,6 +17,7 @@ import javax.transaction.Transactional; @CrossOrigin @RequestMapping(value = "api/contactEmail") public class ContactEmail { + private static final Logger logger = LoggerFactory.getLogger(ContactEmail.class); private ContactEmailManager contactEmailManager; @@ -31,7 +34,7 @@ public class ContactEmail { this.contactEmailManager.sendContactEmail(contactEmailModel, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); } catch (Exception ex) { - ex.printStackTrace(); + logger.error(ex.getMessage(), ex); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(ex.getMessage())); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java index 5208e5d43..01596ad28 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java @@ -29,6 +29,8 @@ import eu.eudat.models.data.security.Principal; import eu.eudat.query.DMPQuery; import eu.eudat.types.ApiMessageCode; import eu.eudat.types.Authorities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; @@ -55,6 +57,7 @@ import java.util.UUID; @CrossOrigin @RequestMapping(value = {"/api/dmps/"}) public class DMPs extends BaseController { + private static final Logger logger = LoggerFactory.getLogger(DMPs.class); private DynamicGrantConfiguration dynamicGrantConfiguration; private Environment environment; @@ -95,7 +98,7 @@ public class DMPs extends BaseController { if (contentType.equals("application/xml") || contentType.equals("application/msword")) { return this.dataManagementPlanManager.getDocument(id, contentType, principal, this.configLoader); } else { - eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = this.dataManagementPlanManager.getSingle(id, principal, this.dynamicGrantConfiguration); + eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = this.dataManagementPlanManager.getSingle(id, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); } } @@ -110,14 +113,18 @@ public class DMPs extends BaseController { @RequestMapping(method = RequestMethod.GET, value = {"rda/{id}"}) public @ResponseBody ResponseEntity getRDAJsonDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IOException { - return this.dataManagementPlanManager.getRDAJsonDocument(id, principal); + return this.dataManagementPlanManager.getRDAJsonDocument(id, datasetManager, principal); } @RequestMapping(method = RequestMethod.GET, value = {"/overview/{id}"}) public @ResponseBody - ResponseEntity getOverviewSingle(@PathVariable String id, Principal principal) throws IllegalAccessException, InstantiationException { - DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSingle(id, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); + ResponseEntity getOverviewSingle(@PathVariable String id, Principal principal) { + try { + DataManagementPlanOverviewModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSingle(id, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); + } } @RequestMapping(method = RequestMethod.GET, value = {"/public/{id}"}) @@ -195,7 +202,7 @@ public class DMPs extends BaseController { String name = file.getName().substring(0, file.getName().length() - 5); File pdffile = datasetManager.convertToPDF(file, environment, name); InputStream resource = new FileInputStream(pdffile); - System.out.println("Mime Type of " + file.getName() + " is " + + logger.info("Mime Type of " + file.getName() + " is " + new MimetypesFileTypeMap().getContentType(file)); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(pdffile.length()); @@ -269,7 +276,7 @@ public class DMPs extends BaseController { String zenodoDOI = this.dataManagementPlanManager.createZenodoDoi(UUID.fromString(id), principal, configLoader); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(zenodoDOI)); } catch (Exception e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage())); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java index 9c2dff6a1..4fb4e00ca 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java @@ -1,6 +1,7 @@ package eu.eudat.controllers; import eu.eudat.logic.managers.DashBoardManager; +import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; import eu.eudat.models.data.dashboard.recent.RecentActivity; import eu.eudat.models.data.dashboard.searchbar.SearchBarItem; @@ -8,6 +9,7 @@ import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; +import eu.eudat.types.Authorities; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -46,7 +48,8 @@ public class DashBoardController extends BaseController { } @RequestMapping(method = RequestMethod.GET, value = {"/dashboard/search"}, produces = "application/json") - public ResponseEntity>> search(@RequestParam(name = "like") String like, Principal principal) { + public ResponseEntity>> search(@RequestParam(name = "like") String like, + @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { List searchBarItemList = dashBoardManager.searchUserData(like, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(searchBarItemList)); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DataRepositories.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DataRepositories.java index cd9589615..f6bfed9d3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DataRepositories.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DataRepositories.java @@ -43,10 +43,10 @@ public class DataRepositories extends BaseController { @Transactional @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> create(@RequestBody eu.eudat.models.data.datarepository.DataRepositoryModel dataRepositoryModel, Principal principal) throws Exception { + ResponseEntity> create(@RequestBody eu.eudat.models.data.datarepository.DataRepositoryModel dataRepositoryModel, Principal principal) throws Exception { DataRepository dataRepository = this.dataRepositoryManager.create(dataRepositoryModel, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(dataRepository).status(ApiMessageCode.SUCCESS_MESSAGE)); + DataRepositoryModel dataRepositoryModel1 = new DataRepositoryModel().fromDataModel(dataRepository); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(dataRepositoryModel1).status(ApiMessageCode.SUCCESS_MESSAGE)); } - } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java index f25beabdd..17573e46a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java @@ -19,6 +19,8 @@ import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.types.ApiMessageCode; import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; @@ -44,6 +46,7 @@ import static eu.eudat.types.Authorities.ANONYMOUS; @CrossOrigin @RequestMapping(value = {"api/datasetwizard"}) public class DatasetWizardController extends BaseController { + private static final Logger logger = LoggerFactory.getLogger(DatasetWizardController.class); private Environment environment; private DatasetManager datasetManager; @@ -191,7 +194,7 @@ public class DatasetWizardController extends BaseController { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Import was unsuccessful.")); } } catch (Exception e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Import was unsuccessful.")); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java index 7a6f11416..d1c9582aa 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/EmailConfirmation.java @@ -36,7 +36,11 @@ public class EmailConfirmation { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); } catch (HasConfirmedEmailException | TokenExpiredException ex) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); + if (ex instanceof TokenExpiredException) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); + } else { + return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); + } } } @@ -48,6 +52,9 @@ public class EmailConfirmation { this.emailConfirmationManager.sendConfirmationEmail(email, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); } catch (Exception ex) { + if (ex instanceof HasConfirmedEmailException) { + return ResponseEntity.status(HttpStatus.FOUND).body(new ResponseItem().status(ApiMessageCode.WARN_MESSAGE)); + } return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/ExternalDatasets.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/ExternalDatasets.java index 532cacdac..642ff7f60 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/ExternalDatasets.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/ExternalDatasets.java @@ -62,8 +62,9 @@ public class ExternalDatasets extends BaseController { @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/externaldatasets"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> create(@RequestBody eu.eudat.models.data.externaldataset.ExternalDatasetModel externalDatasetModel, Principal principal) throws Exception { + ResponseEntity> create(@RequestBody eu.eudat.models.data.externaldataset.ExternalDatasetModel externalDatasetModel, Principal principal) throws Exception { ExternalDataset externalDataset = this.externalDatasetManager.create(externalDatasetModel, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(externalDataset).status(ApiMessageCode.SUCCESS_MESSAGE)); + ExternalDatasetListingModel externalDatasetListingModel = new ExternalDatasetListingModel().fromDataModel(externalDataset); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(externalDatasetListingModel).status(ApiMessageCode.SUCCESS_MESSAGE)); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/LanguageController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/LanguageController.java new file mode 100644 index 000000000..440922b11 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/LanguageController.java @@ -0,0 +1,58 @@ +package eu.eudat.controllers; + +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.security.Principal; +import eu.eudat.types.ApiMessageCode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.io.*; +import java.util.UUID; + +@RestController +@CrossOrigin +@RequestMapping(value = {"/api/language/"}) +public class LanguageController { + + Environment environment; + + @Autowired + public LanguageController(Environment environment) { + this.environment = environment; + } + + @RequestMapping(value = "{lang}", method = RequestMethod.GET) + public ResponseEntity getLanguage(@PathVariable String lang) throws IOException { + + String fileName = this.environment.getProperty("language.path") + lang + ".json"; + InputStream is = new FileInputStream(fileName); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentLength(is.available()); + responseHeaders.setContentType(MediaType.APPLICATION_JSON); + responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName); + responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); + responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); + + byte[] content = new byte[is.available()]; + is.read(content); + is.close(); + + return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); + } + + @RequestMapping(value = "update/{lang}", method = RequestMethod.POST) + public @ResponseBody + ResponseEntity> updateLang(@PathVariable String lang, @RequestBody String json) throws Exception { + String fileName = this.environment.getProperty("language.path") + lang + ".json"; + OutputStream os = new FileOutputStream(fileName); + os.write(json.getBytes()); + os.close(); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java index 954ab00e2..78304aa20 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java @@ -1,6 +1,6 @@ package eu.eudat.controllers; -import eu.eudat.core.logger.Logger; + import eu.eudat.exceptions.security.NullEmailException; import eu.eudat.logic.managers.UserManager; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; @@ -28,6 +28,8 @@ import eu.eudat.models.data.login.Credentials; import eu.eudat.models.data.login.LoginInfo; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -42,6 +44,7 @@ import java.security.GeneralSecurityException; @CrossOrigin @RequestMapping(value = "api/auth") public class Login { + private static final Logger logger = LoggerFactory.getLogger(Login.class); private CustomAuthenticationProvider customAuthenticationProvider; private AuthenticationService nonVerifiedUserAuthenticationService; @@ -53,13 +56,13 @@ public class Login { private ConfigurableProviderTokenValidator configurableProviderTokenValidator; private ConfigLoader configLoader; - private Logger logger; +// private Logger logger; private UserManager userManager; @Autowired public Login(CustomAuthenticationProvider customAuthenticationProvider, AuthenticationService nonVerifiedUserAuthenticationService, TwitterTokenValidator twitterTokenValidator, LinkedInTokenValidator linkedInTokenValidator, B2AccessTokenValidator b2AccessTokenValidator, - ORCIDTokenValidator orcidTokenValidator, OpenAIRETokenValidator openAIRETokenValidator, ConfigurableProviderTokenValidator configurableProviderTokenValidator, ConfigLoader configLoader, UserManager userManager, Logger logger) { + ORCIDTokenValidator orcidTokenValidator, OpenAIRETokenValidator openAIRETokenValidator, ConfigurableProviderTokenValidator configurableProviderTokenValidator, ConfigLoader configLoader, UserManager userManager/*, Logger logger*/) { this.customAuthenticationProvider = customAuthenticationProvider; this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService; this.twitterTokenValidator = twitterTokenValidator; @@ -69,7 +72,7 @@ public class Login { this.openAIRETokenValidator = openAIRETokenValidator; this.configurableProviderTokenValidator = configurableProviderTokenValidator; this.configLoader = configLoader; - this.logger = logger; +// this.logger = logger; this.userManager = userManager; } @@ -77,7 +80,7 @@ public class Login { @RequestMapping(method = RequestMethod.POST, value = {"/externallogin"}, consumes = "application/json", produces = "application/json") public @ResponseBody ResponseEntity> externallogin(@RequestBody LoginInfo credentials) throws GeneralSecurityException, NullEmailException { - this.logger.info(credentials, "Trying To Login With " + credentials.getProvider()); + logger.info("Trying To Login With " + credentials.getProvider()); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(customAuthenticationProvider.authenticate(credentials)).status(ApiMessageCode.SUCCESS_MESSAGE)); } @@ -85,7 +88,7 @@ public class Login { @RequestMapping(method = RequestMethod.POST, value = {"/nativelogin"}, consumes = "application/json", produces = "application/json") public @ResponseBody ResponseEntity> nativelogin(@RequestBody Credentials credentials) throws NullEmailException { - this.logger.info(credentials.getUsername(), "Trying To Login"); + logger.info(credentials.getUsername() + " Trying To Login"); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(userManager.authenticate(this.nonVerifiedUserAuthenticationService, credentials)).status(ApiMessageCode.SUCCESS_MESSAGE)); } @@ -128,7 +131,7 @@ public class Login { @RequestMapping(method = RequestMethod.POST, value = {"/me"}, consumes = "application/json", produces = "application/json") public @ResponseBody ResponseEntity> authMe(Principal principal) throws NullEmailException { - this.logger.info(principal, "Getting Me"); + logger.info(principal + " Getting Me"); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(this.nonVerifiedUserAuthenticationService.Touch(principal.getToken())).status(ApiMessageCode.NO_MESSAGE)); } @@ -137,7 +140,7 @@ public class Login { public @ResponseBody ResponseEntity> logout(Principal principal) { this.nonVerifiedUserAuthenticationService.Logout(principal.getToken()); - this.logger.info(principal, "Logged Out"); + logger.info(principal + " Logged Out"); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Organisations.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Organisations.java index 76b5557f3..2158b892c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Organisations.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Organisations.java @@ -2,12 +2,10 @@ package eu.eudat.controllers; import eu.eudat.data.query.items.table.organisations.OrganisationsTableRequest; import eu.eudat.logic.managers.OrganisationsManager; -import eu.eudat.logic.proxy.config.ExternalUrlCriteria; import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; import eu.eudat.logic.proxy.config.exceptions.NoURLFound; import eu.eudat.logic.services.ApiContext; import eu.eudat.models.data.dmp.Organisation; -import eu.eudat.models.data.external.OrganisationsExternalSourcesModel; import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; @@ -19,7 +17,6 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; -import java.util.Map; @RestController @@ -28,6 +25,8 @@ import java.util.Map; public class Organisations extends BaseController { private OrganisationsManager organisationsManager; + private ApiContext apiContext; + @Autowired public Organisations(ApiContext apiContext, OrganisationsManager organisationsManager) { super(apiContext); @@ -36,13 +35,11 @@ public class Organisations extends BaseController { @RequestMapping(method = RequestMethod.GET, value = {"/external/organisations"}, produces = "application/json") public @ResponseBody - ResponseEntity> listExternalOrganisations( + ResponseEntity>> listExternalOrganisations( @RequestParam(value = "query", required = false) String query, @RequestParam(value = "type", required = false) String type ) throws HugeResultSet, NoURLFound { - ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = this.getApiContext().getOperationsContext().getRemoteFetcher().getOrganisations(externalUrlCriteria, type); - OrganisationsExternalSourcesModel organisationsExternalSourcesModel = new OrganisationsExternalSourcesModel().fromExternalItem(remoteRepos); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(organisationsExternalSourcesModel).status(ApiMessageCode.NO_MESSAGE)); + List organisations = organisationsManager.getCriteriaWithExternal(query, type); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(organisations).status(ApiMessageCode.NO_MESSAGE)); } @RequestMapping(method = RequestMethod.POST, value = {"/internal/organisations"}, produces = "application/json") diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java index adedfcb4f..727d4f0bf 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java @@ -3,11 +3,13 @@ package eu.eudat.controllers; import eu.eudat.data.entities.Funder; import eu.eudat.data.entities.Project; -import eu.eudat.logic.managers.*; +import eu.eudat.logic.managers.DatasetManager; +import eu.eudat.logic.managers.QuickWizardManager; import eu.eudat.logic.services.ApiContext; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.dmp.DataManagementPlan; import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.quickwizard.DatasetCreateWizardModel; import eu.eudat.models.data.quickwizard.DatasetDescriptionQuickWizardModel; import eu.eudat.models.data.quickwizard.QuickWizardModel; import eu.eudat.models.data.security.Principal; @@ -16,7 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import eu.eudat.models.data.quickwizard.DatasetCreateWizardModel; import javax.transaction.Transactional; import javax.validation.Valid; @@ -47,7 +48,6 @@ public class QuickWizardController extends BaseController { if (quickWizard.getFunder() == null) { throw new Exception("Funder is a mandatory entity"); } else if (quickWizard.getFunder().getExistFunder() == null && quickWizard.getFunder().getLabel() == null) { - // funderEntity = null; throw new Exception("Funder is a mandatory entity"); } else if (quickWizard.getFunder().getExistFunder() == null && quickWizard.getFunder().getLabel() != null) { funderEntity = this.quickWizardManager.createOrUpdate(quickWizard.getFunder().toDataFunder(), principal); @@ -57,7 +57,11 @@ public class QuickWizardController extends BaseController { eu.eudat.data.entities.Grant grantEntity; //Create Grant - if (quickWizard.getGrant().getExistGrant() == null) { + if (quickWizard.getGrant() == null) { + throw new Exception("Grant is a mandatory entity"); + } else if (quickWizard.getGrant().getExistGrant() == null && quickWizard.getGrant().getLabel() == null) { + throw new Exception("Grant is a mandatory entity"); + } else if (quickWizard.getGrant().getExistGrant() == null) { grantEntity = this.quickWizardManager.createOrUpdate(quickWizard.getGrant().toDataGrant(), principal); } else { grantEntity = quickWizard.getGrant().getExistGrant().toDataModel(); @@ -68,17 +72,15 @@ public class QuickWizardController extends BaseController { if (quickWizard.getProject().getExistProject() == null && quickWizard.getProject().getLabel() == null) { projectEntity = null; - } else if (quickWizard.getProject().getExistProject() == null && quickWizard.getProject().getLabel() != null){ + } else if (quickWizard.getProject().getExistProject() == null && quickWizard.getProject().getLabel() != null) { projectEntity = this.quickWizardManager.createOrUpdate(quickWizard.getProject().toDataProject(), principal); } else { projectEntity = quickWizard.getProject().getExistProject().toDataModel(); } //Create Dmp - eu.eudat.data.entities.DMP dmpEntity = this.quickWizardManager.createOrUpdate( - quickWizard.getDmp().toDataDmp(grantEntity, projectEntity, principal), - funderEntity, - principal); + DataManagementPlan dataManagementPlan = quickWizard.getDmp().toDataDmp(grantEntity, projectEntity, principal); + eu.eudat.data.entities.DMP dmpEntity = this.quickWizardManager.createOrUpdate(dataManagementPlan, funderEntity, principal); //Create Datasets quickWizard.getDmp().setId(dmpEntity.getId()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Registries.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Registries.java index 6289d4f0f..c0a5a58b9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Registries.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Registries.java @@ -42,10 +42,10 @@ public class Registries extends BaseController { @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/registries"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> create(@RequestBody RegistryModel registryModel, Principal principal) throws Exception { + ResponseEntity> create(@RequestBody RegistryModel registryModel, Principal principal) throws Exception { Registry registry = this.registryManager.create(registryModel, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(registry).status(ApiMessageCode.SUCCESS_MESSAGE)); + RegistryModel registryModel1 = new RegistryModel().fromDataModel(registry); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(registryModel1).status(ApiMessageCode.SUCCESS_MESSAGE)); } - } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Services.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Services.java index 02bfd279e..d24928ca1 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Services.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Services.java @@ -43,9 +43,10 @@ public class Services extends BaseController { @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/services"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> create(@RequestBody ServiceModel serviceModel, Principal principal) throws Exception { + ResponseEntity> create(@RequestBody ServiceModel serviceModel, Principal principal) throws Exception { Service service = serviceManager.create(serviceModel, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(service).status(ApiMessageCode.SUCCESS_MESSAGE)); + ServiceModel serviceModel1 = new ServiceModel().fromDataModel(service); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(serviceModel1).status(ApiMessageCode.SUCCESS_MESSAGE)); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerErrorHandler.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerErrorHandler.java index 55ff5e514..02054bdba 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerErrorHandler.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerErrorHandler.java @@ -4,11 +4,12 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; -import eu.eudat.core.logger.Logger; import eu.eudat.core.models.exception.ApiExceptionLoggingModel; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -27,13 +28,14 @@ import java.util.Map; @ControllerAdvice @Priority(5) public class ControllerErrorHandler { + private static final Logger logger = LoggerFactory.getLogger(ControllerErrorHandler.class); - private Logger logger; +// private Logger logger; - @Autowired + /*@Autowired public ControllerErrorHandler(Logger logger) { this.logger = logger; - } + }*/ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @@ -49,12 +51,11 @@ public class ControllerErrorHandler { exceptionMap.put("exception", json); apiExceptionLoggingModel.setData(ow.writeValueAsString(exceptionMap)); } catch (JsonProcessingException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } apiExceptionLoggingModel.setMessage(ex.getMessage()); apiExceptionLoggingModel.setType(LoggingType.ERROR); - ex.printStackTrace(); - this.logger.error(apiExceptionLoggingModel); + logger.error(ex.getMessage(), ex); return new ResponseItem().message(ex.getMessage()).status(ApiMessageCode.DEFAULT_ERROR_MESSAGE); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerUnauthorisedHandler.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerUnauthorisedHandler.java index 72e02ad89..0a8599265 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerUnauthorisedHandler.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/controllerhandler/ControllerUnauthorisedHandler.java @@ -1,7 +1,8 @@ package eu.eudat.controllers.controllerhandler; -import eu.eudat.core.logger.Logger; import eu.eudat.exceptions.security.UnauthorisedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; @@ -18,19 +19,19 @@ import javax.annotation.Priority; @ControllerAdvice @Priority(4) public class ControllerUnauthorisedHandler { - - private Logger logger; + private static final Logger logger = LoggerFactory.getLogger(ControllerUnauthorisedHandler.class); +// private Logger logger; @Autowired - public ControllerUnauthorisedHandler(Logger logger) { - this.logger = logger; + public ControllerUnauthorisedHandler(/*Logger logger*/) { +// this.logger = logger; } @ExceptionHandler(UnauthorisedException.class) @ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseBody public void processValidationError(UnauthorisedException ex) { - this.logger.error(ex, ex.getMessage()); + logger.error(ex.getMessage(), ex); return; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/interceptors/RequestInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/interceptors/RequestInterceptor.java index 7bf712829..24d0278e3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/interceptors/RequestInterceptor.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/interceptors/RequestInterceptor.java @@ -2,6 +2,8 @@ package eu.eudat.controllers.interceptors; import eu.eudat.logic.services.helpers.LoggerService; import eu.eudat.types.WarningLevel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; @@ -15,19 +17,19 @@ import java.util.Date; */ @Component public class RequestInterceptor extends HandlerInterceptorAdapter { - - private LoggerService loggerService; + private static final Logger logger = LoggerFactory.getLogger(RequestInterceptor.class); +// private LoggerService loggerService; @Autowired - public RequestInterceptor(LoggerService loggerService) { - this.loggerService = loggerService; + public RequestInterceptor(/*LoggerService loggerService*/) { +// this.loggerService = loggerService; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String reqUri = request.getRequestURI(); - this.loggerService.log("Call to " + reqUri + " method: " + request.getMethod() + " at: " + new Date(), WarningLevel.INFO); + logger.info("Call to " + reqUri + " method: " + request.getMethod() + " at: " + new Date(), WarningLevel.INFO); return super.preHandle(request, response, handler); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/BuilderFactoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/BuilderFactoryImpl.java index 4bdaba8f3..9a99fcc9f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/BuilderFactoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/BuilderFactoryImpl.java @@ -7,9 +7,7 @@ import eu.eudat.logic.builders.model.criteria.RegistryCriteriaBuilder; import eu.eudat.logic.builders.model.models.*; import org.springframework.stereotype.Service; -/** - * Created by ikalyvas on 2/15/2018. - */ + @Service("builderFactory") public class BuilderFactoryImpl implements BuilderFactory { @@ -29,6 +27,7 @@ public class BuilderFactoryImpl implements BuilderFactory { if (tClass.equals(ResearcherBuilder.class)) return (T) new ResearcherBuilder(); if (tClass.equals(ExternalDatasetCriteriaBuilder.class)) return (T) new ExternalDatasetCriteriaBuilder(); if (tClass.equals(RecentActivityDataBuilder.class)) return (T) new RecentActivityDataBuilder(); + if (tClass.equals(OrganisationBuilder.class)) return (T) new OrganisationBuilder(); return null; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/FunderBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/FunderBuilder.java index 0bbcc235f..ae8414d49 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/FunderBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/FunderBuilder.java @@ -17,6 +17,7 @@ public class FunderBuilder extends Builder { private Date modified; private Integer type; private String source; + private String key; public FunderBuilder id(UUID id) { this.id = id; @@ -63,6 +64,11 @@ public class FunderBuilder extends Builder { return this; } + public FunderBuilder key(String key) { + this.key = key; + return this; + } + @Override public Funder build() { Funder funder = new Funder(); @@ -75,6 +81,7 @@ public class FunderBuilder extends Builder { funder.setModified(modified); funder.setType(type); funder.setSource(source); + funder.setKey(key); return funder; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/GrantBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/GrantBuilder.java index 12f87f4d9..cd8d57df2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/GrantBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/GrantBuilder.java @@ -9,9 +9,6 @@ import java.util.Date; import java.util.List; import java.util.UUID; -/** - * Created by ikalyvas on 2/15/2018. - */ public class GrantBuilder extends Builder { private UUID id; @@ -44,6 +41,8 @@ public class GrantBuilder extends Builder { private String source; + private String key; + public GrantBuilder id(UUID id) { this.id = id; return this; @@ -119,6 +118,11 @@ public class GrantBuilder extends Builder { return this; } + public GrantBuilder key(String key) { + this.key = key; + return this; + } + @Override public Grant build() { Grant grant = new Grant(); @@ -137,6 +141,7 @@ public class GrantBuilder extends Builder { grant.setCreationUser(creationUser); grant.setStartDate(startDate); grant.setSource(source); + grant.setKey(key); return grant; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/OrganisationBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/OrganisationBuilder.java new file mode 100644 index 000000000..04e2ab7e8 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/OrganisationBuilder.java @@ -0,0 +1,88 @@ +package eu.eudat.logic.builders.model.models; + +import eu.eudat.logic.builders.Builder; +import eu.eudat.models.data.dmp.Organisation; + +public class OrganisationBuilder extends Builder { + private String label; + private String name; + private String id; + private String reference; + private int status; + private String tag; + private String key; + + public String getLabel() { + return label; + } + + public OrganisationBuilder label(String label) { + this.label = label; + return this; + } + + public String getName() { + return name; + } + + public OrganisationBuilder name(String name) { + this.name = name; + return this; + } + + public String getId() { + return id; + } + + public OrganisationBuilder id(String id) { + this.id = id; + return this; + } + + public String getReference() { return reference; } + + public OrganisationBuilder reference(String reference) { + this.reference = reference; + return this; + } + + public int getStatus() { + return status; + } + + public OrganisationBuilder status(int status) { + this.status = status; + return this; + } + + public String getTag() { + return tag; + } + + public OrganisationBuilder tag(String tag) { + this.tag = tag; + return this; + } + + public String getKey() { + return key; + } + + public OrganisationBuilder key(String key) { + this.key = key; + return this; + } + + @Override + public Organisation build() { + Organisation Organisation = new Organisation(); + Organisation.setId(id); + Organisation.setReference(reference); + Organisation.setLabel(label); + Organisation.setName(name); + Organisation.setStatus(status); + Organisation.setTag(tag); + Organisation.setKey(key); + return Organisation; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ProjectBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ProjectBuilder.java index d0741d631..a0560d5d5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ProjectBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ProjectBuilder.java @@ -28,6 +28,7 @@ public class ProjectBuilder extends Builder { private Date modified; private String description; private String source; + private String key; public ProjectBuilder id(UUID id) { this.id = id; @@ -109,6 +110,11 @@ public class ProjectBuilder extends Builder { return this; } + public ProjectBuilder key(String key) { + this.key = key; + return this; + } + @Override public Project build() { Project project = new Project(); @@ -127,6 +133,7 @@ public class ProjectBuilder extends Builder { project.setCreationUser(creationUser); project.setStartDate(startDate); project.setSource(source); + project.setKey(key); return project; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ResearcherBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ResearcherBuilder.java index ba001431d..c8f9f0084 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ResearcherBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/ResearcherBuilder.java @@ -3,15 +3,14 @@ package eu.eudat.logic.builders.model.models; import eu.eudat.logic.builders.Builder; import eu.eudat.models.data.dmp.Researcher; -/** - * Created by ikalyvas on 3/6/2018. - */ public class ResearcherBuilder extends Builder { private String label; private String name; private String id; + private String reference; private int status; private String tag; + private String key; public String getLabel() { return label; @@ -40,6 +39,13 @@ public class ResearcherBuilder extends Builder { return this; } + public String getReference() { return reference; } + + public ResearcherBuilder reference(String reference) { + this.reference = reference; + return this; + } + public int getStatus() { return status; } @@ -58,14 +64,25 @@ public class ResearcherBuilder extends Builder { return this; } + public String getKey() { + return key; + } + + public ResearcherBuilder key(String key) { + this.key = key; + return this; + } + @Override public Researcher build() { Researcher researcher = new Researcher(); researcher.setId(id); + researcher.setReference(reference); researcher.setLabel(label); researcher.setName(name); researcher.setStatus(status); researcher.setTag(tag); + researcher.setKey(key); return researcher; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java index d351e492b..281ae0147 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java @@ -80,7 +80,7 @@ public class DashBoardManager { List roles = new LinkedList<>(); CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated(dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).countAsync() .whenComplete((dmpsStats, throwable) -> statistics.setTotalDataManagementPlanCount(dmpsStats)); - CompletableFuture datasetFuture = datasetRepository.getAuthenticated(datasetRepository.getWithCriteria(datasetCriteria), user).countAsync() + CompletableFuture datasetFuture = datasetRepository.getAuthenticated(datasetRepository.getWithCriteria(datasetCriteria), user, roles).countAsync() .whenComplete((datasetsStats, throwable) -> statistics.setTotalDataSetCount(datasetsStats)); CompletableFuture grantFuture = grantRepository.getAuthenticated(grantRepository.getWithCriteria(grantCriteria), user).countAsync() .whenComplete((grantsStats, throwable) -> statistics.setTotalGrantCount(grantsStats)); @@ -113,7 +113,7 @@ public class DashBoardManager { .selectAsync(item -> recentActivityDataBuilder.label(item.getLabel()).timestamp(item.getModified()).id(item.getId().toString()).build()) .whenComplete((dmpActivities, throwable) -> activity.setRecentDmpActivities(dmpActivities)); - CompletableFuture> datasets = datasetRepository.getAuthenticated(datasetRepository.getWithCriteria(datasetCriteria), user) + CompletableFuture> datasets = datasetRepository.getAuthenticated(datasetRepository.getWithCriteria(datasetCriteria), user, roles) .withHint("datasetRecentActivity") .orderBy((builder, root) -> builder.desc(root.get("modified"))) .take(numberofactivities) @@ -132,7 +132,6 @@ public class DashBoardManager { } public List searchUserData(String like, Principal principal) { - RecentActivity activity = new RecentActivity(); UserInfo user = new UserInfo(); user.setId(principal.getId()); DMPDao dataManagementPlanRepository = databaseRepository.getDmpDao(); @@ -141,29 +140,53 @@ public class DashBoardManager { List roles = new LinkedList<>(); List searchBarItems = new LinkedList<>(); - CompletableFuture> dmps = dataManagementPlanRepository.getAuthenticated(dataManagementPlanRepository.asQueryable(), principal.getId(), roles) - .withHint("dmpRecentActivity") + + CompletableFuture> publicDmps = dataManagementPlanRepository.asQueryable() .where((builder, root) -> builder.like(builder.upper(root.get("label")), "%" + like.toUpperCase() + "%")) + .where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue())) + .where((builder, root) -> builder.equal(root.get("isPublic"), true)) .orderBy((builder, root) -> builder.desc(root.get("modified"))) - .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DMP.getValue())) + .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DMP.getValue(), true)) .whenComplete((dmpItems, throwable) -> searchBarItems.addAll(dmpItems)); - CompletableFuture> datasets = datasetRepository.getAuthenticated(datasetRepository.asQueryable(), user) - .withHint("datasetRecentActivity") + CompletableFuture> publicDatasets = datasetRepository.asQueryable() .where((builder, root) -> builder.like(builder.upper(root.get("label")), "%" + like.toUpperCase() + "%")) + .where((builder, root) -> builder.equal(root.get("status"), Dataset.Status.FINALISED.getValue())) + .where((builder, root) -> builder.equal(root.get("dmp").get("isPublic"), true)) .orderBy((builder, root) -> builder.desc(root.get("modified"))) - .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DATASET.getValue())) + .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DATASET.getValue(), true)) .whenComplete((dataSetItems, throwable) -> searchBarItems.addAll(dataSetItems)); - CompletableFuture> grants = grantRepository.getAuthenticated(grantRepository.asQueryable(), user) - .withHint("grantRecentActivity") - .where((builder, root) -> builder.like(builder.upper(root.get("label")), "%" + like.toUpperCase() + "%")) - .orderBy((builder, root) -> builder.desc(root.get("modified"))) - .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.GRANT.getValue())) - .whenComplete((grantItems, throwable) -> searchBarItems.addAll(grantItems)); + if (principal.getId() != null) { + CompletableFuture> dmps = dataManagementPlanRepository.getAuthenticated(dataManagementPlanRepository.asQueryable(), principal.getId(), roles) + .withHint("dmpRecentActivity") + .where((builder, root) -> builder.like(builder.upper(root.get("label")), "%" + like.toUpperCase() + "%")) + .where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue())) + .orderBy((builder, root) -> builder.desc(root.get("modified"))) + .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DMP.getValue(), false)) + .whenComplete((dmpItems, throwable) -> searchBarItems.addAll(dmpItems)); + + CompletableFuture> datasets = datasetRepository.getAuthenticated(datasetRepository.asQueryable(), user, roles) + .withHint("datasetRecentActivity") + .where((builder, root) -> builder.like(builder.upper(root.get("label")), "%" + like.toUpperCase() + "%")) + .where((builder, root) -> builder.notEqual(root.get("status"), Dataset.Status.DELETED.getValue())) + .where((builder, root) -> builder.notEqual(root.get("status"), Dataset.Status.CANCELED.getValue())) + .orderBy((builder, root) -> builder.desc(root.get("modified"))) + .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DATASET.getValue(), false)) + .whenComplete((dataSetItems, throwable) -> searchBarItems.addAll(dataSetItems)); + + CompletableFuture> grants = grantRepository.getAuthenticated(grantRepository.asQueryable(), user) + .withHint("grantRecentActivity") + .where((builder, root) -> builder.like(builder.upper(root.get("label")), "%" + like.toUpperCase() + "%")) + .orderBy((builder, root) -> builder.desc(root.get("modified"))) + .selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.GRANT.getValue(), false)) + .whenComplete((grantItems, throwable) -> searchBarItems.addAll(grantItems)); + + CompletableFuture.allOf(grants, dmps, datasets, publicDmps, publicDatasets).join(); + } else { + CompletableFuture.allOf(publicDmps, publicDatasets).join(); + } - CompletableFuture.allOf(grants, dmps, datasets).join(); return searchBarItems; } - } 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 8dde96a2d..d4aef39e0 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 @@ -1,5 +1,6 @@ package eu.eudat.logic.managers; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.configurations.dynamicgrant.DynamicGrantConfiguration; import eu.eudat.configurations.dynamicgrant.entities.Property; @@ -49,6 +50,8 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.core.io.FileSystemResource; @@ -68,15 +71,14 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import java.io.*; import java.math.BigInteger; -import java.net.URL; import java.nio.file.Files; -import java.nio.file.Paths; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @Component public class DataManagementPlanManager { + private static final Logger logger = LoggerFactory.getLogger(DataManagementPlanManager.class); private ApiContext apiContext; private DatasetManager datasetManager; @@ -105,7 +107,6 @@ public class DataManagementPlanManager { CompletableFuture itemsFuture; if (fieldsGroup.equals("listing")) { - itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) .selectAsync(item -> { item.setDataset( @@ -119,15 +120,17 @@ public class DataManagementPlanManager { return new DataManagementPlanListingModel().fromDataModelDatasets(item); }) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); + } else if (fieldsGroup.equals("autocomplete")) { + itemsFuture = pagedItems + .selectAsync(item -> new DataManagementPlanListingModel().fromDataModelAutoComplete(item)) + .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } else { itemsFuture = pagedItems .selectAsync(item -> new DataManagementPlanListingModel().fromDataModelAssociatedProfiles(item)) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } - CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> - dataTable.setTotalCount(count) - ); + CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count)); CompletableFuture.allOf(itemsFuture, countFuture).join(); return dataTable; } @@ -311,7 +314,7 @@ public class DataManagementPlanManager { try { wordBuilder.build(document, pagedDatasetProfile, visibilityRuleService); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } // Page break at the end of the Dataset. XWPFParagraph parBreakDataset = document.createParagraph(); @@ -341,34 +344,31 @@ public class DataManagementPlanManager { return this.datasetManager.convertToPDF(file, environment, fileName); }*/ - public eu.eudat.models.data.dmp.DataManagementPlan getSingle(String id, Principal principal, DynamicGrantConfiguration dynamicGrantConfiguration) throws InstantiationException, IllegalAccessException { + public eu.eudat.models.data.dmp.DataManagementPlan getSingle(String id, Principal principal) { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (dataManagementPlanEntity.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) - throw new UnauthorisedException(); - eu.eudat.models.data.dmp.DataManagementPlan datamanagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); - datamanagementPlan.fromDataModel(dataManagementPlanEntity); + if (dataManagementPlanEntity.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) { + if (!dataManagementPlanEntity.isPublic()) { + throw new UnauthorisedException(); + } + } + eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); + dataManagementPlan.fromDataModel(dataManagementPlanEntity); Map dmpProperties = dataManagementPlanEntity.getDmpProperties() != null ? new org.json.JSONObject(dataManagementPlanEntity.getDmpProperties()).toMap() : null; -// datamanagementPlan.setDynamicFields(dynamicGrantConfiguration.getFields().stream().map(item -> { -// DynamicFieldWithValue fieldWithValue = new DynamicFieldWithValue(); -// fieldWithValue.setId(item.getId()); -// fieldWithValue.setDependencies(item.getDependencies()); -// fieldWithValue.setName(item.getName()); -// fieldWithValue.setQueryProperty(item.getQueryProperty()); -// fieldWithValue.setRequired(item.getRequired()); -// return fieldWithValue; -// }).collect(Collectors.toList())); - if (dmpProperties != null && datamanagementPlan.getDynamicFields() != null) - datamanagementPlan.getDynamicFields().forEach(item -> { + if (dmpProperties != null && dataManagementPlan.getDynamicFields() != null) + dataManagementPlan.getDynamicFields().forEach(item -> { Map properties = (Map) dmpProperties.get(item.getId()); if (properties != null) item.setValue(new Tuple<>(properties.get("id"), properties.get("label"))); }); - return datamanagementPlan; + return dataManagementPlan; } - public DataManagementPlanOverviewModel getOverviewSingle(String id, Principal principal) throws InstantiationException, IllegalAccessException { + public DataManagementPlanOverviewModel getOverviewSingle(String id, Principal principal) throws Exception { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); + if (dataManagementPlanEntity.getStatus() == DMP.DMPStatus.DELETED.getValue()) { + throw new Exception("DMP is deleted."); + } if (dataManagementPlanEntity.getUsers() .stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) .collect(Collectors.toList()).size() == 0) @@ -478,10 +478,13 @@ public class DataManagementPlanManager { if (dataManagementPlan.getId() != null) { DMP dmp1 = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(dataManagementPlan.getId()); + if (!isUserOwnerOfDmp(dmp1, principal)) { + throw new Exception("User not being the creator is not authorized to edit this DMP."); + } List datasetList = new ArrayList<>(dmp1.getDataset()); for (Dataset dataset : datasetList) { if (dataManagementPlan.getProfiles().stream().filter(associatedProfile -> dataset.getProfile().getId().equals(associatedProfile.getId())).findAny().orElse(null) == null) - throw new Exception("Dataset Template for Dataest Description is missing from the DMP."); + throw new Exception("Dataset Template for Dataset Description is missing from the DMP."); } if (dataManagementPlan.getStatus() == (int) DMP.DMPStatus.FINALISED.getValue() && dmp1.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is finalized, therefore cannot be edited."); @@ -566,7 +569,7 @@ public class DataManagementPlanManager { } - public void assignUser(DMP dmp, UserInfo userInfo) { + private void assignUser(DMP dmp, UserInfo userInfo) { UserDMP userDMP = new UserDMP(); userDMP.setDmp(dmp); userDMP.setUser(userInfo); @@ -576,7 +579,9 @@ public class DataManagementPlanManager { public void newVersion(UUID uuid, DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { DMP oldDmp = databaseRepository.getDmpDao().find(uuid); - + if (!isUserOwnerOfDmp(oldDmp, principal)) { + throw new Exception("User not being the creator is not authorized to perform this action."); + } DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); LinkedList list = new LinkedList<>(); list.push(oldDmp.getGroupId()); @@ -587,7 +592,6 @@ public class DataManagementPlanManager { if (latestVersionDMP.get(0).getVersion().equals(oldDmp.getVersion())) { DMP newDmp = dataManagementPlan.toDataModel(); - UserInfo user = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build(); createOrganisationsIfTheyDontExist(newDmp, databaseRepository.getOrganisationDao()); createResearchersIfTheyDontExist(newDmp, databaseRepository.getResearcherDao(), user); @@ -644,7 +648,6 @@ public class DataManagementPlanManager { databaseRepository.getGrantDao().createOrUpdate(newDmp.getGrant()); newDmp = databaseRepository.getDmpDao().createOrUpdate(newDmp); - // Assign creator. assignUser(newDmp, user); copyDatasets(newDmp, databaseRepository.getDatasetDao()); } @@ -696,6 +699,7 @@ public class DataManagementPlanManager { if (grantEntity != null) grant.setId(grantEntity.getId()); else { grant.setType(Grant.GrantType.EXTERNAL.getValue()); + grant.setCreationUser(null); grantDao.createOrUpdate(grant); } } @@ -723,6 +727,7 @@ public class DataManagementPlanManager { if (projectEntity != null) project.setId(projectEntity.getId()); else { project.setType(Project.ProjectType.EXTERNAL.getValue()); + if (project.getId() == null) project.setId(UUID.randomUUID()); projectDao.createOrUpdate(project); } } @@ -785,11 +790,12 @@ public class DataManagementPlanManager { if (newDataset.getDatasetDataRepositories() != null) { newDataset.setDatasetDataRepositories(newDataset.getDatasetDataRepositories().stream().map(item -> { DataRepository dataRepository = new DataRepository(); - dataRepository.setId(item.getId()); + dataRepository.setId(item.getDataRepository().getId()); DatasetDataRepository datasetDataRepository = new DatasetDataRepository(); datasetDataRepository.setDataRepository(dataRepository); datasetDataRepository.setDataset(newDataset); + datasetDataRepository.setData(item.getData()); return datasetDataRepository; }).collect(Collectors.toSet())); } @@ -797,10 +803,11 @@ public class DataManagementPlanManager { if (newDataset.getDatasetExternalDatasets() != null) { newDataset.setDatasetExternalDatasets(newDataset.getDatasetExternalDatasets().stream().map(item -> { ExternalDataset externalDataset = new ExternalDataset(); - externalDataset.setId(item.getId()); + externalDataset.setId(item.getExternalDataset().getId()); DatasetExternalDataset datasetExternalDataset = new DatasetExternalDataset(); datasetExternalDataset.setExternalDataset(externalDataset); datasetExternalDataset.setDataset(newDataset); + datasetExternalDataset.setData(item.getData()); return datasetExternalDataset; }).collect(Collectors.toSet())); } @@ -820,6 +827,7 @@ public class DataManagementPlanManager { DatasetService datasetService = new DatasetService(); datasetService.setService(service); datasetService.setDataset(newDataset); + datasetService.setData(item.getData()); return datasetService; }).collect(Collectors.toSet())); } @@ -833,7 +841,7 @@ public class DataManagementPlanManager { } } - public FileEnvelope getXmlDocument(String id, Principal principal) throws InstantiationException, IllegalAccessException, IOException { + private FileEnvelope getXmlDocument(String id, Principal principal) throws InstantiationException, IllegalAccessException, IOException { ExportXmlBuilder xmlBuilder = new ExportXmlBuilder(); VisibilityRuleService visibilityRuleService = utilitiesService.getVisibilityRuleService(); eu.eudat.data.entities.DMP dmp = databaseRepository.getDmpDao().find(UUID.fromString(id)); @@ -868,14 +876,34 @@ public class DataManagementPlanManager { } dmpElement.appendChild(dmpProfileElement); + // Funder. + Element funder = xmlDoc.createElement("funder"); + Element funderLabel = xmlDoc.createElement("label"); + Element funderId = xmlDoc.createElement("id"); + funderLabel.setTextContent(dmp.getGrant().getFunder().getLabel()); + funderId.setTextContent(dmp.getGrant().getFunder().getId().toString()); + funder.appendChild(funderLabel); + funder.appendChild(funderId); + dmpElement.appendChild(funder); + // Grant. Element grant = xmlDoc.createElement("grant"); - Element label = xmlDoc.createElement("label"); - label.setTextContent(dmp.getGrant().getLabel()); - grant.appendChild(label); + Element grantLabel = xmlDoc.createElement("label"); Element grantId = xmlDoc.createElement("id"); + grantLabel.setTextContent(dmp.getGrant().getLabel()); grantId.setTextContent(dmp.getGrant().getId().toString()); + grant.appendChild(grantLabel); grant.appendChild(grantId); dmpElement.appendChild(grant); + // Project. + Element project = xmlDoc.createElement("project"); + Element projectLabel = xmlDoc.createElement("label"); + Element projectId = xmlDoc.createElement("id"); + projectLabel.setTextContent(dmp.getProject().getLabel()); + projectId.setTextContent(dmp.getProject().getId().toString()); + project.appendChild(projectLabel); + project.appendChild(projectId); + dmpElement.appendChild(project); + Element organisationsElement = xmlDoc.createElement("organisations"); for (Organisation organisation : dmp.getOrganisations()) { Element organisationElement = xmlDoc.createElement("organisation"); @@ -944,20 +972,21 @@ public class DataManagementPlanManager { return fileEnvelope; } - public ResponseEntity getRDAJsonDocument(String id, Principal principal) throws IOException { + public ResponseEntity getRDAJsonDocument(String id, DatasetManager datasetManager, Principal principal) throws IOException { eu.eudat.data.entities.DMP dmp = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (!dmp.isPublic() && dmp.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) + if (!dmp.isPublic() && dmp.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) throw new UnauthorisedException(); - RDAExportModel rdaExportModel = new RDAExportModel().fromDataModel(dmp); + RDAExportModel rdaExportModel = new RDAExportModel().fromDataModel(dmp, datasetManager); ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String fileName = dmp.getLabel(); fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); File file = new File(fileName); try { mapper.writeValue(file, rdaExportModel); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } InputStream resource = new FileInputStream(file); @@ -1015,7 +1044,7 @@ public class DataManagementPlanManager { DmpImportModel dmpImportModel = (DmpImportModel) jaxbUnmarshaller.unmarshal(in); dataManagementPlans.add(dmpImportModel); } catch (IOException | JAXBException ex) { - ex.printStackTrace(); + logger.error(ex.getMessage(), ex); } // TODO Iterate through the list of dataManagementPlans. // Creates new dataManagementPlan to fill it with the data model that was parsed from the xml. @@ -1078,7 +1107,7 @@ public class DataManagementPlanManager { //createOrUpdate(apiContext, dm, principal); - System.out.println(dm); + logger.info(dm.toString()); } return dataManagementPlans; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java index 1355b9884..983165034 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java @@ -21,6 +21,8 @@ import eu.eudat.models.data.listingmodels.DataManagementPlanProfileListingModel; import eu.eudat.models.data.security.Principal; import eu.eudat.queryable.QueryableList; import eu.eudat.logic.services.ApiContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; @@ -43,6 +45,7 @@ import org.w3c.dom.Element; */ @Component public class DataManagementProfileManager { + private static final Logger logger = LoggerFactory.getLogger(DataManagementProfileManager.class); private ApiContext apiContext; private DatabaseRepository databaseRepository; @@ -93,7 +96,7 @@ public class DataManagementProfileManager { public ResponseEntity getDocument(DataManagementPlanProfileListingModel dmpProfile, String label) throws IllegalAccessException, IOException, InstantiationException { FileEnvelope envelope = getXmlDocument(dmpProfile, label); InputStream resource = new FileInputStream(envelope.getFile()); - System.out.println("Mime Type of " + envelope.getFilename() + " is " + + logger.info("Mime Type of " + envelope.getFilename() + " is " + new MimetypesFileTypeMap().getContentType(envelope.getFile())); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(envelope.getFile().length()); @@ -124,7 +127,7 @@ public class DataManagementProfileManager { try { return xmlBuilder.build(convert(multiPartFile)); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return null; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java index 5b04ef777..ee76ea42c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java @@ -36,6 +36,8 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.core.io.FileSystemResource; @@ -73,6 +75,7 @@ import java.util.zip.ZipInputStream; @Component public class DatasetManager { + private static final Logger logger = LoggerFactory.getLogger(DatasetManager.class); private ApiContext apiContext; private DatabaseRepository databaseRepository; @@ -109,7 +112,9 @@ public class DatasetManager { } else items.where((builder, root) -> root.get("id").in(new UUID[]{UUID.randomUUID()})); } - QueryableList authItems = databaseRepository.getDatasetDao().getAuthenticated(items, userInfo); + List roles = new LinkedList<>(); + if (datasetTableRequest.getCriteria().getRole() != null) roles.add(datasetTableRequest.getCriteria().getRole()); + QueryableList authItems = databaseRepository.getDatasetDao().getAuthenticated(items, userInfo, roles); QueryableList pagedItems = PaginationManager.applyPaging(authItems, datasetTableRequest); DataTableData dataTable = new DataTableData(); @@ -172,7 +177,7 @@ public class DatasetManager { return dataTable; } - public DatasetWizardModel getSingle(String id) throws InstantiationException, IllegalAccessException, IOException { + public DatasetWizardModel getSingle(String id) { DatasetWizardModel dataset = new DatasetWizardModel(); eu.eudat.data.entities.Dataset datasetEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class)); eu.eudat.elastic.entities.Dataset datasetElastic; @@ -542,7 +547,7 @@ public class DatasetManager { public ResponseEntity getDocument(String id, VisibilityRuleService visibilityRuleService, String contentType) throws IllegalAccessException, IOException, InstantiationException { FileEnvelope envelope = getXmlDocument(id, visibilityRuleService); InputStream resource = new FileInputStream(envelope.getFile()); - System.out.println("Mime Type of " + envelope.getFilename() + " is " + + logger.info("Mime Type of " + envelope.getFilename() + " is " + new MimetypesFileTypeMap().getContentType(envelope.getFile())); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(envelope.getFile().length()); @@ -572,7 +577,7 @@ public class DatasetManager { DatasetImportPagedDatasetProfile datasetImport = (DatasetImportPagedDatasetProfile) jaxbUnmarshaller.unmarshal(in); importModel = datasetImport; } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } // Checks if XML datasetProfileId GroupId matches the one selected. @@ -583,7 +588,7 @@ public class DatasetManager { throw new Exception(); } } catch (Exception e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java index 7bff0808a..079359827 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java @@ -22,6 +22,8 @@ import eu.eudat.models.data.externaldataset.ExternalAutocompleteFieldModel; import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.queryable.QueryableList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.stereotype.Component; @@ -41,6 +43,7 @@ import java.io.*; @Component public class DatasetProfileManager { + private static final Logger logger = LoggerFactory.getLogger(DatasetProfileManager.class); private ApiContext apiContext; private DatabaseRepository databaseRepository; @@ -119,7 +122,7 @@ public class DatasetProfileManager { public ResponseEntity getDocument(eu.eudat.models.data.user.composite.DatasetProfile datasetProfile, String label) throws IllegalAccessException, IOException, InstantiationException { FileEnvelope envelope = getXmlDocument(datasetProfile, label); InputStream resource = new FileInputStream(envelope.getFile()); - System.out.println("Mime Type of " + envelope.getFilename() + " is " + + logger.info("Mime Type of " + envelope.getFilename() + " is " + new MimetypesFileTypeMap().getContentType(envelope.getFile())); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(envelope.getFile().length()); @@ -151,7 +154,7 @@ public class DatasetProfileManager { try { return xmlBuilder.build(convert(multiPartFile)); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return null; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DocumentManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DocumentManager.java index 1f7cfbee1..c50e987c7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DocumentManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DocumentManager.java @@ -13,6 +13,8 @@ import eu.eudat.models.data.user.composite.PagedDatasetProfile; import org.apache.commons.io.IOUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import org.springframework.core.io.FileSystemResource; import org.springframework.http.*; @@ -36,6 +38,7 @@ import java.util.zip.ZipInputStream; */ @Service public class DocumentManager { + private static final Logger logger = LoggerFactory.getLogger(DocumentManager.class); private ApiContext context; private DatasetManager datasetManager; @@ -104,12 +107,12 @@ public class DocumentManager { Map mediaResult = new RestTemplate().getForObject(environment.getProperty("pdf.converter.url") + "/api/v1/" + queueResult.get("id"), Map.class); - System.out.println("Status: " + mediaResult.get("status")); + logger.info("Status: " + mediaResult.get("status")); while (!mediaResult.get("status").equals("finished")) { Thread.sleep(500); mediaResult = new RestTemplate().getForObject(environment.getProperty("pdf.converter.url") + "api/v1/" + queueResult.get("id"), Map.class); - System.out.println("Polling"); + logger.info("Polling"); } RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java index 907ceac18..bf26fa3e4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/EmailConfirmationManager.java @@ -34,20 +34,21 @@ public class EmailConfirmationManager { .getDatabaseRepository().getLoginConfirmationEmailDao().asQueryable() .where((builder, root) -> builder.equal(root.get("token"), UUID.fromString(token))).getSingle(); - if (loginConfirmationEmail.getExpiresAt().compareTo(new Date()) < 0) - throw new TokenExpiredException("Token has expired."); - UserInfo user = databaseRepository.getUserInfoDao().asQueryable() .where((builder, root) -> builder.equal(root.get("id"), loginConfirmationEmail.getUserId())).getSingle(); if (user.getEmail() != null) throw new HasConfirmedEmailException("User already has confirmed his Email."); + if (loginConfirmationEmail.getExpiresAt().compareTo(new Date()) < 0) + throw new TokenExpiredException("Token has expired."); + loginConfirmationEmail.setIsConfirmed(true); // Checks if mail is used by another user. If it is, merges the new the old. - UserInfo oldUser = databaseRepository.getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), loginConfirmationEmail.getEmail())).getSingle(); - if (oldUser != null) { + Long existingUsers = databaseRepository.getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), loginConfirmationEmail.getEmail())).count(); + if (existingUsers > 0) { + UserInfo oldUser = databaseRepository.getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), loginConfirmationEmail.getEmail())).getSingle(); mergeNewUserToOld(user, oldUser); expireUserToken(user); databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java index 1db66f391..a14a1e8df 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java @@ -3,6 +3,7 @@ package eu.eudat.logic.managers; import eu.eudat.data.query.items.item.funder.FunderCriteriaRequest; import eu.eudat.logic.builders.model.models.FunderBuilder; import eu.eudat.logic.proxy.config.ExternalUrlCriteria; +import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; import eu.eudat.logic.proxy.config.exceptions.NoURLFound; import eu.eudat.logic.proxy.fetching.RemoteFetcher; @@ -47,6 +48,8 @@ public class FunderManager { eu.eudat.models.data.funder.Funder funder = apiContext.getOperationsContext().getBuilderFactory().getBuilder(FunderBuilder.class) .reference(externalListingItem.getRemoteId()).label(externalListingItem.getName()) .status(eu.eudat.data.entities.Funder.Status.fromInteger(0)) + .key(externalListingItem.getKey()) + .source(externalListingItem.getTag()) .build(); if (externalListingItem.getSource() != null) { funder.setSource(externalListingItem.getSource()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java index 03213aa87..e69ca22e6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java @@ -109,21 +109,24 @@ public class GrantManager { public List getCriteriaWithExternal(GrantCriteriaRequest grantCriteria, Principal principal) throws HugeResultSet, NoURLFound { eu.eudat.data.entities.UserInfo userInfo = new eu.eudat.data.entities.UserInfo(); userInfo.setId(principal.getId()); - if (grantCriteria.getCriteria().getFunderReference() != null && !grantCriteria.getCriteria().getFunderReference().trim().isEmpty()) { + /*if (grantCriteria.getCriteria().getFunderReference() != null && !grantCriteria.getCriteria().getFunderReference().trim().isEmpty()) { FunderCriteria funderCriteria = new FunderCriteria(); funderCriteria.setReference(grantCriteria.getCriteria().getFunderReference()); Funder funder = apiContext.getOperationsContext().getDatabaseRepository().getFunderDao().getWithCritetia(funderCriteria).getSingleOrDefault(); if (funder != null) { grantCriteria.getCriteria().setFunderId(funder.getId().toString()); } + }*/ + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(grantCriteria.getCriteria().getLike()); + if (grantCriteria.getCriteria().getFunderReference() != null) { + externalUrlCriteria.setFunderId(grantCriteria.getCriteria().getFunderReference()); + grantCriteria.getCriteria().setFunderReference(null); } grantCriteria.getCriteria().setReference("dmp:"); QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().getWithCriteria(grantCriteria.getCriteria()); QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().getAuthenticated(items, userInfo); List grants = authItems.select(item -> new Grant().fromDataModel(item)); - ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(grantCriteria.getCriteria().getLike()); - if (grantCriteria.getCriteria().getFunderReference() != null) externalUrlCriteria.setFunderId(grantCriteria.getCriteria().getFunderReference()); List> remoteRepos = remoteFetcher.getGrants(externalUrlCriteria); GrantsExternalSourcesModel grantsExternalSourcesModel = new GrantsExternalSourcesModel().fromExternalItem(remoteRepos); @@ -131,6 +134,7 @@ public class GrantManager { eu.eudat.models.data.grant.Grant grant = apiContext.getOperationsContext().getBuilderFactory().getBuilder(GrantBuilder.class) .reference(externalListingItem.getRemoteId()).label(externalListingItem.getName()) .description(externalListingItem.getDescription()).uri(externalListingItem.getUri()) + .key(externalListingItem.getKey()) .abbreviation(externalListingItem.getAbbreviation()).status(eu.eudat.data.entities.Grant.Status.fromInteger(0)) .source(externalListingItem.getTag()) .build(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java index 0f5d8617d..5e67be552 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java @@ -1,24 +1,25 @@ package eu.eudat.logic.managers; -import eu.eudat.data.dao.criteria.OrganisationCriteria; import eu.eudat.data.dao.entities.OrganisationDao; -import eu.eudat.data.entities.DMP; -import eu.eudat.data.query.items.table.dmp.DataManagmentPlanPublicTableRequest; import eu.eudat.data.query.items.table.organisations.OrganisationsTableRequest; +import eu.eudat.logic.builders.model.models.OrganisationBuilder; +import eu.eudat.logic.proxy.config.ExternalUrlCriteria; +import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; +import eu.eudat.logic.proxy.config.exceptions.NoURLFound; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.operations.DatabaseRepository; -import eu.eudat.models.HintedModelFactory; import eu.eudat.models.data.dmp.Organisation; +import eu.eudat.models.data.external.ExternalSourcesItemModel; +import eu.eudat.models.data.external.OrganisationsExternalSourcesModel; import eu.eudat.models.data.helpers.common.DataTableData; -import eu.eudat.models.data.listingmodels.DataManagementPlanListingModel; import eu.eudat.models.data.security.Principal; import eu.eudat.queryable.QueryableList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Component @@ -64,4 +65,21 @@ public class OrganisationsManager { return organisationDataTableData; } + + public List getCriteriaWithExternal(String query, String type) throws HugeResultSet, NoURLFound { + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); + List> remoteRepos = apiContext.getOperationsContext().getRemoteFetcher().getOrganisations(externalUrlCriteria, type); + OrganisationsExternalSourcesModel organisationsExternalSourcesModel = new OrganisationsExternalSourcesModel().fromExternalItem(remoteRepos); + List organisations = new LinkedList<>(); + for (ExternalSourcesItemModel externalListingItem : organisationsExternalSourcesModel) { + Organisation organisation = apiContext.getOperationsContext().getBuilderFactory().getBuilder(OrganisationBuilder.class) + .name(externalListingItem.getName()) + .reference(externalListingItem.getRemoteId()) + .tag(externalListingItem.getTag()) + .key(externalListingItem.getKey()) + .build(); + organisations.add(organisation); + } + return organisations.stream().distinct().collect(Collectors.toList()); + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java index bd9b494b0..6919a5de5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java @@ -48,6 +48,7 @@ public class ProjectManager { .reference(externalListingItem.getRemoteId()).label(externalListingItem.getName()) .description(externalListingItem.getDescription()).uri(externalListingItem.getUri()) .abbreviation(externalListingItem.getAbbreviation()).status(eu.eudat.data.entities.Project.Status.fromInteger(0)) + .key(externalListingItem.getKey()) .source(externalListingItem.getTag()) .build(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/QuickWizardManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/QuickWizardManager.java index b0a424c3f..d75c07603 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/QuickWizardManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/QuickWizardManager.java @@ -13,6 +13,7 @@ import org.springframework.stereotype.Component; import java.io.IOException; import java.text.ParseException; +import java.util.UUID; @Component public class QuickWizardManager { @@ -109,6 +110,7 @@ public class QuickWizardManager { eu.eudat.data.entities.Project projectEntity = databaseRepository.getProjectDao().getWithCritetia(criteria).getSingleOrDefault(); if (projectEntity != null) project.setId(projectEntity.getId()); else { + if (project.getId() == null) project.setId(UUID.randomUUID()); project.setType(Project.ProjectType.EXTERNAL.getValue()); databaseRepository.getProjectDao().createOrUpdate(project); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java index e09988e80..0d9104056 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java @@ -3,6 +3,8 @@ package eu.eudat.logic.managers; import eu.eudat.logic.builders.model.models.ResearcherBuilder; import eu.eudat.data.entities.Researcher; import eu.eudat.logic.proxy.config.ExternalUrlCriteria; +import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; +import eu.eudat.logic.utilities.helpers.ListHelper; import eu.eudat.models.data.external.ExternalSourcesItemModel; import eu.eudat.models.data.external.ResearchersExternalSourcesModel; import eu.eudat.data.query.items.item.researcher.ResearcherCriteriaRequest; @@ -17,7 +19,6 @@ import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.stream.Collectors; /** @@ -28,11 +29,13 @@ public class ResearcherManager { private ApiContext apiContext; private RemoteFetcher remoteFetcher; + private ConfigLoader configLoader; @Autowired - public ResearcherManager(ApiContext apiContext) { + public ResearcherManager(ApiContext apiContext, ConfigLoader configLoader) { this.apiContext = apiContext; this.remoteFetcher = apiContext.getOperationsContext().getRemoteFetcher(); + this.configLoader = configLoader; } public Researcher create(eu.eudat.models.data.researcher.Researcher researcher, Principal principal) throws Exception { @@ -46,6 +49,13 @@ public class ResearcherManager { QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getResearcherDao().getWithCriteria(researcherCriteriaRequest.getCriteria()); items.where((builder, root) -> builder.equal(root.get("creationUser").get("id"), principal.getId())); List researchers = items.select(item -> new eu.eudat.models.data.dmp.Researcher().fromDataModel(item)); + Map keyToSourceMap = configLoader.getKeyToSourceMap(); + for (eu.eudat.models.data.dmp.Researcher item : researchers) { + if (item.getKey().equals("Internal")) + item.setTag(item.getKey()); + else + item.setTag(keyToSourceMap.get(item.getKey())); + } ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(researcherCriteriaRequest.getCriteria().getName()); List> remoteRepos = remoteFetcher.getResearchers(externalUrlCriteria,null); ResearchersExternalSourcesModel researchersExternalSourcesModel = new ResearchersExternalSourcesModel().fromExternalItem(remoteRepos); @@ -53,8 +63,10 @@ public class ResearcherManager { eu.eudat.models.data.dmp.Researcher researcher = apiContext.getOperationsContext().getBuilderFactory().getBuilder(ResearcherBuilder.class) .label(externalListingItem.getAbbreviation()) .id(externalListingItem.getId()) + .reference(externalListingItem.getRemoteId()) .name(externalListingItem.getName()) .tag(externalListingItem.getTag()) + .key(externalListingItem.getKey()) .build(); researchers.add(researcher); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java index 8a935aa53..37a166027 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java @@ -5,10 +5,12 @@ import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.Con import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.util.List; +import java.util.Map; public interface ConfigLoader { ExternalUrls getExternalUrls(); List getRdaProperties(); XWPFDocument getDocument(); ConfigurableProviders getConfigurableProviders(); + Map getKeyToSourceMap(); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java index 934a472c4..14d5099f0 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DevelConfigLoader.java @@ -5,73 +5,81 @@ import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.logic.proxy.config.ExternalUrls; import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders; import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.*; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service("configLoader") @Profile("devel") public class DevelConfigLoader implements ConfigLoader { + private static final Logger logger = LoggerFactory.getLogger(DevelConfigLoader.class); private ExternalUrls externalUrls; private List rdaProperties; private XWPFDocument document; private ConfigurableProviders configurableProviders; + private Map keyToSourceMap; @Autowired private Environment environment; private void setExternalUrls() { String fileUrl = this.environment.getProperty("configuration.externalUrls"); - System.out.println("Loaded also config file: " + fileUrl); - String current = null; + logger.info("Loaded also config file: " + fileUrl); InputStream is = null; try { - current = new java.io.File(".").getCanonicalPath(); - JAXBContext jaxbContext = JAXBContext.newInstance(ExternalUrls.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///" + current + fileUrl).openStream(); + is = getClass().getClassLoader().getResource(fileUrl).openStream(); externalUrls = (ExternalUrls) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find resource in classpath", ex); } finally { try { if (is != null) is.close(); - } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + } catch (IOException | NullPointerException e) { + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } } private void setRdaProperties() { String filePath = environment.getProperty("configuration.rda"); - String current = null; BufferedReader reader; List rdaList = new LinkedList<>(); try { - current = new java.io.File(".").getCanonicalPath(); - reader = new BufferedReader(new FileReader(current + filePath)); + reader = new BufferedReader(new FileReader(getClass().getClassLoader().getResource(filePath).getFile())); String line = reader.readLine(); while (line != null) { rdaList.add(line); line = reader.readLine(); } reader.close(); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException | NullPointerException e) { + logger.error(e.getMessage(), e); } rdaProperties = rdaList; @@ -79,43 +87,63 @@ public class DevelConfigLoader implements ConfigLoader { private void setDocument() { String filePath = environment.getProperty("configuration.h2020template"); - String current = null; InputStream is = null; try { - current = new java.io.File(".").getCanonicalPath(); - is = new URL("file:///" + current + filePath).openStream(); + is = getClass().getClassLoader().getResource(filePath).openStream(); this.document = new XWPFDocument(is); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException | NullPointerException e) { + logger.error(e.getMessage(), e); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + filePath); + logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e); } } } - public void setConfigurableProviders() { + private void setConfigurableProviders() { String filePath = environment.getProperty("configuration.configurable_login_providers"); - String current = null; InputStream is = null; try { - current = new java.io.File(".").getCanonicalPath(); - is = new URL("file:///" + current + filePath).openStream(); + is = getClass().getClassLoader().getResource(filePath).openStream(); ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); this.configurableProviders = mapper.readValue(is, ConfigurableProviders.class); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException | NullPointerException e) { + logger.error(e.getMessage(), e); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + filePath); + logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e); } } } + private void setKeyToSourceMap() { + String filePath = this.environment.getProperty("configuration.externalUrls"); + logger.info("Loaded also config file: " + filePath); + Document doc = getXmlDocumentFromFilePath(filePath); + if (doc == null) { + this.keyToSourceMap = null; + return; + } + String xpathExpression = "//key"; + Map keysToSourceMap = new HashMap<>(); + List keys = getXmlValuesFromXPath(doc, xpathExpression); + keys = keys.stream().distinct().collect(Collectors.toList()); + for (String key : keys) { + String sourceExpression = String.format("//urlConfig[key='%s']/label", key); + List sources = getXmlValuesFromXPath(doc, sourceExpression); + if (sources.size() != 0) { + keysToSourceMap.put(key, sources.get(0)); + } + } + this.keyToSourceMap = keysToSourceMap; + } + + + public ExternalUrls getExternalUrls() { this.setExternalUrls(); return externalUrls; @@ -135,4 +163,52 @@ public class DevelConfigLoader implements ConfigLoader { this.setConfigurableProviders(); return configurableProviders; } + + public Map getKeyToSourceMap() { + this.setKeyToSourceMap(); + return keyToSourceMap; + } + + private Document getXmlDocumentFromFilePath(String filePath) { + InputStream is = null; + Document doc; + try { + is = getClass().getClassLoader().getResource(filePath).openStream(); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + doc = documentBuilder.parse(is); + return doc; + } catch (IOException | ParserConfigurationException | SAXException | NullPointerException e) { + logger.error(e.getMessage(), e); + } finally { + try { + if (is != null) { + is.close(); + } + } catch (IOException e) { + logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e); + } + } + return null; + } + + private List getXmlValuesFromXPath(Document doc, String expression) { + XPath xPath = XPathFactory.newInstance().newXPath(); + NodeList nodeList = null; + List values = new LinkedList<>(); + try { + nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET); + } catch (XPathExpressionException e) { + logger.error(e.getMessage(), e); + } + if (nodeList != null) { + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node.hasChildNodes()) { + values.add(nodeList.item(i).getChildNodes().item(0).getNodeValue()); + } + } + } + return values; + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ProductionConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ProductionConfigLoader.java index 57d16e2c0..9d53f645f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ProductionConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ProductionConfigLoader.java @@ -4,55 +4,68 @@ import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.logic.proxy.config.ExternalUrls; import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders; import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.*; import java.net.URL; import java.nio.file.Paths; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service("configLoader") @Profile({ "production", "staging" }) public class ProductionConfigLoader implements ConfigLoader { + private static final Logger logger = LoggerFactory.getLogger(ProductionConfigLoader.class); private ExternalUrls externalUrls; private List rdaProperties; private XWPFDocument document; private ConfigurableProviders configurableProviders; + private Map keyToSourceMap; @Autowired private Environment environment; private void setExternalUrls() { String fileUrl = this.environment.getProperty("configuration.externalUrls"); - System.out.println("Loaded also config file: " + fileUrl); + logger.info("Loaded also config file: " + fileUrl); String current = null; InputStream is = null; try { current = new java.io.File(".").getCanonicalPath(); - JAXBContext jaxbContext = JAXBContext.newInstance(ExternalUrls.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream(); externalUrls = (ExternalUrls) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { - ex.printStackTrace(); - System.out.println("Cannot find in folder" + current); + logger.error("Cannot find in folder" + current, ex); } finally { try { if (is != null) is.close(); } catch (IOException e) { - System.out.println("Warning: Could not close a stream after reading from file: " + fileUrl); + logger.warn("Warning: Could not close a stream after reading from file: " + fileUrl, e); } } } @@ -70,7 +83,7 @@ public class ProductionConfigLoader implements ConfigLoader { } reader.close(); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } rdaProperties = rdaList; @@ -78,28 +91,64 @@ public class ProductionConfigLoader implements ConfigLoader { private void setDocument() { String filePath = environment.getProperty("configuration.h2020template"); - String current = null; + InputStream is = null; try { - current = new java.io.File(".").getCanonicalPath(); - InputStream is = new URL(Paths.get(filePath).toUri().toURL().toString()).openStream(); + is = new URL(Paths.get(filePath).toUri().toURL().toString()).openStream(); this.document = new XWPFDocument(is); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); + } finally { + try { + if (is != null) is.close(); + } catch (IOException e) { + logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e); + } } } - public void setConfigurableProviders() { + private void setConfigurableProviders() { String filePath = environment.getProperty("configuration.configurable_login_providers"); - String current = null; + InputStream is = null; try { - current = new java.io.File(".").getCanonicalPath(); - InputStream is = new URL(Paths.get(filePath).toUri().toURL().toString()).openStream(); - ObjectMapper objectMapper = new ObjectMapper(); - this.configurableProviders = objectMapper.readValue(is, ConfigurableProviders.class); + File tempFile = new File(filePath); + if (tempFile.exists()) { + is = new URL(Paths.get(filePath).toUri().toURL().toString()).openStream(); + ObjectMapper objectMapper = new ObjectMapper(); + this.configurableProviders = objectMapper.readValue(is, ConfigurableProviders.class); + } else { + this.configurableProviders = new ConfigurableProviders(); + } } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); + } finally { + try { + if (is != null) is.close(); + } catch (IOException e) { + logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e); + } } } + private void setKeyToSourceMap() { + String filePath = this.environment.getProperty("configuration.externalUrls"); + logger.info("Loaded also config file: " + filePath); + Document doc = getXmlDocumentFromFilePath(filePath); + if (doc == null) { + this.keyToSourceMap = null; + return; + } + String xpathExpression = "//key"; + Map keysToSourceMap = new HashMap<>(); + List keys = getXmlValuesFromXPath(doc, xpathExpression); + keys = keys.stream().distinct().collect(Collectors.toList()); + for (String key : keys) { + String sourceExpression = String.format("//urlConfig[key='%s']/label", key); + List sources = getXmlValuesFromXPath(doc, sourceExpression); + if (sources.size() != 0) { + keysToSourceMap.put(key, sources.get(0)); + } + } + this.keyToSourceMap = keysToSourceMap; + } public ExternalUrls getExternalUrls() { this.setExternalUrls(); @@ -120,4 +169,52 @@ public class ProductionConfigLoader implements ConfigLoader { this.setConfigurableProviders(); return configurableProviders; } + + public Map getKeyToSourceMap() { + this.setKeyToSourceMap(); + return keyToSourceMap; + } + + private Document getXmlDocumentFromFilePath(String filePath) { + InputStream is = null; + Document doc; + try { + is = new URL(Paths.get(filePath).toUri().toURL().toString()).openStream(); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + doc = documentBuilder.parse(is); + return doc; + } catch (IOException | ParserConfigurationException | SAXException e) { + logger.error(e.getMessage(), e); + } finally { + try { + if (is != null) { + is.close(); + } + } catch (IOException e) { + logger.warn("Warning: Could not close a stream after reading from file: " + filePath, e); + } + } + return null; + } + + private List getXmlValuesFromXPath(Document doc, String expression) { + XPath xPath = XPathFactory.newInstance().newXPath(); + NodeList nodeList = null; + List values = new LinkedList<>(); + try { + nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET); + } catch (XPathExpressionException e) { + logger.error(e.getMessage(), e); + } + if (nodeList != null) { + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node.hasChildNodes()) { + values.add(nodeList.item(i).getChildNodes().item(0).getNodeValue()); + } + } + } + return values; + } } \ No newline at end of file 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 efc0b1db4..e7a53c40f 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 @@ -8,6 +8,8 @@ import eu.eudat.logic.proxy.config.*; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; import eu.eudat.logic.proxy.config.exceptions.NoURLFound; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -25,6 +27,7 @@ import java.util.stream.Collectors; @Service public class RemoteFetcher { + private static final Logger logger = LoggerFactory.getLogger(RemoteFetcher.class); private ConfigLoader configLoader; @@ -120,15 +123,16 @@ public class RemoteFetcher { private List> getAll(List urlConfigs, FetchStrategy fetchStrategy, ExternalUrlCriteria externalUrlCriteria) throws NoURLFound, HugeResultSet { - if (urlConfigs == null || urlConfigs.isEmpty()) - throw new NoURLFound("No Repository urls found in configuration"); + List> results = new LinkedList<>(); + + if (urlConfigs == null || urlConfigs.isEmpty()) return results; +// throw new NoURLFound("No Repository urls found in configuration"); urlConfigs.sort(Comparator.comparing(UrlConfiguration::getOrdinal)); - List> results = new LinkedList<>(); for (UrlConfiguration urlConfig : urlConfigs) { ifFunderQueryExist(urlConfig, externalUrlCriteria); if (urlConfig.getType() == null || urlConfig.getType().equals("External")) { - results.addAll(getAllResultsFromUrl(urlConfig.getUrl(), fetchStrategy, urlConfig.getData(), urlConfig.getPaginationPath(), externalUrlCriteria, urlConfig.getLabel(), urlConfig.getContentType(), urlConfig.getFirstpage())); + results.addAll(getAllResultsFromUrl(urlConfig.getUrl(), fetchStrategy, urlConfig.getData(), urlConfig.getPaginationPath(), externalUrlCriteria, urlConfig.getLabel(), urlConfig.getKey(), urlConfig.getContentType(), urlConfig.getFirstpage())); } else if (urlConfig.getType() != null && urlConfig.getType().equals("Internal")) { results.addAll(getAllResultsFromMockUpJson(urlConfig.getUrl(), externalUrlCriteria.getLike())); } @@ -138,7 +142,7 @@ public class RemoteFetcher { private void ifFunderQueryExist(UrlConfiguration urlConfiguration, ExternalUrlCriteria externalUrlCriteria) { if (urlConfiguration.getFunderQuery() != null) { - if (externalUrlCriteria.getFunderId() != null && urlConfiguration.getFunderQuery().startsWith("dmp:")) { + if (externalUrlCriteria.getFunderId() != null && !urlConfiguration.getFunderQuery().startsWith("dmp:")) { urlConfiguration.setUrl(urlConfiguration.getUrl().replace("{funderQuery}", urlConfiguration.getFunderQuery())); } else { @@ -162,7 +166,7 @@ public class RemoteFetcher { try { funderId = URLEncoder.encode(externalUrlCriteria.getFunderId(), "UTF-8"); } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } completedPath = completedPath.replace("{funderId}", funderId); } @@ -178,19 +182,19 @@ public class RemoteFetcher { if (externalUrlCriteria.getPageSize() != null) { completedPath = completedPath.replace("{pageSize}", externalUrlCriteria.getPageSize()); } else { - completedPath = completedPath.replace("{pageSize}", "10"); + completedPath = completedPath.replace("{pageSize}", "60"); } return completedPath; } - private List> getAllResultsFromUrl(String path, FetchStrategy fetchStrategy, final DataUrlConfiguration jsonDataPath, final String jsonPaginationPath, ExternalUrlCriteria externalUrlCriteria, String key, String contentType, String firstPage) throws HugeResultSet { + private List> getAllResultsFromUrl(String path, FetchStrategy fetchStrategy, final DataUrlConfiguration jsonDataPath, final String jsonPaginationPath, ExternalUrlCriteria externalUrlCriteria, String tag, String key, String contentType, String firstPage) throws HugeResultSet { Set pages = new HashSet<>(); String replacedPath = replaceCriteriaOnUrl(path, externalUrlCriteria, firstPage); Results results = getResultsFromUrl(replacedPath, jsonDataPath, jsonPaginationPath, contentType); if (fetchStrategy == FetchStrategy.FIRST) - return results == null ? new LinkedList<>() : results.getResults().stream().peek(x -> x.put("tag", key)).collect(Collectors.toList()); + return results == null ? new LinkedList<>() : results.getResults().stream().peek(x -> x.put("tag", tag)).peek(x -> x.put("key", key)).collect(Collectors.toList()); if (results != null && results.getPagination() != null && results.getPagination().get("pages") != null) //if has more pages, add them to the pages set for (int i = 2; i <= results.getPagination().get("pages"); i++) @@ -209,7 +213,7 @@ public class RemoteFetcher { Results remainingResults = optionalResults.orElseGet(Results::new); remainingResults.getResults().addAll(results.getResults()); - return remainingResults.getResults().stream().peek(x -> x.put("tag", key)).collect(Collectors.toList()); + return remainingResults.getResults().stream().peek(x -> x.put("tag", tag)).collect(Collectors.toList()); } @@ -243,20 +247,20 @@ public class RemoteFetcher { results = new Results(jsonContext.read(jsonDataPath.getPath() + "[" + jsonDataPath.getFieldsUrlConfiguration().getName() + "," + jsonDataPath.getFieldsUrlConfiguration().getDescription() + "," + jsonDataPath.getFieldsUrlConfiguration().getUri() + "," + jsonDataPath.getFieldsUrlConfiguration().getId() + "]"), - jsonContext.read(jsonPaginationPath)); + new HashMap<>(1, 1)); } results.results = results.results.stream().map(e -> e.entrySet().stream().collect(Collectors.toMap(x -> this.transformKey(jsonDataPath,x.getKey()), Map.Entry::getValue))) .collect(Collectors.toList()); return results; } } catch (MalformedURLException e1) { - e1.printStackTrace(); + logger.error(e1.getMessage(), e1); } //maybe print smth... catch (IOException e2) { - e2.printStackTrace(); + logger.error(e2.getMessage(), e2); } //maybe print smth... catch (Exception exception) { - exception.printStackTrace(); + logger.error(exception.getMessage(), exception); } //maybe print smth... finally { } @@ -270,10 +274,9 @@ public class RemoteFetcher { String filePath = Paths.get(path).toUri().toURL().toString(); ObjectMapper mapper = new ObjectMapper(); internalResults = mapper.readValue(new File(filePath), new TypeReference>>(){}); - searchListMap(internalResults, query); - return internalResults; + return searchListMap(internalResults, query); } catch (Exception e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return new LinkedList<>(); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java index 5e8c75dd6..f002d93d7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java @@ -6,6 +6,8 @@ import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.models.data.login.LoginInfo; import eu.eudat.models.data.security.Principal; import eu.eudat.logic.security.validators.TokenValidatorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +16,7 @@ import java.security.GeneralSecurityException; @Component public class CustomAuthenticationProvider { + private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class); @Autowired @@ -25,14 +28,13 @@ public class CustomAuthenticationProvider { Principal principal = this.tokenValidatorFactory.getProvider(credentials.getProvider()).validateToken(credentials); return principal; } catch (NonValidTokenException e) { - e.printStackTrace(); - System.out.println("Could not validate a user by his token! Reason: " + e.getMessage()); + logger.error("Could not validate a user by his token! Reason: " + e.getMessage(), e); throw new UnauthorisedException("Token validation failed - Not a valid token"); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); throw new UnauthorisedException("IO Exeption"); } catch (NullEmailException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); throw new NullEmailException(); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/FileStorageServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/FileStorageServiceImpl.java index e8909696f..244a8e503 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/FileStorageServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/FileStorageServiceImpl.java @@ -2,6 +2,8 @@ package eu.eudat.logic.services.helpers; import eu.eudat.exceptions.files.TempFileNotFoundException; import eu.eudat.models.data.files.ContentFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.core.io.Resource; @@ -22,6 +24,7 @@ import java.util.UUID; */ @Service("fileStorageService") public class FileStorageServiceImpl implements FileStorageService { + private static final Logger logger = LoggerFactory.getLogger(FileStorageServiceImpl.class); private Environment environment; @@ -68,7 +71,7 @@ public class FileStorageServiceImpl implements FileStorageService { Files.createDirectory(Paths.get(environment.getProperty("files.storage.final"))); } } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersService.java index e8f2954b0..df4fdaa64 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersService.java @@ -9,5 +9,5 @@ public interface HelpersService { MessageSource getMessageSource(); - LoggerService getLoggerService(); +// LoggerService getLoggerService(); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersServiceImpl.java index e6f6806bc..c09003c23 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/HelpersServiceImpl.java @@ -11,12 +11,12 @@ import org.springframework.stereotype.Service; public class HelpersServiceImpl implements HelpersService { private MessageSource messageSource; - private LoggerService loggerService; +// private LoggerService loggerService; @Autowired - public HelpersServiceImpl(MessageSource messageSource, LoggerService loggerService) { + public HelpersServiceImpl(MessageSource messageSource/*, LoggerService loggerService*/) { this.messageSource = messageSource; - this.loggerService = loggerService; +// this.loggerService = loggerService; } @Override @@ -24,8 +24,8 @@ public class HelpersServiceImpl implements HelpersService { return messageSource; } - @Override + /*@Override public LoggerService getLoggerService() { return loggerService; - } + }*/ } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/LoggerServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/LoggerServiceImpl.java index d0fff2fee..7e4533707 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/LoggerServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/helpers/LoggerServiceImpl.java @@ -12,7 +12,7 @@ import java.util.Map; /** * Created by ikalyvas on 3/1/2018. */ -@Service("loggerService") +//@Service("loggerService") public class LoggerServiceImpl implements LoggerService { private Logger logger; private WarningLevel level; @@ -22,7 +22,7 @@ public class LoggerServiceImpl implements LoggerService { this.level = level; } - @Autowired +// @Autowired public LoggerServiceImpl(Logger logger) { this.logger = logger; this.options.put(WarningLevel.DEBUG, (log, message) -> log.debug(message)); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java index 731ea109c..cb7506ab6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java @@ -15,12 +15,15 @@ import eu.eudat.models.data.loginprovider.LoginProviderUser; import eu.eudat.models.data.security.Principal; import eu.eudat.types.Authorities; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import org.springframework.transaction.annotation.Transactional; import java.util.*; public abstract class AbstractAuthenticationService implements AuthenticationService { + private static final Logger logger = LoggerFactory.getLogger(AbstractAuthenticationService.class); protected ApiContext apiContext; protected Environment environment; @@ -86,7 +89,7 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer try { credential = this.autoCreateUser(credentials.getUsername(), credentials.getSecret()); } catch (Exception e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java index 9b7db8421..c92cb231b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/ConfirmationEmailServiceImpl.java @@ -1,9 +1,10 @@ package eu.eudat.logic.services.utilities; -import eu.eudat.core.logger.Logger; import eu.eudat.data.dao.entities.LoginConfirmationEmailDao; import eu.eudat.data.entities.LoginConfirmationEmail; import eu.eudat.models.data.mail.SimpleMail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; @@ -13,11 +14,12 @@ import java.util.concurrent.CompletableFuture; @Service("ConfirmationEmailService") public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { - private Logger logger; + private static final Logger logger = LoggerFactory.getLogger(ConfirmationEmailServiceImpl.class); + //private Logger logger; private Environment environment; - public ConfirmationEmailServiceImpl(Logger logger, Environment environment) { - this.logger = logger; + public ConfirmationEmailServiceImpl(/*Logger logger,*/ Environment environment) { +// this.logger = logger; this.environment = environment; } @@ -48,8 +50,7 @@ public class ConfirmationEmailServiceImpl implements ConfirmationEmailService { try { mailService.sendSimpleMail(mail); } catch (Exception ex) { - ex.printStackTrace(); - this.logger.error(ex, ex.getMessage()); + logger.error(ex.getMessage(), ex); } }); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java index 4f28028b4..ed175bda2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java @@ -1,6 +1,5 @@ package eu.eudat.logic.services.utilities; -import eu.eudat.core.logger.Logger; import eu.eudat.core.models.exception.ApiExceptionLoggingModel; import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.dao.entities.InvitationDao; @@ -8,6 +7,8 @@ import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.Invitation; import eu.eudat.data.entities.UserInfo; import eu.eudat.models.data.mail.SimpleMail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.HttpStatus; @@ -25,13 +26,13 @@ import java.util.stream.Collectors; @Service("invitationService") public class InvitationServiceImpl implements InvitationService { - - private Logger logger; + private static final Logger logger = LoggerFactory.getLogger(InvitationServiceImpl.class); +// private Logger logger; private Environment environment; @Autowired - public InvitationServiceImpl(Logger logger, Environment environment) { - this.logger = logger; + public InvitationServiceImpl(/*Logger logger,*/ Environment environment) { +// this.logger = logger; this.environment = environment; } @@ -75,8 +76,7 @@ public class InvitationServiceImpl implements InvitationService { try { mailService.sendSimpleMail(mail); } catch (Exception ex) { - ex.printStackTrace(); - this.logger.error(ex, ex.getMessage()); + logger.error(ex.getMessage(), ex); } }); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/MailServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/MailServiceImpl.java index fb1983949..2ef6c4720 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/MailServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/MailServiceImpl.java @@ -2,6 +2,8 @@ package eu.eudat.logic.services.utilities; import eu.eudat.models.data.mail.SimpleMail; import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.env.Environment; @@ -17,6 +19,7 @@ import java.io.*; @Service("mailService") public class MailServiceImpl implements MailService { + private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class); private Environment env; @@ -54,7 +57,7 @@ public class MailServiceImpl implements MailService { IOUtils.copy(inputStream, writer, "UTF-8"); return writer.toString(); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return ""; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/ModelBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/ModelBuilder.java index 76d14be74..906d3d392 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/ModelBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/ModelBuilder.java @@ -5,6 +5,8 @@ import eu.eudat.models.data.components.commons.datafield.*; import eu.eudat.models.data.entities.xmlmodels.modeldefinition.DatabaseModelDefinition; import eu.eudat.logic.utilities.interfaces.ModelDefinition; import eu.eudat.logic.utilities.interfaces.ViewStyleDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import java.util.LinkedList; @@ -12,15 +14,16 @@ import java.util.List; import java.util.Map; public class ModelBuilder { + private static final Logger logger = LoggerFactory.getLogger(ModelBuilder.class); public , T extends DatabaseModelDefinition> List toModelDefinition(List items, Class clazz) { List list = new LinkedList(); for (U item : items) { try { list.add(item.toDatabaseDefinition(clazz.newInstance())); } catch (InstantiationException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } catch (IllegalAccessException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } } return list; @@ -32,9 +35,9 @@ public class ModelBuilder { try { list.add(item.toDatabaseDefinition(clazz.newInstance())); } catch (InstantiationException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } catch (IllegalAccessException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } } return list; @@ -48,9 +51,9 @@ public class ModelBuilder { modelItem.fromDatabaseDefinition(item); list.add(modelItem); } catch (InstantiationException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } catch (IllegalAccessException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } } return list; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/XmlBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/XmlBuilder.java index 7735fe326..408bbfde8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/XmlBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/builders/XmlBuilder.java @@ -1,5 +1,7 @@ package eu.eudat.logic.utilities.builders; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -21,6 +23,7 @@ import java.io.StringWriter; public class XmlBuilder { + private static final Logger logger = LoggerFactory.getLogger(XmlBuilder.class); public static Document getDocument() { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); @@ -31,7 +34,7 @@ public class XmlBuilder { return doc; } catch (ParserConfigurationException e) { // TODO Auto-generated catch block - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } } @@ -48,7 +51,7 @@ public class XmlBuilder { return writer.toString(); } catch (TransformerException e) { // TODO Auto-generated catch block - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } } @@ -63,7 +66,7 @@ public class XmlBuilder { return doc; } catch (ParserConfigurationException | SAXException | IOException e) { // TODO Auto-generated catch block - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java index f8733633a..39a217ec2 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java @@ -19,15 +19,17 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STNumberFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.math.BigInteger; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; public class WordBuilder { + private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class); private Map> options = new HashMap<>(); private CTAbstractNum cTAbstractNum; @@ -132,13 +134,13 @@ public class WordBuilder { return document; } - public void createPages(List datasetProfilePages, XWPFDocument mainDocumentPart, Boolean createListing, VisibilityRuleService visibilityRuleService) { + private void createPages(List datasetProfilePages, XWPFDocument mainDocumentPart, Boolean createListing, VisibilityRuleService visibilityRuleService) { datasetProfilePages.forEach(item -> { createSections(item.getSections(), mainDocumentPart, ParagraphStyle.HEADER4, 0, createListing, visibilityRuleService); }); } - public void createSections(List
sections, XWPFDocument mainDocumentPart, ParagraphStyle style, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) { + private void createSections(List
sections, XWPFDocument mainDocumentPart, ParagraphStyle style, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) { if (createListing) this.addListing(mainDocumentPart, indent, false, true); sections.forEach(section -> { if (visibilityRuleService.isElementVisible(section.getId())) { @@ -153,7 +155,7 @@ public class WordBuilder { }); } - public void createCompositeFields(List
compositeFields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) { + private void createCompositeFields(List
compositeFields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) { if (createListing) this.addListing(mainDocumentPart, indent, true, true); compositeFields.forEach(compositeField -> { if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) { @@ -177,7 +179,7 @@ public class WordBuilder { }); } - public void createFields(List fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) { + private void createFields(List fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) { if (createListing) this.addListing(mainDocumentPart, indent, false, false); fields.forEach(field -> { if (visibilityRuleService.isElementVisible(field.getId())) { @@ -187,7 +189,7 @@ public class WordBuilder { CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl(); number.setVal(BigInteger.valueOf(indent)); } catch (IOException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } } } @@ -202,7 +204,7 @@ public class WordBuilder { return paragraph; } - public void addListing(XWPFDocument document, int indent, Boolean question, Boolean hasIndication) { + private void addListing(XWPFDocument document, int indent, Boolean question, Boolean hasIndication) { CTLvl cTLvl = this.cTAbstractNum.addNewLvl(); String textLevel = ""; @@ -222,7 +224,7 @@ public class WordBuilder { } } - public String formatter(Field field) throws IOException { + private String formatter(Field field) throws IOException { switch (field.getViewStyle().getRenderStyle()) { case "combobox": { String comboboxType = ((ComboBoxData) field.getData()).getType(); @@ -232,7 +234,7 @@ public class WordBuilder { Map map = new HashMap<>(); if (!field.getValue().equals("")) { try { - JSONArray jsonarray = new JSONArray(field.getValue()); + JSONArray jsonarray = new JSONArray(field.getValue().toString()); for (int i = 0; i < jsonarray.length(); i++) { JSONObject jsonobject = jsonarray.getJSONObject(i); String id = jsonobject.getString("id"); @@ -241,37 +243,39 @@ public class WordBuilder { map.put(id, label); } } - } catch (Exception e){ - Map exMap = mapper.readValue(field.getValue(), new TypeReference>() { + } catch (Exception e) { + Map exMap = mapper.readValue(field.getValue().toString(), new TypeReference>() { }); return exMap.get("label"); } } StringBuilder sb = new StringBuilder(); + int index = 0; for (Map.Entry entry : map.entrySet()) { - sb.append("\n"); sb.append(entry.getValue()); + if (index != map.size() - 1) sb.append(", "); + index++; } return sb.toString(); } else if (comboboxType.equals("wordlist")) { - return field.getValue(); + return field.getValue().toString(); } } case "booleanDecision": if (field.getValue() != null && field.getValue().equals("true")) return "Yes"; else return "No"; case "radiobox": - return field.getValue(); + return field.getValue().toString(); case "checkBox": CheckBoxData data = (CheckBoxData) field.getData(); if (field.getValue() == null || field.getValue().equals("false")) return null; return data.getLabel(); case "freetext": - return field.getValue(); + return field.getValue().toString(); case "textarea": - return field.getValue(); + return field.getValue().toString(); case "datepicker": - return field.getValue(); + return field.getValue().toString(); } return null; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/ExportXmlBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/ExportXmlBuilder.java index 3c0f7024f..6f1948853 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/ExportXmlBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/ExportXmlBuilder.java @@ -7,6 +7,8 @@ import eu.eudat.models.data.user.components.datasetprofile.FieldSet; import eu.eudat.models.data.user.components.datasetprofile.Section; import eu.eudat.models.data.user.composite.DatasetProfilePage; import eu.eudat.models.data.user.composite.PagedDatasetProfile; +import org.json.JSONArray; +import org.json.JSONException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -17,9 +19,6 @@ import java.io.IOException; import java.util.List; import java.util.UUID; -/** - * Created by ikalyvas on 3/5/2018. - */ public class ExportXmlBuilder { public File build(PagedDatasetProfile pagedDatasetProfile, UUID datasetProfileId, VisibilityRuleService visibilityRuleService) throws IOException { @@ -49,7 +48,7 @@ public class ExportXmlBuilder { return pages; } - public Element createSections(List
sections, VisibilityRuleService visibilityRuleService, Document element) { + private Element createSections(List
sections, VisibilityRuleService visibilityRuleService, Document element) { Element elementSections = element.createElement("sections"); sections.forEach(section -> { Element elementSection = element.createElement("section"); @@ -62,7 +61,7 @@ public class ExportXmlBuilder { return elementSections; } - public Element createCompositeFields(List
compositeFields, VisibilityRuleService visibilityRuleService, Document element) { + private Element createCompositeFields(List
compositeFields, VisibilityRuleService visibilityRuleService, Document element) { Element elementComposites = element.createElement("composite-fields"); compositeFields.forEach(compositeField -> { if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) { @@ -86,15 +85,25 @@ public class ExportXmlBuilder { return elementComposites; } - public Element createFields(List fields, VisibilityRuleService visibilityRuleService, Document element) { + private Element createFields(List fields, VisibilityRuleService visibilityRuleService, Document element) { Element elementFields = element.createElement("fields"); fields.forEach(field -> { if (visibilityRuleService.isElementVisible(field.getId())) { Element elementField = element.createElement("field"); elementField.setAttribute("id", field.getId()); - if (field.getValue() != null && !field.getValue().isEmpty()) { + if (field.getValue() != null) { Element valueField = element.createElement("value"); - valueField.setTextContent(field.getValue()); + try { + JSONArray jsonArray = new JSONArray(field.getValue().toString()); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < jsonArray.length(); i++) { + sb.append(jsonArray.getJSONObject(i).get("label").toString()); + if (i != jsonArray.length() - 1) sb.append(", "); + } + valueField.setTextContent(sb.toString()); + } catch (JSONException ex) { + valueField.setTextContent(field.getValue().toString()); + } elementField.appendChild(valueField); } elementFields.appendChild(elementField); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ImportXmlBuilderDatasetProfile.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ImportXmlBuilderDatasetProfile.java index ffd789d76..b7931bd74 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ImportXmlBuilderDatasetProfile.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ImportXmlBuilderDatasetProfile.java @@ -1,5 +1,7 @@ package eu.eudat.logic.utilities.documents.xml.datasetProfileXml; import eu.eudat.logic.utilities.documents.xml.datasetProfileXml.datasetProfileModel.DatasetProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -7,6 +9,7 @@ import javax.xml.bind.Unmarshaller; import java.io.*; public class ImportXmlBuilderDatasetProfile { + private static final Logger logger = LoggerFactory.getLogger(ImportXmlBuilderDatasetProfile.class); public DatasetProfile build(File xmlFile) throws IOException { DatasetProfile datasetProfile = new DatasetProfile(); @@ -16,7 +19,7 @@ public class ImportXmlBuilderDatasetProfile { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); datasetProfile = (DatasetProfile) unmarshaller.unmarshal(xmlFile); } catch (JAXBException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return datasetProfile; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/dmpXml/ImportXmlBuilderDmpProfile.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/dmpXml/ImportXmlBuilderDmpProfile.java index 717b6ac2b..7962beb51 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/dmpXml/ImportXmlBuilderDmpProfile.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/dmpXml/ImportXmlBuilderDmpProfile.java @@ -1,6 +1,8 @@ package eu.eudat.logic.utilities.documents.xml.dmpXml; import eu.eudat.logic.utilities.documents.xml.dmpXml.dmpProfileModel.DmpProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -9,6 +11,7 @@ import java.io.File; import java.io.IOException; public class ImportXmlBuilderDmpProfile { + private static final Logger logger = LoggerFactory.getLogger(ImportXmlBuilderDmpProfile.class); public DmpProfile build(File xmlFile) throws IOException { DmpProfile dmpProfile = new DmpProfile(); @@ -18,7 +21,7 @@ public class ImportXmlBuilderDmpProfile { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); dmpProfile = (DmpProfile) unmarshaller.unmarshal(xmlFile); } catch (JAXBException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return dmpProfile; diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/HintedModelFactory.java b/dmp-backend/web/src/main/java/eu/eudat/models/HintedModelFactory.java index 15a418112..305aebc7d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/HintedModelFactory.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/HintedModelFactory.java @@ -1,16 +1,20 @@ package eu.eudat.models; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class HintedModelFactory { + private static final Logger logger = LoggerFactory.getLogger(HintedModelFactory.class); public static String getHint(Class clazz) { try { return clazz.newInstance().getHint(); } catch (InstantiationException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } catch (IllegalAccessException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); return null; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dashboard/searchbar/SearchBarItem.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dashboard/searchbar/SearchBarItem.java index 57ada987d..a698910f9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dashboard/searchbar/SearchBarItem.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dashboard/searchbar/SearchBarItem.java @@ -1,17 +1,16 @@ package eu.eudat.models.data.dashboard.searchbar; -/** - * Created by ikalyvas on 7/26/2018. - */ public class SearchBarItem { private String id; private String label; private int type; + private boolean isPublished; - public SearchBarItem(String id, String label, int type) { + public SearchBarItem(String id, String label, int type, boolean isPublished) { this.id = id; this.label = label; this.type = type; + this.isPublished = isPublished; } public String getId() { @@ -37,4 +36,12 @@ public class SearchBarItem { public void setType(int type) { this.type = type; } + + public boolean getIsPublished() { + return isPublished; + } + + public void setPublished(boolean published) { + isPublished = published; + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/datarepository/DataRepositoryModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/datarepository/DataRepositoryModel.java index 200bf2d78..fc8b32c26 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/datarepository/DataRepositoryModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/datarepository/DataRepositoryModel.java @@ -1,6 +1,5 @@ package eu.eudat.models.data.datarepository; -import com.fasterxml.jackson.annotation.JsonProperty; import eu.eudat.data.entities.DataRepository; import eu.eudat.data.entities.UserInfo; import eu.eudat.models.DataModel; @@ -8,13 +7,9 @@ import eu.eudat.models.DataModel; import java.util.Date; import java.util.UUID; -/** - * Created by ikalyvas on 9/3/2018. - */ public class DataRepositoryModel implements DataModel { private UUID id; - @JsonProperty("name") - private String label; + private String name; private String pid; private String abbreviation; private String uri; @@ -30,11 +25,11 @@ public class DataRepositoryModel implements DataModel, LabelGenerator { + private String id; private String pid; - private String label; + private String name; private String uri; private String info; private String reference; + private String abbreviation; private String tag; private String source; + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getPid() { return pid; } @@ -21,11 +31,11 @@ public class DataRepository implements DataModel new Registry().fromDataModel(item)).collect(Collectors.toList()); this.dataRepositories = entity.getDatasetDataRepositories().stream().map(item -> { DataRepository dataRepository = new DataRepository().fromDataModel(item.getDataRepository()); - if(item.getData()!=null) { + if (item.getData() != null) { Map> data = (Map>) JSONValue.parse(item.getData()); Map values = data.get("data"); dataRepository.setInfo(values.get("info")); @@ -171,7 +171,7 @@ public class DatasetWizardModel implements DataModel { ExternalDatasetListingModel externalDatasetListingModel = new ExternalDatasetListingModel().fromDataModel(item.getExternalDataset()); - if(item.getData()!= null) { + if (item.getData() != null) { Map> data = (Map>) JSONValue.parse(item.getData()); Map values = data.get("data"); externalDatasetListingModel.setInfo(values.get("info")); @@ -214,10 +214,10 @@ public class DatasetWizardModel implements DataModel> data = new HashMap<>(); - Map values = new HashMap<>(); - values.put("info",dataRepositoryModel.getInfo()); - data.put("data",values); + Map> data = new HashMap<>(); + Map values = new HashMap<>(); + values.put("info", dataRepositoryModel.getInfo()); + data.put("data", values); datasetDataRepository.setData(JSONValue.toJSONString(data)); entity.getDatasetDataRepositories().add(datasetDataRepository); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java index db6772f94..8b9bcd8ea 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java @@ -28,7 +28,7 @@ public class DataManagementPlan implements DataModel { private String description; private List datasets; private List profiles; - private eu.eudat.models.data.grant.Grant grant; + private Grant grant; private List organisations; private List researchers; private List associatedUsers; @@ -218,7 +218,7 @@ public class DataManagementPlan implements DataModel { this.organisations = entity.getOrganisations().stream().map(item -> new Organisation().fromDataModel(item)).collect(Collectors.toList()); this.researchers = entity.getResearchers().stream().map(item -> new Researcher().fromDataModel(item)).collect(Collectors.toList()); this.version = entity.getVersion(); - this.groupId = this.groupId == null ? null : this.groupId; + this.groupId = this.groupId == null ? null : entity.getGroupId(); this.label = entity.getLabel(); this.grant = new Grant(); this.properties = entity.getProperties() != null ? new org.json.JSONObject(entity.getProperties()).toMap() : null; @@ -243,9 +243,15 @@ public class DataManagementPlan implements DataModel { this.profiles.add(associatedProfile); } } - this.datasets = entity.getDataset().stream() - .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED.getValue()) && !dataset.getStatus().equals(Dataset.Status.CANCELED.getValue())) - .map(x-> new DatasetListingModel().fromDataModel(x)).collect(Collectors.toList()); + if (entity.isPublic()) { + this.datasets = entity.getDataset().stream() + .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED.getValue()) && !dataset.getStatus().equals(Dataset.Status.CANCELED.getValue()) && !dataset.getStatus().equals(Dataset.Status.SAVED.getValue())) + .map(x-> new DatasetListingModel().fromDataModel(x)).collect(Collectors.toList()); + } else { + this.datasets = entity.getDataset().stream() + .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED.getValue()) && !dataset.getStatus().equals(Dataset.Status.CANCELED.getValue())) + .map(x-> new DatasetListingModel().fromDataModel(x)).collect(Collectors.toList()); + } this.modified = entity.getModified(); this.created = entity.getCreated(); this.description = entity.getDescription(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlanEditorModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlanEditorModel.java index 8a9d283e9..3be36c2e7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlanEditorModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlanEditorModel.java @@ -218,11 +218,12 @@ public class DataManagementPlanEditorModel implements DataModel new Organisation().fromDataModel(item)).collect(Collectors.toList()); this.researchers = entity.getResearchers().stream().map(item -> new Researcher().fromDataModel(item)).collect(Collectors.toList()); this.version = entity.getVersion(); - this.groupId = this.groupId == null ? null : this.groupId; + this.groupId = this.groupId == null ? null : entity.getGroupId(); this.label = entity.getLabel(); this.grant = new GrantDMPEditorModel(); this.properties = entity.getProperties() != null ? new org.json.JSONObject(entity.getProperties()).toMap() : null; this.grant.getExistGrant().fromDataModel(entity.getGrant()); + this.grant.getExistGrant().setSource(""); this.creator = new eu.eudat.models.data.userinfo.UserInfo(); this.groupId = entity.getGroupId(); this.lockable = entity.getDataset().stream().findAny().isPresent(); @@ -278,10 +279,11 @@ public class DataManagementPlanEditorModel implements DataModel, LabelGenerator { + private static final Logger logger = LoggerFactory.getLogger(Researcher.class); private String label; private String name; private String id; + private String reference; private int status; private String tag; + private String key; public String getLabel() { return label; } - public void setLabel(String label) { this.label = label; } @@ -23,7 +28,6 @@ public class Researcher implements DataModel> values) { for (Map item : values) { ExternalSourcesItemModel model = new ExternalSourcesItemModel(); - model.setId(item.get("pid")); + model.setRemoteId(item.get("pid")); model.setUri(item.get("uri")); model.setName(item.get("name")); model.setTag(item.get("tag")); + model.setKey(item.get("key")); this.add(model); } return this; diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ProjectsExternalSourcesModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ProjectsExternalSourcesModel.java index 84537d5b2..3fc922d09 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ProjectsExternalSourcesModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/external/ProjectsExternalSourcesModel.java @@ -2,12 +2,15 @@ package eu.eudat.models.data.external; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.List; import java.util.Map; public class ProjectsExternalSourcesModel extends ExternalListingItem { + private static final Logger logger = LoggerFactory.getLogger(ProjectsExternalSourcesModel.class); private static final ObjectMapper mapper = new ObjectMapper(); @Override @@ -51,10 +54,17 @@ public class ProjectsExternalSourcesModel extends ExternalListingItem> values) { for (Map item : values) { ExternalSourcesItemModel model = new ExternalSourcesItemModel(); - model.setId(item.get("pid")); + model.setRemoteId(item.get("pid")); model.setUri(item.get("uri")); model.setName(item.get("name")); model.setTag(item.get("tag")); + model.setKey(item.get("key")); this.add(model); } return this; diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java index 2ffc2c525..f874fa74e 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java @@ -140,6 +140,9 @@ public class ExternalDatasetListingModel implements DataModel { public UUID id; - public String label; + public String name; public String abbreviation; public Date created; public Date modified; @@ -22,11 +22,11 @@ public class ExternalDatasetModel implements DataModel private Date modified; private Integer type; private String source; + private String key; public UUID getId() { return id; @@ -80,6 +81,13 @@ public class Funder implements DataModel this.source = source; } + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + @Override public Funder fromDataModel(eu.eudat.data.entities.Funder entity) { this.id = entity.getId(); @@ -90,28 +98,41 @@ public class Funder implements DataModel this.status = entity.getStatus(); this.created = entity.getCreated(); this.modified = entity.getModified(); - String source = entity.getReference().substring(0, entity.getReference().indexOf(":")); - if (source.equals("dmp")) { - this.source = "Internal"; - } else { - this.source = source; + if (entity.getReference() != null) { + String source = entity.getReference().substring(0, entity.getReference().indexOf(":")); + if (source.equals("dmp")) { + this.key = "Internal"; + } else { + this.key = source; + } } + return this; } @Override public eu.eudat.data.entities.Funder toDataModel() { eu.eudat.data.entities.Funder entity = new eu.eudat.data.entities.Funder(); - entity.setId(this.id); + if (this.getId() != null) { + entity.setId(this.getId()); + } else { + entity.setId(UUID.randomUUID()); + } entity.setLabel(this.label); entity.setType(this.type); - if (this.source != null && this.source.equals("Internal")) this.source = "dmp"; - if (this.reference != null && !this.reference.trim().isEmpty() - && this.source != null && !this.source.trim().isEmpty()) { - if (this.source.equals(this.reference.substring(0, this.source.length()))) { + // If internal, key has no value, fill it. + if ((this.source != null && this.source.equals("Internal")) || (this.key != null && this.key.equals("Internal"))) this.key = "dmp"; + // Logic for the different "key" cases. + if ((this.key == null || this.key.trim().isEmpty()) && (this.source != null && !this.source.trim().isEmpty())) { + this.key = this.source; + } + if (this.reference != null && this.reference.startsWith("dmp:")) { + entity.setReference(this.reference); + } else if (this.reference != null && !this.reference.trim().isEmpty() && this.key != null && !this.key.trim().isEmpty()) { + if (this.key.equals(this.reference.substring(0, this.key.length()))) { entity.setReference(this.reference); } else { - entity.setReference(this.source.toLowerCase() + ":" + this.reference); + entity.setReference(this.key.toLowerCase() + ":" + this.reference); } } entity.setDefinition(this.definition); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/grant/Grant.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/grant/Grant.java index 56884fe73..798b3a6ab 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/grant/Grant.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/grant/Grant.java @@ -32,6 +32,7 @@ public class Grant implements DataModel { private List files; private UUID funderId; private String source; + private String key; public UUID getId() { return id; @@ -159,6 +160,13 @@ public class Grant implements DataModel { this.source = source; } + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + @Override public Grant fromDataModel(eu.eudat.data.entities.Grant entity) { this.id = entity.getId(); @@ -177,11 +185,13 @@ public class Grant implements DataModel { this.files = entity.getContent() != null ? Arrays.asList(new ContentFile(entity.getContent().getLabel(), UUID.fromString(entity.getContent().getUri().split(":")[1]), "final", entity.getContent().getExtension())) : Arrays.asList(new ContentFile("default.png", null, null, null)); if (entity.getFunder() != null) this.funderId = entity.getFunder().getId(); - String source = entity.getReference().substring(0, entity.getReference().indexOf(":")); - if (source.equals("dmp")) { - this.source = "Internal"; - } else { - this.source = source; + if (entity.getReference() != null) { + String source = entity.getReference().substring(0, entity.getReference().indexOf(":")); + if (source.equals("dmp")) { + this.key = "Internal"; + } else { + this.key = source; + } } return this; @@ -190,17 +200,22 @@ public class Grant implements DataModel { @Override public eu.eudat.data.entities.Grant toDataModel() { eu.eudat.data.entities.Grant entity = new eu.eudat.data.entities.Grant(); - entity.setId(this.id); + if (this.getId() != null) { + entity.setId(this.getId()); + } else { + entity.setId(UUID.randomUUID()); + } entity.setAbbreviation(this.abbreviation); entity.setLabel(this.label); entity.setType(this.type); - if (this.source != null && this.source.equals("Internal")) this.source = "dmp"; - if (this.reference != null && !this.reference.trim().isEmpty() - && this.source != null && !this.source.trim().isEmpty()) { - if (this.source.equals(this.reference.substring(0, this.source.length()))) { + if ((this.source != null && this.source.equals("Internal")) || (this.key != null && this.key.equals("Internal"))) this.key = "dmp"; + if (this.reference != null && this.reference.startsWith("dmp:")) { + entity.setReference(this.reference); + } else if (this.reference != null && !this.reference.trim().isEmpty() && this.key != null && !this.key.trim().isEmpty()) { + if (this.key.equals(this.reference.substring(0, this.key.length()))) { entity.setReference(this.reference); } else { - entity.setReference(this.source.toLowerCase() + ":" + this.reference); + entity.setReference(this.key.toLowerCase() + ":" + this.reference); } } entity.setUri(this.uri); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanListingModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanListingModel.java index bfb8bf1cc..1a2483314 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanListingModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanListingModel.java @@ -187,10 +187,19 @@ public class DataManagementPlanListingModel implements DataModel new AssociatedProfile().fromData(item)).collect(Collectors.toList()); return this; } + public DataManagementPlanListingModel fromDataModelAutoComplete(DMP entity) { + this.id = entity.getId().toString(); + this.label = entity.getLabel(); + this.groupId = entity.getGroupId(); + this.creationTime = entity.getCreated(); + return this; + } + public DataManagementPlanListingModel fromDataModelDatasets(DMP entity) { this.fromDataModel(entity); this.status = entity.getStatus(); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java index d1cd16647..9906baeb6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DatasetListingModel.java @@ -28,6 +28,7 @@ public class DatasetListingModel implements DataModel new Service().fromDataModel(item.getService())).collect(Collectors.toList())); this.finalizedAt = entity.getFinalizedAt(); this.dmpPublishedAt = entity.getDmp().getPublishedAt(); + this.version = entity.getDmp().getVersion(); return this; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java index 8752e0bd6..430eb6017 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/project/Project.java @@ -29,6 +29,7 @@ public class Project implements DataModel files; private String source; + private String key; public UUID getId() { return id; @@ -149,6 +150,13 @@ public class Project implements DataModel format; // Format according to: https://www.iana.org/assignments/media-types/media-types.xhtml if appropriate, otherwise use the common name for this format + private HostRDAExportModel host; + private List license; + private String title; + + public String getAccess_url() { + return access_url; + } + public void setAccess_url(String access_url) { + this.access_url = access_url; + } + + public String getAvailable_till() { + return available_till; + } + public void setAvailable_till(String available_till) { + this.available_till = available_till; + } + + public String getByte_size() { + return byte_size; + } + public void setByte_size(String byte_size) { + this.byte_size = byte_size; + } + + public String getData_access() { + return data_access; + } + public void setData_access(String data_access) { + this.data_access = data_access; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public String getDownload_url() { + return download_url; + } + public void setDownload_url(String download_url) { + this.download_url = download_url; + } + + public List getFormat() { + return format; + } + public void setFormat(List format) { + this.format = format; + } + + public HostRDAExportModel getHost() { + return host; + } + public void setHost(HostRDAExportModel host) { + this.host = host; + } + + public List getLicense() { + return license; + } + public void setLicense(List license) { + this.license = license; + } + + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + + @JsonIgnore + public boolean isValid() { + return title != null || data_access != null; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetIdRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetIdRDAExportModel.java deleted file mode 100644 index 0267514c5..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetIdRDAExportModel.java +++ /dev/null @@ -1,25 +0,0 @@ -package eu.eudat.models.data.rda; - -public class DatasetIdRDAExportModel { - private String dataset_id; - private String dataset_id_type; - - public String getDataset_id() { - return dataset_id; - } - public void setDataset_id(String dataset_id) { - this.dataset_id = dataset_id; - } - - public String getDataset_id_type() { - return dataset_id_type; - } - public void setDataset_id_type(String dataset_id_type) { - this.dataset_id_type = dataset_id_type; - } - - DatasetIdRDAExportModel(String dataset_id, String dataset_id_type) { - this.dataset_id = dataset_id; - this.dataset_id_type = dataset_id_type; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataIdRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataIdRDAExportModel.java deleted file mode 100644 index f6b3130ba..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataIdRDAExportModel.java +++ /dev/null @@ -1,31 +0,0 @@ -package eu.eudat.models.data.rda; - -public class DatasetMetadataIdRDAExportModel { - private String metadata_id; - private String metadata_id_type; - - public String getMetadata_id() { - return metadata_id; - } - public void setMetadata_id(String metadata_id) { - this.metadata_id = metadata_id; - } - - public String getMetadata_id_type() { - return metadata_id_type; - } - public void setMetadata_id_type(String metadata_id_type) { - this.metadata_id_type = metadata_id_type; - } - - - public DatasetMetadataIdRDAExportModel fromDataModel(String key, Object value) { - DatasetMetadataIdRDAExportModel metadataIdRDAExportModel = new DatasetMetadataIdRDAExportModel(); - if (key.contains(".metadata_id")) - metadataIdRDAExportModel.setMetadata_id(value.toString()); - else if (key.contains(".metadata_id_type")) - metadataIdRDAExportModel.setMetadata_id_type(value.toString()); - - return metadataIdRDAExportModel; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataRDAExportModel.java index 9a70ed7d2..2b5da6abd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataRDAExportModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetMetadataRDAExportModel.java @@ -1,9 +1,11 @@ package eu.eudat.models.data.rda; +import com.fasterxml.jackson.annotation.JsonIgnore; + public class DatasetMetadataRDAExportModel { private String description; // Not mandatory. private String language; - private DatasetMetadataIdRDAExportModel metadata_id; + private IdRDAExportModel metadata_standard_id; public String getDescription() { return description; @@ -19,17 +21,17 @@ public class DatasetMetadataRDAExportModel { this.language = language; } - public DatasetMetadataIdRDAExportModel getMetadata_id() { - return metadata_id; + public IdRDAExportModel getMetadata_standard_id() { + return metadata_standard_id; } - public void setMetadata_id(DatasetMetadataIdRDAExportModel metadata_id) { - this.metadata_id = metadata_id; + public void setMetadata_standard_id(IdRDAExportModel metadata_standard_id) { + this.metadata_standard_id = metadata_standard_id; } public DatasetMetadataRDAExportModel fromDataModel(String key, Object value) { DatasetMetadataRDAExportModel metadataRDAExportModel = new DatasetMetadataRDAExportModel(); - if (key.contains("metadata_id")) - metadataRDAExportModel.setMetadata_id(new DatasetMetadataIdRDAExportModel().fromDataModel(key, value)); + if (key.contains("metadata_standard_id")) + metadataRDAExportModel.setMetadata_standard_id(new IdRDAExportModel(value.toString(), "other")); else if (key.contains("language")) metadataRDAExportModel.setLanguage(value.toString()); else if (key.contains("description")) @@ -37,4 +39,9 @@ public class DatasetMetadataRDAExportModel { return metadataRDAExportModel; } + + @JsonIgnore + public boolean isValid() { + return description != null || language != null || metadata_standard_id != null; + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetRDAExportModel.java index 94931b782..396e66286 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetRDAExportModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DatasetRDAExportModel.java @@ -1,36 +1,59 @@ package eu.eudat.models.data.rda; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.jsonpath.JsonPath; import eu.eudat.data.entities.Dataset; +import eu.eudat.logic.managers.DatasetManager; import eu.eudat.logic.utilities.builders.XmlBuilder; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.json.JSONArray; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.xpath.*; +import java.text.DateFormat; import java.util.*; +import static java.util.stream.Collectors.groupingBy; + public class DatasetRDAExportModel { + private static final Logger logger = LoggerFactory.getLogger(DatasetRDAExportModel.class); private static final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + private Map multiplicityIdToFieldSetId = new HashMap<>(); - private DatasetIdRDAExportModel dataset_id; + private List data_quality_assurance; + private IdRDAExportModel dataset_id; private String description; - private Date issued; // Created Date, could also use finalized one. + private List distribution; + private String issued; // Created Date, could also use finalized one. + private List keyword; private String language; - private String title; - private String sensitive_data; - private String data_quality_assurance; private List metadata; + private String personal_data; // Allowed Values: yes no unknown. + private String preservation_statement; + private List security_and_privacy; + private String sensitive_data; // Allowed Values: yes no unknown. + private List technical_resource; + private String title; + private String type; // Type according to: http://vocabularies.coar-repositories.org/pubby/resource_type.html - public DatasetIdRDAExportModel getDataset_id() { + public List getData_quality_assurance() { + return data_quality_assurance; + } + public void setData_quality_assurance(List data_quality_assurance) { + this.data_quality_assurance = data_quality_assurance; + } + + public IdRDAExportModel getDataset_id() { return dataset_id; } - public void setDataset_id(DatasetIdRDAExportModel dataset_id) { + public void setDataset_id(IdRDAExportModel dataset_id) { this.dataset_id = dataset_id; } @@ -41,13 +64,27 @@ public class DatasetRDAExportModel { this.description = description; } - public Date getIssued() { + public List getDistribution() { + return distribution; + } + public void setDistribution(List distribution) { + this.distribution = distribution; + } + + public String getIssued() { return issued; } - public void setIssued(Date issued) { + public void setIssued(String issued) { this.issued = issued; } + public List getKeyword() { + return keyword; + } + public void setKeyword(List keyword) { + this.keyword = keyword; + } + public String getLanguage() { return language; } @@ -55,11 +92,32 @@ public class DatasetRDAExportModel { this.language = language; } - public String getTitle() { - return title; + public List getMetadata() { + return metadata; } - public void setTitle(String title) { - this.title = title; + public void setMetadata(List metadata) { + this.metadata = metadata; + } + + public String getPersonal_data() { + return personal_data; + } + public void setPersonal_data(String personal_data) { + this.personal_data = personal_data; + } + + public String getPreservation_statement() { + return preservation_statement; + } + public void setPreservation_statement(String preservation_statement) { + this.preservation_statement = preservation_statement; + } + + public List getSecurity_and_privacy() { + return security_and_privacy; + } + public void setSecurity_and_privacy(List security_and_privacy) { + this.security_and_privacy = security_and_privacy; } public String getSensitive_data() { @@ -69,72 +127,331 @@ public class DatasetRDAExportModel { this.sensitive_data = sensitive_data; } - public String getData_quality_assurance() { - return data_quality_assurance; + public List getTechnical_resource() { + return technical_resource; } - public void setData_quality_assurance(String data_quality_assurance) { - this.data_quality_assurance = data_quality_assurance; + public void setTechnical_resource(List technical_resource) { + this.technical_resource = technical_resource; } - public List getMetadata() { - return metadata; + public String getTitle() { + return title; } - public void setMetadata(List metadata) { - this.metadata = metadata; + public void setTitle(String title) { + this.title = title; + } + + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; } - public DatasetRDAExportModel fromDataModel(Dataset dataset) { - // Parsing dataset template definition to create a map of which question of the template corresponds to the RDA common standard. Map: TemplateId -> rdaProperty - List rdaPropertiesThatExistOnDatasetTemplate = xmlNodeListFromExpression(dataset.getProfile().getDefinition(), "//rdaCommonStandard/text()"); - List rdaProperties = new LinkedList<>(); - for (String item : rdaPropertiesThatExistOnDatasetTemplate) { - item = item.replace("dataset.", ""); - rdaProperties.add(item); - } - List datasetTemplateIdsWithRdaProperties = xmlNodeListFromExpression(dataset.getProfile().getDefinition(), "//rdaCommonStandard/text()/ancestor::field/@id"); - Map templateIdsToRDAProperties = combineListsIntoOrderedMap(datasetTemplateIdsWithRdaProperties, rdaProperties); - - // Parsing dataset answers from json to map. Map: TemplateId -> datasetValue + public DatasetRDAExportModel fromDataModel(Dataset dataset, DatasetManager datasetManager) { + // Map of template Ids to rda values. JSONObject jObject = new JSONObject(dataset.getProperties()); Map templateIdsToValues = jObject.toMap(); - // Map: rdaProperty -> datasetValue - MultiValuedMap rdaToValueMap = new ArrayListValuedHashMap<>(); - for (String templateId : templateIdsToRDAProperties.keySet()) { - if (templateIdsToValues.containsKey(templateId)) { - rdaToValueMap.put(templateIdsToRDAProperties.get(templateId), templateIdsToValues.get(templateId).toString()); - } - } - - // Creates and fills a map to include metadata keys and values. - MultiValuedMap metadataJsonMap = new ArrayListValuedHashMap<>(); - for (String key : rdaToValueMap.keySet()) { - if (key.startsWith("metadata.")) { - metadataJsonMap.putAll(key.replace("metadata.", ""), rdaToValueMap.get(key)); - } - } - // Removes metadata keys from rdaToValueMap. - for (String metadataKey : metadataJsonMap.keySet()) rdaToValueMap.remove(metadataKey); - - DatasetRDAExportModel datasetRDAExportModel = mapper.convertValue(rdaToValueMap, DatasetRDAExportModel.class); + /*--------- Building dataset rda export model ---------*/ + DatasetRDAExportModel datasetRDAExportModel = new DatasetRDAExportModel(); + datasetRDAExportModel.setDataset_id(new IdRDAExportModel(dataset.getId().toString(), "other")); + if (dataset.getDescription() != null) datasetRDAExportModel.setDescription(dataset.getDescription().replace("\n", " ")); + datasetRDAExportModel.setIssued(DateFormat.getDateInstance(DateFormat.SHORT).format(dataset.getCreated())); + datasetRDAExportModel.setLanguage("en"); // mock data datasetRDAExportModel.setTitle(dataset.getLabel()); - datasetRDAExportModel.setIssued(dataset.getCreated()); - datasetRDAExportModel.setLanguage("en"); // mock data; - datasetRDAExportModel.setDataset_id(new DatasetIdRDAExportModel(dataset.getId().toString(), "argos_internal")); - List datasetMetadataRDAExportModels = new LinkedList<>(); - for (String key : metadataJsonMap.keySet()) { - for (String value : metadataJsonMap.get(key)) { - datasetMetadataRDAExportModels.add(new DatasetMetadataRDAExportModel().fromDataModel(key,value)); - } + // Transform the answered dataset description to json so we can parse it and fill the rda model. + JSONObject datasetDescriptionJson = null; + try { + String jsonResult = mapper.writeValueAsString(datasetManager.getSingle(dataset.getId().toString()).getDatasetProfileDefinition()); + datasetDescriptionJson = new JSONObject(jsonResult); + } catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); } - datasetRDAExportModel.setMetadata(datasetMetadataRDAExportModels); + setMultiplicityIdToFieldSetId(datasetDescriptionJson); + + /*--------- Building personal data. ---------*/ + String personalData = buildSingleProperties("dataset.personal_data", datasetDescriptionJson, templateIdsToValues); + if (personalData != null) { + datasetRDAExportModel.setPersonal_data(personalData); + } else { + datasetRDAExportModel.setPersonal_data("unknown"); + } + + /*--------- Building preservation statement. ---------*/ + datasetRDAExportModel.setPreservation_statement(buildSingleProperties("dataset.preservation_statement", datasetDescriptionJson, templateIdsToValues)); + + /*--------- Building sensitive data. ---------*/ + String sensitiveData = buildSingleProperties("dataset.sensitive_data", datasetDescriptionJson, templateIdsToValues); + if (personalData != null) { + datasetRDAExportModel.setSensitive_data(sensitiveData); + } else { + datasetRDAExportModel.setSensitive_data("unknown"); + } + + /*--------- Building type. ---------*/ + datasetRDAExportModel.setType(buildSingleProperties("dataset.type", datasetDescriptionJson, templateIdsToValues)); + + /*--------- Building data_quality_assurance. ---------*/ + datasetRDAExportModel.setData_quality_assurance(buildDataQualityAssurance(datasetDescriptionJson, templateIdsToValues, dataset.getProfile().getDefinition())); + + /*--------- Building distribution. ---------*/ + datasetRDAExportModel.setDistribution(buildDistribution(datasetDescriptionJson, templateIdsToValues, dataset.getProfile().getDefinition())); + + /*--------- Building keywords. ---------*/ + datasetRDAExportModel.setKeyword(buildKeywords(datasetDescriptionJson, templateIdsToValues, dataset.getProfile().getDefinition())); + + /*--------- Building metadata items. ---------*/ + datasetRDAExportModel.setMetadata(buildMetadata(datasetDescriptionJson, templateIdsToValues, dataset.getProfile().getDefinition())); + + /*--------- Building security and privacy items. ---------*/ + datasetRDAExportModel.setSecurity_and_privacy(buildSecurityAndPrivacy(datasetDescriptionJson, templateIdsToValues, dataset.getProfile().getDefinition())); + + /*--------- Building technical_resource. ---------*/ + datasetRDAExportModel.setTechnical_resource(buildTechnicalResource(datasetDescriptionJson, templateIdsToValues, dataset.getProfile().getDefinition())); return datasetRDAExportModel; } - private List xmlNodeListFromExpression(String xml, String expression) { + private String buildSingleProperties(String rdaKey, JSONObject datasetDescriptionJson, Map templateIdsToValues) { + String expression = "$..fields[*][?(@.rdaProperty == \"" + rdaKey + "\" )].id"; + List list = jsonValueListFromExpression(datasetDescriptionJson, expression); + if (!list.isEmpty()) { + return templateIdsToValues.get(list.get(0)).toString(); + } else { + return null; + } + } + + private List buildDataQualityAssurance(JSONObject datasetDescriptionJson, Map templateIdsToValues, String datasetProfileDefinition) { + List dataQualityFields = getRDAFieldsFromJson(datasetDescriptionJson, new String[]{"dataset.data_quality_assurance"}, datasetProfileDefinition); + for (RdaField rdaField : dataQualityFields) { + rdaField.setRdaValue(templateIdsToValues.get(rdaField.getFieldId()).toString()); + } + List dataQualityAssuranceList = new LinkedList<>(); + for (RdaField rdaField : dataQualityFields) { + dataQualityAssuranceList.add(rdaField.getRdaValue()); + } + + return dataQualityAssuranceList; + } + + private List buildDistribution(JSONObject datasetDescriptionJson, Map templateIdsToValues, String datasetProfileDefinition) { + DatasetDistributionRDAExportModel distributionModel = new DatasetDistributionRDAExportModel(); + distributionModel.setAccess_url(buildSingleProperties("dataset.distribution.access_url", datasetDescriptionJson, templateIdsToValues)); + distributionModel.setAvailable_till(buildSingleProperties("dataset.distribution.available_till", datasetDescriptionJson, templateIdsToValues)); + distributionModel.setByte_size(buildSingleProperties("dataset.distribution.byte_size", datasetDescriptionJson, templateIdsToValues)); + distributionModel.setData_access(buildSingleProperties("dataset.distribution.data_access", datasetDescriptionJson, templateIdsToValues)); + distributionModel.setDescription(buildSingleProperties("dataset.distribution.description", datasetDescriptionJson, templateIdsToValues)); + distributionModel.setDownload_url(buildSingleProperties("dataset.distribution.download_url", datasetDescriptionJson, templateIdsToValues)); + distributionModel.setTitle(buildSingleProperties("dataset.distribution.title", datasetDescriptionJson, templateIdsToValues)); + + /*--------- Building format. ---------*/ + + + // We currently support the return of only one distribution. + List distributionList = new LinkedList<>(); + if (distributionModel.isValid()) { + distributionList.add(distributionModel); + } else { + DatasetDistributionRDAExportModel model = new DatasetDistributionRDAExportModel(); + model.setDescription("Distribution data was not valid"); + distributionList.add(model); + } + + return distributionList; + } + + private List buildKeywords(JSONObject datasetDescriptionJson, Map templateIdsToValues, String datasetProfileDefinition) { + List keywordFields = getRDAFieldsFromJson(datasetDescriptionJson, new String[]{"dataset.keyword"}, datasetProfileDefinition); + for (RdaField rdaField : keywordFields) { + rdaField.setRdaValue(templateIdsToValues.get(rdaField.getFieldId()).toString()); + } + List keywordsList = new LinkedList<>(); + for (RdaField rdaField : keywordFields) { + keywordsList.add(rdaField.getRdaValue()); + } + + return keywordsList; + } + + private List buildMetadata(JSONObject datasetDescriptionJson, Map templateIdsToValues, String datasetProfileDefinition) { + List metadataFields = getRDAFieldsFromJson(datasetDescriptionJson, + new String[]{"dataset.metadata.metadata_standard_id.type", "dataset.metadata.metadata_standard_id.identifier", "dataset.metadata.description", "dataset.metadata.language", "dataset.metadata.metadata_standard_id"}, + datasetProfileDefinition); + + // Adding rdaValue and FieldSetIds on metadataFields. + for (RdaField rdaField : metadataFields) { + rdaField.setRdaValue(templateIdsToValues.get(rdaField.getFieldId()).toString()); + } + // Group metadataFields based on their field set id. + Map> groupedMetadataFields = metadataFields.stream().collect(groupingBy(RdaField::getFieldSetId)); + + // Creating the metadata. + List metadataRDAExportModelList = new LinkedList<>(); + for (String fieldSetId : groupedMetadataFields.keySet()) { + DatasetMetadataRDAExportModel metadataRda = new DatasetMetadataRDAExportModel(); + for (RdaField rdaField : groupedMetadataFields.get(fieldSetId)) { + if (rdaField.getRdaProperty().equals("dataset.metadata.metadata_standard_id.identifier")) { + if (metadataRda.getMetadata_standard_id() != null) { + metadataRda.getMetadata_standard_id().setIdentifier(rdaField.getRdaValue()); + } else { + metadataRda.setMetadata_standard_id(new IdRDAExportModel(rdaField.getRdaValue(), "other")); + } + } + if (rdaField.getRdaProperty().equals("dataset.metadata.metadata_standard_id.type")) { + if (metadataRda.getMetadata_standard_id() != null) { + metadataRda.getMetadata_standard_id().setType(rdaField.getRdaValue()); + } else { + metadataRda.setMetadata_standard_id(new IdRDAExportModel("", rdaField.getRdaValue())); + } + } + if (rdaField.getRdaProperty().equals("dataset.metadata.description")) { + metadataRda.setDescription(rdaField.getRdaValue()); + } + if (rdaField.getRdaProperty().equals("dataset.metadata.language")) { + metadataRda.setLanguage(rdaField.getRdaValue()); + } + if (rdaField.getRdaProperty().equals("dataset.metadata.metadata_standard_id")) { + JSONArray jsonArray = new JSONArray(rdaField.getRdaValue()); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + Map jsonObjectMap = jsonObject.toMap(); + DatasetMetadataRDAExportModel metadataRda1 = new DatasetMetadataRDAExportModel(); + metadataRda1.setMetadata_standard_id(new IdRDAExportModel(jsonObjectMap.get("label").toString(), jsonObjectMap.get("source").toString())); + metadataRDAExportModelList.add(metadataRda1); + } + } + } + if (metadataRda.isValid()) { + metadataRDAExportModelList.add(metadataRda); + } + } + + return new LinkedList<>(metadataRDAExportModelList); + } + + private List buildSecurityAndPrivacy(JSONObject datasetDescriptionJson, Map templateIdsToValues, String datasetProfileDefinition) { + List secAndPrFields = getRDAFieldsFromJson( + datasetDescriptionJson, + new String[]{"dataset.security_and_privacy.description", "dataset.security_and_privacy.title", "dataset.security_and_privacy"}, + datasetProfileDefinition); + for (RdaField rdaField : secAndPrFields) { + rdaField.setRdaValue(templateIdsToValues.get(rdaField.getFieldId()).toString()); + } + Map> groupedSecurityAndPrivacyFields = secAndPrFields.stream().collect(groupingBy(RdaField::getFieldSetId)); + + List securityAndPrivacyRDAExportModelList = new LinkedList<>(); + for (String fieldSetId : groupedSecurityAndPrivacyFields.keySet()) { + DatasetSecurityAndPrivacyRDAExportModel securityAndPrivacyModel = new DatasetSecurityAndPrivacyRDAExportModel(); + for (RdaField rdaField : groupedSecurityAndPrivacyFields.get(fieldSetId)) { + if (rdaField.getRdaProperty().equals("dataset.security_and_privacy.description")) { + securityAndPrivacyModel.setDescription(rdaField.getRdaValue()); + } + if (rdaField.getRdaProperty().equals("dataset.security_and_privacy.title")) { + securityAndPrivacyModel.setTitle(rdaField.getRdaValue()); + } + if (rdaField.getRdaProperty().equals("dataset.security_and_privacy")) { + JSONArray jsonArray = new JSONArray(rdaField.getRdaValue()); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + Map jsonObjectMap = jsonObject.toMap(); + DatasetSecurityAndPrivacyRDAExportModel secAndPrivacy = new DatasetSecurityAndPrivacyRDAExportModel(jsonObjectMap.get("label").toString(), jsonObjectMap.get("source").toString()); + securityAndPrivacyRDAExportModelList.add(secAndPrivacy); + } + } + } + securityAndPrivacyRDAExportModelList.add(securityAndPrivacyModel); + } + + return securityAndPrivacyRDAExportModelList; + } + + private List buildTechnicalResource(JSONObject datasetDescriptionJson, Map templateIdsToValues, String datasetProfileDefinition) { + List dataQualityFields = getRDAFieldsFromJson(datasetDescriptionJson, + new String[]{"dataset.technical_resource.technical_resource", "dataset.technical_resource.technical_resource.description", "dataset.technical_resource.technical_resource.name"}, + datasetProfileDefinition); + for (RdaField rdaField : dataQualityFields) { + rdaField.setRdaValue(templateIdsToValues.get(rdaField.getFieldId()).toString()); + } + List technicalResourceList = new LinkedList<>(); + Map> groupedDataQualityFields = dataQualityFields.stream().collect(groupingBy(RdaField::getFieldSetId)); + for (String fieldSetId : groupedDataQualityFields.keySet()) { + DatasetTechnicalResourceRDAExportModel technicalResourceModel = new DatasetTechnicalResourceRDAExportModel(); + for (RdaField rdaField : groupedDataQualityFields.get(fieldSetId)) { + if (rdaField.getRdaProperty().equals("dataset.technical_resource.technical_resource.description")) { + technicalResourceModel.setDescription(rdaField.getRdaValue()); + } + if (rdaField.getRdaProperty().equals("dataset.technical_resource.technical_resource.name")) { + technicalResourceModel.setName(rdaField.getRdaValue()); + } + if (rdaField.getRdaProperty().equals("dataset.security_and_privacy")) { + JSONArray jsonArray = new JSONArray(rdaField.getRdaValue()); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + Map jsonObjectMap = jsonObject.toMap(); + DatasetTechnicalResourceRDAExportModel technicalResource = new DatasetTechnicalResourceRDAExportModel(jsonObjectMap.get("label").toString(), jsonObjectMap.get("label").toString()); + technicalResourceList.add(technicalResource); + } + } + } + technicalResourceList.add(technicalResourceModel); + } + + return technicalResourceList; + } + + private void setMultiplicityIdToFieldSetId(JSONObject json) { + String multiplicityItemsFieldSetIdExp = "$..multiplicityItems[*].id"; + List multiplicityItemsFieldSetIdList = jsonValueListFromExpression(json, multiplicityItemsFieldSetIdExp); + for (String fieldSetId : multiplicityItemsFieldSetIdList) { + String fieldsFromFieldSetIdExp = "$..multiplicityItems[*][?(@.id == \""+ fieldSetId +"\")].fields[*].id"; + List fieldsIdList = jsonValueListFromExpression(json, fieldsFromFieldSetIdExp); + for (String fieldId : fieldsIdList) { + this.multiplicityIdToFieldSetId.put(fieldId, fieldSetId); + } + } + } + + private List getRDAFieldsFromJson(JSONObject json, String[] rdaKey, String datasetProfileDefinition) { + List rdaFields = new LinkedList<>(); + for (String key : rdaKey) { + String fieldIdExpression = "$..fields[*][?(@.rdaProperty == \"" + key + "\" )].id"; + List listFromExpression = jsonValueListFromExpression(json, fieldIdExpression); + for (String fieldId : listFromExpression) { + RdaField rdaField = new RdaField(); + rdaField.setRdaProperty(key); + rdaField.setFieldId(fieldId); + if (fieldId.startsWith("multiple_")) { + rdaField.setFieldSetId(this.multiplicityIdToFieldSetId.get(fieldId)); + } else { + rdaField.setFieldSetId(getFieldSetIdForFieldFromXML(datasetProfileDefinition, fieldId)); + } + rdaFields.add(rdaField); + } + } + return rdaFields; + } + + private List jsonValueListFromExpression(JSONObject json, String expression) { + net.minidev.json.JSONArray jsonArray = JsonPath.parse(json.toString()).read(expression); + List valueList = new LinkedList<>(); + for (Object o : jsonArray) { + valueList.add(o.toString()); + } + return valueList; + } + + private String getFieldSetIdForFieldFromXML(String datasetProfileDefinition, String fieldId) { + String fieldSetIdExpression = "//field[@id ='" + fieldId + "']/ancestor::fieldSet/@id"; + List listFromExpression = xmlValueListFromExpression(datasetProfileDefinition, fieldSetIdExpression); + if (listFromExpression.size() == 1) return listFromExpression.get(0); + return null; + } + + private List xmlValueListFromExpression(String xml, String expression) { List valuesList = new LinkedList<>(); Document document = XmlBuilder.fromXml(xml); XPathFactory xpathFactory = XPathFactory.newInstance(); @@ -147,19 +464,9 @@ public class DatasetRDAExportModel { valuesList.add(node.getNodeValue()); } } catch (XPathExpressionException e) { - e.printStackTrace(); + logger.error(e.getMessage(), e); } return valuesList; } - - private Map combineListsIntoOrderedMap (List keys, List values) { - if (keys.size() != values.size()) - throw new IllegalArgumentException ("Cannot combine lists with dissimilar sizes"); - Map map = new LinkedHashMap<>(); - for (int i=0; i role; + + public IdRDAExportModel getContributor_id() { + return contributor_id; + } + public void setContributor_id(IdRDAExportModel contributor_id) { + this.contributor_id = contributor_id; + } + + public String getMbox() { + return mbox; + } + public void setMbox(String mbox) { + this.mbox = mbox; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public List getRole() { + return role; + } + public void setRole(List role) { + this.role = role; + } + + public DmpContributorRDAExportModel fromDataModel(UserInfo user, String role) { + DmpContributorRDAExportModel contributor = new DmpContributorRDAExportModel(); + contributor.contributor_id = new IdRDAExportModel(user.getId().toString(), "other"); + contributor.mbox = user.getEmail(); + contributor.name = user.getName(); + contributor.role = new LinkedList<>(); + contributor.role.add(role); + + return contributor; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpCostRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpCostRDAExportModel.java new file mode 100644 index 000000000..98abbadd8 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpCostRDAExportModel.java @@ -0,0 +1,36 @@ +package eu.eudat.models.data.rda; + +public class DmpCostRDAExportModel { + private String currency_code; //Allowed values defined by ISO 4217. + private String description; + private String title; + private String value; + + public String getCurrency_code() { + return currency_code; + } + public void setCurrency_code(String currency_code) { + this.currency_code = currency_code; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpIdRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpIdRDAExportModel.java deleted file mode 100644 index 1c7e09793..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpIdRDAExportModel.java +++ /dev/null @@ -1,25 +0,0 @@ -package eu.eudat.models.data.rda; - -public class DmpIdRDAExportModel { - private String dmp_id; - private String dmp_id_type; - - public String getDmp_id() { - return dmp_id; - } - public void setDmp_id(String dmp_id) { - this.dmp_id = dmp_id; - } - - public String getDmp_id_type() { - return dmp_id_type; - } - public void setDmp_id_type(String dmp_id_type) { - this.dmp_id_type = dmp_id_type; - } - - DmpIdRDAExportModel(String dmp_id, String dmp_id_type) { - this.dmp_id = dmp_id; - this.dmp_id_type = dmp_id_type; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java index a4fab5c74..53fda76d0 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/DmpRDAExportModel.java @@ -1,34 +1,67 @@ package eu.eudat.models.data.rda; import eu.eudat.data.entities.DMP; +import eu.eudat.data.entities.Dataset; import eu.eudat.data.entities.UserDMP; +import eu.eudat.data.entities.UserInfo; +import eu.eudat.logic.managers.DatasetManager; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Date; -import java.util.UUID; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; public class DmpRDAExportModel { - private DmpIdRDAExportModel dmp_id; - private String title; - private String description; - private Date created; - private Date modified; private ContactRDAExportModel contact; + private List contributor; + private List cost; + private String created; + private List dataset; + private String description; + private IdRDAExportModel dmp_id; + private String ethical_issues_description; + private String ethical_issues_exist; // Allowed Values: yes no unknown. + private String ethical_issues_report; private String language; - private String ethical_issues_exist; + private String modified; private ProjectRDAExportModel project; + private String title; - public DmpIdRDAExportModel getDmp_id() { - return dmp_id; + public ContactRDAExportModel getContact() { + return contact; } - public void setDmp_id(DmpIdRDAExportModel dmp_id) { - this.dmp_id = dmp_id; + public void setContact(ContactRDAExportModel contact) { + this.contact = contact; } - public String getTitle() { - return title; + public List getContributor() { + return contributor; } - public void setTitle(String title) { - this.title = title; + public void setContributor(List contributor) { + this.contributor = contributor; + } + + public List getCost() { + return cost; + } + public void setCost(List cost) { + this.cost = cost; + } + + public String getCreated() { + return created; + } + public void setCreated(String created) { + this.created = created; + } + + public List getDataset() { + return dataset; + } + public void setDataset(List dataset) { + this.dataset = dataset; } public String getDescription() { @@ -38,32 +71,18 @@ public class DmpRDAExportModel { this.description = description; } - public Date getCreated() { - return created; + public IdRDAExportModel getDmp_id() { + return dmp_id; } - public void setCreated(Date created) { - this.created = created; + public void setDmp_id(IdRDAExportModel dmp_id) { + this.dmp_id = dmp_id; } - public Date getModified() { - return modified; + public String getEthical_issues_description() { + return ethical_issues_description; } - public void setModified(Date modified) { - this.modified = modified; - } - - public ContactRDAExportModel getContact() { - return contact; - } - public void setContact(ContactRDAExportModel contact) { - this.contact = contact; - } - - public String getLanguage() { - return language; - } - public void setLanguage(String language) { - this.language = language; + public void setEthical_issues_description(String ethical_issues_description) { + this.ethical_issues_description = ethical_issues_description; } public String getEthical_issues_exist() { @@ -73,6 +92,27 @@ public class DmpRDAExportModel { this.ethical_issues_exist = ethical_issues_exist; } + public String getEthical_issues_report() { + return ethical_issues_report; + } + public void setEthical_issues_report(String ethical_issues_report) { + this.ethical_issues_report = ethical_issues_report; + } + + public String getLanguage() { + return language; + } + public void setLanguage(String language) { + this.language = language; + } + + public String getModified() { + return modified; + } + public void setModified(String modified) { + this.modified = modified; + } + public ProjectRDAExportModel getProject() { return project; } @@ -80,25 +120,44 @@ public class DmpRDAExportModel { this.project = project; } + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } - public DmpRDAExportModel fromDataModel(DMP entity) { - if (entity.getDoi() != null) - this.dmp_id = new DmpIdRDAExportModel(entity.getDoi(), "zenodo"); - else - this.dmp_id = new DmpIdRDAExportModel(entity.getId().toString(), "argos_internal"); + public DmpRDAExportModel fromDataModel(DMP entity, DatasetManager datasetManager) { + DmpRDAExportModel dmpRda = new DmpRDAExportModel(); + dmpRda.contact = new ContactRDAExportModel().fromDataModel(entity.getUsers().stream().filter(x -> x.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser()); + if (entity.getUsers().stream().anyMatch(x -> x.getRole().equals(UserDMP.UserDMPRoles.USER.getValue()))) { + dmpRda.contributor = new LinkedList<>(); + for (UserDMP userdmp : entity.getUsers().stream().filter(x -> x.getRole().equals(UserDMP.UserDMPRoles.USER.getValue())).collect(Collectors.toList())) { + dmpRda.contributor.add(new DmpContributorRDAExportModel().fromDataModel(userdmp.getUser(), UserDMP.UserDMPRoles.fromInteger(userdmp.getRole()).toString())); + } + } + dmpRda.cost = null; + SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); + dmpRda.created = formatter.format(entity.getCreated()); + dmpRda.dataset = new LinkedList<>(); + for (Dataset dataset : entity.getDataset()) { + if (dataset.getStatus() != Dataset.Status.DELETED.getValue() && dataset.getStatus() != Dataset.Status.CANCELED.getValue()) + dmpRda.dataset.add(new DatasetRDAExportModel().fromDataModel(dataset, datasetManager)); + } + dmpRda.description = entity.getDescription().replace("\n", " "); + if (entity.getDoi() != null) { + dmpRda.dmp_id = new IdRDAExportModel(entity.getDoi(), "zenodo"); + } + else { + dmpRda.dmp_id = new IdRDAExportModel(entity.getId().toString(), "other"); + } + // Mock up data on "language" and "ethical_issues_*" for now. + dmpRda.ethical_issues_exist = "unknown"; + dmpRda.language = "en"; + dmpRda.modified = formatter.format(new Date()); + dmpRda.project = new ProjectRDAExportModel().fromDataModel(entity.getGrant()); + dmpRda.title = entity.getLabel(); - this.title = entity.getLabel(); - this.description = entity.getDescription(); - this.created = entity.getCreated(); - this.modified = entity.getModified(); - this.contact = new ContactRDAExportModel().fromDataModel(entity.getUsers().stream().filter(x -> x.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser()); - - // Mock up data on "language" and "ethical_issues" for now. - this.language = "en"; - this.ethical_issues_exist = "unknown"; - - this.project = new ProjectRDAExportModel().fromDataModel(entity.getGrant()); - - return this; + return dmpRda; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FunderIdRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FunderIdRDAExportModel.java deleted file mode 100644 index d58abeb5f..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FunderIdRDAExportModel.java +++ /dev/null @@ -1,25 +0,0 @@ -package eu.eudat.models.data.rda; - -public class FunderIdRDAExportModel { - private String funder_id; - private String funder_id_type; - - public String getFunder_id() { - return funder_id; - } - public void setFunder_id(String funder_id) { - this.funder_id = funder_id; - } - - public String getFunder_id_type() { - return funder_id_type; - } - public void setFunder_id_type(String funder_id_type) { - this.funder_id_type = funder_id_type; - } - - FunderIdRDAExportModel(String funder_id, String funder_id_type) { - this.funder_id = funder_id; - this.funder_id_type = funder_id_type; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FundingRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FundingRDAExportModel.java index 0739b7766..5691cae2c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FundingRDAExportModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/FundingRDAExportModel.java @@ -4,21 +4,21 @@ import eu.eudat.data.entities.Funder; import eu.eudat.data.entities.Grant; public class FundingRDAExportModel { - private FunderIdRDAExportModel funder_id; - private GrantIdRDAExportModel grant_id; + private IdRDAExportModel funder_id; + private IdRDAExportModel grant_id; private String funding_status; - public FunderIdRDAExportModel getFunder_id() { + public IdRDAExportModel getFunder_id() { return funder_id; } - public void setFunder_id(FunderIdRDAExportModel funder_id) { + public void setFunder_id(IdRDAExportModel funder_id) { this.funder_id = funder_id; } - public GrantIdRDAExportModel getGrant_id() { + public IdRDAExportModel getGrant_id() { return grant_id; } - public void setGrant_id(GrantIdRDAExportModel grant_id) { + public void setGrant_id(IdRDAExportModel grant_id) { this.grant_id = grant_id; } @@ -30,13 +30,14 @@ public class FundingRDAExportModel { } public FundingRDAExportModel fromDataModel(Funder funder, Grant grant) { - this.funding_status = "planned"; // mock data + FundingRDAExportModel funding = new FundingRDAExportModel(); + funding.funding_status = "planned"; // mock data if (funder != null) { - this.funder_id = new FunderIdRDAExportModel(funder.getReference(), "argos_internal"); + funding.funder_id = new IdRDAExportModel(funder.getReference(), "other"); } if (grant != null) { - this.grant_id = new GrantIdRDAExportModel(grant.getReference(), "argos_internal"); + funding.grant_id = new IdRDAExportModel(grant.getReference(), "other"); } - return this; + return funding; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/GrantIdRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/GrantIdRDAExportModel.java deleted file mode 100644 index 8bcac2735..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/GrantIdRDAExportModel.java +++ /dev/null @@ -1,25 +0,0 @@ -package eu.eudat.models.data.rda; - -public class GrantIdRDAExportModel { - private String grant_id; - private String grant_id_type; - - public String getGrant_id() { - return grant_id; - } - public void setGrant_id(String grant_id) { - this.grant_id = grant_id; - } - - public String getGrant_id_type() { - return grant_id_type; - } - public void setGrant_id_type(String grant_id_type) { - this.grant_id_type = grant_id_type; - } - - GrantIdRDAExportModel(String grant_id, String grant_id_type) { - this.grant_id = grant_id; - this.grant_id_type = grant_id_type; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/HostRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/HostRDAExportModel.java new file mode 100644 index 000000000..bac169259 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/HostRDAExportModel.java @@ -0,0 +1,86 @@ +package eu.eudat.models.data.rda; + +import java.util.List; + +public class HostRDAExportModel { + private String availability; + private String backup__frequency; + private String backup_type; + private String certified_with; // Repository certified with one the following standards: DIN31644 / DINI-Zertifikat / DSA / ISO16363 / ISO16919 /TRAC / WDS / CoreTrustSeal + private String description; + private String geo_location; // Physical location of the data expressed using ISO 3166-1 country code. + private List pid_system; // PID System: ark arxiv bibcode doi ean13 eissn handle igsn isbn issn istc lissn lsid pmid purl upc url urn other + private String storage_type; + private String support_versioning; // Allowed values: yes / no / unknown + private String title; + + public String getAvailability() { + return availability; + } + public void setAvailability(String availability) { + this.availability = availability; + } + + public String getBackup__frequency() { + return backup__frequency; + } + public void setBackup__frequency(String backup__frequency) { + this.backup__frequency = backup__frequency; + } + + public String getBackup_type() { + return backup_type; + } + public void setBackup_type(String backup_type) { + this.backup_type = backup_type; + } + + public String getCertified_with() { + return certified_with; + } + public void setCertified_with(String certified_with) { + this.certified_with = certified_with; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public String getGeo_location() { + return geo_location; + } + public void setGeo_location(String geo_location) { + this.geo_location = geo_location; + } + + public List getPid_system() { + return pid_system; + } + public void setPid_system(List pid_system) { + this.pid_system = pid_system; + } + + public String getStorage_type() { + return storage_type; + } + public void setStorage_type(String storage_type) { + this.storage_type = storage_type; + } + + public String getSupport_versioning() { + return support_versioning; + } + public void setSupport_versioning(String support_versioning) { + this.support_versioning = support_versioning; + } + + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/IdRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/IdRDAExportModel.java new file mode 100644 index 000000000..2aef46e5b --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/IdRDAExportModel.java @@ -0,0 +1,25 @@ +package eu.eudat.models.data.rda; + +public class IdRDAExportModel { + private String identifier; + private String type; + + public String getIdentifier() { + return identifier; + } + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + IdRDAExportModel(String identifier, String type) { + this.identifier = identifier; + this.type = type; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/LicenseRDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/LicenseRDAExportModel.java new file mode 100644 index 000000000..dec57a467 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/LicenseRDAExportModel.java @@ -0,0 +1,20 @@ +package eu.eudat.models.data.rda; + +public class LicenseRDAExportModel { + private String license_ref; + private String start_date; // If date is set in the future, it indicates embargo period. + + public String getLicense_ref() { + return license_ref; + } + public void setLicense_ref(String license_ref) { + this.license_ref = license_ref; + } + + public String getStart_date() { + return start_date; + } + public void setStart_date(String start_date) { + this.start_date = start_date; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RDAExportModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RDAExportModel.java index b4720d350..ad3d3c16b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RDAExportModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RDAExportModel.java @@ -2,13 +2,13 @@ package eu.eudat.models.data.rda; import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.Dataset; +import eu.eudat.logic.managers.DatasetManager; import java.util.LinkedList; import java.util.List; public class RDAExportModel { private DmpRDAExportModel dmp; - private List datasets; public DmpRDAExportModel getDmp() { return dmp; @@ -17,20 +17,8 @@ public class RDAExportModel { this.dmp = dmp; } - public List getDatasets() { - return datasets; - } - public void setDatasets(List datasets) { - this.datasets = datasets; - } - - public RDAExportModel fromDataModel(DMP dmp) { - this.dmp = new DmpRDAExportModel().fromDataModel(dmp); - this.datasets = new LinkedList<>(); - for (Dataset dataset : dmp.getDataset()) { - if (dataset.getStatus() != Dataset.Status.DELETED.getValue() && dataset.getStatus() != Dataset.Status.CANCELED.getValue()) - this.datasets.add(new DatasetRDAExportModel().fromDataModel(dataset)); - } + public RDAExportModel fromDataModel(DMP dmp, DatasetManager datasetManager) { + this.dmp = new DmpRDAExportModel().fromDataModel(dmp, datasetManager); return this; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RdaField.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RdaField.java new file mode 100644 index 000000000..31acd5c51 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/rda/RdaField.java @@ -0,0 +1,36 @@ +package eu.eudat.models.data.rda; + +public class RdaField { + private String rdaProperty; + private String rdaValue; + private String fieldId; + private String fieldSetId; + + public String getRdaProperty() { + return rdaProperty; + } + public void setRdaProperty(String rdaProperty) { + this.rdaProperty = rdaProperty; + } + + public String getRdaValue() { + return rdaValue; + } + public void setRdaValue(String rdaValue) { + this.rdaValue = rdaValue; + } + + public String getFieldId() { + return fieldId; + } + public void setFieldId(String fieldId) { + this.fieldId = fieldId; + } + + public String getFieldSetId() { + return fieldSetId; + } + public void setFieldSetId(String fieldSetId) { + this.fieldSetId = fieldSetId; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/registries/RegistryModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/registries/RegistryModel.java index 89906eb03..1a2d5afb7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/registries/RegistryModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/registries/RegistryModel.java @@ -18,6 +18,7 @@ public class RegistryModel implements DataModel { private String uri; private Date created; private Date modified; + private String reference; private String tag; // Api fetching the data private String source; // Actual harvested source @@ -70,6 +71,13 @@ public class RegistryModel implements DataModel { this.modified = modified; } + public String getReference() { + return reference; + } + public void setReference(String reference) { + this.reference = reference; + } + public String getTag() { return tag; } @@ -106,6 +114,7 @@ public class RegistryModel implements DataModel { } else { this.source = source1; } + this.reference = entity.getReference(); return this; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/user/components/datasetprofile/Field.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/user/components/datasetprofile/Field.java index f01ecf678..4950261c4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/user/components/datasetprofile/Field.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/user/components/datasetprofile/Field.java @@ -9,6 +9,9 @@ import eu.eudat.models.data.user.composite.PropertiesModelBuilder; import eu.eudat.logic.utilities.interfaces.ViewStyleDefinition; import eu.eudat.logic.utilities.builders.ModelBuilder; +import org.json.JSONArray; +import org.json.JSONException; + import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -17,7 +20,7 @@ import java.util.stream.Collectors; public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefinition, PropertiesGenerator { private String id; private Integer ordinal; - private String value; + private Object value; private ViewStyle viewStyle; private String datatype; private String numbering; @@ -28,6 +31,7 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin private List multiplicityItems; private List validations; private Visibility visible; + private String rdaProperty; public List getMultiplicityItems() { return multiplicityItems; @@ -57,11 +61,11 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin this.ordinal = ordinal; } - public String getValue() { + public Object getValue() { return value; } - public void setValue(String value) { + public void setValue(Object value) { this.value = value; } @@ -137,7 +141,15 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin this.numbering = numbering; } - public Field cloneForMultiplicity(String key, Map properties) { + public String getRdaProperty() { + return rdaProperty; + } + + public void setRdaProperty(String rdaProperty) { + this.rdaProperty = rdaProperty; + } + + Field cloneForMultiplicity(String key, Map properties) { Field newField = new Field(); newField.id = key; newField.ordinal = this.ordinal; @@ -148,6 +160,7 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin newField.defaultValue = this.defaultValue; newField.data = this.data; newField.validations = this.validations; + newField.rdaProperty = this.rdaProperty; return newField; } @@ -160,6 +173,7 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin field.setDefaultValue(this.defaultValue); field.setVisible(this.visible); field.setValidations(this.validations); + field.setRdaCommonStandard(this.rdaProperty); return field; } @@ -173,17 +187,26 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin this.defaultValue = item.getDefaultValue(); this.visible = item.getVisible(); this.validations = item.getValidations(); + this.rdaProperty = item.getRdaCommonStandard(); } @Override public void fromJsonObject(Map properties) { - this.value = (String) properties.get(this.id); - this.multiplicityItems = new LinkedList(); + try { + JSONArray jsonArray = new JSONArray(properties.get(this.id).toString()); + List stringList = new LinkedList<>(); + for (int i = 0; i < jsonArray.length(); i++) { + stringList.add(jsonArray.getJSONObject(i).toString()); + } + this.value = stringList; + } catch (JSONException | NullPointerException e) { + this.value = (String) properties.get(this.id); + } + this.multiplicityItems = new LinkedList<>(); List compositeKeys = properties.keySet().stream().filter(keys -> keys.startsWith("multiple_" + this.getId())).collect(Collectors.toList()); for (String key : compositeKeys) { this.multiplicityItems.add(this.cloneForMultiplicity(key, properties)); } - } @Override @@ -198,7 +221,11 @@ public class Field implements Comparable, PropertiesModelBuilder, ViewStyleDefin @Override public void toMap(Map fieldValues) { - fieldValues.put(this.id, this.value); + if (this.value != null) { + fieldValues.put(this.id, this.value.toString()); + } else { + fieldValues.put(this.id, ""); + } } @Override diff --git a/dmp-backend/web/src/main/resources/ExternalUrls.xml b/dmp-backend/web/src/main/resources/ExternalUrls.xml index d987d3fcc..70d437e0e 100644 --- a/dmp-backend/web/src/main/resources/ExternalUrls.xml +++ b/dmp-backend/web/src/main/resources/ExternalUrls.xml @@ -49,7 +49,7 @@ 1 Internal - mockData/RegistriesInternalMockUpData.json + web/src/main/resources/mockData/RegistriesInternalMockUpData.json $['data'][*]['attributes'] @@ -109,7 +109,7 @@ 1 Internal - mockData/TagsInternalMockUpData.json + web/src/main/resources/mockData/TagsInternalMockUpData.json $['data'][*]['attributes'] @@ -146,7 +146,7 @@ $['meta']['pagination']['page','pages','count'] - openAIRE + openaire 1 https://services.openaire.eu/search/v2/api/resources?query=((oaftype%20exact%20project)%20and%20((projectcode_nt%20exact%20%22{like}%22)or({like}))){funderQuery}&page={page}&size={pageSize}&format=json @@ -185,7 +185,7 @@ internal 1 - mockData/GrantInternalMockUpData.json + web/src/main/resources/mockData/GrantInternalMockUpData.json Internal $['data'][*]['attributes'] @@ -224,7 +224,7 @@ $['meta']['pagination']['page','pages','count'] - openAIRE + openaire 1 External @@ -265,7 +265,7 @@ 1 Internal - mockData/ProjectInternalMockUpData.json + web/src/main/resources/mockData/ProjectInternalMockUpData.json $['data'][*]['attributes'] @@ -283,6 +283,74 @@ + + openaire + + 1 + External + https://services.openaire.eu/search/v2/api/publications?&refine=true&fields=relfunder&page={page}&size=0&format=json + 0 + application/json; charset=utf-8 + + $['refineResults']['relfunder'][*] + + 'name' + 'id' + 'count' + + + + + openaire + + 1 + External + https://services.openaire.eu/search/v2/api/datasets?&refine=true&fields=relfunder&page=0&size={page}&format=json + 0 + application/json; charset=utf-8 + + $['refineResults']['relfunder'][*] + + 'name' + 'id' + 'count' + + + + + openaire + + 1 + External + https://services.openaire.eu/search/v2/api/software?&refine=true&fields=relfunder&page={page}&size=0&format=json + 0 + application/json; charset=utf-8 + + $['refineResults']['relfunder'][*] + + 'name' + 'id' + 'count' + + + + + openaire + + 1 + External + https://services.openaire.eu/search/v2/api/other?&refine=true&fields=relfunder&page={page}&size=0&format=json + 0 + application/json; charset=utf-8 + + $['refineResults']['relfunder'][*] + + 'name' + 'id' + 'count' + + + - openAire - + cristin + 1 External https://eestore.paas2.uninett.no/api/projectrepo/?search={like}&page={page}&size={pageSize} @@ -317,11 +385,26 @@ 'name' 'uri' 'description' - 'source' $['meta']['pagination']['page','pages','count'] + + crossref + + 1 + External + https://api.crossref.org/funders?query={like}&rows={pageSize} + application/json; charset=utf-8 + + $['message']['items'][*] + + 'name' + 'id' + 'count' + + + - + +
+ {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
- - {{_titleFn(item)}} -
- {{_subtitleFn(item)}} -
+
+ + + + +
+ {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
+
+
+ + No results found! + +
+ + loading... +
diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss index 07c37ced4..a2ff47c86 100644 --- a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.scss @@ -1,32 +1,23 @@ .multiple-auto-complete { - margin-left: inherit; - margin-right: inherit; + margin-left: inherit; + margin-right: inherit; - .multi-chip-list { - padding-left: 0; + .not-loading { + display: none; + } - .chip { - border-radius: 2em !important; - height: auto !important; - min-width: fit-content !important; - } - } - .multi-loading-bar { - padding-right: 0; - padding-left: 0; - } + .align-arrow-right { + position: absolute; + right: 0; + vertical-align: middle; + cursor: pointer; + align-self: center; + color: rgba(0, 0, 0, 0.54); + } - .not-loading { - display: none; - } } .two-line-mat-option { - // height: 3.5em; - line-height: 1.2em; -} - -::ng-deep .mat-autocomplete-panel.panel-width { - max-width: 78vw !important; + line-height: 1.2em; } diff --git a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts index a19d1c55d..245f1d2be 100644 --- a/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts +++ b/dmp-frontend/src/app/library/auto-complete/multiple/multiple-auto-complete.component.ts @@ -1,15 +1,25 @@ import { FocusMonitor } from '@angular/cdk/a11y'; import { COMMA, ENTER } from '@angular/cdk/keycodes'; -import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Optional, Output, Self, ViewChild } from '@angular/core'; -import { ControlValueAccessor, NgControl } from '@angular/forms'; -import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; -import { MatChipInputEvent } from '@angular/material/chips'; +import { Component, DoCheck, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Optional, Output, Self, SimpleChanges, TemplateRef, ViewChild } from '@angular/core'; +import { ControlValueAccessor, FormGroupDirective, NgControl, NgForm } from '@angular/forms'; +import { ErrorStateMatcher, MatChipInputEvent, mixinErrorState } from '@angular/material'; +import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { MatFormFieldControl } from '@angular/material/form-field'; +import { AutoCompleteGroup } from '@app/library/auto-complete/auto-complete-group'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; import { Observable, of as observableOf, Subject } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, tap } from 'rxjs/operators'; -import { AutoCompleteGroup } from '../auto-complete-group'; -import { MultipleAutoCompleteConfiguration } from './multiple-auto-complete-configuration'; -import { switchMap } from 'rxjs/internal/operators/switchMap'; +import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, takeUntil } from 'rxjs/operators'; + +export class CustomComponentBase extends BaseComponent { + constructor( + public _defaultErrorStateMatcher: ErrorStateMatcher, + public _parentForm: NgForm, + public _parentFormGroup: FormGroupDirective, + public ngControl: NgControl + ) { super(); } +} +export const _CustomComponentMixinBase = mixinErrorState(CustomComponentBase); @Component({ selector: 'app-multiple-auto-complete', @@ -17,40 +27,39 @@ import { switchMap } from 'rxjs/internal/operators/switchMap'; styleUrls: ['./multiple-auto-complete.component.scss'], providers: [{ provide: MatFormFieldControl, useExisting: MultipleAutoCompleteComponent }] }) -export class MultipleAutoCompleteComponent implements OnInit, MatFormFieldControl, ControlValueAccessor, OnDestroy { +export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase implements OnInit, MatFormFieldControl, ControlValueAccessor, OnDestroy, DoCheck, OnChanges { static nextId = 0; + @ViewChild('autocomplete', { static: true }) autocomplete: MatAutocomplete; + @ViewChild('autocompleteTrigger', { static: true }) autocompleteTrigger: MatAutocompleteTrigger; + @ViewChild('autocompleteInput', { static: true }) autocompleteInput: ElementRef; - separatorKeysCodes = [ENTER, COMMA]; + @Input() + get configuration(): MultipleAutoCompleteConfiguration { return this._configuration; } + set configuration(configuration: MultipleAutoCompleteConfiguration) { + this._configuration = configuration; + } + private _configuration: MultipleAutoCompleteConfiguration; - @Input() configuration: MultipleAutoCompleteConfiguration; // Selected Option Event @Output() optionSelected: EventEmitter = new EventEmitter(); - // Removed Option Event @Output() optionRemoved: EventEmitter = new EventEmitter(); id = `multiple-autocomplete-${MultipleAutoCompleteComponent.nextId++}`; stateChanges = new Subject(); focused = false; - errorState = false; controlType = 'multiple-autocomplete'; describedBy = ''; - _inputValue: string; + inputValue = ''; _inputSubject = new Subject(); - loading = false; _items: Observable; + _selectedItems: Map = new Map(); _groupedItems: Observable; - private requestDelay = 200; //ms - private minFilteringChars = 1; - private loadDataOnStart = true; - visible = true; - selectable = true; + selectable = false; removable = true; - addOnBlur = false; + separatorKeysCodes = [ENTER, COMMA]; - get empty() { - return !this._inputValue || this._inputValue.length === 0; - } + get empty() { return (!this.value || this.value.length === 0) && (!this.inputValue || this.inputValue.length === 0); } get shouldLabelFloat() { return this.focused || !this.empty; } @@ -83,21 +92,22 @@ export class MultipleAutoCompleteComponent implements OnInit, MatFormFieldContro return this._selectedValue; } set value(value: any | null) { - this._selectedValue = value; - this._inputValue = value; + this._selectedValue = (value != null && value.length === 0) ? null : value; this.stateChanges.next(); } private _selectedValue; - @ViewChild('textInput', { static: true }) textInput: ElementRef; - @ViewChild(MatAutocompleteTrigger, { static: true }) autocomplete: MatAutocompleteTrigger; - constructor( private fm: FocusMonitor, private elRef: ElementRef, - @Optional() @Self() public ngControl: NgControl) { + @Optional() @Self() public ngControl: NgControl, + @Optional() _parentForm: NgForm, + @Optional() _parentFormGroup: FormGroupDirective, + _defaultErrorStateMatcher: ErrorStateMatcher + ) { + super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl); - fm.monitor(elRef.nativeElement, true).subscribe((origin) => { + fm.monitor(elRef.nativeElement, true).pipe(takeUntil(this._destroyed)).subscribe((origin) => { this.focused = !!origin; this.stateChanges.next(); }); @@ -109,83 +119,84 @@ export class MultipleAutoCompleteComponent implements OnInit, MatFormFieldContro } } - ngOnInit() { + ngOnInit() { } + + ngDoCheck(): void { + if (this.ngControl) { + this.updateErrorState(); + } + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['configuration'] && changes['configuration'].isFirstChange) { + this.getSelectedItems(this.value); + } + } + + getSelectedItems(value: any) { + if (value != null && Array.isArray(value) && this.configuration) { + const newSelections = value.filter(x => !this._selectedItems.has(this.stringify(x))); + if (newSelections.length > 0 && this.configuration.getSelectedItems != null) { + this.configuration.getSelectedItems(newSelections).pipe(takeUntil(this._destroyed)).subscribe(x => { + x.forEach(element => { + this._selectedItems.set(this.stringify(this.configuration.valueAssign != null ? this.configuration.valueAssign(element) : element), element); + }); + }); + } else { + newSelections.forEach(element => { + this._selectedItems.set(this.stringify(this.configuration.valueAssign != null ? this.configuration.valueAssign(element) : element), element); + }); + } + } } filter(query: string): Observable { // If loadDataOnStart is enabled and query is empty we return the initial items. if (this.isNullOrEmpty(query) && this.loadDataOnStart) { - return this.configuration.initialItems(this.value || []) || observableOf([]); + return this.configuration.initialItems(this.configuration.extraData) || observableOf([]); } else if (query && query.length >= this.minFilteringChars) { if (this.configuration.filterFn) { - return this.configuration.filterFn(query, this.value || []); + return this.configuration.filterFn(query, this.configuration.extraData); } else { - return this.configuration.initialItems(this.value || []) || observableOf([]); + return this.configuration.initialItems(this.configuration.extraData) || observableOf([]); } } else { return observableOf([]); } } + stringify(value: any): string { + return typeof (value) == 'string' ? value : JSON.stringify(value); + } + isNullOrEmpty(query: string): boolean { return typeof query !== 'string' || query === null || query.length === 0; } - _displayFn(item: any): string { - if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } - return item; - } - - _titleFn(item: any): string { - if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } - return item; - } - - _subtitleFn(item: any): string { - if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } - return null; - } - - _requestDelay(): number { - return this.configuration.requestDelay || this.requestDelay; - } - - _minFilteringChars(): number { - return this.configuration.minFilteringChars || this.minFilteringChars; - } - - _loadDataOnStart(): boolean { - return this.configuration.loadDataOnStart || this.loadDataOnStart; - } - - _chipItems(): any[] { - return this.value || []; - } - - _arraysEqual(arr1, arr2) { - if (arr1.length !== arr2.length) - return false; - for (var i = arr1.length; i--;) { - if (arr1[i].id !== arr2[i].id) - return false; - } - - return true; - } - _optionSelected(event: MatAutocompleteSelectedEvent) { - if (this.configuration.valueAssign) { - const newValue = this.configuration.valueAssign(this.value) || []; - newValue.push(event.option.value); - this._setValue(this.configuration.valueAssign(newValue)); - } - else { - const newValue = this.value || []; - newValue.push(event.option.value); - this._setValue(newValue); - this.stateChanges.next(); - this.optionSelected.emit(newValue); - this.textInput.nativeElement.value = ''; + this.optionSelectedInternal(event.option.value); + this.autocompleteInput.nativeElement.value = ''; + } + + private optionSelectedInternal(item: any) { + const newValue = this._valueToAssign(item); + + //Update selected items + this._selectedItems.set(this.stringify(newValue), item); + + const newValueArray = (Array.isArray(this.value) ? this.value : []); + newValueArray.push(newValue); + this._setValue(newValueArray); + + this.stateChanges.next(); + this.optionSelected.emit(item); + } + + public onKeyUp(event) { + this.inputValue = event.target.value; + // prevent filtering results if arrow were pressed + if (event.keyCode !== ENTER && (event.keyCode < 37 || event.keyCode > 40)) { + this._inputSubject.next(this.inputValue); } } @@ -201,88 +212,39 @@ export class MultipleAutoCompleteComponent implements OnInit, MatFormFieldContro startWith(null), debounceTime(this.requestDelay), distinctUntilChanged(), - tap(() => { this.loading = true; }), - switchMap(query => { - // If its a valid object, a selection just made and the object is set as the value of the form control. That means we should fire an extra request to the server. - if (this._isValidObject(query)) { return observableOf([]); } - - // Since the object is changed we need to clear any existing selections, except for the first time. - // if (query !== null) { this.pushChanges(null); } - return this.filter(query); - }), - tap(() => { this.loading = false; })); + distinctUntilChanged(), + mergeMap(query => this.filter(query))); if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); } } } - _inputValueChange(value: string) { - this._inputValue = value; - this._inputSubject.next(value); - this.stateChanges.next(); - } - - _isValidObject(value: any): boolean { - try { - if (!value) { return false; } - if (typeof value !== 'object') { JSON.parse(value); } - } catch (e) { - return false; - } - return true; - } - - _removeSelectedItem(item: any): void { - if (this.configuration.valueAssign) { - this.optionRemoved.emit(item); - this.textInput.nativeElement.focus(); - } - else { - const index = this.value.indexOf(item); - if (index >= 0) { - this.value.splice(index, 1); - this.optionRemoved.emit(item); - } - this.textInput.nativeElement.focus(); - this.pushChanges(this.value); + public onBlur($event: MouseEvent) { + if (this.inputValue && this.inputValue.length > 1 && this.autocomplete.options && this.autocomplete.options.length > 0 && this.autoSelectFirstOptionOnBlur) { + this.optionSelectedInternal(this.autocomplete.options.first.value); } } - _onInputClick(item: any) { - if (!this.autocomplete.panelOpen) { - this.autocomplete.openPanel(); - } - } - - _addItem(event: MatChipInputEvent): void { - // const input = event.input; - // const value = event.value; - // // Add our fruit - // if ((value || '').trim()) { - // this.selectedItems.push(value.trim()); - // } - // // Reset the input value - // if (input) { - // input.value = ''; - // } - // this.inputFormControl.setValue(null); - } onChange = (_: any) => { }; - onTouched = () => { }; - writeValue(value: any): void { this.value = value || ''; } + private _onTouched = () => { }; + writeValue(value: any): void { + this.value = Array.isArray(value) ? value : null; + // Update chips observable + this.getSelectedItems(value); + } pushChanges(value: any) { this.onChange(value); } registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; } - registerOnTouched(fn: () => {}): void { this.onTouched = fn; } + registerOnTouched(fn: () => {}): void { this._onTouched = fn; } setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } - - setDescribedByIds(ids: string[]) { - this.describedBy = ids.join(' '); - } + setDescribedByIds(ids: string[]) { this.describedBy = ids.join(' '); } onContainerClick(event: MouseEvent) { - if ((event.target as Element).tagName.toLowerCase() !== 'input') { - this.elRef.nativeElement.querySelector('input').focus(); + event.stopPropagation(); + if (this.disabled) { return; } + this._onInputFocus(); + if (!this.autocomplete.isOpen) { + this.autocompleteTrigger.openPanel(); } } @@ -290,4 +252,80 @@ export class MultipleAutoCompleteComponent implements OnInit, MatFormFieldContro this.stateChanges.complete(); this.fm.stopMonitoring(this.elRef.nativeElement); } -} + + //Configuration getters + _displayFn(item: any): string { + // console.log('_displayFn' + item); + if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } + return item; + } + + _titleFn(item: any): string { + if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } + return item; + } + + _optionTemplate(item: any): TemplateRef { + if (this.configuration.optionTemplate && item) { return this.configuration.optionTemplate; } + return null; + } + + _selectedValueTemplate(item: any): TemplateRef { + if (this.configuration.selectedValueTemplate && item) { return this.configuration.selectedValueTemplate; } + return null; + } + + _subtitleFn(item: any): string { + if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } + return null; + } + + _valueToAssign(item: any): any { + if (this.configuration.valueAssign && item) { return this.configuration.valueAssign(item); } + return item; + } + + get requestDelay(): number { + return this.configuration.requestDelay != null ? this.configuration.requestDelay : 200; + } + + get minFilteringChars(): number { + return this.configuration.minFilteringChars != null ? this.configuration.minFilteringChars : 1; + } + + get loadDataOnStart(): boolean { + return this.configuration.loadDataOnStart != null ? this.configuration.loadDataOnStart : true; + } + + get autoSelectFirstOptionOnBlur(): boolean { + return this.configuration.autoSelectFirstOptionOnBlur != null ? this.configuration.autoSelectFirstOptionOnBlur : false; + } + + //Chip Functions + _addItem(event: MatChipInputEvent): void { + const input = event.input; + const value = event.value; + // Add our fruit + // if ((value || '').trim()) { + // this.selectedItems.push(value.trim()); + // } + // Reset the input value + if (input) { + this.inputValue = ''; + } + //this.inputFormControl.setValue(null); + } + + _removeSelectedItem(item: any, event: MouseEvent): void { + if (event != null) { event.stopPropagation(); } + const valueToDelete = this._valueToAssign(item); + this.value = this.value.filter(x => this.stringify(x) !== this.stringify(valueToDelete)); //TODO, maybe we need to implement equality here differently. + this.optionRemoved.emit(item); + + //Update chips + this._selectedItems.delete(this.stringify(valueToDelete)); + + this.autocompleteInput.nativeElement.focus(); + this.pushChanges(this.value); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts index 97aedab67..dad7fcf59 100644 --- a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete-configuration.ts @@ -1,3 +1,4 @@ +import { TemplateRef } from '@angular/core'; import { Observable } from 'rxjs'; import { AutoCompleteGroup } from '../auto-complete-group'; @@ -8,28 +9,29 @@ export interface SingleAutoCompleteConfiguration { minFilteringChars?: number; // Load and present items from start, without user query. Default: true. loadDataOnStart?: boolean; - // Remove item after selection. - removeAfterSelection?: boolean; // Static or initial items. initialItems?: (data?: any) => Observable; // Data retrieval function filterFn?: (searchQuery: string, data?: any) => Observable; + // Get selected items. Used when valueAssign is used so the full object can be retrieved for presentation. + getSelectedItem?: (selectedItem: any) => Observable; // Property formating for input displayFn?: (item: any) => string; - // Property formating for dropdown + // Function to group results in the drop down groupingFn?: (items: any[]) => AutoCompleteGroup[]; - // Property formating for dropdown + // Display function for the drop down title titleFn?: (item: any) => string; - // Property formating for dropdown + // Display function for the drop down subtitle subtitleFn?: (item: any) => string; - // Property formating for icon on chip - iconFn?: (item: any) => string; - // Property for link on chip - linkFn?: (item: any) => string; - // Disable option. - disableOption?: (item: any) => boolean; //Extra data passed to query function extraData?: any; // Callback to intercept value assignment based on item selection valueAssign?: (selectedItem: any) => any; + // Property formating template + optionTemplate?: TemplateRef; + // Selected value formating template + selectedValueTemplate?: TemplateRef; + + + autoSelectFirstOptionOnBlur?: boolean; } diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html index abe733c08..5ca49de77 100644 --- a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.html @@ -1,32 +1,44 @@
- - - {{_iconFn(value)}} - {{_displayFn(value)}} - cancel - - - - - - + + arrow_drop_down + - + - {{_titleFn(item)}} -
- {{_subtitleFn(item)}} + +
+ {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
- - - {{_titleFn(item)}} -
- {{_subtitleFn(item)}} -
+
+ + + + +
+ {{_titleFn(item)}} +
+ {{_subtitleFn(item)}} +
+
+
+ + No results found! + +
+ + loading... +
diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss index 4a8d65c72..d87344f60 100644 --- a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.scss @@ -1,35 +1,62 @@ .auto-complete { - margin-left: inherit; - margin-right: inherit; + margin-left: inherit; + margin-right: inherit; - .not-loading { - display: none; - } + .not-loading { + display: none; + } - .chip-list { - width: 100%; - } + .chip-item { + transition: none; + background-color: transparent; + padding: 0; + box-shadow: none !important; + border-radius: unset; + min-height: auto; + height: auto; + } - .progress-loader { - position: absolute; - right: 0; - } + .chip-list { + width: 100%; + } + + .progress-loader { + position: absolute; + right: 0; + } + + .align-arrow-right { + position: absolute; + right: 0; + vertical-align: middle; + cursor: pointer; + align-self: center; + color: rgba(0, 0, 0, 0.54); + } +} + +.chip-list { + width: auto; } .two-line-mat-option { - // height: 3.5em; - line-height: 1.2em; + line-height: 1.2em; } -.chip { - cursor: pointer; - opacity: 1 !important; +// .two-line-mat-option { +// height: 3.5em; +// line-height: 1.2em; +// } + +.mat-standard-chip:hover::after { + opacity: 0; } -.chip:hover { - background-color: #c5c5c5; +.mat-standard-chip:focus::after { + opacity: 0; } -::ng-deep .mat-autocomplete-panel.panel-width { - max-width: 78vw !important; -} + +// .mat-form-field-type-single-autocomplete:not(.mat-form-field-disabled) .mat-form-field-flex { +// cursor: pointer; +// } diff --git a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts index 2079b101a..86000d024 100644 --- a/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts +++ b/dmp-frontend/src/app/library/auto-complete/single/single-auto-complete.component.ts @@ -1,52 +1,69 @@ import { FocusMonitor } from '@angular/cdk/a11y'; -import { COMMA, ENTER } from '@angular/cdk/keycodes'; -import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Optional, Output, Self } from '@angular/core'; -import { ControlValueAccessor, NgControl } from '@angular/forms'; -import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { ENTER } from '@angular/cdk/keycodes'; +import { Component, DoCheck, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Optional, Output, Self, SimpleChanges, TemplateRef, ViewChild } from '@angular/core'; +import { ControlValueAccessor, FormGroupDirective, NgControl, NgForm } from '@angular/forms'; +import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; +import { ErrorStateMatcher, mixinErrorState } from '@angular/material/core'; import { MatFormFieldControl } from '@angular/material/form-field'; +import { AutoCompleteGroup } from '@app/library/auto-complete/auto-complete-group'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; import { Observable, of as observableOf, Subject } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, tap } from 'rxjs/operators'; -import { AutoCompleteGroup } from '../auto-complete-group'; -import { SingleAutoCompleteConfiguration } from './single-auto-complete-configuration'; -import { switchMap } from 'rxjs/internal/operators/switchMap'; -import { Router } from '@angular/router'; +import { debounceTime, distinctUntilChanged, map, mergeMap, startWith, takeUntil } from 'rxjs/operators'; +export class CustomComponentBase extends BaseComponent { + constructor( + public _defaultErrorStateMatcher: ErrorStateMatcher, + public _parentForm: NgForm, + public _parentFormGroup: FormGroupDirective, + public ngControl: NgControl + ) { super(); } +} +export const _CustomComponentMixinBase = mixinErrorState(CustomComponentBase); + @Component({ selector: 'app-single-auto-complete', templateUrl: './single-auto-complete.component.html', styleUrls: ['./single-auto-complete.component.scss'], providers: [{ provide: MatFormFieldControl, useExisting: SingleAutoCompleteComponent }], }) -export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl, ControlValueAccessor, OnDestroy { +export class SingleAutoCompleteComponent extends _CustomComponentMixinBase implements OnInit, MatFormFieldControl, ControlValueAccessor, OnDestroy, DoCheck, OnChanges { static nextId = 0; + @ViewChild('autocomplete', { static: true }) autocomplete: MatAutocomplete; + @ViewChild('autocompleteTrigger', { static: true }) autocompleteTrigger: MatAutocompleteTrigger; + @ViewChild('autocompleteInput', { static: true }) autocompleteInput: ElementRef; + + @Input() initialSelectedData: any; + @Input() + get configuration(): SingleAutoCompleteConfiguration { return this._configuration; } + set configuration(configuration: SingleAutoCompleteConfiguration) { + this._configuration = configuration; + //On startup, fill the input with the existing value + if (this.autocompleteInput && this.value) { + this.inputValue = this._displayFn(this.value); + } + } + private _configuration: SingleAutoCompleteConfiguration; - @Input() configuration: SingleAutoCompleteConfiguration; // Selected Option Event @Output() optionSelected: EventEmitter = new EventEmitter(); - // Removed Option Event - @Output() optionRemoved: EventEmitter = new EventEmitter(); id = `single-autocomplete-${SingleAutoCompleteComponent.nextId++}`; stateChanges = new Subject(); focused = false; - errorState = false; controlType = 'single-autocomplete'; describedBy = ''; - _inputValue: string; + inputValue = ''; _inputSubject = new Subject(); loading = false; _items: Observable; _groupedItems: Observable; - private requestDelay = 200; //ms - private minFilteringChars = 1; - private loadDataOnStart = true; - separatorKeysCodes: number[] = [ENTER, COMMA]; + _selectedItems: Map = new Map(); - get empty() { - return !this._inputValue || this._inputValue.length === 0; - } + + get empty() { return (this.value == null) && (!this.inputValue || this.inputValue.length === 0); } get shouldLabelFloat() { return this.focused || !this.empty; } @@ -80,7 +97,6 @@ export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl< } set value(value: any | null) { this._selectedValue = value; - this._inputValue = (value && value != "") ? " " : null; this.stateChanges.next(); } private _selectedValue; @@ -88,10 +104,14 @@ export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl< constructor( private fm: FocusMonitor, private elRef: ElementRef, - private router: Router, - @Optional() @Self() public ngControl: NgControl) { + @Optional() @Self() public ngControl: NgControl, + @Optional() _parentForm: NgForm, + @Optional() _parentFormGroup: FormGroupDirective, + _defaultErrorStateMatcher: ErrorStateMatcher + ) { + super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl); - fm.monitor(elRef.nativeElement, true).subscribe((origin) => { + fm.monitor(elRef.nativeElement, true).pipe(takeUntil(this._destroyed)).subscribe((origin) => { this.focused = !!origin; this.stateChanges.next(); }); @@ -103,8 +123,43 @@ export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl< } } - ngOnInit() { + ngOnInit() { } + ngDoCheck(): void { + if (this.ngControl) { + this.updateErrorState(); + } + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['initialSelectedData'] && changes['initialSelectedData'].currentValue && changes['initialSelectedData'].isFirstChange && this.configuration != null) { + this._selectedItems.set(JSON.stringify(this.configuration.valueAssign != null ? this.configuration.valueAssign(this.initialSelectedData) : this.initialSelectedData), this.initialSelectedData); + this.inputValue = this._displayFn(this.initialSelectedData); + } + + if (changes['configuration'] && changes['configuration'].isFirstChange) { + if (changes['initialSelectedData'] != null && this.value != null) { + if (this._valueToAssign(this.initialSelectedData) != this.value) { this.getSelectedItems(this.value); } + } else { + this.getSelectedItems(this.value); + } + } + } + + getSelectedItems(value: any) { + if (value != null && !this._selectedItems.has(JSON.stringify(value)) && this.configuration) { + if (this.configuration.getSelectedItem != null) { + this.configuration.getSelectedItem(value).pipe(takeUntil(this._destroyed)).subscribe(x => { + if (x != null) { + this._selectedItems.set(JSON.stringify(this.configuration.valueAssign != null ? this.configuration.valueAssign(x) : x), x); + this.inputValue = this._displayFn(x); + } + }); + } else { + this._selectedItems.set(JSON.stringify(this.configuration.valueAssign != null ? this.configuration.valueAssign(value) : value), value); + this.inputValue = this._displayFn(value); + } + } } filter(query: string): Observable { @@ -122,64 +177,40 @@ export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl< } } + stringify(value: any): string { + return JSON.stringify(value); + } + isNullOrEmpty(query: string): boolean { return typeof query !== 'string' || query === null || query.length === 0; } - _displayFn(item: any): string { - if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } - return item; - } - - _titleFn(item: any): string { - if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } - return item; - } - - _subtitleFn(item: any): string { - if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } - return null; - } - - _iconFn(item: any): string { - if (this.configuration.iconFn && item) { return this.configuration.iconFn(item); } - return null; - } - - _linkFn(item: any): string { - if (this.configuration.linkFn && item) { return this.configuration.linkFn(item); } - return null; - } - - _disableOption(item: any): boolean { - if (this.configuration.disableOption && item) { return this.configuration.disableOption(item); } - return null; - } - - _requestDelay(): number { - return this.configuration.requestDelay || this.requestDelay; - } - - _minFilteringChars(): number { - return this.configuration.minFilteringChars || this.minFilteringChars; - } - - _loadDataOnStart(): boolean { - return this.configuration.loadDataOnStart || this.loadDataOnStart; - } - _optionSelected(event: MatAutocompleteSelectedEvent) { - this._setValue(this.configuration.valueAssign ? this.configuration.valueAssign(event.option.value) : event.option.value); - //this._inputValue = " "; - this.stateChanges.next(); - this.optionSelected.emit(event.option.value); - if (this.configuration.removeAfterSelection) { - this.clearAutocomplete() - } + this.inputValue = this._displayFn(event.option.value); + this.optionSelectedInternal(event.option.value); } - private clearAutocomplete() { - this._setValue(null); + private optionSelectedInternal(item: any) { + const newValue = this._valueToAssign(item); + + //Update selected items + this._selectedItems.set(JSON.stringify(newValue), item); + + this._setValue(newValue); + + this.stateChanges.next(); + this.optionSelected.emit(item); + } + + public onKeyUp(event) { + this.inputValue = event.target.value; + // prevent filtering results if arrow were pressed + if (event.keyCode !== ENTER && (event.keyCode < 37 || event.keyCode > 40)) { + if (this.inputValue.length === 0 && this.value != null) { + this.optionSelectedInternal(null); + } + this._inputSubject.next(this.inputValue); + } } private _setValue(value: any) { @@ -194,72 +225,100 @@ export class SingleAutoCompleteComponent implements OnInit, MatFormFieldControl< startWith(null), debounceTime(this.requestDelay), distinctUntilChanged(), - tap(() => { this.loading = true; }), - switchMap(query => { - // If its a valid object, a selection just made and the object is set as the value of the form control. That means we should fire an extra request to the server. - if (this._isValidObject(query)) { return observableOf([]); } - - // Since the object is changed we need to clear any existing selections, except for the first time. - if (query !== null) { this.pushChanges(null); } - return this.filter(query); - }), - tap(() => { this.loading = false; })); + mergeMap(query => this.filter(query))); if (this.configuration.groupingFn) { this._groupedItems = this._items.pipe(map(items => this.configuration.groupingFn(items))); } } } - _inputValueChange(value: string) { - //this._inputValue = value; - this._inputSubject.next(value); - this.stateChanges.next(); - } - - _isValidObject(value: any): boolean { - try { - if (!value) { return false; } - if (typeof value !== 'object') { JSON.parse(value); } - } catch (e) { - return false; + public onBlur($event: MouseEvent) { + if (this.value != null) { + const inputLabel = this.inputValue; + const selectedLabel = this._displayFn(this._selectedItems.get(JSON.stringify(this.value))); + if (inputLabel && selectedLabel !== inputLabel) { + this.inputValue = selectedLabel; + } + } else if (this.inputValue && this.inputValue.length > 1 && this.autocomplete.options && this.autocomplete.options.length > 0 && this.autoSelectFirstOptionOnBlur) { + this.inputValue = this._displayFn(this.autocomplete.options.first.value); + this.optionSelectedInternal(this.autocomplete.options.first.value); } - return true; } onChange = (_: any) => { }; - onTouched = () => { }; - writeValue(value: any): void { this.value = value || ''; } + private _onTouched = () => { }; + writeValue(value: any): void { + this.value = value; + // Update chips observable + if (value != null) { this.getSelectedItems(value); } else { + if (this.autocompleteInput && this.autocompleteInput.nativeElement && this.autocompleteInput.nativeElement.value) { this.autocompleteInput.nativeElement.value = ''; } + this.inputValue = null; + } + } pushChanges(value: any) { this.onChange(value); } registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; } - registerOnTouched(fn: () => {}): void { this.onTouched = fn; } + registerOnTouched(fn: () => {}): void { this._onTouched = fn; } setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } - - setDescribedByIds(ids: string[]) { - this.describedBy = ids.join(' '); - } + setDescribedByIds(ids: string[]) { this.describedBy = ids.join(' '); } onContainerClick(event: MouseEvent) { - if ((event.target as Element).tagName.toLowerCase() !== 'input') { - this.elRef.nativeElement.querySelector('input').focus(); + event.stopPropagation(); + if (this.disabled) { return; } + this._onInputFocus(); + if (!this.autocomplete.isOpen) { + this.autocompleteTrigger.openPanel(); } } - chipRemove(): void { - this._setValue(null); - this.optionRemoved.emit(); - } - - linkToOption(value: any): void { - if (this._linkFn(value)) { - this.router.navigate([]).then(result => { window.open(this._linkFn(value), '_blank'); }); - } - } - - autoCompleteDisplayFn() { - return (val) => ""; - } - ngOnDestroy() { this.stateChanges.complete(); this.fm.stopMonitoring(this.elRef.nativeElement); } + + //Configuration getters + _displayFn(item: any): string { + // console.log('_displayFn' + item); + if (this.configuration.displayFn && item) { return this.configuration.displayFn(item); } + return item; + } + + _titleFn(item: any): string { + if (this.configuration.titleFn && item) { return this.configuration.titleFn(item); } + return item; + } + + _optionTemplate(item: any): TemplateRef { + if (this.configuration.optionTemplate && item) { return this.configuration.optionTemplate; } + return null; + } + + _selectedValueTemplate(item: any): TemplateRef { + if (this.configuration.selectedValueTemplate && item) { return this.configuration.selectedValueTemplate; } + return null; + } + + _subtitleFn(item: any): string { + if (this.configuration.subtitleFn && item) { return this.configuration.subtitleFn(item); } + return null; + } + + _valueToAssign(item: any): any { + if (this.configuration.valueAssign && item) { return this.configuration.valueAssign(item); } + return item; + } + + get requestDelay(): number { + return this.configuration.requestDelay != null ? this.configuration.requestDelay : 200; + } + + get minFilteringChars(): number { + return this.configuration.minFilteringChars != null ? this.configuration.minFilteringChars : 1; + } + + get loadDataOnStart(): boolean { + return this.configuration.loadDataOnStart != null ? this.configuration.loadDataOnStart : true; + } + + get autoSelectFirstOptionOnBlur(): boolean { + return this.configuration.autoSelectFirstOptionOnBlur != null ? this.configuration.autoSelectFirstOptionOnBlur : false; + } } diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss deleted file mode 100644 index 025bfb9d5..000000000 --- a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.scss +++ /dev/null @@ -1,44 +0,0 @@ -.confirmation-dialog { - .confirmation { - padding-bottom: 20px; - } - - .privacy-policy-names { - font-weight: 700; - padding: 1em; - } - - .close-btn { - margin-left: auto; - cursor: pointer; - } - - .warn-text { - color: #f44336; - } - - .cancel { - background-color: #aaaaaa; - color: #ffffff; - } - - .confirm { - background-color: #2cba6c; - color: #ffffff; - } - - .delete { - background-color: #ba2c2c; - color: #ffffff; - } - - .checkbox-privacy { - padding: 0em 1em; - } - - .required-policy { - padding: 0em 1.2em 1em; - font-size: smaller; - color: #f44336; - } -} diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts b/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts deleted file mode 100644 index cda63242d..000000000 --- a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { ConfirmationDialogComponent } from './confirmation-dialog.component'; - -@NgModule({ - imports: [CommonUiModule], - declarations: [ConfirmationDialogComponent], - exports: [ConfirmationDialogComponent], - entryComponents: [ConfirmationDialogComponent] -}) -export class ConfirmationDialogModule { - constructor() { } -} diff --git a/dmp-frontend/src/app/library/deactivate/can-deactivate.guard.ts b/dmp-frontend/src/app/library/deactivate/can-deactivate.guard.ts index aac88736e..75d89ac2d 100644 --- a/dmp-frontend/src/app/library/deactivate/can-deactivate.guard.ts +++ b/dmp-frontend/src/app/library/deactivate/can-deactivate.guard.ts @@ -1,12 +1,12 @@ import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { CanDeactivate } from '@angular/router'; -import { Observable } from 'rxjs'; +import { CheckDeactivateBaseComponent } from '@app/library/deactivate/deactivate.component'; +import { BaseComponent } from '@common/base/base.component'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { CheckDeactivateBaseComponent } from './deactivate.component'; -import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component'; @Injectable() export class CanDeactivateGuard extends BaseComponent implements CanDeactivate { @@ -21,19 +21,19 @@ export class CanDeactivateGuard extends BaseComponent implements CanDeactivate { if (component.canDeactivate()) { - return true; - } else { - const dialogRef = this.dialog.open(ConfirmationDialogComponent, { - maxWidth: '700px', - data: { + return true; + } else { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '700px', + data: { message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.LEAVE-PAGE'), warning: this.language.instant('GENERAL.CONFIRMATION-DIALOG.LEAVE-WARNING'), - cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.LEAVE'), icon: 'error_outline' - } - }); - return dialogRef.afterClosed().pipe(map(x => x ? true : false)); - } + } + }); + return dialogRef.afterClosed().pipe(map(x => x ? true : false)); + } } } diff --git a/dmp-frontend/src/app/library/deactivate/deactivate.component.ts b/dmp-frontend/src/app/library/deactivate/deactivate.component.ts index ce05a6632..2b854f125 100644 --- a/dmp-frontend/src/app/library/deactivate/deactivate.component.ts +++ b/dmp-frontend/src/app/library/deactivate/deactivate.component.ts @@ -1,5 +1,5 @@ -import { BaseComponent } from '../../core/common/base/base.component'; import { HostListener } from '@angular/core'; +import { BaseComponent } from '@common/base/base.component'; export abstract class CheckDeactivateBaseComponent extends BaseComponent { diff --git a/dmp-frontend/src/app/library/export-method-dialog/export-method-dialog.module.ts b/dmp-frontend/src/app/library/export-method-dialog/export-method-dialog.module.ts index 327bc17e7..b72241c53 100644 --- a/dmp-frontend/src/app/library/export-method-dialog/export-method-dialog.module.ts +++ b/dmp-frontend/src/app/library/export-method-dialog/export-method-dialog.module.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { ExportMethodDialogComponent } from './export-method-dialog.component'; +import { ExportMethodDialogComponent } from '@app/library/export-method-dialog/export-method-dialog.component'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [CommonUiModule], diff --git a/dmp-frontend/src/app/library/notification/notification.component.ts b/dmp-frontend/src/app/library/notification/notification.component.ts index 20527fe02..2bc6c31b6 100644 --- a/dmp-frontend/src/app/library/notification/notification.component.ts +++ b/dmp-frontend/src/app/library/notification/notification.component.ts @@ -1,11 +1,11 @@ import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { PopupNotification, SnackBarNotification, SnackBarNotificationLevel, UiNotificationService, UiNotificationType } from '@app/core/services/notification/ui-notification-service'; +import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component'; +import { SnackBarNotificationComponent } from '@app/library/notification/snack-bar/snack-bar-notification.component'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { UiNotificationService, UiNotificationType, PopupNotification, SnackBarNotification, SnackBarNotificationLevel } from '../../core/services/notification/ui-notification-service'; -import { PopupNotificationDialogComponent } from './popup/popup-notification.component'; -import { SnackBarNotificationComponent } from './snack-bar/snack-bar-notification.component'; @Component({ selector: 'app-notification', diff --git a/dmp-frontend/src/app/library/notification/notification.module.ts b/dmp-frontend/src/app/library/notification/notification.module.ts index 7d7a194d5..2abf82c9d 100644 --- a/dmp-frontend/src/app/library/notification/notification.module.ts +++ b/dmp-frontend/src/app/library/notification/notification.module.ts @@ -1,8 +1,8 @@ import { NgModule } from '@angular/core'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { NotificationComponent } from './notification.component'; -import { PopupNotificationDialogComponent } from './popup/popup-notification.component'; -import { SnackBarNotificationComponent } from './snack-bar/snack-bar-notification.component'; +import { NotificationComponent } from '@app/library/notification/notification.component'; +import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component'; +import { SnackBarNotificationComponent } from '@app/library/notification/snack-bar/snack-bar-notification.component'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/library/url-listing/url-listing.module.ts b/dmp-frontend/src/app/library/url-listing/url-listing.module.ts index c0112e256..3ee5b0996 100644 --- a/dmp-frontend/src/app/library/url-listing/url-listing.module.ts +++ b/dmp-frontend/src/app/library/url-listing/url-listing.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { FormattingModule } from '../../core/formatting.module'; -import { UrlListingComponent } from './url-listing.component'; +import { FormattingModule } from '@app/core/formatting.module'; +import { UrlListingComponent } from '@app/library/url-listing/url-listing.component'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/about/about.module.ts b/dmp-frontend/src/app/ui/about/about.module.ts index e6830d4b2..0d119dc88 100644 --- a/dmp-frontend/src/app/ui/about/about.module.ts +++ b/dmp-frontend/src/app/ui/about/about.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { AboutComponent } from './about.component'; -import { AboutRoutingModule } from './about.routing'; +import { AboutComponent } from '@app/ui/about/about.component'; +import { AboutRoutingModule } from '@app/ui/about/about.routing'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts index 1a35db433..6f16b2c02 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/page-editor-model.ts @@ -1,7 +1,7 @@ import { FormGroup, Validators } from '@angular/forms'; -import { Page } from '../../../../core/model/admin/dataset-profile/dataset-profile'; -import { BaseFormModel } from '../../../../core/model/base-form-model'; -import { Guid } from '../../../../common/types/guid'; +import { Page } from '@app/core/model/admin/dataset-profile/dataset-profile'; +import { BaseFormModel } from '@app/core/model/base-form-model'; +import { Guid } from '@common/types/guid'; export class PageEditorModel extends BaseFormModel { public title: string; diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts index c4fdba9cc..1e7c9eb19 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts @@ -1,32 +1,32 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../../common/ui/common-ui.module'; -import { FormattingModule } from '../../../core/formatting.module'; -import { DatasetProfileRoutingModule } from './dataset-profile.routing'; -import { DatasetProfileEditorDefaultValueComponent } from './editor/components/composite-profile-editor-default-value/component-profile-editor-default-value.component'; -import { DatasetProfileEditorCompositeFieldComponent } from './editor/components/composite-field/dataset-profile-editor-composite-field.component'; -import { DatasetProfileEditorAutoCompleteFieldComponent } from './editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component'; -import { DatasetProfileEditorBooleanDecisionFieldComponent } from './editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component'; -import { DatasetProfileEditorCheckboxFieldComponent } from './editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component'; -import { DatasetProfileEditorComboBoxFieldComponent } from './editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component'; -import { DatasetProfileEditorFreeTextFieldComponent } from './editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component'; -import { DatasetProfileEditorRadioBoxFieldComponent } from './editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component'; -import { DatasetProfileEditorTextAreaFieldComponent } from './editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component'; -import { DatasetProfileEditorWordListFieldComponent } from './editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component'; -import { DatasetProfileEditorFieldComponent } from './editor/components/field/dataset-profile-editor-field.component'; -import { DatasetProfileEditorPageComponent } from './editor/components/page/dataset-profile-editor-page.component'; -import { DatasetProfileEditorRuleComponent } from './editor/components/rule/dataset-profile-editor-rule.component'; -import { DatasetProfileEditorSectionComponent } from './editor/components/section/dataset-profile-editor-section.component'; -import { DatasetProfileEditorComponent } from './editor/dataset-profile-editor.component'; -import { DatasetProfileCriteriaComponent } from './listing/criteria/dataset-profile.component'; -import { DatasetProfileListingComponent } from './listing/dataset-profile-listing.component'; -import { ConfirmationDialogModule } from '../../../library/confirmation-dialog/confirmation-dialog.module'; -import { DatasetProfileEditorDatePickerFieldComponent } from './editor/components/field-type/datepicker/dataset-profile-editor-date-picker-field.component'; -import { DialodConfirmationUploadDatasetProfiles } from './listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; -import { DatasetProfileEditorInternalDmpEntitiesFieldComponent } from './editor/components/field-type/internal-dmp-entities/dataset-profile-editor-internal-dmp-entities-field.component'; -import { DatasetProfileEditorResearchersAutoCompleteFieldComponent } from './editor/components/field-type/researchers-auto-complete/dataset-profile-editor-researchers-auto-complete-field.component'; -import { DatasetProfileEditorDatasetsAutoCompleteFieldComponent } from './editor/components/field-type/datasets-auto-complete/dataset-profile-editor-datasets-autocomplete-field.component'; -import { DatasetProfileEditorDmpsAutoCompleteFieldComponent } from './editor/components/field-type/dmps-auto-complete/dataset-profile-editor-dmps-autocomplete-field.component'; +import { FormattingModule } from '@app/core/formatting.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { DatasetProfileRoutingModule } from '@app/ui/admin/dataset-profile/dataset-profile.routing'; +import { DatasetProfileEditorCompositeFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component'; +import { DatasetProfileEditorDefaultValueComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-profile-editor-default-value/component-profile-editor-default-value.component'; +import { DatasetProfileEditorAutoCompleteFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/auto-complete/dataset-profile-editor-auto-complete-field.component'; +import { DatasetProfileEditorBooleanDecisionFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/boolean-decision/dataset-profile-editor-boolean-decision-field.component'; +import { DatasetProfileEditorCheckboxFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/checkbox/dataset-profile-editor-checkbox-field.component'; +import { DatasetProfileEditorComboBoxFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component'; +import { DatasetProfileEditorDatasetsAutoCompleteFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/datasets-auto-complete/dataset-profile-editor-datasets-autocomplete-field.component'; +import { DatasetProfileEditorDatePickerFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/datepicker/dataset-profile-editor-date-picker-field.component'; +import { DatasetProfileEditorDmpsAutoCompleteFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/dmps-auto-complete/dataset-profile-editor-dmps-autocomplete-field.component'; +import { DatasetProfileEditorFreeTextFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/free-text/dataset-profile-editor-free-text-field.component'; +import { DatasetProfileEditorInternalDmpEntitiesFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/internal-dmp-entities/dataset-profile-editor-internal-dmp-entities-field.component'; +import { DatasetProfileEditorRadioBoxFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/radio-box/dataset-profile-editor-radio-box-field.component'; +import { DatasetProfileEditorResearchersAutoCompleteFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/researchers-auto-complete/dataset-profile-editor-researchers-auto-complete-field.component'; +import { DatasetProfileEditorTextAreaFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/textarea/dataset-profile-editor-text-area-field.component'; +import { DatasetProfileEditorWordListFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field-type/word-list/dataset-profile-editor-word-list-field.component'; +import { DatasetProfileEditorFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component'; +import { DatasetProfileEditorPageComponent } from '@app/ui/admin/dataset-profile/editor/components/page/dataset-profile-editor-page.component'; +import { DatasetProfileEditorRuleComponent } from '@app/ui/admin/dataset-profile/editor/components/rule/dataset-profile-editor-rule.component'; +import { DatasetProfileEditorSectionComponent } from '@app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component'; +import { DatasetProfileEditorComponent } from '@app/ui/admin/dataset-profile/editor/dataset-profile-editor.component'; +import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component'; +import { DialodConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; +import { DatasetProfileListingComponent } from '@app/ui/admin/dataset-profile/listing/dataset-profile-listing.component'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts index e0ed0479f..e4fd16dfa 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { FieldEditorModel } from '../../../admin/field-editor-model'; -import { Guid } from '../../../../../../common/types/guid'; +import { Guid } from '@common/types/guid'; @Component({ selector: 'app-dataset-profile-editor-composite-field-component', diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts index 4770e4ce9..86cc30d8d 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/combo-box/dataset-profile-editor-combo-box-field.component.ts @@ -1,11 +1,11 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; +import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { AutoCompleteFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/auto-complete-field-data-editor-model'; +import { WordListFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../../../../core/common/base/base.component'; -import { DatasetProfileComboBoxType } from '../../../../../../../core/common/enum/dataset-profile-combo-box-type'; -import { EnumUtils } from '../../../../../../../core/services/utilities/enum-utils.service'; -import { AutoCompleteFieldDataEditorModel } from '../../../../admin/field-data/auto-complete-field-data-editor-model'; -import { WordListFieldDataEditorModel } from '../../../../admin/field-data/word-list-field-data-editor-model'; @Component({ selector: 'app-dataset-profile-editor-combo-box-field-component', diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/internal-dmp-entities/dataset-profile-editor-internal-dmp-entities-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/internal-dmp-entities/dataset-profile-editor-internal-dmp-entities-field.component.ts index 533669c20..2c7163000 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/internal-dmp-entities/dataset-profile-editor-internal-dmp-entities-field.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field-type/internal-dmp-entities/dataset-profile-editor-internal-dmp-entities-field.component.ts @@ -1,13 +1,12 @@ -import { DatasetProfileInternalDmpEntitiesType } from "../../../../../../../core/common/enum/dataset-profile-internal-dmp-entities-type"; -import { EnumUtils } from "../../../../../../../core/services/utilities/enum-utils.service"; -import { Component, Input, OnInit } from "@angular/core"; -import { FormGroup } from "@angular/forms"; -import { BaseComponent } from "../../../../../../../core/common/base/base.component"; -import { takeUntil } from "rxjs/operators"; -import { ResearchersAutoCompleteFieldDataEditorModel } from "../../../../admin/field-data/researchers-auto-complete-field-data-editor-model"; -import { DatasetsAutoCompleteFieldDataEditorModel } from "../../../../admin/field-data/datasets-autocomplete-field-data-editor-mode"; -import { DmpsAutoCompleteFieldDataEditorModel } from "../../../../admin/field-data/dmps-autocomplete-field-data-editor-model"; - +import { Component, Input, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { DatasetProfileInternalDmpEntitiesType } from '@app/core/common/enum/dataset-profile-internal-dmp-entities-type'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { DatasetsAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/datasets-autocomplete-field-data-editor-mode'; +import { DmpsAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/dmps-autocomplete-field-data-editor-model'; +import { ResearchersAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/researchers-auto-complete-field-data-editor-model'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dataset-profile-internal-dmp-entities-field-component', diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts index bdc243b73..c9b082e4f 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts @@ -1,22 +1,21 @@  import { Component, Input, OnInit } from '@angular/core'; import { FormArray, FormControl, FormGroup } from '@angular/forms'; +import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style'; +import { ValidationType } from '@app/core/common/enum/validation-type'; +import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { BooleanDecisionFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/boolean-decision-field-data-editor-model'; +import { CheckBoxFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/check-box-field-data-editor-model'; +import { DatePickerDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/date-picker-data-editor-models'; +import { FreeTextFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/free-text-field-data-editor-model'; +import { RadioBoxFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/radio-box-field-data-editor-model'; +import { ResearchersAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/researchers-auto-complete-field-data-editor-model'; +import { TextAreaFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/text-area-field-data-editor-model'; +import { WordListFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model'; +import { RuleEditorModel } from '@app/ui/admin/dataset-profile/admin/rule-editor-model'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../../../core/common/base/base.component'; -import { DatasetProfileFieldViewStyle } from '../../../../../../core/common/enum/dataset-profile-field-view-style'; -import { ValidationType } from '../../../../../../core/common/enum/validation-type'; -import { EnumUtils } from '../../../../../../core/services/utilities/enum-utils.service'; -import { BooleanDecisionFieldDataEditorModel } from '../../../admin/field-data/boolean-decision-field-data-editor-model'; -import { CheckBoxFieldDataEditorModel } from '../../../admin/field-data/check-box-field-data-editor-model'; -import { FreeTextFieldDataEditorModel } from '../../../admin/field-data/free-text-field-data-editor-model'; -import { RadioBoxFieldDataEditorModel } from '../../../admin/field-data/radio-box-field-data-editor-model'; -import { TextAreaFieldDataEditorModel } from '../../../admin/field-data/text-area-field-data-editor-model'; -import { WordListFieldDataEditorModel } from '../../../admin/field-data/word-list-field-data-editor-model'; -import { RuleEditorModel } from '../../../admin/rule-editor-model'; -import { DatePickerDataEditorModel } from '../../../admin/field-data/date-picker-data-editor-models'; -import { ResearchersAutoCompleteFieldDataEditorModel } from '../../../admin/field-data/researchers-auto-complete-field-data-editor-model'; -import { DatasetProfileInternalDmpEntitiesType } from '../../../../../../core/common/enum/dataset-profile-internal-dmp-entities-type'; -import { DatasetProfileService } from "../../../../../../core/services/dataset-profile/dataset-profile.service"; @Component({ selector: 'app-dataset-profile-editor-field-component', diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts index 92a3dc424..9f54487c6 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component.ts @@ -1,11 +1,11 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormArray, FormGroup } from '@angular/forms'; +import { FieldEditorModel } from '@app/ui/admin/dataset-profile/admin/field-editor-model'; +import { FieldSetEditorModel } from '@app/ui/admin/dataset-profile/admin/field-set-editor-model'; +import { SectionEditorModel } from '@app/ui/admin/dataset-profile/admin/section-editor-model'; +import { BaseComponent } from '@common/base/base.component'; +import { Guid } from '@common/types/guid'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../../../core/common/base/base.component'; -import { FieldEditorModel } from '../../../admin/field-editor-model'; -import { FieldSetEditorModel } from '../../../admin/field-set-editor-model'; -import { SectionEditorModel } from '../../../admin/section-editor-model'; -import { Guid } from '../../../../../../common/types/guid'; @Component({ selector: 'app-dataset-profile-editor-section-component', @@ -32,10 +32,10 @@ export class DatasetProfileEditorSectionComponent extends BaseComponent implemen addField() { const fieldSet: FieldSetEditorModel = new FieldSetEditorModel(); const field: FieldEditorModel = new FieldEditorModel(); - field.id=Guid.create().toString(); + field.id = Guid.create().toString(); fieldSet.fields.push(field); if (this.dataModel.fieldSets) { - fieldSet.id=Guid.create().toString(); + fieldSet.id = Guid.create().toString(); this.dataModel.fieldSets.push(fieldSet); } (this.form.get('fieldSets')).push(fieldSet.buildForm()); @@ -48,7 +48,7 @@ export class DatasetProfileEditorSectionComponent extends BaseComponent implemen } DeleteSectionInSection(index) { - this.dataModel.sections.splice(index,1); + this.dataModel.sections.splice(index, 1); (this.form.get('sections')).removeAt(index); } diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts index 4dd912dfa..e27f94cad 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts @@ -8,21 +8,20 @@ import { MatHorizontalStepper } from '@angular/material/stepper'; import { ActivatedRoute, ParamMap, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DatasetProfile } from '../../../../core/model/admin/dataset-profile/dataset-profile'; -import { DatasetWizardModel } from '../../../../core/model/dataset/dataset-wizard'; -import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; -import { LoggingService } from '../../../../core/services/logging/logging-service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../../core/services/notification/ui-notification-service'; -import { PageEditorModel } from '../admin/page-editor-model'; -import { SectionEditorModel } from '../admin/section-editor-model'; -import { DatasetProfileEditorModel } from './dataset-profile-editor-model'; -import { ConfirmationDialogComponent } from '../../../../library/confirmation-dialog/confirmation-dialog.component'; -import { DatasetProfileEnum } from '../../../../core/common/enum/dataset-profile'; import * as FileSaver from 'file-saver'; -import { BreadcrumbItem } from '../../../misc/breadcrumb/definition/breadcrumb-item'; -import { DatasetStatus } from '../../../../core/common/enum/dataset-status'; -//import * as data from 'src/assets/resources/skipDisable.json'; +import { BaseComponent } from '@common/base/base.component'; +import { DatasetProfileEditorModel } from '@app/ui/admin/dataset-profile/editor/dataset-profile-editor-model'; +import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; +import { LoggingService } from '@app/core/services/logging/logging-service'; +import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service'; +import { DatasetProfile } from '@app/core/model/admin/dataset-profile/dataset-profile'; +import { DatasetProfileEnum } from '@app/core/common/enum/dataset-profile'; +import { SectionEditorModel } from '@app/ui/admin/dataset-profile/admin/section-editor-model'; +import { PageEditorModel } from '@app/ui/admin/dataset-profile/admin/page-editor-model'; +import { DatasetStatus } from '@app/core/common/enum/dataset-status'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json'); @@ -197,6 +196,8 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn this.router.navigate(['/dataset-profiles']); }); } else if (this.newVersionId) { + data.label = this.form.get('label').value; + data.description = this.form.get('description').value; this.datasetProfileService.newVersion(this.newVersionId, data) .pipe(takeUntil(this._destroyed)) .subscribe(() => { diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts index 3b39d931b..f0b1b3e17 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component.ts @@ -1,12 +1,12 @@ import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; +import { DialodConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; +import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; -import { ValidationErrorModel } from '../../../../../common/forms/validation/error-model/validation-error-model'; -import { DatasetProfileCriteria } from '../../../../../core/query/dataset-profile/dataset-profile-criteria'; -import { DatasetProfileService } from '../../../../../core/services/dataset-profile/dataset-profile.service'; -import { BaseCriteriaComponent } from '../../../../misc/criteria/base-criteria.component'; -import { DialodConfirmationUploadDatasetProfiles } from './dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; @Component({ selector: 'app-dataset-profile-criteria-component', diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts index ffa8c646b..8f903dedd 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/listing/dataset-profile-listing.component.ts @@ -3,19 +3,19 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; import { map, startWith, switchMap, takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; -import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; -import { DmpModel } from '../../../../core/model/dmp/dmp'; -import { DatasetProfileCriteria } from '../../../../core/query/dataset-profile/dataset-profile-criteria'; -import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; -import { DmpService } from '../../../../core/services/dmp/dmp.service'; -import { UiNotificationService } from '../../../../core/services/notification/ui-notification-service'; -import { BreadcrumbItem } from '../../../misc/breadcrumb/definition/breadcrumb-item'; -import { DatasetProfileCriteriaComponent } from './criteria/dataset-profile.component'; @Component({ selector: 'app-dataset-profile-listing-component', @@ -148,6 +148,7 @@ export class DatasetDataSource extends DataSource { if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); request.criteria = this._criteria.criteria; + request.criteria.finalized = false; if (this.itemId) { request.criteria.groupIds = [this.itemId]; request.criteria.allVersions = true; diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts index 97ea7d06d..092d41f6a 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/preview/dataset-profile-preview.component.ts @@ -1,10 +1,10 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { Inject, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; +import { DatasetWizardEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; -import { DatasetWizardEditorModel } from '../../../dataset/dataset-wizard/dataset-wizard-editor.model'; // @Component({ // selector: 'app-dataset-profile-preview-component', diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts index 373432037..4e4e79439 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts @@ -1,14 +1,14 @@ import { NgModule } from "@angular/core"; -import { CommonFormsModule } from "../../../common/forms/common-forms.module"; -import { CommonUiModule } from "../../../common/ui/common-ui.module"; -import { ConfirmationDialogModule } from "../../../library/confirmation-dialog/confirmation-dialog.module"; -import { UrlListingModule } from "../../../library/url-listing/url-listing.module"; -import { DmpProfileRoutingModule } from "./dmp-profile.routing"; -import { DmpProfileEditorComponent } from "./editor/dmp-profile-editor.component"; -import { DmpProfileCriteriaComponent } from "./listing/criteria/dmp-profile-criteria.component"; -import { DmpProfileListingComponent } from "./listing/dmp-profile-listing.component"; -import { DialodConfirmationUploadDmpProfiles } from "./listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component"; -import { DmpProfileExternalAutocompleteFieldEditorComponent } from "./editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.component"; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { DmpProfileRoutingModule } from './dmp-profile.routing'; +import { DmpProfileEditorComponent } from './editor/dmp-profile-editor.component'; +import { DmpProfileExternalAutocompleteFieldEditorComponent } from './editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.component'; +import { DialodConfirmationUploadDmpProfiles } from './listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; +import { DmpProfileCriteriaComponent } from './listing/criteria/dmp-profile-criteria.component'; +import { DmpProfileListingComponent } from './listing/dmp-profile-listing.component'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts index f56b1843f..b7cf3cdd0 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts @@ -1,25 +1,26 @@ -import {of as observableOf, Observable } from 'rxjs'; - -import {map, takeUntil } from 'rxjs/operators'; -import { AfterViewInit, Component, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { AfterViewInit, Component } from '@angular/core'; +import { FormArray, FormGroup } from '@angular/forms'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DmpProfileFieldDataType } from '@app/core/common/enum/dmp-profile-field-type'; +import { DmpProfileStatus } from '@app/core/common/enum/dmp-profile-status'; +import { DmpProfileType } from '@app/core/common/enum/dmp-profile-type'; +import { DmpProfile } from '@app/core/model/dmp-profile/dmp-profile'; +import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { DmpProfileEditorModel, DmpProfileFieldEditorModel } from '@app/ui/admin/dmp-profile/editor/dmp-profile-editor.model'; +import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dmp-profile/editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.model'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; +import { environment } from 'environments/environment'; import * as FileSaver from 'file-saver'; -import { environment } from '../../../../../environments/environment'; -import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DmpProfileFieldDataType } from '../../../../core/common/enum/dmp-profile-field-type'; -import { DmpProfileStatus } from '../../../../core/common/enum/dmp-profile-status'; -import { DmpProfileType } from '../../../../core/common/enum/dmp-profile-type'; -import { DmpProfile } from '../../../../core/model/dmp-profile/dmp-profile'; -import { DmpProfileService } from '../../../../core/services/dmp/dmp-profile.service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../../core/services/notification/ui-notification-service'; -import { EnumUtils } from '../../../../core/services/utilities/enum-utils.service'; -import { DmpProfileEditorModel, DmpProfileFieldEditorModel } from './dmp-profile-editor.model'; -import { BreadcrumbItem } from '../../../misc/breadcrumb/definition/breadcrumb-item'; -import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from './external-autocomplete/dmp-profile-external-autocomplete-field-editor.model'; +import { Observable, of as observableOf } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; + @Component({ selector: 'app-dmp-profile-editor-component', @@ -42,7 +43,8 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie private router: Router, private language: TranslateService, private enumUtils: EnumUtils, - private uiNotificationService: UiNotificationService + private uiNotificationService: UiNotificationService, + private formService: FormService ) { super(); } @@ -86,7 +88,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie } formSubmit(): void { - this.touchAllFormFields(this.formGroup); + this.formService.touchAllFormFields(this.formGroup); if (!this.isFormValid()) { return; } this.onSubmit(); } @@ -99,8 +101,8 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie this.dmpProfileService.createDmp(this.formGroup.value) .pipe(takeUntil(this._destroyed)) .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) ); } @@ -111,7 +113,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie onCallbackError(errorResponse: any) { this.setErrorModel(errorResponse.error); - this.validateAllFormFields(this.formGroup); + this.formService.validateAllFormFields(this.formGroup); } public setErrorModel(validationErrorModel: ValidationErrorModel) { @@ -124,37 +126,6 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie this.router.navigate(['/dmp-profiles']); } - - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - addField() { (this.formGroup.get('definition').get('fields')).push(new DmpProfileFieldEditorModel().buildForm()); } @@ -202,8 +173,8 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie this.dmpProfileService.createDmp(this.formGroup.value) .pipe(takeUntil(this._destroyed)) .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) ); } diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts index cd32c2d40..aa8b71b81 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.model.ts @@ -1,10 +1,10 @@ import { FormBuilder, FormGroup } from '@angular/forms'; -import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; -import { DmpProfileFieldDataType } from '../../../../core/common/enum/dmp-profile-field-type'; -import { DmpProfileType } from '../../../../core/common/enum/dmp-profile-type'; -import { DmpProfile, DmpProfileDefinition } from '../../../../core/model/dmp-profile/dmp-profile'; -import { DmpProfileField } from '../../../../core/model/dmp-profile/dmp-profile-field'; -import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from './external-autocomplete/dmp-profile-external-autocomplete-field-editor.model'; +import { DmpProfileFieldDataType } from '@app/core/common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '@app/core/common/enum/dmp-profile-type'; +import { DmpProfile, DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; +import { DmpProfileField } from '@app/core/model/dmp-profile/dmp-profile-field'; +import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dmp-profile/editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.model'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; export class DmpProfileEditorModel { diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts index def43eae6..bac44b696 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts @@ -1,14 +1,14 @@ import { Component, Input, OnInit } from '@angular/core'; -import { ValidationErrorModel } from '../../../../../common/forms/validation/error-model/validation-error-model'; -import { GrantListingModel } from '../../../../../core/model/grant/grant-listing'; -import { DmpCriteria } from '../../../../../core/query/dmp/dmp-criteria'; -import { DmpProfileCriteria } from '../../../../../core/query/dmp/dmp-profile-criteria'; -import { BaseCriteriaComponent } from '../../../../misc/criteria/base-criteria.component'; -import { DialodConfirmationUploadDmpProfiles } from './dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; -import { MatDialog } from '@angular/material/dialog'; +import { MatDialog } from '@angular/material'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; +import { DmpProfileCriteria } from '@app/core/query/dmp/dmp-profile-criteria'; +import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service'; +import { DialodConfirmationUploadDmpProfiles } from '@app/ui/admin/dmp-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; +import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; -import { DmpProfileService } from '../../../../../core/services/dmp/dmp-profile.service'; @Component({ selector: 'app-dmp-profile-criteria-component', diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts index 856548bc0..6a954910d 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts @@ -1,21 +1,21 @@ -import {merge as observableMerge, of as observableOf, Observable } from 'rxjs'; - -import {map, switchMap, startWith, takeUntil } from 'rxjs/operators'; import { DataSource } from '@angular/cdk/table'; import { Component, OnInit, ViewChild } from '@angular/core'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DmpProfileListing } from '@app/core/model/dmp-profile/dmp-profile-listing'; +import { DmpProfileCriteria } from '@app/core/query/dmp/dmp-profile-criteria'; +import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service'; +import { DmpProfileCriteriaComponent } from '@app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DmpProfileListing } from '../../../../core/model/dmp-profile/dmp-profile-listing'; -import { DmpProfileCriteria } from '../../../../core/query/dmp/dmp-profile-criteria'; -import { DmpProfileService } from '../../../../core/services/dmp/dmp-profile.service'; -import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; -import { DmpProfileCriteriaComponent } from './criteria/dmp-profile-criteria.component'; -import { BreadcrumbItem } from '../../../misc/breadcrumb/definition/breadcrumb-item'; +import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; +import { map, startWith, switchMap, takeUntil } from 'rxjs/operators'; + @Component({ selector: 'app-dmp-profile-listing-component', @@ -131,7 +131,7 @@ export class DatasetDataSource extends DataSource { if (!result) { return []; } if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } return result.data; - }),); + })); } disconnect() { diff --git a/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts index ffa011faf..5431debc9 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts +++ b/dmp-frontend/src/app/ui/admin/user/listing/criteria/user-criteria.component.ts @@ -1,11 +1,11 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { AppRole } from '@app/core/common/enum/app-role'; +import { UserCriteria } from '@app/core/query/user/user-criteria'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { debounceTime, takeUntil } from 'rxjs/operators'; -import { ValidationErrorModel } from '../../../../../common/forms/validation/error-model/validation-error-model'; -import { AppRole } from '../../../../../core/common/enum/app-role'; -import { UserCriteria } from '../../../../../core/query/user/user-criteria'; -import { EnumUtils } from '../../../../../core/services/utilities/enum-utils.service'; -import { BaseCriteriaComponent } from '../../../../misc/criteria/base-criteria.component'; @Component({ selector: 'app-user-criteria-component', diff --git a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts index ca4393546..1e1c7a10f 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.ts @@ -1,14 +1,14 @@ import { Component, Input, OnInit } from '@angular/core'; import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { AppRole } from '@app/core/common/enum/app-role'; +import { UserListingModel } from '@app/core/model/user/user-listing'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { UserService } from '@app/core/services/user/user.service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { BaseComponent } from '@common/base/base.component'; +import { Validation, ValidationContext } from '@common/forms/validation/validation-context'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; -import { Validation, ValidationContext } from '../../../../../common/forms/validation/validation-context'; -import { BaseComponent } from '../../../../../core/common/base/base.component'; -import { AppRole } from '../../../../../core/common/enum/app-role'; -import { UserListingModel } from '../../../../../core/model/user/user-listing'; -import { UserService } from '../../../../../core/services/user/user.service'; -import { EnumUtils } from '../../../../../core/services/utilities/enum-utils.service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../../../core/services/notification/ui-notification-service'; @Component({ selector: 'app-user-role-editor-component', @@ -26,7 +26,7 @@ export class UserRoleEditorComponent extends BaseComponent implements OnInit { private userService: UserService, private formBuilder: FormBuilder, private enumUtils: EnumUtils, - private uiNotificationService:UiNotificationService + private uiNotificationService: UiNotificationService ) { super(); } ngOnInit() { @@ -117,12 +117,12 @@ export class UserRoleEditorComponent extends BaseComponent implements OnInit { onCallbackSuccess() { this.nowEditing = false; this.formGroup.disable(); - this.uiNotificationService.snackBarNotification( this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); } onCallbackError(error: any) { this.validateAllFormFields(this.formGroup); - this.uiNotificationService.snackBarNotification( this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Error); } getPrincipalAppRoleValues(): Number[] { diff --git a/dmp-frontend/src/app/ui/admin/user/user.module.ts b/dmp-frontend/src/app/ui/admin/user/user.module.ts index 18257c942..38dae797a 100644 --- a/dmp-frontend/src/app/ui/admin/user/user.module.ts +++ b/dmp-frontend/src/app/ui/admin/user/user.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../../common/ui/common-ui.module'; -import { FormattingModule } from '../../../core/formatting.module'; +import { FormattingModule } from '@app/core/formatting.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; import { UserCriteriaComponent } from './listing/criteria/user-criteria.component'; import { UserRoleEditorComponent } from './listing/role-editor/user-role-editor.component'; import { UserListingComponent } from './listing/user-listing.component'; diff --git a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts index ece1c430d..3619d9897 100644 --- a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts +++ b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.component.ts @@ -1,13 +1,14 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, HostListener } from '@angular/core'; import { Router } from '@angular/router'; +import { Credential } from '@app/core/model/auth/credential'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { CultureService } from '@app/core/services/culture/culture-service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { Credential } from '../../../core/model/auth/credential'; -import { CultureService } from '../../../core/services/culture/culture-service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { AuthService } from '../../../core/services/auth/auth.service'; - +import { TranslateServerLoader } from '@app/core/services/language/server.loader'; +import { LanguageService } from '@app/core/services/language/language.service'; @Component({ selector: 'app-admin-login', templateUrl: './admin-login.component.html', @@ -18,12 +19,17 @@ export class AdminLoginComponent extends BaseComponent implements OnInit { public auth2: any; public credential: Credential; + @HostListener('document:keydown.enter', ['$event']) onKeydownHandler() { + this.nativeLogin(); + } + constructor( private authService: AuthService, private uiNotificationService: UiNotificationService, - private language: TranslateService, + private translate: TranslateService, private cultureService: CultureService, - private router: Router + private router: Router, + private language: LanguageService ) { super(); } @@ -45,12 +51,13 @@ export class AdminLoginComponent extends BaseComponent implements OnInit { } public onLogInSuccess(loginResponse: any) { - this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success); + this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success); if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); } + if (this.authService.current().language) { this.language.changeLanguage(this.authService.current().language); } this.router.navigate(['/']); } public onLogInError(errorMessage: string) { - this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error); } } diff --git a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts index c4c98b17d..766ca5e31 100644 --- a/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts +++ b/dmp-frontend/src/app/ui/auth/admin-login/admin-login.module.ts @@ -1,8 +1,8 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../../common/ui/common-ui.module'; -import { AdminLoginComponent } from './admin-login.component'; -import { AdminLoginRoutingModule } from './admin-login.routing'; +import { AdminLoginComponent } from '@app/ui/auth/admin-login/admin-login.component'; +import { AdminLoginRoutingModule } from '@app/ui/auth/admin-login/admin-login.routing'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts b/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts index a0c38b6ec..bdba62c6c 100644 --- a/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts +++ b/dmp-frontend/src/app/ui/auth/login/b2access/b2access-login.component.ts @@ -1,12 +1,12 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; +import { AuthProvider } from '@app/core/common/enum/auth-provider'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { LoginService } from '@app/ui/auth/login/utilities/login.service'; +import { BaseComponent } from '@common/base/base.component'; +import { environment } from 'environments/environment'; import { takeUntil } from 'rxjs/operators'; -import { environment } from '../../../../../environments/environment'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { AuthProvider } from '../../../../core/common/enum/auth-provider'; -import { AuthService } from '../../../../core/services/auth/auth.service'; -import { LoginService } from '../utilities/login.service'; @Component({ selector: 'app-b2access-login', @@ -37,10 +37,10 @@ export class B2AccessLoginComponent extends BaseComponent implements OnInit { public b2AccessGetAuthCode() { window.location.href = environment.loginProviders.b2accessConfiguration.oauthUrl - + '?response_type=code&client_id=' + environment.loginProviders.b2accessConfiguration.clientId - + '&redirect_uri=' + environment.loginProviders.b2accessConfiguration.redirectUri - + '&state=' + environment.loginProviders.b2accessConfiguration.state - + '&scope=USER_PROFILE'; + + '?response_type=code&client_id=' + environment.loginProviders.b2accessConfiguration.clientId + + '&redirect_uri=' + environment.loginProviders.b2accessConfiguration.redirectUri + + '&state=' + environment.loginProviders.b2accessConfiguration.state + + '&scope=USER_PROFILE'; } public b2AccessLogin(code: String) { diff --git a/dmp-frontend/src/app/ui/auth/login/configurable-login/configurable-login.component.ts b/dmp-frontend/src/app/ui/auth/login/configurable-login/configurable-login.component.ts index dfeef2274..95f170f8d 100644 --- a/dmp-frontend/src/app/ui/auth/login/configurable-login/configurable-login.component.ts +++ b/dmp-frontend/src/app/ui/auth/login/configurable-login/configurable-login.component.ts @@ -1,14 +1,14 @@ -import { Component, OnInit, Input } from "@angular/core"; -import { BaseComponent } from "../../../../core/common/base/base.component"; -import { ActivatedRoute, Router, Params } from "@angular/router"; -import { HttpClient } from "@angular/common/http"; -import { LoginService } from "../utilities/login.service"; -import { AuthService } from "../../../../core/services/auth/auth.service"; -import { takeUntil } from "rxjs/operators"; -import { environment } from "../../../../../environments/environment"; -import { AuthProvider } from "../../../../core/common/enum/auth-provider"; -import { ConfigurableProvider } from "../../../../core/model/configurable-provider/configurableProvider"; -import { ConfigurableProvidersService } from "../utilities/configurableProviders.service"; +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { AuthProvider } from '@app/core/common/enum/auth-provider'; +import { ConfigurableProvider } from '@app/core/model/configurable-provider/configurableProvider'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { ConfigurableProvidersService } from '@app/ui/auth/login/utilities/configurableProviders.service'; +import { LoginService } from '@app/ui/auth/login/utilities/login.service'; +import { BaseComponent } from '@common/base/base.component'; +import { environment } from 'environments/environment'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-configurable-login', diff --git a/dmp-frontend/src/app/ui/auth/login/email-confirmation/email-confirmation.component.ts b/dmp-frontend/src/app/ui/auth/login/email-confirmation/email-confirmation.component.ts index fdffc2199..317f563fb 100644 --- a/dmp-frontend/src/app/ui/auth/login/email-confirmation/email-confirmation.component.ts +++ b/dmp-frontend/src/app/ui/auth/login/email-confirmation/email-confirmation.component.ts @@ -1,11 +1,11 @@ import { Component, OnInit } from "@angular/core"; -import { ActivatedRoute, Params, Router } from "@angular/router"; +import { FormControl } from '@angular/forms'; +import { ActivatedRoute, Router } from "@angular/router"; +import { EmailConfirmationService } from '@app/core/services/email-confirmation/email-confirmation.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { BaseComponent } from '@common/base/base.component'; +import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from "rxjs/operators"; -import { BaseComponent } from "../../../../core/common/base/base.component"; -import { EmailConfirmationService } from "../../../../core/services/email-confirmation/email-confirmation.service"; -import { UiNotificationService, SnackBarNotificationLevel } from "../../../../core/services/notification/ui-notification-service"; -import { TranslateService } from "@ngx-translate/core"; -import { FormControl } from "@angular/forms"; @Component({ selector: 'app-email-confirmation-component', @@ -35,8 +35,8 @@ export class EmailConfirmation extends BaseComponent implements OnInit { this.emailConfirmationService.emailConfirmation(token) .pipe(takeUntil(this._destroyed)) .subscribe( - result => this.onCallbackEmailConfirmationSuccess(), - error => this.onCallbackError(error) + result => this.onCallbackEmailConfirmationSuccess(), + error => this.onCallbackError(error) ) } else { this.showForm = true; @@ -48,8 +48,8 @@ export class EmailConfirmation extends BaseComponent implements OnInit { this.emailConfirmationService.sendConfirmationEmail(this.emailFormControl.value) .pipe(takeUntil(this._destroyed)) .subscribe( - result => this.onCallbackSuccess(), - error => this.onCallbackError(error) + result => this.onCallbackSuccess(), + error => this.onCallbackError(error) ) } @@ -62,7 +62,12 @@ export class EmailConfirmation extends BaseComponent implements OnInit { } onCallbackError(error: any) { + if (error.status === 302) { + this.uiNotificationService.snackBarNotification(this.language.instant('EMAIL-CONFIRMATION.EMAIL-FOUND'), SnackBarNotificationLevel.Warning); + this.router.navigate(['home']); + } else { this.uiNotificationService.snackBarNotification(this.language.instant('EMAIL-CONFIRMATION.EXPIRED-EMAIL'), SnackBarNotificationLevel.Error); this.router.navigate(['login']); + } } } diff --git a/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts b/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts index bf2981f99..4d6acf28e 100644 --- a/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts +++ b/dmp-frontend/src/app/ui/auth/login/linkedin-login/linkedin-login.component.ts @@ -1,12 +1,12 @@ +import { HttpClient } from "@angular/common/http"; import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { AuthProvider } from '@app/core/common/enum/auth-provider'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { LoginService } from '@app/ui/auth/login/utilities/login.service'; +import { BaseComponent } from '@common/base/base.component'; +import { environment } from 'environments/environment'; import { takeUntil } from 'rxjs/operators'; -import { environment } from '../../../../../environments/environment'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { AuthProvider } from '../../../../core/common/enum/auth-provider'; -import { AuthService } from '../../../../core/services/auth/auth.service'; -import { LoginService } from '../utilities/login.service'; -import { HttpClient } from "@angular/common/http"; @Component({ selector: 'app-linkedin-login', diff --git a/dmp-frontend/src/app/ui/auth/login/login.component.html b/dmp-frontend/src/app/ui/auth/login/login.component.html index 7b674a5c4..d8be9c88b 100644 --- a/dmp-frontend/src/app/ui/auth/login/login.component.html +++ b/dmp-frontend/src/app/ui/auth/login/login.component.html @@ -2,24 +2,24 @@ +
+ + history + +

{{ dataset.version }}

+

{{'DATASET-LISTING.COLUMNS.LAST-EDITED' | translate}} {{ dataset.modified | date: "shortDate"}}

diff --git a/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.html b/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.html index e79ab5628..546df6e76 100644 --- a/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.html +++ b/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.html @@ -19,14 +19,14 @@ view_agenda {{ 'SIDE-BAR.GENERAL' | translate }} - + work_outline {{ 'DMP-LISTING.COLUMNS.GRANT' | translate }} - + diff --git a/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.ts b/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.ts index f9c8bd81d..e3ec8a6e6 100644 --- a/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.ts +++ b/dmp-frontend/src/app/ui/dmp/clone/dmp-clone.component.ts @@ -1,22 +1,23 @@ -import {of as observableOf, Observable } from 'rxjs'; - -import {map, takeUntil } from 'rxjs/operators'; -import { Component, OnInit } from '@angular/core'; -import { DmpWizardEditorModel } from '../wizard/dmp-wizard-editor.model'; -import { FormGroup } from '@angular/forms'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { DmpModel } from '../../../core/model/dmp/dmp'; -import { TranslateService } from '@ngx-translate/core'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { UiNotificationService, SnackBarNotificationLevel } from '../../../core/services/notification/ui-notification-service'; -import { FunderFormModel } from '../editor/grant-tab/funder-form-model'; -import { ProjectFormModel } from '../editor/grant-tab/project-form-model'; -import { GrantTabModel } from '../editor/grant-tab/grant-tab-model'; import { HttpErrorResponse } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +import { DmpWizardEditorModel } from '@app/ui/dmp/wizard/dmp-wizard-editor.model'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { BaseComponent } from '@common/base/base.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable, of as observableOf } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; +import { DmpStatus } from '@app/core/common/enum/dmp-status'; + @Component({ selector: 'app-dmp-clone', @@ -34,6 +35,8 @@ export class DmpCloneComponent extends BaseComponent implements OnInit { selectedTab = 0; parentDmpLabel: string; isNewVersion: boolean = false; + isClone: boolean = true; + isNew: boolean = false; constructor( private route: ActivatedRoute, @@ -58,6 +61,7 @@ export class DmpCloneComponent extends BaseComponent implements OnInit { this.dmp.project = new ProjectFormModel(); this.dmp.funder = new FunderFormModel(); this.dmp.fromModel(data); + this.dmp.status = DmpStatus.Draft; this.formGroup = this.dmp.buildForm(); this.parentDmpLabel = this.formGroup.get('label').value; diff --git a/dmp-frontend/src/app/ui/dmp/dmp.module.ts b/dmp-frontend/src/app/ui/dmp/dmp.module.ts index 22702fe5b..b701a8e40 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp.module.ts @@ -1,34 +1,35 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { FormattingModule } from '../../core/formatting.module'; -import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; -import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module'; -import { UrlListingModule } from '../../library/url-listing/url-listing.module'; -import { DmpRoutingModule } from './dmp.routing'; -import { AddResearcherComponent } from './editor/add-researcher/add-researcher.component'; -import { AvailableProfilesComponent } from './editor/available-profiles/available-profiles.component'; -import { DmpEditorComponent } from './editor/dmp-editor.component'; -import { DmpFinalizeDialogComponent } from './editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; -import { DynamicDmpFieldResolverComponent } from './editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component'; -import { DynamicFieldGrantComponent } from './editor/dynamic-fields-grant/dynamic-field-grant/dynamic-field-grant.component'; -import { DynamicFieldsGrantComponent } from './editor/dynamic-fields-grant/dynamic-fields-grant.component'; -import { InvitationAcceptedComponent } from './invitation/accepted/dmp-invitation-accepted.component'; -import { DmpInvitationDialogComponent } from './invitation/dmp-invitation.component'; -import { DmpCriteriaComponent } from './listing/criteria/dmp-criteria.component'; -import { DmpUploadDialogue } from './listing/criteria/upload-dialogue/dmp-upload-dialogue.component'; -import { DmpListingComponent } from './listing/dmp-listing.component'; -import { DmpListingItemComponent } from './listing/listing-item/dmp-listing-item.component'; -import { DmpWizardComponent } from './wizard/dmp-wizard.component'; -import { DmpWizardEditorComponent } from './wizard/editor/dmp-wizard-editor.component'; -import { DmpWizardDatasetListingComponent } from './wizard/listing/dmp-wizard-dataset-listing.component'; -import { ExportMethodDialogModule } from '../../library/export-method-dialog/export-method-dialog.module'; -import { GeneralTabComponent } from './editor/general-tab/general-tab.component'; -import { PeopleTabComponent } from './editor/people-tab/people-tab.component'; -import { GrantTabComponent } from './editor/grant-tab/grant-tab.component'; -import { DatasetsTabComponent } from './editor/datasets-tab/datasets-tab.component'; -import { DmpOverviewModule } from './overview/dmp-overview.module'; -import { DmpCloneComponent } from './clone/dmp-clone.component'; +import { FormattingModule } from '@app/core/formatting.module'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { ExportMethodDialogModule } from '@app/library/export-method-dialog/export-method-dialog.module'; +import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; +import { DmpCloneComponent } from '@app/ui/dmp/clone/dmp-clone.component'; +import { DmpRoutingModule } from '@app/ui/dmp/dmp.routing'; +import { AddResearcherComponent } from '@app/ui/dmp/editor/add-researcher/add-researcher.component'; +import { AvailableProfilesComponent } from '@app/ui/dmp/editor/available-profiles/available-profiles.component'; +import { DatasetsTabComponent } from '@app/ui/dmp/editor/datasets-tab/datasets-tab.component'; +import { DmpEditorComponent } from '@app/ui/dmp/editor/dmp-editor.component'; +import { DmpFinalizeDialogComponent } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; +import { DynamicDmpFieldResolverComponent } from '@app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component'; +import { DynamicFieldGrantComponent } from '@app/ui/dmp/editor/dynamic-fields-grant/dynamic-field-grant/dynamic-field-grant.component'; +import { DynamicFieldsGrantComponent } from '@app/ui/dmp/editor/dynamic-fields-grant/dynamic-fields-grant.component'; +import { GeneralTabComponent } from '@app/ui/dmp/editor/general-tab/general-tab.component'; +import { GrantTabComponent } from '@app/ui/dmp/editor/grant-tab/grant-tab.component'; +import { PeopleTabComponent } from '@app/ui/dmp/editor/people-tab/people-tab.component'; +import { InvitationAcceptedComponent } from '@app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component'; +import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation.component'; +import { DmpCriteriaComponent } from '@app/ui/dmp/listing/criteria/dmp-criteria.component'; +import { DmpUploadDialogue } from '@app/ui/dmp/listing/criteria/upload-dialogue/dmp-upload-dialogue.component'; +import { DmpListingComponent } from '@app/ui/dmp/listing/dmp-listing.component'; +import { DmpListingItemComponent } from '@app/ui/dmp/listing/listing-item/dmp-listing-item.component'; +import { DmpOverviewModule } from '@app/ui/dmp/overview/dmp-overview.module'; +import { DmpWizardComponent } from '@app/ui/dmp/wizard/dmp-wizard.component'; +import { DmpWizardEditorComponent } from '@app/ui/dmp/wizard/editor/dmp-wizard-editor.component'; +import { DmpWizardDatasetListingComponent } from '@app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ @@ -40,7 +41,8 @@ import { DmpCloneComponent } from './clone/dmp-clone.component'; FormattingModule, AutoCompleteModule, DmpRoutingModule, - DmpOverviewModule + DmpOverviewModule, + FormValidationErrorsDialogModule ], declarations: [ DmpListingComponent, diff --git a/dmp-frontend/src/app/ui/dmp/dmp.routing.ts b/dmp-frontend/src/app/ui/dmp/dmp.routing.ts index dc84fb904..3b3fcb74a 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp.routing.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp.routing.ts @@ -23,13 +23,13 @@ const routes: Routes = [ }, }, // Uncomment to get dmp plans for grant with grantId - // { - // path: 'grant/:grantId', - // component: DmpListingComponent, - // data: { - // breadcrumb: true - // }, - // }, + { + path: 'grant/:grantId', + component: DmpListingComponent, + data: { + breadcrumb: true + }, + }, { path: 'edit/:id', component: DmpEditorComponent, diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html index 34133f7ad..acdcdbf46 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html @@ -12,7 +12,7 @@
-
+
diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts index 08d3940aa..ca87c4f60 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts @@ -1,11 +1,10 @@ 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 { ResearcherEditorModel } from '@app/ui/dmp/editor/add-researcher/add-researcher.model'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { ExternalResearcherService } from '../../../../core/services/external-sources/researcher/external-researcher.service'; -import { ResearcherEditorModel } from './add-researcher.model'; -import { ResearcherModel } from '../../../../core/model/researcher/researcher'; @Component({ selector: 'app-add-researcher-component', @@ -30,11 +29,15 @@ export class AddResearcherComponent extends BaseComponent implements OnInit { this.externalResearcherService.createResearcher(this.formGroup.value) .pipe(takeUntil(this._destroyed)) .subscribe( - null, null, () => this.dialogRef.close() + null, null, () => this.dialogRef.close() ); } addResearcher() { this.dialogRef.close(this.formGroup.value); } + + isFormValid() { + return this.formGroup.valid; + } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts index 529a0bb3d..80dca6276 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts @@ -1,5 +1,8 @@ import { FormBuilder, FormGroup } from '@angular/forms'; -import { ResearcherModel } from '../../../../core/model/researcher/researcher'; +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'; export class ResearcherEditorModel { public id: String; @@ -7,6 +10,7 @@ export class ResearcherEditorModel { public lastName: String; public uri: String; public email: String; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); fromModel(item: ResearcherModel): ResearcherEditorModel { this.id = item.id; @@ -17,13 +21,20 @@ export class ResearcherEditorModel { return this; } - buildForm(): FormGroup { + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ - firstName: [this.name], - lastName: [this.lastName] + firstName: [{ value: this.name, disabled: disabled }, context.getValidation('firstName').validators], + lastName: [{ value: this.lastName, disabled: disabled }, context.getValidation('lastName').validators] }); return formGroup; } + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'firstName', validators: [BackendErrorValidator(this.validationErrorModel, 'firstName')] }); + baseContext.validation.push({ key: 'lastName', validators: [BackendErrorValidator(this.validationErrorModel, 'lastName')] }); + return baseContext; + } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts b/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts index 8045b1195..12dea9dad 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/available-profiles/available-profiles.component.ts @@ -1,12 +1,12 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DatasetProfileModel } from '../../../../core/model/dataset/dataset-profile'; -import { DatasetService } from '../../../../core/services/dataset/dataset.service'; -import { DataTableRequest } from "../../../../core/model/data-table/data-table-request"; -import { DatasetProfileCriteria } from "../../../../core/query/dataset-profile/dataset-profile-criteria"; @Component({ selector: 'app-available-profiles-component', diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html index 1f9240f5f..f26d1fa67 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html @@ -13,16 +13,16 @@ more_horiz - - - @@ -58,14 +58,14 @@ view_agenda {{ 'SIDE-BAR.GENERAL' | translate }} - + work_outline {{ 'DMP-LISTING.COLUMNS.GRANT' | translate }} - + @@ -107,15 +107,15 @@
- -
-
diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts index 4f01c3b24..c9cb70752 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -1,39 +1,41 @@ -import { of as observableOf, Observable } from 'rxjs'; - -import { map, takeUntil } from 'rxjs/operators'; import { Component, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DmpStatus } from '@app/core/common/enum/dmp-status'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; +import { DmpProfileListing } from '@app/core/model/dmp-profile/dmp-profile-listing'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { UserModel } from '@app/core/model/user/user'; +import { UserInfoListingModel } from '@app/core/model/user/user-info-listing'; +import { BaseCriteria } from '@app/core/query/base-criteria'; +import { DmpProfileCriteria } from '@app/core/query/dmp/dmp-profile-criteria'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { DmpEditorModel } from '@app/ui/dmp/editor/dmp-editor.model'; +import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DmpStatus } from '../../../core/common/enum/dmp-status'; -import { Status } from '../../../core/common/enum/Status'; -import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; -import { DmpProfileDefinition } from '../../../core/model/dmp-profile/dmp-profile'; -import { DmpProfileListing } from '../../../core/model/dmp-profile/dmp-profile-listing'; -import { DmpModel } from '../../../core/model/dmp/dmp'; -import { UserModel } from '../../../core/model/user/user'; -import { BaseCriteria } from '../../../core/query/base-criteria'; -import { DmpProfileCriteria } from '../../../core/query/dmp/dmp-profile-criteria'; -import { GrantCriteria } from '../../../core/query/grant/grant-criteria'; -import { RequestItem } from '../../../core/query/request-item'; -import { DmpProfileService } from '../../../core/services/dmp/dmp-profile.service'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { ConfirmationDialogComponent } from '../../../library/confirmation-dialog/confirmation-dialog.component'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { DmpEditorModel } from './dmp-editor.model'; -import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput } from './dmp-finalize-dialog/dmp-finalize-dialog.component'; -import { AuthService } from '../../../core/services/auth/auth.service'; -import { UserInfoListingModel } from '../../../core/model/user/user-info-listing'; -import { GrantTabModel } from './grant-tab/grant-tab-model'; -import { ProjectFormModel } from './grant-tab/project-form-model'; -import { FunderFormModel } from './grant-tab/funder-form-model'; +import { Observable, of as observableOf } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; +import { Principal } from "@app/core/model/auth/Principal"; +import { Role } from "@app/core/common/enum/role"; @Component({ selector: 'app-dmp-editor-component', @@ -59,6 +61,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC filteredOptions: DmpProfileListing[]; selectedDmpProfileDefinition: DmpProfileDefinition; DynamicDmpFieldResolverComponent: any; + isUserOwner: boolean = true; constructor( private dmpProfileService: DmpProfileService, @@ -68,7 +71,9 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC private language: TranslateService, private dialog: MatDialog, private uiNotificationService: UiNotificationService, + private authentication: AuthService, private authService: AuthService, + private formService: FormService ) { super(); } @@ -105,8 +110,13 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmp.funder = new FunderFormModel(); this.dmp.fromModel(data); this.formGroup = this.dmp.buildForm(); + this.setIsUserOwner(); + if (!this.isUserOwner) { + this.isFinalized = true; + this.formGroup.disable(); + } //this.registerFormEventsForDmpProfile(this.dmp.definition); - if (!this.editMode || this.dmp.status === Status.Inactive) { + if (!this.editMode || this.dmp.status === DmpStatus.Finalized) { this.isFinalized = true; this.formGroup.disable(); } @@ -143,7 +153,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmp.fromModel(data); this.formGroup = this.dmp.buildForm(); //this.registerFormEventsForDmpProfile(this.dmp.definition); - if (!this.editMode || this.dmp.status === Status.Inactive) { this.formGroup.disable(); } + if (!this.editMode || this.dmp.status === DmpStatus.Finalized) { this.formGroup.disable(); } // if (!this.isAuthenticated) { const breadcrumbs = []; breadcrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS').toUpperCase(), url: '/plans' }); @@ -198,6 +208,13 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC return this.authService.current() != null; } + setIsUserOwner() { + if (this.dmp) { + const principal: Principal = this.authentication.current(); + this.isUserOwner = principal.id === this.dmp.users.find(x => x.role === Role.Owner).id; + } + } + registerFormEventsForNewItem() { this.breadCrumbs = observableOf([ { @@ -223,15 +240,29 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC // } formSubmit(showAddDatasetDialog?: boolean): void { - //this.touchAllFormFields(this.formGroup); - if (!this.isFormValid()) { return; } + this.formService.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { + this.showValidationErrorsDialog(); + return; + } this.onSubmit(showAddDatasetDialog); } public isFormValid() { - return this.formGroup.get('label').valid && this.formGroup.get('profiles').valid && - (this.formGroup.get('funder').get('label').valid || this.formGroup.get('funder').get('existFunder').valid) && - (this.formGroup.get('grant').get('label').valid || this.formGroup.get('grant').get('existGrant').valid); + return this.formGroup.valid; + // return this.formGroup.get('label').valid && this.formGroup.get('profiles').valid && + // (this.formGroup.get('funder').get('label').valid || this.formGroup.get('funder').get('existFunder').valid) && + // (this.formGroup.get('grant').get('label').valid || this.formGroup.get('grant').get('existGrant').valid); + } + + private showValidationErrorsDialog(projectOnly?: boolean) { + const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, { + disableClose: true, + data: { + formGroup: this.formGroup, + projectOnly: projectOnly + }, + }); } onSubmit(showAddDatasetDialog?: boolean): void { @@ -242,7 +273,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC if (showAddDatasetDialog) { this.addDatasetOpenDialog(complete); } - else { this.onCallbackSuccess() } + else { this.onCallbackSuccess(complete) } }, error => { this.formGroup.get('status').setValue(DmpStatus.Draft); @@ -252,9 +283,9 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC } - onCallbackSuccess(): void { + onCallbackSuccess(id?: String): 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(['/plans']); + id != null ? this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans', 'edit', id]); }) : this.router.navigate(['/reload']).then(() => { this.router.navigate(['/plans']); }); } onCallbackError(error: any) { @@ -430,7 +461,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC if (result) { this.router.navigate(['datasets/new/' + id]); } else { - this.router.navigate(['/plans']); + id != null ? this.router.navigate(['/plans', 'edit', id]) : this.router.navigate(['/plans']); } }); } @@ -454,14 +485,17 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), } }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { - if (result && !result.cancelled) { - this.formGroup.get('status').setValue(DmpStatus.Finalized); - this.formGroup.get('datasetsToBeFinalized').setValue(result.datasetsToBeFinalized); - this.formSubmit(false); - dialogRef.close(); - } - }); + dialogRef.afterClosed() + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (result && !result.cancelled) { + this.formGroup.get('status').setValue(DmpStatus.Finalized); + this.formGroup.get('datasetsToBeFinalized').setValue(result.datasetsToBeFinalized); + this.formSubmit(false); + //this.router.navigate(['/plans/overview/' + this.formGroup.get('id').value]); + dialogRef.close(); + } + }); } // advancedClicked() { diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts index 2eaee767b..372ca7250 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts @@ -1,25 +1,25 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -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 { Status } from "../../../core/common/enum/Status"; -import { DmpProfile, DmpProfileDefinition } from "../../../core/model/dmp-profile/dmp-profile"; -import { DmpModel } from "../../../core/model/dmp/dmp"; -import { DmpDynamicField } from "../../../core/model/dmp/dmp-dynamic-field"; -import { DmpDynamicFieldDependency } from "../../../core/model/dmp/dmp-dynamic-field-dependency"; -import { OrganizationModel } from "../../../core/model/organisation/organization"; -import { ResearcherModel } from "../../../core/model/researcher/researcher"; -import { UserModel } from "../../../core/model/user/user"; -import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator"; -import { UserInfoListingModel } from "../../../core/model/user/user-info-listing"; -import { DatasetModel } from "../../../core/model/dataset/dataset"; -import { GrantTabModel } from "./grant-tab/grant-tab-model"; -import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from "../../admin/dmp-profile/editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.model"; -import { DmpProfileType } from "../../../core/common/enum/dmp-profile-type"; -import { DmpProfileFieldDataType } from "../../../core/common/enum/dmp-profile-field-type"; -import { DmpProfileField } from "../../../core/model/dmp-profile/dmp-profile-field"; -import { ProjectFormModel } from "./grant-tab/project-form-model"; -import { FunderFormModel } from "./grant-tab/funder-form-model"; +import { DmpProfileFieldDataType } from '@app/core/common/enum/dmp-profile-field-type'; +import { DmpProfileType } from '@app/core/common/enum/dmp-profile-type'; +import { DmpStatus } from '@app/core/common/enum/dmp-status'; +import { DatasetModel } from '@app/core/model/dataset/dataset'; +import { DmpProfile, DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; +import { DmpProfileField } from '@app/core/model/dmp-profile/dmp-profile-field'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { DmpDynamicField } from '@app/core/model/dmp/dmp-dynamic-field'; +import { DmpDynamicFieldDependency } from '@app/core/model/dmp/dmp-dynamic-field-dependency'; +import { OrganizationModel } from '@app/core/model/organisation/organization'; +import { ResearcherModel } from '@app/core/model/researcher/researcher'; +import { UserModel } from '@app/core/model/user/user'; +import { UserInfoListingModel } from '@app/core/model/user/user-info-listing'; +import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; +import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from '@app/ui/admin/dmp-profile/editor/external-autocomplete/dmp-profile-external-autocomplete-field-editor.model'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +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'; export class DmpEditorModel { public id: string; @@ -29,7 +29,7 @@ export class DmpEditorModel { public version: number; public lockable: boolean; public creator: UserModel; - public status: Status = Status.Active; + public status: DmpStatus = DmpStatus.Draft; public description: String; public grant: GrantTabModel; public project: ProjectFormModel; diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts index 9708fff9a..c8aca013d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Router } from '@angular/router'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DatasetStatus } from '../../../../core/common/enum/dataset-status'; -import { DatasetService } from '../../../../core/services/dataset/dataset.service'; +import { DatasetStatus } from '@app/core/common/enum/dataset-status'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { BaseComponent } from '@common/base/base.component'; @Component({ selector: 'app-dmp-finalize-dialog-component', diff --git a/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts index d95540f87..23ff93644 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component.ts @@ -26,6 +26,7 @@ export class DynamicDmpFieldResolverComponent implements OnInit, OnDestroy { @Input() dmpProfileId: string; @Input() dmpProfileDefinition: DmpProfileDefinition; @Input() formGroup: FormGroup; + @Input() isUserOwner: boolean; constructor( private dmpProfileService: DmpProfileService diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html index 9131651d7..a1090650e 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html @@ -31,7 +31,7 @@ {{formGroup.get('profiles').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} - @@ -56,7 +56,7 @@ {{formGroup.get('researchers').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} - @@ -68,7 +68,7 @@ - + diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts index dff382cfd..4330d7332 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts @@ -1,25 +1,25 @@ -import {map, takeUntil } from 'rxjs/operators'; import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; -import { Observable } from 'rxjs'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; -import { DatasetProfileModel } from '../../../../core/model/dataset/dataset-profile'; -import { DmpProfileDefinition } from '../../../../core/model/dmp-profile/dmp-profile'; -import { ExternalSourceItemModel } from '../../../../core/model/external-sources/external-source-item'; -import { DatasetProfileCriteria } from '../../../../core/query/dataset-profile/dataset-profile-criteria'; -import { DmpProfileCriteria } from '../../../../core/query/dmp/dmp-profile-criteria'; -import { RequestItem } from '../../../../core/query/request-item'; -import { DmpProfileService } from '../../../../core/services/dmp/dmp-profile.service'; -import { DmpService } from '../../../../core/services/dmp/dmp.service'; -import { ExternalSourcesService } from '../../../../core/services/external-sources/external-sources.service'; -import { MultipleAutoCompleteConfiguration } from '../../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; -import { SingleAutoCompleteConfiguration } from '../../../../library/auto-complete/single/single-auto-complete-configuration'; -import { AddResearcherComponent } from '../add-researcher/add-researcher.component'; -import { AvailableProfilesComponent } from '../available-profiles/available-profiles.component'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; +import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { DmpProfileCriteria } from '@app/core/query/dmp/dmp-profile-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { AddResearcherComponent } from '@app/ui/dmp/editor/add-researcher/add-researcher.component'; +import { AvailableProfilesComponent } from '@app/ui/dmp/editor/available-profiles/available-profiles.component'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-general-tab', @@ -30,18 +30,37 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { @Input() formGroup: FormGroup = null; @Input() isNewVersion: boolean; + @Input() isUserOwner: boolean; + @Input() isClone: boolean; - filteringOrganisationsAsync = false; - filteringResearchersAsync = false; - filteredProfilesAsync = false; - filteredOrganisations: ExternalSourceItemModel[]; - filteredResearchers: ExternalSourceItemModel[]; - filteredProfiles: DatasetProfileModel[]; + profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { + filterFn: this.filterProfiles.bind(this), + initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + subtitleFn: (item) => item['description'] + }; - profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - researchersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; - dmpProfileAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { + 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) => item['name'], + titleFn: (item) => item['name'], + subtitleFn: (item) => 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')) + }; + researchersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { + 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) => item['name'], + titleFn: (item) => item['name'], + subtitleFn: (item) => 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')) + }; + dmpProfileAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { + filterFn: this.dmpProfileSearch.bind(this), + initialItems: (extraData) => this.dmpProfileSearch(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'] + }; selectedDmpProfileDefinition: DmpProfileDefinition; @@ -64,42 +83,15 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { this.formGroup.get('label').disable(); } - this.dmpProfileAutoCompleteConfiguration = { - filterFn: this.dmpProfileSearch.bind(this), - initialItems: (extraData) => this.dmpProfileSearch(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'] - }; - - this.profilesAutoCompleteConfiguration = { - filterFn: this.filterProfiles.bind(this), - initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - subtitleFn: (item) => item['description'] - }; - - 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) => item['name'], - titleFn: (item) => item['name'], - subtitleFn: (item) => item ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') - }; - - 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) => item['name'], - titleFn: (item) => item['name'], - subtitleFn: (item) => item ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['tag'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') - }; + if (!this.isUserOwner && !this.isClone) { + this.formGroup.disable(); + } } registerFormEventsForDmpProfile(definitionProperties?: DmpProfileDefinition): void { this.formGroup.get('profile').valueChanges .pipe( - takeUntil(this._destroyed)) + takeUntil(this._destroyed)) .subscribe(Option => { if (Option instanceof Object) { this.selectedDmpProfileDefinition = null; @@ -140,26 +132,15 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { // } filterOrganisations(value: string): Observable { - - this.filteredOrganisations = undefined; - this.filteringOrganisationsAsync = true; - return this.externalSourcesService.searchDMPOrganizations(value); } filterResearchers(value: string): Observable { - - this.filteredResearchers = undefined; - this.filteringResearchersAsync = true; - return this.externalSourcesService.searchDMPResearchers({ criteria: { name: value, like: null } }); } filterProfiles(value: string): Observable { - this.filteredProfiles = undefined; - this.filteredProfilesAsync = true; - const request = new RequestItem(); const criteria = new DatasetProfileCriteria(); criteria.like = value; @@ -167,25 +148,30 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { return this._service.searchDMPProfiles(request); } - addResearcher() { + addResearcher(event: MouseEvent) { + event.stopPropagation(); const dialogRef = this.dialog.open(AddResearcherComponent, { data: this.formGroup.get('researchers') }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { if (result) { const fullName = result.firstName + " " + result.lastName; - this.formGroup.get('researchers').value.push({ + const newItem = { label: null, name: fullName, - id: "dmp:" + fullName, + id: null, status: 0, - tag: null, - }); + key: "Internal", + }; + const researchersArray = this.formGroup.get('researchers').value || []; + researchersArray.push(newItem); + this.formGroup.get('researchers').setValue(researchersArray); } }); } - availableProfiles() { + availableProfiles(event: MouseEvent) { + event.stopPropagation(); const dialogRef = this.dialog.open(AvailableProfilesComponent, { data: { profiles: this.formGroup.get('profiles') diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts index 50a229331..76adf4e24 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts @@ -1,9 +1,10 @@ -import { Status } from "../../../../core/common/enum/Status"; -import { FunderModel } from "../../../../core/model/funder/funder"; -import { ValidationErrorModel } from "../../../../common/forms/validation/error-model/validation-error-model"; -import { ValidationContext } from "../../../../common/forms/validation/validation-context"; -import { FormGroup, FormBuilder, Validators } from "@angular/forms"; -import { BackendErrorValidator } from "../../../../common/forms/validation/custom-validator"; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Status } from '@app/core/common/enum/Status'; +import { FunderModel } from '@app/core/model/funder/funder'; +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'; + export class FunderFormModel { public id: string; diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts index f89ca6cce..afba9fce2 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts @@ -1,10 +1,11 @@ -import { Status } from "../../../../core/common/enum/Status"; -import { GrantListingModel } from "../../../../core/model/grant/grant-listing"; -import { ValidationErrorModel } from "../../../../common/forms/validation/error-model/validation-error-model"; -import { ValidationContext } from "../../../../common/forms/validation/validation-context"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { BackendErrorValidator } from "../../../../common/forms/validation/custom-validator"; -import { ValidJsonValidator } from "../../../../library/auto-complete/auto-complete-custom-validator"; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Status } from '@app/core/common/enum/Status'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; +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'; + export class GrantTabModel { public id: string; diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html index e4f7ae5a2..6e7cd3fcb 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html @@ -24,7 +24,7 @@
-
+
settings_backup_restore {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST-FUNDER' | translate}} @@ -63,7 +63,7 @@
-
+
settings_backup_restore {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST-GRANT' | translate}} @@ -104,7 +104,7 @@
-
+
settings_backup_restore {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST-PROJECT' | translate}} diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts index f76bf72e1..843176570 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts @@ -1,17 +1,17 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { SingleAutoCompleteConfiguration } from '../../../../library/auto-complete/single/single-auto-complete-configuration'; -import { RequestItem } from '../../../../core/query/request-item'; -import { GrantCriteria } from '../../../../core/query/grant/grant-criteria'; -import { GrantService } from '../../../../core/services/grant/grant.service'; -import { GrantTabModel } from './grant-tab-model'; -import { ProjectService } from '../../../../core/services/project/project.service'; -import { FunderService } from '../../../../core/services/funder/funder.service'; -import { FunderCriteria } from '../../../../core/query/funder/funder-criteria'; -import { ProjectCriteria } from '../../../../core/query/project/project-criteria'; +import { FunderCriteria } from '@app/core/query/funder/funder-criteria'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { ProjectCriteria } from '@app/core/query/project/project-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { FunderService } from '@app/core/services/funder/funder.service'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { ProjectService } from '@app/core/services/project/project.service'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from "rxjs/operators"; -import { BaseComponent } from "../../../../core/common/base/base.component"; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-grant-tab', @@ -26,6 +26,8 @@ export class GrantTabComponent extends BaseComponent implements OnInit { @Input() isFinalized: boolean; @Input() isNewVersion: boolean; @Input() isNew: boolean; + @Input() isUserOwner: boolean; + @Input() isClone: boolean = false; isCreateNew = false; isCreateNewProject = false; @@ -45,6 +47,14 @@ export class GrantTabComponent extends BaseComponent implements OnInit { super(); } + getGrantIdText(item) { + if (item.reference != null && typeof item.reference == 'string') { + const parts = (item.reference as String).split('::'); + return parts.length > 1 ? ' (' + parts[parts.length - 1] + ')' : ''; + } + return ''; + } + ngOnInit() { const grantRequestItem: RequestItem = new RequestItem(); @@ -55,15 +65,15 @@ export class GrantTabComponent extends BaseComponent implements OnInit { initialItems: () => this.searchFunder(''), displayFn: (item) => item['label'], titleFn: (item) => item['label'], - subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') + subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } this.grantAutoCompleteConfiguration = { filterFn: this.searchGrant.bind(this), initialItems: () => this.searchGrant(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') + displayFn: (item) => item['label'] + this.getGrantIdText(item), + titleFn: (item) => item['label'] + this.getGrantIdText(item), + subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) }; this.projectAutoCompleteConfiguration = { @@ -71,7 +81,7 @@ export class GrantTabComponent extends BaseComponent implements OnInit { initialItems: () => this.searchProject(''), displayFn: (item) => item['label'], titleFn: (item) => item['label'], - subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') + subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) } this.isCreateNew = (this.grantformGroup.get('label').value != null && this.grantformGroup.get('label').value.length > 0); @@ -81,7 +91,7 @@ export class GrantTabComponent extends BaseComponent implements OnInit { this.setProjectValidators(); this.setFunderValidators(); this.registerFormListeners(); - if (this.isNew) { + if (this.isNew && !this.isClone) { this.grantformGroup.reset(); this.grantformGroup.disable(); } @@ -135,7 +145,13 @@ export class GrantTabComponent extends BaseComponent implements OnInit { this.grantformGroup.get('existGrant').disable(); this.grantformGroup.get('label').enable(); this.grantformGroup.get('description').enable(); - } else if (this.isFinalized || this.isNewVersion) { + } else if (this.isClone && !this.isNewVersion) { + this.grantformGroup.get('existGrant').enable(); + this.grantformGroup.get('label').disable(); + this.grantformGroup.get('label').reset(); + this.grantformGroup.get('description').disable(); + this.grantformGroup.get('description').reset(); + } else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) { this.grantformGroup.get('existGrant').disable(); this.grantformGroup.get('label').disable(); this.grantformGroup.get('description').disable(); @@ -153,7 +169,13 @@ export class GrantTabComponent extends BaseComponent implements OnInit { this.projectFormGroup.get('existProject').disable(); this.projectFormGroup.get('label').enable(); this.projectFormGroup.get('description').enable(); - } else if (this.isFinalized || this.isNewVersion) { + } else if (this.isClone && !this.isNewVersion) { + this.projectFormGroup.get('existProject').enable(); + this.projectFormGroup.get('label').disable() + this.projectFormGroup.get('label').reset(); + this.projectFormGroup.get('description').disable(); + this.projectFormGroup.get('description').reset(); + } else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) { this.projectFormGroup.get('existProject').disable(); this.projectFormGroup.get('label').disable(); this.projectFormGroup.get('description').disable(); @@ -170,7 +192,15 @@ export class GrantTabComponent extends BaseComponent implements OnInit { if (this.isCreateNewFunder) { this.funderFormGroup.get('existFunder').disable(); this.funderFormGroup.get('label').enable(); - } else if (this.isFinalized || this.isNewVersion) { + } else if (this.isClone && !this.isNewVersion) { + if (this.funderFormGroup.get('existFunder')) { + this.funderFormGroup.get('existFunder').enable(); + this.funderFormGroup.get('label').disable(); + this.funderFormGroup.get('label').reset(); + } else { + this.funderFormGroup.get('label').enable(); + } + } else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) { this.funderFormGroup.get('existFunder').disable(); this.funderFormGroup.get('label').disable(); } else { @@ -191,9 +221,10 @@ export class GrantTabComponent extends BaseComponent implements OnInit { funderValueChanged(funder: any) { if ((funder.label !== "" && funder.label != null && funder.label !== undefined) || (funder.existFunder !== null && funder.existFunder !== undefined && funder.existFunder.id !== undefined)) { + this.grantformGroup.reset(); this.grantformGroup.enable(); - } - else { + this.setGrantValidators(); + } else { this.grantformGroup.reset(); this.grantformGroup.disable(); if (this.isCreateNew) this.isCreateNew = !this.isCreateNew; @@ -203,4 +234,8 @@ export class GrantTabComponent extends BaseComponent implements OnInit { isGrantDisabled() { return this.grantformGroup.disabled; } + + showToggleButton() { + return (!this.isFinalized && this.isUserOwner) || this.isClone; + } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts index 15e46491a..797dfee69 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts @@ -1,10 +1,10 @@ -import { Status } from "../../../../core/common/enum/Status"; -import { ProjectModel } from "../../../../core/model/project/project"; -import { ValidationErrorModel } from "../../../../common/forms/validation/error-model/validation-error-model"; -import { ValidationContext } from "../../../../common/forms/validation/validation-context"; -import { FormGroup, FormBuilder, Validators } from "@angular/forms"; -import { BackendErrorValidator } from "../../../../common/forms/validation/custom-validator"; -import { ValidJsonValidator } from "../../../../library/auto-complete/auto-complete-custom-validator"; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Status } from '@app/core/common/enum/Status'; +import { ProjectModel } from '@app/core/model/project/project'; +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'; + export class ProjectFormModel { public id: string; diff --git a/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts index 33678428f..1c303c446 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/people-tab/people-tab.component.ts @@ -1,12 +1,12 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { TranslateService } from '@ngx-translate/core'; import { Principal } from '../../../../core/model/auth/Principal'; import { UserInfoListingModel } from '../../../../core/model/user/user-info-listing'; import { AuthService } from '../../../../core/services/auth/auth.service'; import { DmpService } from '../../../../core/services/dmp/dmp.service'; -import { ConfirmationDialogComponent } from '../../../../library/confirmation-dialog/confirmation-dialog.component'; import { DmpInvitationDialogComponent } from '../../invitation/dmp-invitation.component'; import { DmpEditorModel } from '../dmp-editor.model'; diff --git a/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts b/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts index 8441d4d6d..4f9f8726b 100644 --- a/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts +++ b/dmp-frontend/src/app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; +import { DmpInvitationService } from '@app/core/services/dmp/dmp-invitation.service'; +import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DmpInvitationService } from '../../../../core/services/dmp/dmp-invitation.service'; @Component({ selector: 'app-dmp-invitation-accepted-component', diff --git a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts index ed144faf8..bbda70d88 100644 --- a/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts +++ b/dmp-frontend/src/app/ui/dmp/invitation/dmp-invitation.component.ts @@ -1,22 +1,19 @@ -import {map, takeUntil } from 'rxjs/operators'; import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { Component, Inject, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatChipInputEvent } from '@angular/material/chips'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; +import { DmpInvitation } from '@app/core/model/dmp/invitation/dmp-invitation'; +import { DmpInvitationUser } from '@app/core/model/dmp/invitation/dmp-invitation-user'; +import { DmpInvitationUserCriteria } from '@app/core/query/dmp/dmp-invitation-user-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { DmpInvitationService } from '@app/core/services/dmp/dmp-invitation.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; import { Observable } from 'rxjs'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DmpInvitation } from '../../../core/model/dmp/invitation/dmp-invitation'; -import { DmpInvitationUser } from '../../../core/model/dmp/invitation/dmp-invitation-user'; -import { DmpInvitationUserCriteria } from '../../../core/query/dmp/dmp-invitation-user-criteria'; -import { RequestItem } from '../../../core/query/request-item'; -import { DmpInvitationService } from '../../../core/services/dmp/dmp-invitation.service'; -import { MultipleAutoCompleteConfiguration } from '../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; - - - +import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-invitation-component', @@ -38,7 +35,7 @@ export class DmpInvitationDialogComponent extends BaseComponent implements OnIni usersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { filterFn: this.filterUsers.bind(this), - initialItems: (excludedItems: any[]) => this.filterUsers('').pipe(map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + initialItems: (excludedItems: any[]) => this.filterUsers('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item.name, titleFn: (item) => item.name }; diff --git a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html index f0f777463..b1af0d9aa 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html +++ b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.html @@ -32,7 +32,6 @@ placeholder="{{ 'CRITERIA.DMP.SELECT-DATASET-TEMPLATES' | translate }}" [configuration]="datasetTemplateAutoCompleteConfiguration"> - arrow_drop_down
@@ -45,7 +44,6 @@ placeholder="{{ 'CRITERIA.DMP.SELECT-GRANTS' | translate }}" [configuration]="grantAutoCompleteConfiguration"> - arrow_drop_down
@@ -58,7 +56,6 @@ placeholder="{{'CRITERIA.DMP.SELECT-COLLABORATORS' | translate}}" [configuration]="collaboratorsAutoCompleteConfiguration"> - arrow_drop_down
@@ -82,7 +79,6 @@ placeholder="{{'DMP-RELATED-ORGANIZATION.SELECT-ORGANIZATIONS' | translate}}" [configuration]="organisationAutoCompleteConfiguration"> - arrow_drop_down
diff --git a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts index 88b4a0940..d6b20728d 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts +++ b/dmp-frontend/src/app/ui/dmp/listing/criteria/dmp-criteria.component.ts @@ -1,25 +1,25 @@ -import {map, takeUntil } from 'rxjs/operators'; import { Component, Input, OnInit } from '@angular/core'; import { FormBuilder, FormControl } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { OrganisationCriteria } from '@app/core/query/organisation/organisation-criteria'; +import { UserCriteria } from '@app/core/query/user/user-criteria'; +import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { OrganisationService } from '@app/core/services/organisation/organisation.service'; +import { UserService } from '@app/core/services/user/user.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { DmpUploadDialogue } from '@app/ui/dmp/listing/criteria/upload-dialogue/dmp-upload-dialogue.component'; +import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; -import { ValidationErrorModel } from '../../../../common/forms/validation/error-model/validation-error-model'; -import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; -import { GrantListingModel } from '../../../../core/model/grant/grant-listing'; -import { DmpCriteria } from '../../../../core/query/dmp/dmp-criteria'; -import { OrganisationCriteria } from '../../../../core/query/organisation/organisation-criteria'; -import { GrantCriteria } from '../../../../core/query/grant/grant-criteria'; -import { UserCriteria } from '../../../../core/query/user/user-criteria'; -import { DmpService } from '../../../../core/services/dmp/dmp.service'; -import { OrganisationService } from '../../../../core/services/organisation/organisation.service'; -import { GrantService } from '../../../../core/services/grant/grant.service'; -import { UserService } from '../../../../core/services/user/user.service'; -import { MultipleAutoCompleteConfiguration } from '../../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; -import { BaseCriteriaComponent } from '../../../misc/criteria/base-criteria.component'; -import { DmpUploadDialogue } from './upload-dialogue/dmp-upload-dialogue.component'; -import { DatasetProfileCriteria } from '../../../../core/query/dataset-profile/dataset-profile-criteria'; -import { DatasetProfileService } from '../../../../core/services/dataset-profile/dataset-profile.service'; +import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dmp-criteria-component', @@ -47,14 +47,14 @@ export class DmpCriteriaComponent extends BaseCriteriaComponent implements OnIni collaboratorsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { filterFn: this.filterCollaborators.bind(this), - initialItems: (excludedItems: any[]) => this.filterCollaborators('').pipe(map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + initialItems: (excludedItems: any[]) => this.filterCollaborators('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] }; datasetTemplateAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { filterFn: this.filterDatasetTemplate.bind(this), - initialItems: (excludedItems: any[]) => this.filterDatasetTemplate('').pipe(map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + initialItems: (excludedItems: any[]) => this.filterDatasetTemplate('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'], subtitleFn: (item) => item['description'] @@ -62,14 +62,14 @@ export class DmpCriteriaComponent extends BaseCriteriaComponent implements OnIni grantAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { filterFn: this.filterGrant.bind(this), - initialItems: (excludedItems: any[]) => this.filterGrant('').pipe(map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + initialItems: (excludedItems: any[]) => this.filterGrant('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'] }; organisationAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = { 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))), + initialItems: (excludedItems: any[]) => this.filterOrganisations('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] } diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html index 18d5dc1fe..04e6675f5 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.html @@ -4,6 +4,14 @@

{{'DMP-LISTING.TITLE' | translate}} {{titlePrefix}}

+
+ + {{'DMP-LISTING.VIEW-ALL-VERSIONS' | translate}} + + + {{this.groupLabel}} + +
diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss index 4def11f1b..ead048e9b 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.scss @@ -51,6 +51,14 @@ display: none !important; } +.all-versions { + color: #999999 !important; +} + +.dmp-label { + color: #089dbb !important; +} + // .bot-paginator { // margin-top: auto; // } diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts index 6debbbd2c..384dced5c 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts @@ -1,23 +1,24 @@ -import {of as observableOf, Observable } from 'rxjs'; import { Component, OnInit, ViewChild } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Router } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; -import { DmpListingModel } from '../../../core/model/dmp/dmp-listing'; -import { GrantListingModel } from '../../../core/model/grant/grant-listing'; -import { DmpCriteria } from '../../../core/query/dmp/dmp-criteria'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { EnumUtils } from '../../../core/services/utilities/enum-utils.service'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation.component'; -import { DmpCriteriaComponent } from './criteria/dmp-criteria.component'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DmpListingModel } from '@app/core/model/dmp/dmp-listing'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation.component'; +import { DmpCriteriaComponent } from '@app/ui/dmp/listing/criteria/dmp-criteria.component'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; +import { Observable, of as observableOf } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { GrantService } from "@app/core/services/grant/grant.service"; @Component({ selector: 'app-dmp-listing-component', @@ -37,6 +38,8 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread titlePrefix: string; totalCount: number; listingItems: DmpListingModel[] = []; + allVersions: boolean = false; + groupLabel: string; constructor( private dmpService: DmpService, @@ -45,6 +48,7 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread private dialog: MatDialog, public enumUtils: EnumUtils, private language: TranslateService, + private grantService: GrantService ) { super(); } @@ -56,14 +60,38 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread let grantLabel; if (params['grantId']) { this.grantId = params['grantId']; - this.showGrant = false; - const grant: GrantListingModel = { - id: this.grantId - } - this.criteria.setCriteria({ like: null, grants: [grant], groupIds: null, allVersions: false }); + this.showGrant = true; + this.grantService.getSingle(this.grantId) + .subscribe((grant: GrantListingModel) => { + // const grant: GrantListingModel = { + // id: this.grantId + // } + this.criteria.setCriteria({ like: null, grants: [grant], groupIds: null, allVersions: false }); + + this.refresh(); + grantLabel = this.route.snapshot.queryParams.grantLabel; + // this.breadCrumbs = Observable.of([{ parentComponentName: 'GrantEditorComponent', label: grantLabel, url: '/grants/edit/' + this.grantId }]); + this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages)); + }) + + } else if (params['groupId']) { + this.itemId = params['groupId']; + this.showGrant = true; + const breadCrumbs = []; + this.allVersions = true; + + this.language.get('NAV-BAR.MY-DMPS').pipe(takeUntil(this._destroyed)).subscribe(x => { + this.breadCrumbs = observableOf([ + { + parentComponentName: null, + label: x, + url: '/plans' + }] + ); + }) + this.criteria.setCriteria(this.getDefaultCriteria()); + this.groupLabel = this.route.snapshot.queryParams.groupLabel; this.refresh(); - grantLabel = this.route.snapshot.queryParams.grantLabel; - // this.breadCrumbs = Observable.of([{ parentComponentName: 'GrantEditorComponent', label: grantLabel, url: '/grants/edit/' + this.grantId }]); this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages)); } else { this.itemId = params['groupId']; @@ -108,7 +136,8 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread if (resetPages) this._paginator.pageIndex = 0; const startIndex = this._paginator.pageIndex * this._paginator.pageSize; let fields: Array = new Array(); - if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; } + // if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; } + fields.push('-modified'); const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); let value = this.criteria.formGroup.value; request.criteria = { diff --git a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html index eef507cea..bb2d6c8eb 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html +++ b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html @@ -49,9 +49,12 @@
-
+

{{dmp.description}}

+
+

{{'DMP-LISTING.COLUMNS.VERSION' | translate}} : {{dmp.version}}

+
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index ebb4aef52..7933e2671 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -11,35 +11,35 @@ more_horiz - - -
- - - - @@ -79,9 +79,9 @@

{{ dmp.description }}

-
+
settings -

{{ roleDisplay(dmp.users) }}

+

{{ roleDisplayFromList(dmp.users) }}

@@ -110,6 +110,11 @@

{{ dmp.researchers.length }}

{{ 'DMP-EDITOR.FIELDS.RESEARCHERS' | translate }}

+
+ person +

{{ dmp.users.length }}

+

{{ 'DMP-EDITOR.FIELDS.COLLABORATORS' | translate }}

+
@@ -157,6 +162,12 @@
{{ researcher.name }}
+
+
{{'DMP-OVERVIEW.COLLABORATORS' | translate}}
+
+
{{ user.name }}
+
+
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.scss b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.scss index 8e5b8b8e1..c06a7179f 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.scss +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.scss @@ -66,6 +66,25 @@ text-transform: uppercase; } +.collaborators { + display: flex; + flex-direction: column; + border: 2px solid #f2f2f2; + margin-right: 2em; + margin-top: 2em; + padding: 0.5em; + } + + .collaborators-title { + width: 135px; + color: #089dbb; + background-color: white; + padding: 0px 10px; + margin-top: -16px; + cursor: default; + text-transform: uppercase; + } + .container-header { display: flex; align-items: baseline; diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index 39b5bc55f..ee60fa07b 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -1,25 +1,26 @@ -import {of as observableOf, Observable } from 'rxjs'; import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DatasetStatus } from '@app/core/common/enum/dataset-status'; +import { DmpStatus } from '@app/core/common/enum/dmp-status'; +import { Principal } from '@app/core/model/auth/Principal'; +import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview'; +import { DatasetsToBeFinalized } from '@app/core/model/dataset/datasets-toBeFinalized'; +import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; +import { UserInfoListingModel } from '@app/core/model/user/user-info-listing'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput, DmpFinalizeDialogOutput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; +import { Observable, of as observableOf } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DatasetStatus } from '../../../core/common/enum/dataset-status'; -import { DmpStatus } from '../../../core/common/enum/dmp-status'; -import { Principal } from '../../../core/model/auth/Principal'; -import { DatasetOverviewModel } from '../../../core/model/dataset/dataset-overview'; -import { DmpOverviewModel } from '../../../core/model/dmp/dmp-overview'; -import { UserInfoListingModel } from '../../../core/model/user/user-info-listing'; -import { AuthService } from '../../../core/services/auth/auth.service'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { ConfirmationDialogComponent } from '../../../library/confirmation-dialog/confirmation-dialog.component'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput, DmpFinalizeDialogOutput } from '../editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; -import { DatasetsToBeFinalized } from '../../../core/model/dataset/datasets-toBeFinalized'; +import { Role } from "@app/core/common/enum/role"; @Component({ selector: 'app-dmp-overview', @@ -34,6 +35,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { isPublicView = true; hasPublishButton: boolean = true; breadCrumbs: Observable = observableOf(); + isUserOwner: boolean; constructor( private route: ActivatedRoute, @@ -62,11 +64,16 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { .pipe(takeUntil(this._destroyed)) .subscribe(data => { this.dmp = data; + this.setIsUserOwner(); const breadCrumbs = []; breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DMPS'), url: "/plans" }); breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/overview/' + this.dmp.id }); this.breadCrumbs = observableOf(breadCrumbs); - }) + }, (error: any) => { + if (error.status === 404) { + return this.onFetchingDeletedCallbackError('/plans/'); + } + }); } else if (publicId != null) { this.isNew = false; @@ -76,15 +83,32 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { .pipe(takeUntil(this._destroyed)) .subscribe(data => { this.dmp = data; + this.setIsUserOwner(); const breadCrumbs = []; breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), url: "/explore-plans" }); breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/publicOverview/' + this.dmp.id }); this.breadCrumbs = observableOf(breadCrumbs); + }, (error: any) => { + if (error.status === 404) { + return this.onFetchingDeletedCallbackError('/plans/'); + } }); } }); } + onFetchingDeletedCallbackError(redirectRoot: string) { + this.uiNotificationService.snackBarNotification(this.language.instant('DMP-OVERVIEW.ERROR.DELETED-DMP'), SnackBarNotificationLevel.Error); + this.router.navigate([redirectRoot]); + } + + setIsUserOwner() { + if (this.dmp) { + const principal: Principal = this.authentication.current(); + if (principal) this.isUserOwner = principal.id === this.dmp.users.find(x => x.role === Role.Owner).id; + } + } + editClicked(dmp: DmpOverviewModel) { this.router.navigate(['/plans/edit/' + dmp.id]); } @@ -209,7 +233,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { return filename; } - roleDisplay(value: UserInfoListingModel[]) { + roleDisplayFromList(value: UserInfoListingModel[]) { const principal: Principal = this.authentication.current(); let role: number; if (principal) { @@ -219,13 +243,32 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } }); } - if (role === 0) { + 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'); } - else if (role === 1) { - return this.translate.instant('DMP-LISTING.MEMBER'); + } + + isUserDMPRelated() { + const principal: Principal = this.authentication.current(); + let isRelated: boolean = false; + if (this.dmp && principal) { + this.dmp.users.forEach(element => { + if (element.id === principal.id) { + isRelated = true; + } + }) } - else { + return isRelated; + } + + roleDisplay(value: UserInfoListingModel) { + if (value.role === Role.Member) { + return this.translate.instant('DMP-LISTING.MEMBER'); + } else { return this.translate.instant('DMP-LISTING.OWNER'); } } @@ -355,7 +398,15 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } viewVersions(rowId: String, rowLabel: String) { - this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); + if (this.dmp.isPublic && !this.isUserOwner) { + this.router.navigate(['/explore-plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); + } else { + this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); + } + } + + public isAuthenticated(): boolean { + return !(!this.authentication.current()); } // advancedClicked() { diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.module.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.module.ts index 5969e5e58..269c70146 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.module.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.module.ts @@ -1,12 +1,12 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../../common/ui/common-ui.module'; -import { FormattingModule } from '../../../core/formatting.module'; -import { AutoCompleteModule } from '../../../library/auto-complete/auto-complete.module'; -import { ConfirmationDialogModule } from '../../../library/confirmation-dialog/confirmation-dialog.module'; -import { UrlListingModule } from '../../../library/url-listing/url-listing.module'; -import { DmpOverviewComponent } from './dmp-overview.component'; -import { ExportMethodDialogModule } from '../../../library/export-method-dialog/export-method-dialog.module'; +import { FormattingModule } from '@app/core/formatting.module'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { ExportMethodDialogModule } from '@app/library/export-method-dialog/export-method-dialog.module'; +import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; +import { DmpOverviewComponent } from '@app/ui/dmp/overview/dmp-overview.component'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts index 1f42b1ab2..4582e91e8 100644 --- a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts +++ b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard-editor.model.ts @@ -1,20 +1,20 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -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 { Status } from "../../../core/common/enum/Status"; -import { DmpProfile, DmpProfileDefinition } from "../../../core/model/dmp-profile/dmp-profile"; -import { DmpModel } from "../../../core/model/dmp/dmp"; -import { DmpDynamicField } from "../../../core/model/dmp/dmp-dynamic-field"; -import { DmpDynamicFieldDependency } from "../../../core/model/dmp/dmp-dynamic-field-dependency"; -import { OrganizationModel } from "../../../core/model/organisation/organization"; -import { GrantListingModel } from "../../../core/model/grant/grant-listing"; -import { ResearcherModel } from "../../../core/model/researcher/researcher"; -import { UserModel } from "../../../core/model/user/user"; -import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator"; -import { FunderFormModel } from "../editor/grant-tab/funder-form-model"; -import { ProjectFormModel } from "../editor/grant-tab/project-form-model"; -import { GrantTabModel } from "../editor/grant-tab/grant-tab-model"; +import { Status } from '@app/core/common/enum/Status'; +import { DmpProfile, DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { DmpDynamicField } from '@app/core/model/dmp/dmp-dynamic-field'; +import { DmpDynamicFieldDependency } from '@app/core/model/dmp/dmp-dynamic-field-dependency'; +import { OrganizationModel } from '@app/core/model/organisation/organization'; +import { ResearcherModel } from '@app/core/model/researcher/researcher'; +import { UserModel } from '@app/core/model/user/user'; +import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +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 { DmpStatus } from '@app/core/common/enum/dmp-status'; export class DmpWizardEditorModel { public id: string; @@ -24,7 +24,7 @@ export class DmpWizardEditorModel { public version: number; public lockable: boolean; public creator: UserModel; - public status: Status = Status.Active; + public status: DmpStatus = DmpStatus.Draft; public description: String; public grant: GrantTabModel; public funder: FunderFormModel; diff --git a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts index 10d9901b8..83e8444a8 100644 --- a/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts +++ b/dmp-frontend/src/app/ui/dmp/wizard/dmp-wizard.component.ts @@ -1,24 +1,23 @@ -import {of as observableOf, Observable } from 'rxjs'; - -import {map, takeUntil } from 'rxjs/operators'; +import { HttpErrorResponse } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { GrantTabModel } from '@app/ui/dmp/editor/grant-tab/grant-tab-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +import { DmpWizardEditorModel } from '@app/ui/dmp/wizard/dmp-wizard-editor.model'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseComponent } from '@common/base/base.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { DmpModel } from '../../../core/model/dmp/dmp'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { DmpWizardEditorModel } from './dmp-wizard-editor.model'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { HttpErrorResponse } from '@angular/common/http'; -import { GrantTabModel } from '../editor/grant-tab/grant-tab-model'; -import { ProjectFormModel } from '../editor/grant-tab/project-form-model'; -import { FunderFormModel } from '../editor/grant-tab/funder-form-model'; +import { Observable, of as observableOf } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dmp-wizard-component', diff --git a/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts index f62972f4e..90ba33cee 100644 --- a/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.ts @@ -1,25 +1,25 @@ -import {map, takeUntil } from 'rxjs/operators'; import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute, Router } from '@angular/router'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; +import { UserModel } from '@app/core/model/user/user'; +import { BaseCriteria } from '@app/core/query/base-criteria'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DatasetProfileModel } from '../../../../core/model/dataset/dataset-profile'; -import { ExternalSourceItemModel } from '../../../../core/model/external-sources/external-source-item'; -import { UserModel } from '../../../../core/model/user/user'; -import { BaseCriteria } from '../../../../core/query/base-criteria'; -import { DatasetProfileCriteria } from '../../../../core/query/dataset-profile/dataset-profile-criteria'; -import { GrantCriteria } from '../../../../core/query/grant/grant-criteria'; -import { RequestItem } from '../../../../core/query/request-item'; -import { DmpService } from '../../../../core/services/dmp/dmp.service'; -import { ExternalSourcesService } from '../../../../core/services/external-sources/external-sources.service'; -import { GrantService } from '../../../../core/services/grant/grant.service'; -import { MultipleAutoCompleteConfiguration } from '../../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; -import { SingleAutoCompleteConfiguration } from '../../../../library/auto-complete/single/single-auto-complete-configuration'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../../core/services/notification/ui-notification-service'; +import { map, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dmp-wizard-editor-component', @@ -73,21 +73,21 @@ export class DmpWizardEditorComponent extends BaseComponent implements OnInit { this.profilesAutoCompleteConfiguration = { filterFn: this.filterProfiles.bind(this), - initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'] }; 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))), + initialItems: (excludedItems: any[]) => this.filterOrganisations('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] }; 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))), + initialItems: (excludedItems: any[]) => this.filterResearchers('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] }; @@ -137,9 +137,9 @@ export class DmpWizardEditorComponent extends BaseComponent implements OnInit { } - availableProfiles() {} + availableProfiles() { } - addResearcher() {} + addResearcher() { } public cancel(): void { this.router.navigate(['/plans']); diff --git a/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts b/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts index 5d1d7c131..210b7034b 100644 --- a/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts +++ b/dmp-frontend/src/app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component.ts @@ -5,15 +5,15 @@ import { MatPaginator } from '@angular/material/paginator'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing'; +import { DatasetCriteria } from '@app/core/query/dataset/dataset-criteria'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { DatasetCriteriaComponent } from '@app/ui/dataset/listing/criteria/dataset-criteria.component'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../../../core/common/base/base.component'; -import { DataTableRequest } from '../../../../core/model/data-table/data-table-request'; -import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; -import { DatasetCriteria } from '../../../../core/query/dataset/dataset-criteria'; -import { DatasetService } from '../../../../core/services/dataset/dataset.service'; -import { DmpService } from '../../../../core/services/dmp/dmp.service'; -import { DatasetCriteriaComponent } from '../../../dataset/listing/criteria/dataset-criteria.component'; @Component({ selector: 'app-dmp-wizard-dataset-listing-component', diff --git a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts index cde24dce1..c3d83154b 100644 --- a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts +++ b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset-listing.component.ts @@ -1,18 +1,18 @@ -import {of as observableOf, Observable } from 'rxjs'; -import { Component, OnInit, ViewChild, ɵConsole } from '@angular/core'; +import { Component, OnInit, ViewChild } from '@angular/core'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; -import { Router, ActivatedRoute, Params } from '@angular/router'; -import { takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { DataTableRequest } from '../../core/model/data-table/data-table-request'; -import { DatasetListingModel } from '../../core/model/dataset/dataset-listing'; -import { ExploreDatasetCriteriaModel } from '../../core/query/explore-dataset/explore-dataset-criteria'; -import { DatasetService } from '../../core/services/dataset/dataset.service'; -import { IBreadCrumbComponent } from '../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { BreadcrumbItem } from '../misc/breadcrumb/definition/breadcrumb-item'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing'; +import { ExploreDatasetCriteriaModel } from '@app/core/query/explore-dataset/explore-dataset-criteria'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; -import { DmpService } from '../../core/services/dmp/dmp.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { BreadcrumbItem } from '../misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '../misc/breadcrumb/definition/IBreadCrumbComponent'; @Component({ diff --git a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts index d8598add3..b06554524 100644 --- a/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts +++ b/dmp-frontend/src/app/ui/explore-dataset/explore-dataset.module.ts @@ -1,12 +1,12 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; -import { ExploreDatasetListingComponent } from './explore-dataset-listing.component'; -import { ExploreDatasetRoutingModule } from './explore-dataset.routing'; -import { ExploreDatasetFilterItemComponent } from './filters/explore-dataset-filter-item/explore-dataset-filter-item.component'; -import { ExploreDatasetFiltersComponent } from './filters/explore-dataset-filters.component'; -import { ExploreDatasetListingItemComponent } from './listing-item/explore-dataset-listing-item.component'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; +import { ExploreDatasetListingComponent } from '@app/ui/explore-dataset/explore-dataset-listing.component'; +import { ExploreDatasetRoutingModule } from '@app/ui/explore-dataset/explore-dataset.routing'; +import { ExploreDatasetFilterItemComponent } from '@app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component'; +import { ExploreDatasetFiltersComponent } from '@app/ui/explore-dataset/filters/explore-dataset-filters.component'; +import { ExploreDatasetListingItemComponent } from '@app/ui/explore-dataset/listing-item/explore-dataset-listing-item.component'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts index 718f7baea..fddaa4b57 100644 --- a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filter-item/explore-dataset-filter-item.component.ts @@ -1,12 +1,12 @@ -import {of as observableOf, Observable } from 'rxjs'; - -import {distinctUntilChanged, debounceTime, takeUntil } from 'rxjs/operators'; import { SelectionModel } from '@angular/cdk/collections'; import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { FormControl } from '@angular/forms'; import { MatListOption, MatSelectionList } from '@angular/material/list'; -import { BaseComponent } from '../../../../core/common/base/base.component'; +import { BaseComponent } from '@common/base/base.component'; +import { Observable, of as observableOf } from 'rxjs'; +import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; + @Component({ selector: 'app-explore-dataset-filter-item-component', @@ -53,7 +53,7 @@ export class ExploreDatasetFilterItemComponent extends BaseComponent implements ngOnInit(): void { if (!this.multipleSelect) { this.selectionList.selectedOptions = new SelectionModel(this.multipleSelect); } this.optionSearchControl.valueChanges.pipe(debounceTime(this.requestDelay), - distinctUntilChanged(),) + distinctUntilChanged()) .pipe(takeUntil(this._destroyed)) .subscribe(x => { if (this.filterOptions) { this.options = this.filterOptions(x); } }); } diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html index 3684f2955..01769decb 100644 --- a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.html @@ -23,7 +23,6 @@ - arrow_drop_down
@@ -32,7 +31,6 @@ - arrow_drop_down
@@ -41,7 +39,6 @@ - arrow_drop_down
@@ -59,7 +56,6 @@ - arrow_drop_down
diff --git a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts index 2a2fd6880..084a35f7f 100644 --- a/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts +++ b/dmp-frontend/src/app/ui/explore-dataset/filters/explore-dataset-filters.component.ts @@ -1,34 +1,34 @@ -import { of as observableOf, Observable } from 'rxjs'; - -import { map } from 'rxjs/operators'; import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { MatAccordion } from '@angular/material/expansion'; import { ActivatedRoute } from '@angular/router'; +import { GrantStateType } from '@app/core/common/enum/grant-state-type'; +import { DataTableData } from '@app/core/model/data-table/data-table-data'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { DmpListingModel } from '@app/core/model/dmp/dmp-listing'; +import { ExternalSourceItemModel } from '@app/core/model/external-sources/external-source-item'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { OrganizationModel } from '@app/core/model/organisation/organization'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { ExploreDatasetCriteriaModel } from '@app/core/query/explore-dataset/explore-dataset-criteria'; +import { ExploreDmpCriteriaModel } from '@app/core/query/explore-dmp/explore-dmp-criteria'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { OrganisationCriteria } from '@app/core/query/organisation/organisation-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { TagCriteria } from '@app/core/query/tag/tag-criteria'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { OrganisationService } from '@app/core/services/organisation/organisation.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { GrantStateType } from '../../../core/common/enum/grant-state-type'; -import { DatasetProfileModel } from '../../../core/model/dataset/dataset-profile'; -import { ExternalSourceItemModel } from '../../../core/model/external-sources/external-source-item'; -import { GrantListingModel } from '../../../core/model/grant/grant-listing'; -import { ExploreDatasetCriteriaModel } from '../../../core/query/explore-dataset/explore-dataset-criteria'; -import { GrantCriteria } from '../../../core/query/grant/grant-criteria'; -import { TagCriteria } from '../../../core/query/tag/tag-criteria'; -import { DatasetService } from '../../../core/services/dataset/dataset.service'; -import { ExternalSourcesService } from '../../../core/services/external-sources/external-sources.service'; -import { GrantService } from '../../../core/services/grant/grant.service'; -import { RequestItem } from '../../../core/query/request-item'; -import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; -import { MultipleAutoCompleteConfiguration } from '../../../library/auto-complete/multiple/multiple-auto-complete-configuration'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { OrganisationCriteria } from '../../../core/query/organisation/organisation-criteria'; -import { OrganisationService } from '../../../core/services/organisation/organisation.service'; -import { OrganizationModel } from '../../../core/model/organisation/organization'; -import { DataTableData } from '../../../core/model/data-table/data-table-data'; -import { DmpListingModel } from '../../../core/model/dmp/dmp-listing'; -import { ExploreDmpCriteriaModel } from '../../../core/query/explore-dmp/explore-dmp-criteria'; -import { DatasetProfileCriteria } from "../../../core/query/dataset-profile/dataset-profile-criteria"; -import { AuthService } from '../../../core/services/auth/auth.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; + @Component({ selector: 'app-explore-dataset-filters-component', @@ -65,7 +65,7 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI 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))), + initialItems: (excludedItems: any[]) => this.filterTags('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] }; @@ -81,7 +81,7 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI filterFn: this.filterGrant.bind(this), initialItems: (excludedItems: any[]) => this.filterGrant('').pipe( - map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'] } @@ -90,7 +90,7 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI filterFn: this.filterProfile.bind(this), initialItems: (excludedItems: any[]) => this.filterProfile('').pipe( - map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'] }; @@ -99,7 +99,7 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI filterFn: this.filterOrganisation.bind(this), initialItems: (excludedItems: any[]) => this.getOrganisations().pipe( - map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] } @@ -254,9 +254,8 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI this.facetCriteriaChange.emit(this.facetCriteria); } - onGrantOptionSelected(items: GrantListingModel[]) { - this.facetCriteria.grants.splice(0); - this.facetCriteria.grants.push(...items.map(x => x.id)); + onGrantOptionSelected(item: GrantListingModel) { + this.facetCriteria.grants.push(item.id); this.facetCriteriaChange.emit(this.facetCriteria); } @@ -268,9 +267,8 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI } } - onDmpOptionSelected(items: DmpListingModel[]) { - this.facetCriteria.dmpIds.splice(0); - this.facetCriteria.dmpIds.push(...items.map(x => x.id)); + onDmpOptionSelected(item: DmpListingModel) { + this.facetCriteria.dmpIds.push(item.id); this.facetCriteriaChange.emit(this.facetCriteria); } @@ -282,9 +280,8 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI } } - onProfileOptionSelected(items: DatasetProfileModel[]) { - this.facetCriteria.datasetProfile.splice(0); - this.facetCriteria.datasetProfile.push(...items.map(x => x.id)); + onProfileOptionSelected(item: DatasetProfileModel) { + this.facetCriteria.datasetProfile.push(item.id); this.facetCriteriaChange.emit(this.facetCriteria); } @@ -296,9 +293,8 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI } } - onOrganizationOptionSelected(items: OrganizationModel[]) { - this.facetCriteria.dmpOrganisations.splice(0); - this.facetCriteria.dmpOrganisations.push(...items.map(x => x.id)); + onOrganizationOptionSelected(item: OrganizationModel) { + this.facetCriteria.dmpOrganisations.push(item.id); this.facetCriteriaChange.emit(this.facetCriteria); } @@ -314,7 +310,7 @@ export class ExploreDatasetFiltersComponent extends BaseComponent implements OnI const fields: Array = new Array(); fields.push('-finalizedAt'); const dmpDataTableRequest: DataTableRequest = new DataTableRequest(0, null, { fields: fields }); - dmpDataTableRequest.criteria = new ExploreDatasetCriteriaModel(); + dmpDataTableRequest.criteria = new ExploreDmpCriteriaModel(); dmpDataTableRequest.criteria.like = value; return this.dmpService.getPublicPaged(dmpDataTableRequest, "autocomplete") } diff --git a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filter-item/explore-dmp-filter-item.component.ts b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filter-item/explore-dmp-filter-item.component.ts index 5b706d5e4..f18a44f34 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filter-item/explore-dmp-filter-item.component.ts +++ b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filter-item/explore-dmp-filter-item.component.ts @@ -1,12 +1,12 @@ -import {of as observableOf, Observable } from 'rxjs'; - -import {distinctUntilChanged, debounceTime, takeUntil } from 'rxjs/operators'; import { SelectionModel } from '@angular/cdk/collections'; import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { FormControl } from '@angular/forms'; import { MatListOption, MatSelectionList } from '@angular/material/list'; -import { BaseComponent } from '../../../../core/common/base/base.component'; +import { BaseComponent } from '@common/base/base.component'; +import { Observable, of as observableOf } from 'rxjs'; +import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; + @Component({ selector: 'app-explore-dmp-filter-item-component', @@ -44,7 +44,7 @@ export class ExploreDmpFilterItemComponent extends BaseComponent implements OnIn ngOnInit(): void { if (!this.multipleSelect) { this.selectionList.selectedOptions = new SelectionModel(this.multipleSelect); } this.optionSearchControl.valueChanges.pipe(debounceTime(this.requestDelay), - distinctUntilChanged(),) + distinctUntilChanged()) .pipe(takeUntil(this._destroyed)) .subscribe(x => { if (this.filterOptions) { this.options = this.filterOptions(x); } }); } diff --git a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.html b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.html index 9ae8fe5d3..d7a2e6ce6 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.html +++ b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.html @@ -27,7 +27,6 @@ - arrow_drop_down
@@ -36,7 +35,6 @@ - arrow_drop_down
@@ -60,7 +58,6 @@ - arrow_drop_down diff --git a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.ts b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.ts index 73c4f8048..99917f0e4 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.ts +++ b/dmp-frontend/src/app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component.ts @@ -1,29 +1,29 @@ -import { of as observableOf, Observable } from 'rxjs'; - -import { map } from 'rxjs/operators'; import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild } from "@angular/core"; import { MatAccordion } from "@angular/material/expansion"; import { ActivatedRoute } from "@angular/router"; +import { GrantStateType } from '@app/core/common/enum/grant-state-type'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { OrganizationModel } from '@app/core/model/organisation/organization'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { ExploreDmpCriteriaModel } from '@app/core/query/explore-dmp/explore-dmp-criteria'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { OrganisationCriteria } from '@app/core/query/organisation/organisation-criteria'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { OrganisationService } from '@app/core/services/organisation/organisation.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from "@ngx-translate/core"; -import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; -import { GrantStateType } from '../../../core/common/enum/grant-state-type'; -import { DataTableRequest } from "../../../core/model/data-table/data-table-request"; -import { DatasetProfileModel } from "../../../core/model/dataset/dataset-profile"; -import { GrantListingModel } from "../../../core/model/grant/grant-listing"; -import { ExploreDmpCriteriaModel } from "../../../core/query/explore-dmp/explore-dmp-criteria"; -import { GrantCriteria } from "../../../core/query/grant/grant-criteria"; -import { DatasetService } from "../../../core/services/dataset/dataset.service"; -import { DmpService } from "../../../core/services/dmp/dmp.service"; -import { ExternalSourcesService } from "../../../core/services/external-sources/external-sources.service"; -import { GrantService } from "../../../core/services/grant/grant.service"; -import { MultipleAutoCompleteConfiguration } from "../../../library/auto-complete/multiple/multiple-auto-complete-configuration"; -import { BaseCriteriaComponent } from "../../misc/criteria/base-criteria.component"; -import { OrganizationModel } from "../../../core/model/organisation/organization"; -import { OrganisationCriteria } from "../../../core/query/organisation/organisation-criteria"; -import { OrganisationService } from "../../../core/services/organisation/organisation.service"; -import { DatasetProfileCriteria } from "../../../core/query/dataset-profile/dataset-profile-criteria"; -import { AuthService } from '../../../core/services/auth/auth.service'; +import { Observable, of as observableOf } from 'rxjs'; +import { map } from 'rxjs/operators'; + @Component({ selector: 'app-explore-dmp-filters-component', @@ -69,7 +69,7 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements filterFn: this.filterProfile.bind(this), initialItems: (excludedItems: any[]) => this.filterProfile('').pipe( - map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'] }; @@ -78,7 +78,7 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements filterFn: this.filterOrganisation.bind(this), initialItems: (excludedItems: any[]) => this.getOrganisations().pipe( - map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['name'], titleFn: (item) => item['name'] } @@ -87,7 +87,7 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements filterFn: this.filterGrant.bind(this), initialItems: (excludedItems: any[]) => this.filterGrant('').pipe( - map(result => result.filter(resultItem => excludedItems.map(x => x.id).indexOf(resultItem.id) === -1))), + map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), displayFn: (item) => item['label'], titleFn: (item) => item['label'] } @@ -197,9 +197,9 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements this.facetCriteriaChange.emit(this.facetCriteria); } - onProfileOptionSelected(items: DatasetProfileModel[]) { - this.facetCriteria.datasetProfile.splice(0); - this.facetCriteria.datasetProfile.push(...items.map(x => x.id)); + onProfileOptionSelected(items: DatasetProfileModel) { + //this.facetCriteria.datasetProfile.splice(0); + this.facetCriteria.datasetProfile.push(items.id); this.facetCriteriaChange.emit(this.facetCriteria); } @@ -228,9 +228,8 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements this.facetCriteriaChange.emit(this.facetCriteria); } - onOrganizationOptionSelected(items: OrganizationModel[]) { - this.facetCriteria.dmpOrganisations.splice(0); - this.facetCriteria.dmpOrganisations.push(...items.map(x => x.id)); + onOrganizationOptionSelected(item: OrganizationModel) { + this.facetCriteria.dmpOrganisations.push(item.id); this.facetCriteriaChange.emit(this.facetCriteria); } @@ -242,9 +241,8 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements } } - onGrantOptionSelected(items: GrantListingModel[]) { - this.facetCriteria.grants.splice(0); - this.facetCriteria.grants.push(...items.map(x => x.id)); + onGrantOptionSelected(item: GrantListingModel) { + this.facetCriteria.grants.push(item.id); this.facetCriteriaChange.emit(this.facetCriteria); } diff --git a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.html b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.html index 394cdf4b5..1652e34fe 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.html +++ b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.html @@ -10,7 +10,14 @@

{{'DMP-LISTING.TITLE' | translate}}

- +
+ + {{'DMP-LISTING.VIEW-ALL-VERSIONS' | translate}} + + + {{this.groupLabel}} + +
diff --git a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.scss b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.scss index d56c694f6..fa94d00e3 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.scss +++ b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.scss @@ -76,3 +76,11 @@ text-center { ::ng-deep .mat-paginator-navigation-previous { margin-left: auto !important; } + +.all-versions { + color: #999999 !important; +} + +.dmp-label { + color: #089dbb !important; +} diff --git a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.ts b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.ts index b9b735336..9ca409955 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.ts +++ b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp-listing.component.ts @@ -1,18 +1,18 @@ -import { of as observableOf, Observable } from 'rxjs'; import { Component, OnInit, ViewChild } from "@angular/core"; import { MatPaginator } from "@angular/material/paginator"; import { MatSort } from "@angular/material/sort"; -import { Router, ActivatedRoute } from "@angular/router"; -import { takeUntil } from "rxjs/operators"; -import { BaseComponent } from "../../core/common/base/base.component"; -import { DataTableRequest } from "../../core/model/data-table/data-table-request"; -import { DmpListingModel } from "../../core/model/dmp/dmp-listing"; -import { ExploreDmpCriteriaModel } from "../../core/query/explore-dmp/explore-dmp-criteria"; -import { DmpService } from "../../core/services/dmp/dmp.service"; -import { IBreadCrumbComponent } from "../misc/breadcrumb/definition/IBreadCrumbComponent"; -import { BreadcrumbItem } from "../misc/breadcrumb/definition/breadcrumb-item"; -import { TranslateService } from "@ngx-translate/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DmpListingModel } from '@app/core/model/dmp/dmp-listing'; +import { ExploreDmpCriteriaModel } from '@app/core/query/explore-dmp/explore-dmp-criteria'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseComponent } from '@common/base/base.component'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable, of as observableOf } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-explore-dmp-listing-component', @@ -24,12 +24,15 @@ export class ExploreDmpListingComponent extends BaseComponent implements OnInit, @ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator; sort = new MatSort(); - exploreDmpCriteriaModel: ExploreDmpCriteriaModel; + exploreDmpCriteriaModel: ExploreDmpCriteriaModel = new ExploreDmpCriteriaModel(); titlePrefix: string; totalCount: number; listingItems: DmpListingModel[] = []; breadCrumbs: Observable; linkToDmpId: string; + groupId: string; + allVersions: boolean = false; + groupLabel: string; constructor( private dmpService: DmpService, @@ -43,15 +46,32 @@ export class ExploreDmpListingComponent extends BaseComponent implements OnInit, } ngOnInit() { - this.refresh(); + this.route.params + .pipe(takeUntil(this._destroyed)) + .subscribe(params => { + if (params['groupId']) { + this.groupId = params['groupId']; + this.exploreDmpCriteriaModel.groupIds.push(this.groupId); + this.exploreDmpCriteriaModel.allVersions = true; + this.allVersions = true; + this.route.queryParams + .pipe(takeUntil(this._destroyed)) + .subscribe(queryParams => { + if (queryParams["groupLabel"]) { + this.groupLabel = queryParams["groupLabel"]; + } + }) + } - const breadCrumbs = []; - breadCrumbs.push({ - parentComponentName: null, - label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), - url: "/explore-plans" - }) - this.breadCrumbs = observableOf(breadCrumbs); + this.refresh(); + const breadCrumbs = []; + breadCrumbs.push({ + parentComponentName: null, + label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), + url: "/explore-plans" + }) + this.breadCrumbs = observableOf(breadCrumbs); + }) } refresh() { @@ -76,6 +96,8 @@ export class ExploreDmpListingComponent extends BaseComponent implements OnInit, onCriteriaChange(event: ExploreDmpCriteriaModel) { this.exploreDmpCriteriaModel = event; + if (this.allVersions == true) this.exploreDmpCriteriaModel.allVersions = this.allVersions; + if (this.groupId) this.exploreDmpCriteriaModel.groupIds.push(this.groupId); this._paginator.pageIndex = 0; this.refresh(); } diff --git a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.module.ts b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.module.ts index d5b211fd8..51046c470 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.module.ts +++ b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.module.ts @@ -1,13 +1,13 @@ import { NgModule } from "@angular/core"; -import { CommonFormsModule } from "../../common/forms/common-forms.module"; -import { CommonUiModule } from "../../common/ui/common-ui.module"; -import { AutoCompleteModule } from "../../library/auto-complete/auto-complete.module"; -import { ExploreDmpFilterItemComponent } from "./dmp-explore-filters/explore-dmp-filter-item/explore-dmp-filter-item.component"; -import { ExploreDmpFiltersComponent } from "./dmp-explore-filters/explore-dmp-filters.component"; -import { ExploreDmpListingComponent } from "./explore-dmp-listing.component"; -import { ExploreDmpRoutingModule } from "./explore-dmp.routing"; -import { ExploreDmpListingItemComponent } from "./listing-item/explore-dmp-listing-item.component"; -import { DmpOverviewModule } from "../dmp/overview/dmp-overview.module"; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; +import { DmpOverviewModule } from '@app/ui/dmp/overview/dmp-overview.module'; +import { ExploreDmpFilterItemComponent } from '@app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filter-item/explore-dmp-filter-item.component'; +import { ExploreDmpFiltersComponent } from '@app/ui/explore-dmp/dmp-explore-filters/explore-dmp-filters.component'; +import { ExploreDmpListingComponent } from '@app/ui/explore-dmp/explore-dmp-listing.component'; +import { ExploreDmpRoutingModule } from '@app/ui/explore-dmp/explore-dmp.routing'; +import { ExploreDmpListingItemComponent } from '@app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.routing.ts b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.routing.ts index 6b5ad0cb9..4918a250d 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.routing.ts +++ b/dmp-frontend/src/app/ui/explore-dmp/explore-dmp.routing.ts @@ -11,6 +11,13 @@ const routes: Routes = [ breadcrumb: true } }, + { + path: 'versions/:groupId', + component: ExploreDmpListingComponent, + data: { + breadcrumb: true + }, + }, { path: 'overview/:publicId', component: DmpOverviewComponent, diff --git a/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.html b/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.html index 1668731ed..407534416 100644 --- a/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.html +++ b/dmp-frontend/src/app/ui/explore-dmp/listing-item/explore-dmp-listing-item.component.html @@ -1,5 +1,5 @@
- +
@@ -22,6 +22,9 @@

{{dmp.description}}

+
+

{{'DMP-LISTING.COLUMNS.VERSION' | translate}} : {{dmp.version}}

+
diff --git a/dmp-frontend/src/app/ui/faq/faq.module.ts b/dmp-frontend/src/app/ui/faq/faq.module.ts index 654c43b93..71b795ed3 100644 --- a/dmp-frontend/src/app/ui/faq/faq.module.ts +++ b/dmp-frontend/src/app/ui/faq/faq.module.ts @@ -1,8 +1,8 @@ import { NgModule } from '@angular/core'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { FaqRoutingModule } from './faq.routing'; +import { CommonUiModule } from '@common/ui/common-ui.module'; import { FaqDialogComponent } from './dialog/faq-dialog.component'; import { FaqContentComponent } from './faq-content/faq-content.component'; +import { FaqRoutingModule } from './faq.routing'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/glossary/glossary.module.ts b/dmp-frontend/src/app/ui/glossary/glossary.module.ts index 07cf5d1a6..c84ed0310 100644 --- a/dmp-frontend/src/app/ui/glossary/glossary.module.ts +++ b/dmp-frontend/src/app/ui/glossary/glossary.module.ts @@ -1,8 +1,8 @@ import { NgModule } from '@angular/core'; -import { GlossaryRoutingModule } from './glossary.routing'; -import { GlossaryContentComponent } from './glossary-content/glossary-content.component'; +import { CommonUiModule } from '@common/ui/common-ui.module'; import { GlossaryDialogComponent } from './dialog/glossary-dialog.component'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { GlossaryContentComponent } from './glossary-content/glossary-content.component'; +import { GlossaryRoutingModule } from './glossary.routing'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/grant/editor/grant-editor.component.ts b/dmp-frontend/src/app/ui/grant/editor/grant-editor.component.ts index 6011e48a9..428cf5a1d 100644 --- a/dmp-frontend/src/app/ui/grant/editor/grant-editor.component.ts +++ b/dmp-frontend/src/app/ui/grant/editor/grant-editor.component.ts @@ -1,25 +1,26 @@ -import {of as observableOf, Observable } from 'rxjs'; - -import {map, takeUntil } from 'rxjs/operators'; import { Component, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { GrantType } from '@app/core/common/enum/grant-type'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { GrantFileUploadService } from '@app/core/services/grant/grant-file-upload.service'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { GrantEditorModel } from '@app/ui/grant/editor/grant-editor.model'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { TranslateService } from '@ngx-translate/core'; -import { environment } from '../../../../environments/environment'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { GrantType } from '../../../core/common/enum/grant-type'; -import { GrantListingModel } from '../../../core/model/grant/grant-listing'; -import { GrantFileUploadService } from '../../../core/services/grant/grant-file-upload.service'; -import { GrantService } from '../../../core/services/grant/grant.service'; -import { ConfirmationDialogComponent } from '../../../library/confirmation-dialog/confirmation-dialog.component'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { GrantEditorModel } from './grant-editor.model'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; +import { environment } from 'environments/environment'; +import { Observable, of as observableOf } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; + @Component({ selector: 'app-grant-editor-component', @@ -44,7 +45,8 @@ export class GrantEditorComponent extends BaseComponent implements OnInit, IBrea public language: TranslateService, private dialog: MatDialog, private grantFileUploadService: GrantFileUploadService, - private uiNotificationService: UiNotificationService + private uiNotificationService: UiNotificationService, + private formService: FormService ) { super(); } @@ -100,7 +102,7 @@ export class GrantEditorComponent extends BaseComponent implements OnInit, IBrea } formSubmit(): void { - this.touchAllFormFields(this.formGroup); + this.formService.touchAllFormFields(this.formGroup); if (!this.isFormValid()) { return; } this.onSubmit(); } @@ -125,7 +127,7 @@ export class GrantEditorComponent extends BaseComponent implements OnInit, IBrea onCallbackError(errorResponse: any) { this.setErrorModel(errorResponse.error.payload); - this.validateAllFormFields(this.formGroup); + this.formService.validateAllFormFields(this.formGroup); } public setErrorModel(validationErrorModel: ValidationErrorModel) { @@ -161,36 +163,6 @@ export class GrantEditorComponent extends BaseComponent implements OnInit, IBrea }); } - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - public enableForm() { if (!this.isExternalGrant()) { this.editMode = true; diff --git a/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts b/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts index 13128fb8f..8b783111c 100644 --- a/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts +++ b/dmp-frontend/src/app/ui/grant/editor/grant-editor.model.ts @@ -1,7 +1,7 @@ -import { FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms'; -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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +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 { GrantType } from '../../../core/common/enum/grant-type'; import { Status } from '../../../core/common/enum/Status'; import { ContentFile, GrantListingModel } from '../../../core/model/grant/grant-listing'; @@ -51,7 +51,7 @@ export class GrantEditorModel { startDate: [{ value: this.startDate, disabled: disabled }, context.getValidation('startDate').validators], endDate: [{ value: this.endDate, disabled: disabled }, context.getValidation('endDate').validators], files: [{ value: this.files, disabled: disabled }, context.getValidation('files').validators] - },{ validator: startEndValidator }); + }, { validator: startEndValidator }); return formGroup; } @@ -76,9 +76,8 @@ export class GrantEditorModel { export function startEndValidator(formGroup: FormGroup) { const start = formGroup.get('startDate').value; const end = formGroup.get('endDate').value; - if(start!=null && end != null && end + +
+ +
+ +
+ + {{key}} : + + +
+
+
+ +
+ + +
diff --git a/dmp-frontend/src/app/ui/language-editor/language-editor.component.scss b/dmp-frontend/src/app/ui/language-editor/language-editor.component.scss new file mode 100644 index 000000000..39e04d644 --- /dev/null +++ b/dmp-frontend/src/app/ui/language-editor/language-editor.component.scss @@ -0,0 +1,17 @@ +.language-editor { + padding-top: 5em; + padding-bottom: 2em; + + .language-area { + box-sizing: content-box; + } + + .save-btn { + padding-top: inherit !important; + top: auto !important; + width: 56px !important; + bottom: 10px; + position: fixed; + right: 10px; + } +} diff --git a/dmp-frontend/src/app/ui/language-editor/language-editor.component.ts b/dmp-frontend/src/app/ui/language-editor/language-editor.component.ts new file mode 100644 index 000000000..68050e652 --- /dev/null +++ b/dmp-frontend/src/app/ui/language-editor/language-editor.component.ts @@ -0,0 +1,91 @@ +import { Component, OnInit } from '@angular/core'; +import { LanguageService } from '@app/core/services/language/language.service'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-language-editor', + templateUrl: './language-editor.component.html', + styleUrls: ['./language-editor.component.scss'] +}) +export class LanguageEditorComponent extends BaseComponent implements OnInit { + keys = []; + parseFinished = false; + currentLang: string; + formGroup: FormGroup; + formBuilder: FormBuilder; + + constructor( + private language: LanguageService, + private uiNotificationService: UiNotificationService, + private translate: TranslateService, + private router: Router, + ) { super(); } + + ngOnInit() { + this.formBuilder = new FormBuilder(); + this.formGroup = this.formBuilder.group({}); + this.language.getCurrentLanguageJSON() + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/json' }); + this.convertBlobToJSON(blob); + + }); + } + + convertBlobToJSON(blob: Blob) { + const fr = new FileReader(); + fr.onload = ev => { + const langObj = JSON.parse(fr.result as string); + this.convertObjectToForm(langObj, '', this.formGroup); + this.currentLang = this.language.getCurrentLanguageName(); + this.parseFinished = true; + }; + fr.readAsText(blob); + } + + convertObjectToForm(obj: any, parentKey: string, form: FormGroup) { + for (let prop in obj) { + const key = parentKey !== '' ? `${parentKey}.${prop}` : prop; + if (typeof obj[prop] === 'object') { + form.addControl(prop, this.formBuilder.group({})); + this.convertObjectToForm(obj[prop], key, form.get(prop) as FormGroup); + continue; + } else { + form.addControl(prop, this.formBuilder.control(obj[prop])); + this.keys.push(key); + } + } + return; + } + + updateLang() { + const json = JSON.stringify(this.formGroup.value); + this.language.updateLanguage(json).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => { + this.onCallbackSuccess(complete); + }, + error => { + this.onCallbackError(error); + } + ); + + } + + onCallbackSuccess(id?: String): void { + this.uiNotificationService.snackBarNotification( this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); + this.router.navigate(['/reload']).then(() => this.router.navigate(['/language-editor'])); +} + +onCallbackError(error: any) { + this.uiNotificationService.snackBarNotification( error, SnackBarNotificationLevel.Error); + //this.validateAllFormFields(this.formGroup); +} + +} diff --git a/dmp-frontend/src/app/ui/language-editor/language-editor.module.ts b/dmp-frontend/src/app/ui/language-editor/language-editor.module.ts new file mode 100644 index 000000000..ff38b4929 --- /dev/null +++ b/dmp-frontend/src/app/ui/language-editor/language-editor.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { LanguageEditorComponent } from './language-editor.component'; +import { LanguageEditorRoutingModule } from './language-editor.routing'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; + + + +@NgModule({ + declarations: [LanguageEditorComponent], + imports: [ + CommonUiModule, + CommonFormsModule, + ConfirmationDialogModule, + LanguageEditorRoutingModule + ] +}) +export class LanguageEditorModule { } diff --git a/dmp-frontend/src/app/ui/language-editor/language-editor.routing.ts b/dmp-frontend/src/app/ui/language-editor/language-editor.routing.ts new file mode 100644 index 000000000..423d8dd32 --- /dev/null +++ b/dmp-frontend/src/app/ui/language-editor/language-editor.routing.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { LanguageEditorComponent } from './language-editor.component'; + +const routes: Routes = [ + { path: '', component: LanguageEditorComponent }, + // { path: ':id', component: UserProfileComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class LanguageEditorRoutingModule { } diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts index 380baae34..ef0517c0b 100644 --- a/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/breadcrumb.module.ts @@ -1,8 +1,8 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { CommonUiModule } from '../../../common/ui/common-ui.module'; -import { BreadcrumbComponent } from './breadcrumb.component'; -import { BreadCrumbResolverService } from './service/breadcrumb.service'; +import { BreadcrumbComponent } from '@app/ui/misc/breadcrumb/breadcrumb.component'; +import { BreadCrumbResolverService } from '@app/ui/misc/breadcrumb/service/breadcrumb.service'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts b/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts index 184a50a6a..659234653 100644 --- a/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts +++ b/dmp-frontend/src/app/ui/misc/breadcrumb/service/breadcrumb.service.ts @@ -1,11 +1,11 @@ -import {of as observableOf, Observable } from 'rxjs'; import { Injectable, NgZone } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseService } from '@common/base/base.service'; +import { Observable, of as observableOf } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { BaseService } from '../../../../core/common/base/base.service'; -import { BreadcrumbItem } from '../definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../definition/IBreadCrumbComponent'; @Injectable() export class BreadCrumbResolverService extends BaseService { diff --git a/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts b/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts index bfbbe53c6..c40532065 100644 --- a/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts +++ b/dmp-frontend/src/app/ui/misc/criteria/base-criteria.component.ts @@ -1,7 +1,7 @@ import { OnInit } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from '../../../core/common/base/base.component'; +import { BaseComponent } from '@common/base/base.component'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; export class BaseCriteriaComponent extends BaseComponent implements OnInit { diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html index b39bd663d..9db8790c0 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-field/form-field.component.html @@ -19,7 +19,7 @@
+ [configuration]="multipleAutoCompleteConfiguration">
@@ -47,7 +47,7 @@
+ [configuration]="multipleAutoCompleteConfiguration">
@@ -62,7 +62,7 @@
+ [configuration]="multipleAutoCompleteConfiguration">
@@ -77,7 +77,7 @@
+ [configuration]="multipleAutoCompleteConfiguration">
@@ -98,7 +98,7 @@
-
--> + + +
+ + + + +
+
diff --git a/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.scss b/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.scss index e69de29bb..3d2ff8cf7 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.scss +++ b/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.scss @@ -0,0 +1,10 @@ +.toc-pane-container { + &.is-sticky~.nav-spacer { + height: 500px; // the container size } + // height: calc(100vh - 100px); // the container size } + } +} + +.is-sticky { + margin-top: 70px !important; +} diff --git a/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.ts b/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.ts index 72f746bb5..e1684f122 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component.ts @@ -1,14 +1,15 @@ import { Component, Input, OnInit } from "@angular/core"; import { FormArray, FormGroup } from "@angular/forms"; +import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model'; +import { QuickWizardDatasetDescriptionModel } from '@app/ui/quick-wizard/dataset-editor/quick-wizard-dataset-description-model'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from "@ngx-translate/core"; import { Observable } from "rxjs"; import { takeUntil } from "rxjs/operators"; -import { BaseComponent } from "../../../core/common/base/base.component"; -import { DatasetWizardService } from "../../../core/services/dataset-wizard/dataset-wizard.service"; -import { BreadcrumbItem } from "../../misc/breadcrumb/definition/breadcrumb-item"; -import { IBreadCrumbComponent } from "../../misc/breadcrumb/definition/IBreadCrumbComponent"; -import { DatasetDescriptionFormEditorModel } from "../../misc/dataset-description-form/dataset-description-form.model"; -import { QuickWizardDatasetDescriptionModel } from "./quick-wizard-dataset-description-model"; +import { LinkToScroll } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents'; @Component({ selector: 'app-dataset-editor-wizard-component', @@ -122,4 +123,9 @@ export class DatasetEditorWizardComponent extends BaseComponent implements OnIni window.scrollTo(0, 0); } } + + linkToScroll: LinkToScroll; + onStepFound(linkToScroll: LinkToScroll) { + this.linkToScroll = linkToScroll; + } } diff --git a/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts b/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts index 8da1d888f..fa213f870 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard-model.ts @@ -1,17 +1,18 @@ -import { Status } from "../../../core/common/enum/Status"; -import { DmpProfile, DmpProfileDefinition } from "../../../core/model/dmp-profile/dmp-profile"; -import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; -import { DmpModel } from "../../../core/model/dmp/dmp"; -import { ValidationContext } from "../../../common/forms/validation/validation-context"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { BackendErrorValidator } from "../../../common/forms/validation/custom-validator"; -import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator"; -import { DatasetProfileModel } from "../../../core/model/dataset/dataset-profile"; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Status } from '@app/core/common/enum/Status'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { DmpProfileDefinition } from '@app/core/model/dmp-profile/dmp-profile'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; +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 { DmpStatus } from '@app/core/common/enum/dmp-status'; export class DmpEditorWizardModel { public id: string; public label: string; - public status: Status = Status.Active; + public status: DmpStatus = DmpStatus.Draft; public description: String; public datasetProfile: DatasetProfileModel; public definition: DmpProfileDefinition; diff --git a/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard.component.ts b/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard.component.ts index 7f4fbea97..99d898a15 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard.component.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/dmp-editor/dmp-editor-wizard.component.ts @@ -1,20 +1,21 @@ -import {of as observableOf, Observable } from 'rxjs'; import { Component, Input, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { FormArray, FormGroup } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute, Router } from '@angular/router'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from "../../../core/common/base/base.component"; -import { DatasetProfileModel } from '../../../core/model/dataset/dataset-profile'; -import { DatasetProfileCriteria } from '../../../core/query/dataset-profile/dataset-profile-criteria'; -import { RequestItem } from '../../../core/query/request-item'; -import { DmpService } from '../../../core/services/dmp/dmp.service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; +import { Observable, of as observableOf } from 'rxjs'; import { DmpEditorWizardModel } from './dmp-editor-wizard-model'; @@ -44,7 +45,8 @@ export class DmpEditorWizardComponent extends BaseComponent implements OnInit, I public router: Router, private route: ActivatedRoute, private _service: DmpService, - public language: TranslateService + public language: TranslateService, + private formService: FormService ) { super(); } @@ -74,7 +76,7 @@ export class DmpEditorWizardComponent extends BaseComponent implements OnInit, I } formSubmit(): void { - this.touchAllFormFields(this.formGroup); + this.formService.touchAllFormFields(this.formGroup); if (!this.isFormValid()) { return; } this.onSubmit(); } @@ -83,21 +85,6 @@ export class DmpEditorWizardComponent extends BaseComponent implements OnInit, I return this.formGroup.valid; } - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - onSubmit(): void { // this.grantService.createGrant(this.formGroup.value) // .pipe(takeUntil(this._destroyed)) @@ -115,7 +102,7 @@ export class DmpEditorWizardComponent extends BaseComponent implements OnInit, I onCallbackError(errorResponse: any) { this.setErrorModel(errorResponse.error.payload); - this.validateAllFormFields(this.formGroup); + this.formService.validateAllFormFields(this.formGroup); } public setErrorModel(validationErrorModel: ValidationErrorModel) { @@ -124,21 +111,6 @@ export class DmpEditorWizardComponent extends BaseComponent implements OnInit, I }); } - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - filterProfiles(value: string): Observable { this.filteredProfiles = undefined; diff --git a/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.html b/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.html index b4606ff50..80acc2f60 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.html +++ b/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.html @@ -6,20 +6,19 @@

{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.FIRST-STEP.ABOUT-FUNDER' | translate}}

- + {{'DMP-EDITOR.FIELDS.EXTERNAL-SOURCE-HINT' | translate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}

{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.FIRST-STEP.ABOUT-NEW-FUNDER' | translate}}

- - - {{funderFormGroup.get('label').getError('backendError').message}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{funderFormGroup.get('label').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.ts b/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.ts index 45334e50a..9f0de44d1 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/funder-editor/funder-editor-wizard.component.ts @@ -1,11 +1,12 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; -import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; -import { FunderService } from '../../../core/services/funder/funder.service'; -import { RequestItem } from '../../../core/query/request-item'; -import { FunderCriteria } from '../../../core/query/funder/funder-criteria'; -import { FunderFormModel } from '../../dmp/editor/grant-tab/funder-form-model'; +import { FunderModel } from '@app/core/model/funder/funder'; import { TranslateService } from '@ngx-translate/core'; +import { FunderCriteria } from '../../../core/query/funder/funder-criteria'; +import { RequestItem } from '../../../core/query/request-item'; +import { FunderService } from '../../../core/services/funder/funder.service'; +import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; +import { FunderFormModel } from '../../dmp/editor/grant-tab/funder-form-model'; @Component({ selector: 'app-quick-wizard-funder-editor-component', @@ -18,7 +19,6 @@ export class FunderEditorWizardComponent implements OnInit { funder: FunderFormModel; funderLabelCleared = true; @Input() funderFormGroup: FormGroup; - @Input() grantformGroup: FormGroup; funderAutoCompleteConfiguration: SingleAutoCompleteConfiguration; constructor( @@ -33,7 +33,7 @@ export class FunderEditorWizardComponent implements OnInit { initialItems: (extraData) => this.searchFunder(''), displayFn: (item) => item['label'], titleFn: (item) => item['label'], - subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') + subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) }; if (!this.funderFormGroup) { @@ -55,51 +55,13 @@ export class FunderEditorWizardComponent implements OnInit { create() { this.isNew = !this.isNew; if (this.isNew) { - this.funderFormGroup.get('existFunder').disable(); this.funderFormGroup.get('existFunder').reset(); + this.funderFormGroup.get('existFunder').disable(); this.funderFormGroup.get('label').enable(); } else { - this.funderFormGroup.get('existFunder').enable(); - this.funderFormGroup.get('label').disable(); this.funderFormGroup.get('label').reset(); + this.funderFormGroup.get('label').disable(); + this.funderFormGroup.get('existFunder').enable(); } } - - onFunderSelected() { - if (this.grantformGroup.get('existGrant').disabled) { - this.grantformGroup.get('existGrant').enable(); - this.grantformGroup.get('label').disable(); - this.grantformGroup.get('description').disable(); - } else { - this.grantformGroup.get('existGrant').disable(); - this.grantformGroup.get('label').enable(); - this.grantformGroup.get('description').enable(); - } - } - - onFunderRemoved() { - if (this.grantformGroup.get('existGrant').enabled) { - this.grantformGroup.get('existGrant').disable(); - this.grantformGroup.get('existGrant').reset(); - this.grantformGroup.get('label').enable(); - this.grantformGroup.get('description').enable(); - } else { - this.grantformGroup.get('existGrant').enable(); - this.grantformGroup.get('label').disable(); - this.grantformGroup.get('label').reset(); - this.grantformGroup.get('description').disable(); - this.grantformGroup.get('description').reset(); - } - } - - controlModified(event: any) { - if (event && this.funderLabelCleared) { - this.funderLabelCleared = false; - this.onFunderSelected(); - } else if (!event) { - this.funderLabelCleared = true; - this.onFunderRemoved(); - } - } - } diff --git a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts index 8468d48a1..b8f30cc6e 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard-model.ts @@ -1,10 +1,10 @@ -import { Status } from "../../../core/common/enum/Status"; -import { GrantListingModel } from "../../../core/model/grant/grant-listing"; -import { ValidationContext } from "../../../common/forms/validation/validation-context"; -import { FormGroup, FormBuilder, Validators } from "@angular/forms"; -import { BackendErrorValidator } from "../../../common/forms/validation/custom-validator"; -import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; -import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { Status } from '@app/core/common/enum/Status'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { ValidJsonValidator } from '@app/library/auto-complete/auto-complete-custom-validator'; +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'; export class GrantEditorWizardModel { public id: string; diff --git a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.html b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.html index 2b4d9e1b0..f55f3f3c1 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.html +++ b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.html @@ -10,7 +10,7 @@

{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.FIRST-STEP.ABOUT-GRANT' | translate}}

- + {{'DMP-EDITOR.FIELDS.EXTERNAL-SOURCE-HINT' | translate}} diff --git a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.ts b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.ts index 47f1c730a..f74216ded 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/grant-editor/grant-editor-wizard.component.ts @@ -1,20 +1,23 @@ -import { of as observableOf, Observable } from 'rxjs'; import { Component, Input, OnInit } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Router } from '@angular/router'; +import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; +import { RequestItem } from '@app/core/query/request-item'; +import { GrantService } from '@app/core/services/grant/grant.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { GrantEditorWizardModel } from '@app/ui/quick-wizard/grant-editor/grant-editor-wizard-model'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from "../../../core/common/base/base.component"; -import { GrantCriteria } from '../../../core/query/grant/grant-criteria'; -import { RequestItem } from '../../../core/query/request-item'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { GrantService } from '../../../core/services/grant/grant.service'; -import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { GrantEditorWizardModel } from './grant-editor-wizard-model'; +import { Observable, of as observableOf } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { strict } from 'assert'; @Component({ selector: 'app-quick-wizard-grant-editor-component', @@ -36,11 +39,20 @@ export class GrantEditorWizardComponent extends BaseComponent implements OnInit, public snackBar: MatSnackBar, public router: Router, public language: TranslateService, - private grantService: GrantService + private grantService: GrantService, + private formService: FormService ) { super(); } + getGrantIdText(item) { + if (item.reference != null && typeof item.reference == 'string') { + const parts = (item.reference as String).split('::'); + return parts.length > 1 ? ' (' + parts[parts.length - 1] + ')' : ''; + } + return ''; + } + ngOnInit() { this.breadCrumbs = observableOf([{ parentComponentName: 'QuickCreate', @@ -54,17 +66,12 @@ export class GrantEditorWizardComponent extends BaseComponent implements OnInit, this.grantAutoCompleteConfiguration = { filterFn: this.searchGrant.bind(this), initialItems: (extraData) => this.searchGrant(''), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') + displayFn: (item) => item['label'] + this.getGrantIdText(item), + titleFn: (item) => item['label'] + this.getGrantIdText(item), + subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) }; - if (!this.grantformGroup) { - this.grant = new GrantEditorWizardModel(); - this.grantformGroup = this.grant.buildForm(); - } - - if (this.funderFormGroup && this.funderFormGroup.get('funder')) { + if (this.funderFormGroup && this.funderFormGroup.valid) { this.grantformGroup.get('existGrant').enable(); this.grantformGroup.get('label').disable(); this.grantformGroup.get('description').disable(); @@ -72,55 +79,32 @@ export class GrantEditorWizardComponent extends BaseComponent implements OnInit, this.grantformGroup.get('existGrant').disable(); } - // this.route.params - // .pipe(takeUntil(this._destroyed)) - // .subscribe((params: Params) => { - // const itemId = params['id']; + this.funderFormGroup.statusChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(x => { + this.grantformGroup.reset(); + if (x == 'INVALID') { + this.grantformGroup.get('existGrant').reset(); + this.grantformGroup.get('label').reset(); + this.grantformGroup.get('description').reset(); + this.grantformGroup.get('existGrant').disable(); + this.grantformGroup.get('label').disable(); + this.grantformGroup.get('description').disable(); + } else if (x == 'VALID') { + if (!this.isNew) { + this.grantformGroup.get('label').reset(); + this.grantformGroup.get('description').reset(); + this.grantformGroup.get('label').disable(); + this.grantformGroup.get('description').disable(); + this.grantformGroup.get('existGrant').enable(); - // if (itemId != null) { - // this.isNew = false; - // this.grantService.getSingle(itemId).map(data => data as GrantListingModel) - // .pipe(takeUntil(this._destroyed)) - // .subscribe(data => { - // this.grant = new GrantEditorModel().fromModel(data); - // this.formGroup = this.grant.buildForm(null, this.grant.type === GrantType.External || !this.editMode); - // this.breadCrumbs = Observable.of([ - // { parentComponentName: 'GrantListingComponent', label: 'Grants', url: '/grants' }, - // ]); - // }); - // } else { - // this.breadCrumbs = Observable.of([ - // { parentComponentName: 'QuickWizardComponent', label: 'Grants', url: '/grants' }, - // ]); - // this.grant = new GrantEditorWizardModel(); - // setTimeout(() => { - // this.formGroup = this.grant.buildForm(); - // }); - // } - // }); - } - - public isFormValid() { - return this.grantformGroup.valid; + } + } + }) } isFunderFormInvalid() { - return !this.funderFormGroup.get('existFunder').value && !this.funderFormGroup.get('label').valid; - } - - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } + return !this.funderFormGroup.valid; } onCallbackSuccess(): void { @@ -130,7 +114,7 @@ export class GrantEditorWizardComponent extends BaseComponent implements OnInit, onCallbackError(errorResponse: any) { this.setErrorModel(errorResponse.error.payload); - this.validateAllFormFields(this.grantformGroup); + this.formService.validateAllFormFields(this.grantformGroup); } public setErrorModel(validationErrorModel: ValidationErrorModel) { @@ -139,21 +123,6 @@ export class GrantEditorWizardComponent extends BaseComponent implements OnInit, }); } - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - searchGrant(query: string) { const grantRequestItem: RequestItem = new RequestItem(); grantRequestItem.criteria = new GrantCriteria(); @@ -167,21 +136,16 @@ export class GrantEditorWizardComponent extends BaseComponent implements OnInit, create() { this.isNew = !this.isNew; if (this.isNew) { - this.grantformGroup.get('existGrant').disable(); this.grantformGroup.get('existGrant').reset(); + this.grantformGroup.get('existGrant').disable(); this.grantformGroup.get('label').enable(); this.grantformGroup.get('description').enable(); } else { - this.grantformGroup.get('existGrant').enable(); - this.grantformGroup.get('label').disable(); this.grantformGroup.get('label').reset(); - this.grantformGroup.get('description').disable(); + this.grantformGroup.get('label').disable(); this.grantformGroup.get('description').reset(); + this.grantformGroup.get('description').disable(); + this.grantformGroup.get('existGrant').enable(); } } - - onGrantSelected() { - this.grantformGroup.get('label').disable(); - this.grantformGroup.get('description').disable(); - } } diff --git a/dmp-frontend/src/app/ui/quick-wizard/project-editor/project-editor-wizard.component.ts b/dmp-frontend/src/app/ui/quick-wizard/project-editor/project-editor-wizard.component.ts index bc81cbc21..3734ca29d 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/project-editor/project-editor-wizard.component.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/project-editor/project-editor-wizard.component.ts @@ -30,7 +30,7 @@ export class ProjectEditorWizardComponent implements OnInit { initialItems: (extraData) => this.searchProject(''), displayFn: (item) => item['label'], titleFn: (item) => item['label'], - subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE') + subtitleFn: (item) => item['source'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['source'] : (item['key'] ? this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.SOURCE:') + item['key'] : this.language.instant('TYPES.EXTERNAL-DATASET-TYPE.NO-SOURCE')) }; if (!this.formGroup) { diff --git a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.html b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.html index 8b3a7c7c9..a240ffbc1 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.html +++ b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.html @@ -6,11 +6,11 @@

{{ 'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.POST-SELECTION-INFO' | translate }}

- + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.FIRST-STEP.TITLE' | translate}} - +
@@ -19,7 +19,7 @@
- + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.SECOND-STEP.TITLE' | translate}} @@ -36,7 +36,7 @@
- + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.THIRD-STEP.TITLE' | translate}} diff --git a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.ts b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.ts index 9345b7ea1..35800d86f 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component.ts @@ -1,29 +1,30 @@ -import { of as observableOf, Observable } from 'rxjs'; -import { Component, OnInit, ViewChild, HostListener } from '@angular/core'; +import { Component, OnInit, ViewChild } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatStepper } from '@angular/material/stepper'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Router } from '@angular/router'; +import { DatasetStatus } from '@app/core/common/enum/dataset-status'; +import { DmpStatus } from '@app/core/common/enum/dmp-status'; +import { DatasetService } from '@app/core/services/dataset/dataset.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { QuickWizardService } from '@app/core/services/quick-wizard/quick-wizard.service'; +import { CheckDeactivateBaseComponent } from '@app/library/deactivate/deactivate.component'; +import { DmpFinalizeDialogComponent, DmpFinalizeDialogDataset, DmpFinalizeDialogInput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; +import { DatasetEditorWizardComponent } from '@app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component'; +import { GrantEditorWizardModel } from '@app/ui/quick-wizard/grant-editor/grant-editor-wizard-model'; +import { QuickWizardEditorWizardModel } from '@app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.model'; +import { FormService } from '@common/forms/form-service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { TranslateService } from '@ngx-translate/core'; +import { Observable, of as observableOf } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { DatasetStatus } from '../../../core/common/enum/dataset-status'; -import { DmpStatus } from '../../../core/common/enum/dmp-status'; -import { DatasetService } from '../../../core/services/dataset/dataset.service'; -import { SnackBarNotificationLevel, UiNotificationService, PopupNotification } from '../../../core/services/notification/ui-notification-service'; -import { QuickWizardService } from '../../../core/services/quick-wizard/quick-wizard.service'; -import { ConfirmationDialogComponent } from '../../../library/confirmation-dialog/confirmation-dialog.component'; -import { DmpFinalizeDialogComponent, DmpFinalizeDialogDataset, DmpFinalizeDialogInput } from '../../dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component'; -import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; -import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; -import { DatasetEditorWizardComponent } from '../dataset-editor/dataset-editor-wizard.component'; -import { GrantEditorWizardModel } from '../grant-editor/grant-editor-wizard-model'; -import { QuickWizardEditorWizardModel } from './quick-wizard-editor.model'; -import { FunderFormModel } from '../../dmp/editor/grant-tab/funder-form-model'; -import { ProjectFormModel } from '../../dmp/editor/grant-tab/project-form-model'; -import { CheckDeactivateBaseComponent } from '../../../library/deactivate/deactivate.component'; @Component({ selector: 'app-quick-wizard-editor-component', @@ -48,7 +49,8 @@ export class QuickWizardEditorComponent extends CheckDeactivateBaseComponent imp public datasetService: DatasetService, public quickWizardService: QuickWizardService, private uiNotificationService: UiNotificationService, - private dialog: MatDialog + private dialog: MatDialog, + private formService: FormService ) { super(); } @@ -82,7 +84,7 @@ export class QuickWizardEditorComponent extends CheckDeactivateBaseComponent imp } formSubmit(): void { - this.touchAllFormFields(this.formGroup); + this.formService.touchAllFormFields(this.formGroup); if (this.formGroup.get('datasets') && this.formGroup.get('datasets').get('datasetsList') && (this.formGroup.get('datasets').get('datasetsList') as FormArray).length > 0) { for (let control of (this.formGroup.get('datasets').get('datasetsList') as FormArray).controls) { control.get('status').setValue(DatasetStatus.Draft); @@ -137,21 +139,6 @@ export class QuickWizardEditorComponent extends CheckDeactivateBaseComponent imp return this.formGroup.get('grant').valid && this.formGroup.get('funder').valid; } - public touchAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.markAsTouched(); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.touchAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.touchAllFormFields(item); - }); - } - } - onSubmitSaveAndFinalize() { this.quickWizardService.createQuickWizard(this.formGroup.getRawValue()) .pipe(takeUntil(this._destroyed)) @@ -192,7 +179,7 @@ export class QuickWizardEditorComponent extends CheckDeactivateBaseComponent imp onCallbackError(errorResponse: any) { this.setErrorModel(errorResponse.error.payload); - this.validateAllFormFields(this.formGroup); + this.formService.validateAllFormFields(this.formGroup); } public setErrorModel(validationErrorModel: ValidationErrorModel) { @@ -201,21 +188,6 @@ export class QuickWizardEditorComponent extends CheckDeactivateBaseComponent imp }); } - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } - } - getGrantLabel(): string { if (this.formGroup.get('grant').get('existGrant').value) { return this.formGroup.get('grant').get('existGrant').value['label']; diff --git a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.model.ts b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.model.ts index 617c68ade..c707da664 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.model.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.model.ts @@ -1,23 +1,22 @@ -import { GrantEditorWizardModel } from "../grant-editor/grant-editor-wizard-model"; -import { DmpEditorWizardModel } from "../dmp-editor/dmp-editor-wizard-model"; -import { DmpModel } from "../../../core/model/dmp/dmp"; -import { GrantListingModel } from "../../../core/model/grant/grant-listing"; -import { DatasetModel } from "../../../core/model/dataset/dataset"; -import { ValidationContext } from "../../../common/forms/validation/validation-context"; -import { FormGroup, FormBuilder, Validators } from "@angular/forms"; -import { BackendErrorValidator } from "../../../common/forms/validation/custom-validator"; -import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model"; -import { DatasetEditorWizardModel } from "../dataset-editor/dataset-editor-wizard-model"; -import { DatasetWizardEditorModel } from "../../dataset/dataset-wizard/dataset-wizard-editor.model"; -import { FunderModel } from "../../../core/model/funder/funder"; -import { FunderFormModel } from "../../dmp/editor/grant-tab/funder-form-model"; -import { ProjectFormModel } from "../../dmp/editor/grant-tab/project-form-model"; -import { ProjectModel } from "../../../core/model/project/project"; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { FunderModel } from '@app/core/model/funder/funder'; +import { GrantListingModel } from '@app/core/model/grant/grant-listing'; +import { ProjectModel } from '@app/core/model/project/project'; +import { DatasetWizardEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model'; +import { FunderFormModel } from '@app/ui/dmp/editor/grant-tab/funder-form-model'; +import { ProjectFormModel } from '@app/ui/dmp/editor/grant-tab/project-form-model'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { ValidationContext } from '@common/forms/validation/validation-context'; +import { DatasetEditorWizardModel } from '../dataset-editor/dataset-editor-wizard-model'; +import { DmpEditorWizardModel } from '../dmp-editor/dmp-editor-wizard-model'; +import { GrantEditorWizardModel } from '../grant-editor/grant-editor-wizard-model'; + export class QuickWizardEditorWizardModel { - public grant: GrantEditorWizardModel; - public funder: FunderFormModel; - public project: ProjectFormModel; + public grant: GrantEditorWizardModel; + public funder: FunderFormModel; + public project: ProjectFormModel; public dmp: DmpEditorWizardModel; public datasets: DatasetEditorWizardModel; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); @@ -25,17 +24,17 @@ export class QuickWizardEditorWizardModel { fromModelGrant(item: GrantListingModel): QuickWizardEditorWizardModel { this.grant.fromModel(item); return this; - } + } - fromModelFunder(item: FunderModel): QuickWizardEditorWizardModel { - this.funder.fromModel(item); - return this; - } + fromModelFunder(item: FunderModel): QuickWizardEditorWizardModel { + this.funder.fromModel(item); + return this; + } - fromModelProject(item: ProjectModel): QuickWizardEditorWizardModel { - this.project.fromModel(item); - return this; - } + fromModelProject(item: ProjectModel): QuickWizardEditorWizardModel { + this.project.fromModel(item); + return this; + } fromModelDmp(item: DmpModel): QuickWizardEditorWizardModel { this.dmp.fromModel(item); @@ -45,14 +44,14 @@ export class QuickWizardEditorWizardModel { fromModelDataset(item: DatasetWizardEditorModel[]): QuickWizardEditorWizardModel { this.datasets.fromModel(item); return this; - } + } buildForm(context: ValidationContext = null): FormGroup { // if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ - grant: new GrantEditorWizardModel().buildForm(), - funder: new FunderFormModel().buildForm(), - project: new ProjectFormModel().buildForm(), + grant: new GrantEditorWizardModel().buildForm(), + funder: new FunderFormModel().buildForm(), + project: new ProjectFormModel().buildForm(), dmp: new DmpEditorWizardModel().buildForm(), datasets: new DatasetEditorWizardModel().buildForm() diff --git a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.module.ts b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.module.ts index d0f5980af..eda54f35c 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.module.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.module.ts @@ -1,19 +1,21 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module'; -import { UrlListingModule } from '../../library/url-listing/url-listing.module'; -import { QuickWizardRoutingModule } from './quick-wizard.routing'; -import { GrantEditorWizardComponent } from './grant-editor/grant-editor-wizard.component'; -import { DmpEditorWizardComponent } from './dmp-editor/dmp-editor-wizard.component'; -import { QuickWizardEditorComponent } from './quick-wizard-editor/quick-wizard-editor.component'; -import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; -import { DatasetEditorWizardComponent } from './dataset-editor/dataset-editor-wizard.component'; -import { DatasetDescriptionFormModule } from '../misc/dataset-description-form/dataset-description-form.module'; -import { DmpModule } from '../dmp/dmp.module'; -import { FunderEditorWizardComponent } from './funder-editor/funder-editor-wizard.component'; -import { ProjectEditorWizardComponent } from './project-editor/project-editor-wizard.component'; -import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guard'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { CanDeactivateGuard } from '@app/library/deactivate/can-deactivate.guard'; +import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; +import { DmpModule } from '@app/ui/dmp/dmp.module'; +import { DatasetDescriptionFormModule } from '@app/ui/misc/dataset-description-form/dataset-description-form.module'; +import { DatasetEditorWizardComponent } from '@app/ui/quick-wizard/dataset-editor/dataset-editor-wizard.component'; +import { DmpEditorWizardComponent } from '@app/ui/quick-wizard/dmp-editor/dmp-editor-wizard.component'; +import { FunderEditorWizardComponent } from '@app/ui/quick-wizard/funder-editor/funder-editor-wizard.component'; +import { GrantEditorWizardComponent } from '@app/ui/quick-wizard/grant-editor/grant-editor-wizard.component'; +import { ProjectEditorWizardComponent } from '@app/ui/quick-wizard/project-editor/project-editor-wizard.component'; +import { QuickWizardEditorComponent } from '@app/ui/quick-wizard/quick-wizard-editor/quick-wizard-editor.component'; +import { QuickWizardRoutingModule } from '@app/ui/quick-wizard/quick-wizard.routing'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { TableOfContentsModule } from '../misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.module'; +import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; @NgModule({ imports: [ @@ -24,7 +26,9 @@ import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guar ConfirmationDialogModule, QuickWizardRoutingModule, DatasetDescriptionFormModule, - DmpModule + DmpModule, + TableOfContentsModule, + AngularStickyThingsModule ], declarations: [ GrantEditorWizardComponent, diff --git a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.routing.ts b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.routing.ts index 31456ea00..22f849a67 100644 --- a/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.routing.ts +++ b/dmp-frontend/src/app/ui/quick-wizard/quick-wizard.routing.ts @@ -2,11 +2,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { QuickWizardEditorComponent } from './quick-wizard-editor/quick-wizard-editor.component'; import { CanDeactivateGuard } from '../../library/deactivate/can-deactivate.guard'; +import { AuthGuard } from '@app/core/auth-guard.service'; const routes: Routes = [ { path: '', component: QuickWizardEditorComponent, + canActivate: [AuthGuard], data: { breadcrumb: true }, diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/privacy/privacy.module.ts b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/privacy/privacy.module.ts index 37921fc36..8c303fe91 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/privacy/privacy.module.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/privacy/privacy.module.ts @@ -1,15 +1,15 @@ import { NgModule } from '@angular/core'; -import { PrivacyComponent } from './privacy.component'; -import { PrivacyRoutingModule } from './privacy.routing'; -import { CommonUiModule } from '../../../../common/ui/common-ui.module'; +import { PrivacyComponent } from '@app/ui/sidebar/sidebar-footer/privacy/privacy.component'; +import { PrivacyRoutingModule } from '@app/ui/sidebar/sidebar-footer/privacy/privacy.routing'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ - CommonUiModule, - PrivacyRoutingModule + CommonUiModule, + PrivacyRoutingModule ], declarations: [ - PrivacyComponent + PrivacyComponent ] }) export class PrivacyModule { } diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.html b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.html index d9e66567b..4dd12fe7f 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.html +++ b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.html @@ -8,32 +8,32 @@
Help
-->
-
+

{{'FOOTER.GLOSSARY' | translate}}

-
+

{{'FOOTER.FAQ' | translate}}

-
+
+
+

{{'FOOTER.CONTACT-SUPPORT' | translate}}

-
-
-
+ -
+ + {{'FOOTER.PRIVACY-POLICY' | translate}} -
+
-->
diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.ts b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.ts index c03321df9..dda6326be 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/sidebar-footer.component.ts @@ -1,17 +1,19 @@ import { Component, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; +import { Router } from '@angular/router'; +import { ContactEmailFormModel } from '@app/core/model/contact/contact-email-form-model'; +import { ContactSupportService } from '@app/core/services/contact-support/contact-support.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { ContactDialogComponent } from '@app/ui/contact/contact-dialog/contact-dialog.component'; +import { FaqDialogComponent } from '@app/ui/faq/dialog/faq-dialog.component'; +import { GlossaryDialogComponent } from '@app/ui/glossary/dialog/glossary-dialog.component'; +import { BaseComponent } from '@common/base/base.component'; +import { FormService } from '@common/forms/form-service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; -import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; -import { BaseComponent } from '../../../core/common/base/base.component'; -import { ContactEmailFormModel } from '../../../core/model/contact/contact-email-form-model'; -import { ContactSupportService } from '../../../core/services/contact-support/contact-support.service'; -import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; -import { GlossaryDialogComponent } from '../../glossary/dialog/glossary-dialog.component'; -import { Router } from '@angular/router'; -import { FaqDialogComponent } from '../../faq/dialog/faq-dialog.component'; -import { ContactDialogComponent } from '../../contact/contact-dialog/contact-dialog.component'; +import { AuthService } from "@app/core/services/auth/auth.service"; @Component({ selector: 'app-sidebar-footer', @@ -28,7 +30,9 @@ export class SidebarFooterComponent extends BaseComponent implements OnInit { private language: TranslateService, public router: Router, private contactSupportService: ContactSupportService, - private uiNotificationService: UiNotificationService + private uiNotificationService: UiNotificationService, + private formService: FormService, + private authentication: AuthService, ) { super(); } @@ -99,7 +103,7 @@ export class SidebarFooterComponent extends BaseComponent implements OnInit { onCallbackError(errorResponse: any) { this.setErrorModel(errorResponse.error); - this.validateAllFormFields(this.formGroup); + this.formService.validateAllFormFields(this.formGroup); this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-EMAIL-SEND'), SnackBarNotificationLevel.Error); } @@ -109,19 +113,7 @@ export class SidebarFooterComponent extends BaseComponent implements OnInit { }); } - public validateAllFormFields(formControl: AbstractControl) { - if (formControl instanceof FormControl) { - formControl.updateValueAndValidity({ emitEvent: false }); - } else if (formControl instanceof FormGroup) { - Object.keys(formControl.controls).forEach(item => { - const control = formControl.get(item); - this.validateAllFormFields(control); - }); - } else if (formControl instanceof FormArray) { - formControl.controls.forEach(item => { - this.validateAllFormFields(item); - }); - } + public isAuthenticated(): boolean { + return !(!this.authentication.current()); } - } diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.module.ts b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.module.ts index d9c62dcc5..86c5c4a3a 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.module.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; -import { TermsComponent } from './terms.component'; -import { TermsRoutingModule } from './terms.routing'; -import { CommonUiModule } from '../../../../common/ui/common-ui.module'; +import { TermsComponent } from '@app/ui/sidebar/sidebar-footer/terms/terms.component'; +import { TermsRoutingModule } from '@app/ui/sidebar/sidebar-footer/terms/terms.routing'; +import { CommonUiModule } from '@common/ui/common-ui.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts index f456542fe..1ddc24a89 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts @@ -50,7 +50,8 @@ export const PUBLIC_ROUTES: RouteInfo[] = [ export const ADMIN_ROUTES: RouteInfo[] = [ { path: '/dmp-profiles', title: 'SIDE-BAR.DMP-TEMPLATES', icon: 'library_books' }, { path: '/dataset-profiles', title: 'SIDE-BAR.DATASET-TEMPLATES', icon: 'library_books' }, - { path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' } + { path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' }, + { path: '/language-editor', title: 'Language Editor', icon: 'language'} ]; // export const HISTORY_ROUTES: RouteInfo[] = [ // { path: '/typography', title: 'SIDE-BAR.HISTORY-VISITED', icon: 'visibility'}, diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.module.ts b/dmp-frontend/src/app/ui/sidebar/sidebar.module.ts index a42c97328..9a05ddb09 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.module.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.module.ts @@ -1,12 +1,12 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { CommonFormsModule } from '../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { ContactModule } from '../contact/contact.module'; +import { FaqModule } from '../faq/faq.module'; +import { GlossaryModule } from '../glossary/glossary.module'; import { SidebarFooterComponent } from './sidebar-footer/sidebar-footer.component'; import { SidebarComponent } from './sidebar.component'; -import { GlossaryModule } from '../glossary/glossary.module'; -import { FaqModule } from '../faq/faq.module'; -import { ContactModule } from '../contact/contact.module'; @NgModule({ imports: [ diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.html b/dmp-frontend/src/app/ui/user-profile/user-profile.component.html index 057c922a6..2a61dc7f6 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.component.html +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.html @@ -32,9 +32,8 @@
- -
+ +
{{dmp.label}}
@@ -91,7 +90,7 @@ - {{ language.label }} + {{ language.label | translate }} diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.scss b/dmp-frontend/src/app/ui/user-profile/user-profile.component.scss index 70be43784..36426b892 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.component.scss +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.scss @@ -1,6 +1,10 @@ -// .clickable{ -// cursor: pointer; -// } +.clickable{ + cursor: pointer; +} +.clickable:hover { + //text-decoration: underline; //Alternative + color: #00b29f !important; +} // .two-line-mat-option { // height: 3.5em; // line-height: 1.2em; diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts index a5e847417..de33e2857 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts @@ -1,17 +1,18 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Params, Router } from '@angular/router'; +import { CultureInfo } from '@app/core/model/culture-info'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { UserListingModel } from '@app/core/model/user/user-listing'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { CultureService } from '@app/core/services/culture/culture-service'; +import { UserService } from '@app/core/services/user/user.service'; +import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import * as moment from 'moment-timezone'; import { Observable, of } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; -import { BaseComponent } from '../../core/common/base/base.component'; -import { CultureInfo } from '../../core/model/culture-info'; -import { DmpModel } from '../../core/model/dmp/dmp'; -import { UserListingModel } from '../../core/model/user/user-listing'; -import { AuthService } from '../../core/services/auth/auth.service'; -import { CultureService } from '../../core/services/culture/culture-service'; -import { UserService } from '../../core/services/user/user.service'; +import { LanguageService } from '@app/core/services/language/language.service'; const availableLanguages: any[] = require('../../../assets/resources/language.json'); @@ -37,8 +38,8 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes private authService: AuthService, private language: TranslateService, private cultureService: CultureService, - private translate: TranslateService, - private authentication: AuthService + private authentication: AuthService, + private languageService: LanguageService ) { super(); } ngOnInit() { @@ -76,7 +77,13 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes } getUserRole(dmp: DmpModel) { - if (dmp.creator.id === this.currentUserId) { return this.language.instant('USER-PROFILE.DMPS.CREATOR'); } else if (dmp.associatedUsers.map(x => x.id).indexOf(this.currentUserId) !== -1) { return this.language.instant('USER-PROFILE.DMPS.MEMBER'); } + let role = -1; + dmp.users.forEach(user => { + if (user.id === this.currentUserId) { + role = user.role; + } + }); + if (role === 0) { return this.language.instant('USER-PROFILE.DMPS.CREATOR'); } else if (role === 1) { return this.language.instant('USER-PROFILE.DMPS.MEMBER'); } return ''; } @@ -126,7 +133,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes .subscribe( x => { this.editMode = false; - this.translate.use(this.formGroup.value.language); + this.languageService.changeLanguage(this.formGroup.value.language.value); this.authService.current().culture = this.formGroup.value.culture.name; this.formGroup.disable(); this.authService.me() diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts index be8e300a4..29f166199 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; -import { CommonFormsModule } from '../../common/forms/common-forms.module'; -import { CommonUiModule } from '../../common/ui/common-ui.module'; -import { FormattingModule } from '../../core/formatting.module'; +import { FormattingModule } from '@app/core/formatting.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; import { UserProfileComponent } from './user-profile.component'; import { UserProfileRoutingModule } from './user-profile.routing'; diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts index 0e55168e8..3e3118a8d 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.routing.ts @@ -1,11 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserProfileComponent } from './user-profile.component'; +import { AuthGuard } from '@app/core/auth-guard.service'; const routes: Routes = [ { path: '', component: UserProfileComponent, + canActivate: [AuthGuard], data: { breadcrumb: true }, @@ -16,4 +18,4 @@ const routes: Routes = [ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) -export class UserProfileRoutingModule { } \ No newline at end of file +export class UserProfileRoutingModule { } diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index d0c9ba3a8..cdad8fbd4 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -34,6 +34,18 @@ "EDIT": "Edited", "FINALISED": "Finalized" }, + "FORM-VALIDATION-DISPLAY-DIALOG": { + "WARNING": "Warning!", + "THIS-FIELD": "Field", + "HAS-ERROR": "has error", + "REQUIRED": "Required", + "EMAIL": "Invalid e-mail", + "MIN-VALUE": "Minimum value should be {{min}}", + "MAX-VALUE": "Maximum value should be {{max}}", + "ACTIONS": { + "CANCEL": "Close" + } + }, "CONFIRMATION-DIALOG": { "DELETE-ITEM": "Delete this item?", "DELETE-USER": "Remove this collaborator?", @@ -114,6 +126,11 @@ "XML": "XML", "JSON": "JSON", "DOC": "Document" + }, + "LANGUAGES": { + "ENGLISH": "English", + "GREEK": "Greek", + "SPANISH": "Spanish" } }, "COOKIE": { @@ -129,7 +146,8 @@ "REQUEST-EMAIL-HEADER": "We are almost done! Please fill your e-mail.", "REQUEST-EMAIL-TEXT": "You will need to confirm it to use the application.", "SUBMIT": "Submit", - "SENT-EMAIL-HEADER": "Email was send!" + "SENT-EMAIL-HEADER": "Email was send!", + "EMAIL-FOUND": "Email is already confirmed" }, "HOME": { "DMPS": "DMPs", @@ -163,7 +181,13 @@ "DATASET-TEMPLATES": "DATASET TEMPLATES", "TEMPLATE": "TEMPLATE", "DMP-TEMPLATES": "DMP TEMPLATES", - "USERS-BREADCRUMB": "USERS" + "USERS-BREADCRUMB": "USERS", + "SEARCH": { + "DATASET": "Dataset Description", + "DMP": "DMP", + "GRANT": "Grant", + "PUBLISHED": "Published" + } }, "SIDE-BAR": { "GENERAL": "GENERAL", @@ -342,7 +366,7 @@ "TITLE": "Grants", "SUBTITLE": "Grant Subtitle", "ACTIONS": { - "NEW":"New Grant" + "NEW": "New Grant" } }, "DMP-LISTING": { @@ -359,7 +383,8 @@ "ACTIONS": "Actions", "DATASETS": "Dataset Descriptions", "STATUS": "Status", - "PEOPLE": "People" + "PEOPLE": "People", + "VERSION": "Version" }, "ACTIONS": { "NEW": "New DMP", @@ -392,7 +417,8 @@ "LEVEL-OF-ACCESS": "Level of Access", "INVOLVED-DATASETS": "Involved Dataset Descriptions", "TEMPLATES-INVOLVED": "Dataset Description Templates Involved" - } + }, + "VIEW-ALL-VERSIONS": "All versions of" }, "DMP-PUBLIC-LISTING": { "TITLE": "Published Data Management Plans", @@ -428,7 +454,8 @@ "FIRST-STEP": { "TITLE": "Dataset Description Information", "DMP": "Data Management Plan", - "PROFILE": "Dataset Description Template" + "PROFILE": "Dataset Description Template", + "SUB-TITLE": "Created At: " }, "SECOND-STEP": { "TITLE": "External References", @@ -477,10 +504,14 @@ }, "DMP-OVERVIEW": { "RESEARCHERS": "Researchers", + "COLLABORATORS": "Collaborators", "TOOLTIP": { "LEVEL-OF-ACCESS": "Level of Access", "INVOLVED-DATASETS": "Involved Dataset Descriptions", "TEMPLATES-INVOLVED": "Dataset Description Templates Involved" + }, + "ERROR": { + "DELETED-DMP": "The requested DMP is deleted" } }, "DATASET-LISTING": { @@ -510,7 +541,7 @@ "MAKE-IT-PUBLIC": "Make it public", "VIEW": "View", "NEW": "New Dataset Description", - "CREATE-NEW":"Create new Dataset Description" + "CREATE-NEW": "Create new Dataset Description" }, "TOOLTIP": { "DATASET-STATUS": { @@ -519,7 +550,8 @@ }, "DMP": "DMP", "GRANT": "Grant", - "TEMPLATES-INVOLVED": "Dataset Description Template" + "TEMPLATES-INVOLVED": "Dataset Description Template", + "VERSION": "DMP Version" } }, "DATASET-PUBLIC-LISTING": { @@ -574,8 +606,8 @@ "SELECT": "Select Dataset Description Template" }, "SNACK-BAR": { - "SUCCESSFUL-CREATION" : "Imported Successfully", - "UNSUCCESSFUL" : "Something went wrong" + "SUCCESSFUL-CREATION": "Imported Successfully", + "UNSUCCESSFUL": "Something went wrong" } }, "DMP-PROFILE-EDITOR": { @@ -650,7 +682,8 @@ "GRANT": "Grant", "FUNDER": "Funder", "STATUS": "DMP Status", - "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)" + "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)", + "COLLABORATORS": "Collaborators" }, "ACTIONS": { "GO-TO-GRANT": "Go To DMP Grant", @@ -734,7 +767,8 @@ "SELECT-COLLABORATORS": "Select Collaborators", "RELATED-COLLABORATORS": "Related Collaborators", "SELECT-DATASET-TEMPLATES": "Select Dataset Description Templates", - "RELATED-DATASET-TEMPLATES": "Related Dataset Description Templates" + "RELATED-DATASET-TEMPLATES": "Related Dataset Description Templates", + "ALL-VERSIONS": "From All Versions" }, "DMP": { "LIKE": "Search DMPs", @@ -856,7 +890,7 @@ "DMP-VISIBILITY": { "VISIBILITY": "Visibility", "PUBLIC": "Published", - "FINALIZED": "Finalized" , + "FINALIZED": "Finalized", "DRAFT": "Draft", "ANY": "Any" }, @@ -877,7 +911,7 @@ "DATASET-PROFILE-COMBO-BOX-TYPE": { "WORD-LIST": "Word List", "AUTOCOMPLETE": "Autocomplete", - "EXTERNAL-SOURCE-HINT": "External source", + "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)", "ACTIONS": { "YES": "Yes", "NO": "No" @@ -887,7 +921,7 @@ "RESEARCHERS": "Researchers", "DMPS": "DMPs", "DATASETS": "Dataset Descriptions", - "EXTERNAL-SOURCE-HINT": "External source" + "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)" } }, "ADDRESEARCHERS-EDITOR": { @@ -1118,9 +1152,7 @@ "CREATE-NEW-FUNDER": "Add Funder", "EXIST-FUNDER": "Use Existing Funder", "CREATE-NEW-PROJECT": "Add Project", - "EXIST-PROJECT": "Use Existing Project", - "CREATE-NEW-FUNDER": "Add Funder", - "EXIST-FUNDER": "Use Existing Funder" + "EXIST-PROJECT": "Use Existing Project" }, "FIRST-STEP": { "TITLE": "Grant", @@ -1172,7 +1204,8 @@ "TITLE": "Add a Dataset Description into an existing DMP", "DATASET-WIZARD": "Dataset Description Wizard", "POST-SELECTION-INFO": "This wizard simplifies the process of adding new Dataset Descriptions into existing DMPs, guiding you through and requesting only the most essential pieces of information for completing the task. Full access to the attributes of a Dataset Description can be obtained afterwards via the Dataset Description access menus of the System.", - "SUBTITLE": "This wizard allows you to describe additional Dataset Descriptions managed in the context of a DMP providing only the essential information for their description." + "SUBTITLE": "This wizard allows you to describe additional Dataset Descriptions managed in the context of a DMP providing only the essential information for their description.", + "CREATED": "Created on" } }, "SAVE-DIALOG": { diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json new file mode 100644 index 000000000..f8df10b16 --- /dev/null +++ b/dmp-frontend/src/assets/i18n/es.json @@ -0,0 +1,1219 @@ +{ + "GENERAL": { + "VALIDATION": { + "REQUIRED": "Required", + "GRANT-START-AFTER-END": "Grant start date cannot be after the end date", + "PATTERN-_": "Character \"_\" is not allowed" + }, + "DELETE-CONFIRMATION": { + "TITLE": "Warning", + "MESSAGE": "Are you sure you want to delete this item?", + "POSITIVE": "Yes", + "NEGATIVE": "Cancel" + }, + "SNACK-BAR": { + "SUCCESSFUL-CREATION": "Created Successfully", + "SUCCESSFUL-UPDATE": "Updated Successfully", + "SUCCESSFUL-LOGIN": "Successful Login", + "SUCCESSFUL-LOGOUT": "Successful Logout", + "SUCCESSFUL-EMAIL-SEND": "Email sent successfully", + "UNSUCCESSFUL-LOGOUT": "Unsuccessful Logout", + "UNSUCCESSFUL-LOGIN": "Unsuccessful Login", + "SUCCESSFUL-DATASET-PROFILE-DELETE": "Successful Delete", + "UNSUCCESSFUL-DATASET-PROFILE-DELETE": "This template can not deleted, because Dataset Descriptions are associated with it", + "UNSUCCESSFUL-DELETE": "Unsuccessful Delete", + "UNSUCCESSFUL-EMAIL-SEND": "Failed sending email" + }, + "ERRORS": { + "HTTP-REQUEST-ERROR": "An Unexpected Error Has Occurred" + }, + "NAMES": { + "DATASET": "Dataset Description" + }, + "STATUSES": { + "EDIT": "Edited", + "FINALISED": "Finalized" + }, + "FORM-VALIDATION-DISPLAY-DIALOG": { + "WARNING": "Warning!", + "THIS-FIELD": "Field", + "HAS-ERROR": "has error", + "REQUIRED": "Required", + "EMAIL": "Invalid e-mail", + "MIN-VALUE": "Minimum value should be {{min}}", + "MAX-VALUE": "Maximum value should be {{max}}", + "ACTIONS": { + "CANCEL": "Close" + } + }, + "CONFIRMATION-DIALOG": { + "DELETE-ITEM": "Delete this item?", + "DELETE-USER": "Remove this collaborator?", + "FINALIZE-ITEM": "Finalize this item?", + "PUBLISH-ITEM": "Publish this item?", + "ADD-DATASET": "Do you want to continue by adding a Dataset Description to your DMP? You can always add more Dataset Descriptions using \"Add Dataset Description (Wizard)\" menu.", + "ZENODO-DOI": "Would you like to create digital object identifier (DOI) for the DMP?", + "LEAVE-PAGE": "If you leave, your changes will be lost.", + "LEAVE-WARNING": "You have unsaved changes!", + "PRIVACY-POLICY-NAMES": "The names of all people involved into this DMP will be publicly visible. Do you agree with that?", + "ACTIONS": { + "CONFIRM": "Yes", + "NO": "No", + "DELETE": "Delete", + "REMOVE": "Remove", + "CANCEL": "Cancel", + "LEAVE": "Leave", + "POLICY-AGREE": "Make names publicly visible.", + "REQUIRED": "Click on checkbox is required." + } + }, + "NOTIFICATION-DIALOG": { + "POPUP": { + "TITLE": "Missing Dataset", + "MESSAGE": "At least one dataset has to be created to proceed on saving DMP.", + "CLOSE": "Close" + } + }, + "ACTIONS": { + "VIEW-ALL": "View All", + "SHOW-MORE": "Show more", + "LOG-IN": "Log in" + }, + "PREPOSITIONS": { + "OF": "of" + }, + "TITLES": { + "PREFIX": "Open DMP - ", + "GENERAL": "Data Management Plans Creator", + "ABOUT": "About", + "PRIVACY": "Privacy Policy", + "TERMS": "Terms Of Service", + "PLANS": "My DMPs", + "EXPLORE-PLANS": "Published DMPs", + "QUICK-WIZARD": "New DMP (Wizard)", + "PLANS-NEW": "New DMP (Expert)", + "DATASETS": "My Dataset Descriptions", + "EXPLORE": "Published Dataset Descriptions", + "DATASETCREATEWIZARD": "Add Dataset Description (Wizard)", + "GRANTS": "My Grants", + "DMP-PROFILES": "DMP Templates", + "DATASET-PROFILES": "Dataset Description Templates", + "USERS": "Users", + "PROFILE": "My Profile", + "LOGIN": "INICIAR SESIÓN", + "DMP-OVERVIEW": "DMP Overview", + "DMP-EDIT": "Edit DMP", + "DATASET-EDIT": "Dataset View/Edit", + "DMP-NEW-VERSION": "DMP New Version", + "DMP-CLONE": "Clone DMP", + "DATASET-NEW": "New Dataset Description", + "GRANT-NEW": "New Grant", + "GRANT-EDIT": "View/Edit Grant", + "DMP-PROFILE-NEW": "New DMP Template", + "DMP-PROFILE-EDIT": "Edit DMP Template", + "DATASET-PROFILES-NEW": "New Dataset Description Template", + "DATASET-PROFILES-EDIT": "Edit Dataset Description Template", + "EXPLORE-PLANS-OVERVIEW": "Published DMP Overview", + "DATASET-PUBLIC-EDIT": "View Published Dataset", + "DMP-PUBLIC-EDIT": "View Published DMP", + "DATASET-COPY": "Copy Dataset Description", + "DATASET-UPDATE": "Update Dataset Description", + "DATASET-PROFILES-NEW-VERSION": "New Version of Dataset Description Template", + "DATASET-PROFILES-CLONE": "New Clone of Dataset Description Template" + }, + "FILE-TYPES": { + "PDF": "PDF", + "XML": "XML", + "JSON": "JSON", + "DOC": "Document" + }, + "LANGUAGES": { + "ENGLISH": "Inglés", + "GREEK": "Griego", + "SPANISH": "Espanol" + } + }, + "COOKIE": { + "MESSAGE": "This website uses cookies to enhance the user experience.", + "DISMISS": "Accept", + "DENY": "Refuse cookies", + "LINK": "Learn more", + "POLICY": "Cookie Policy" + }, + "EMAIL-CONFIRMATION": { + "EXPIRED-EMAIL": "Mail invitation expired", + "CARD-TITLE": "E-mail", + "REQUEST-EMAIL-HEADER": "We are almost done! Please fill your e-mail.", + "REQUEST-EMAIL-TEXT": "You will need to confirm it to use the application.", + "SUBMIT": "Submit", + "SENT-EMAIL-HEADER": "Email was send!" + }, + "HOME": { + "DMPS": "DMPs", + "DATASETS": "Dataset Descriptions", + "LOGIN": { + "TITLE": "Login", + "TEXT": "You don't need to have a registered account for ARGOS" + } + }, + "NAV-BAR": { + "BREADCRUMB-ROOT": "Dashboard", + "TITLE": "ARGOS", + "GRANTS": "Grants", + "GRANT": "Grant", + "DMP": "DMP", + "DMPS": "DMPs", + "MY-DMPS": "MY DMPs", + "DATASETS": "Dataset Descriptions", + "DATASET": "Dataset", + "PUBLIC-DATASETS": "Explore ARGOS", + "USERS": "Users", + "DATASETS-ADMIN": "Dataset Templates", + "DMP-PROFILES": "DMP Templates", + "ABOUT": "About", + "MY-DATASET-DESCRIPTIONS": "MY DATASET DESCRIPTIONS", + "DATASET-DESCRIPTION-WIZARD": "Dataset Description wizard", + "PUBLIC DATASETS": "PUBLISHED DATASET DESCRIPTIONS", + "PUBLIC-DMPS": "PUBLISHED DMPS", + "HOME": "HOME", + "DMP-WIZARD": "DMP Wizard", + "DATASET-TEMPLATES": "DATASET TEMPLATES", + "TEMPLATE": "TEMPLATE", + "DMP-TEMPLATES": "DMP TEMPLATES", + "USERS-BREADCRUMB": "USERS", + "SEARCH": { + "DATASET": "Dataset Description", + "DMP": "DMP", + "GRANT": "Grant", + "PUBLISHED": "Published" + } + }, + "SIDE-BAR": { + "GENERAL": "GENERAL", + "ABOUT": "About", + "DASHBOARD": "Home", + "DMP": "DATA MANAGEMENT PLANS", + "MY-DMPS": "My DMPs", + "DATASETS": "DATASET DESCRIPTIONS", + "GRANTS": "GRANTS", + "NEW DATASET": "New Dataset Description", + "QUICK-WIZARD": "New DMP (Wizard)", + "QUICK-WIZARD-DATASET": "Add Dataset Description (Wizard)", + "ADD-EXPERT": "New DMP (Expert)", + "MY-DATASET-DESC": "My Dataset Descriptions", + "MY-GRANTS": "My Grants", + "HISTORY": "HISTORY", + "HISTORY-VISITED": "LAST VISITED", + "HISTORY-EDITED": "LAST EDITED", + "PUBLIC": "PUBLISHED", + "PUBLIC-DMPS": "Published DMPs", + "PUBLIC-DESC": "Published Dataset Descriptions", + "ACCOUNT": "ACCOUNT", + "ADMIN": "ADMIN", + "DATASET-TEMPLATES": "Dataset Description Templates", + "DMP-TEMPLATES": "DMP Templates", + "USERS": "Users" + }, + "DATASET-PROFILE-EDITOR": { + "TITLE": { + "NEW": "New API Client", + "NEW-PROFILE": "New Dataset Description Template", + "NEW-PROFILE-VERSION": "New Version Of ", + "NEW-PROFILE-CLONE": "New Clone Of " + }, + "FIELDS": { + "DATASET-TITLE": "Dataset Description Template Name", + "DATASET-DESCRIPTION": "Description", + "ROLES": "Roles" + }, + "STEPS": { + "PAGES": { + "TITLE": "Page Description", + "PAGE-PREFIX": "Page", + "PAGE-INPUT-TITLE": "Page Title", + "DATASET-DETAILS": "Dataset Description Details", + "EXTERNAL-REFERENCES": "External References", + "DESCRIPTION": "Description" + }, + "FORM": { + "TITLE": "Form Description", + "SECTION": { + "TITLE": "Section Information", + "FIELDS": { + "ID": "Section Unique Identifier", + "TITLE": "Section Name", + "PAGE": "Page to appear", + "ORDER": "Order", + "DESCRIPTION": "Description", + "FIELDS-TITLE": "Fields", + "SUB-SECTIONS-TITLE": "Sub-Sections" + }, + "ACTIONS": { + "ADD-SUB-SECTION": "Add Sub-Section +", + "ADD-FIELD": "Add Field +" + } + }, + "COMPOSITE-FIELD": { + "TITLE": "Composite Field Information", + "SIMPLE-FIELD-TITLE": "Field Information", + "SUB-FIELDS-TITLE": "Child Fields", + "FIELDS": { + "COMPOSITE-CHECKBOX": "Composite Field", + "MULTIPLICITY-CHECKBOX": "Multiplicity", + "COMMENT-CHECKBOX": "Include Comment Field", + "COMPOSITE-TITLE": "Composite Field Name", + "FIELD-TITLE": "Field Name", + "DESCRIPTION": "Description", + "EXTENDED-DESCRIPTION": "Extended Description", + "ADDITIONAL-INFORMATION": "Additional Information", + "MULTIPLICITY-MIN": "Multiplicity Min", + "MULTIPLICITY-MAX": "Multiplicity Max", + "MULTIPLICITY-ADD-ONE-FIELD": "Add one more fieldset", + "ORDER": "Order", + "COMMENT-PLACEHOLDER": "Please Specify", + "COMMENT-HINT": "Provide additional information or justification about your selection", + "RDA-COMMON-STANDARDS": "RDA Common Standards" + }, + "ACTIONS": { + "ADD-CHILD-FIELD": "Add Child Field +" + } + }, + "FIELD": { + "FIELDS": { + "RULES-TITLE": "Visibility Rules", + "FIELD-RULES-VALUE": "Value", + "ID": "Section Unique Identifier", + "VIEW-STYLE": "Type", + "MULTIPLICITY-MIN": "Multiplicity Min", + "MULTIPLICITY-MAX": "Multiplicity Max", + "ORDER": "Order", + "DEFAULT-VALUE": "Default Value", + "VALIDATION": "Validation", + "MULTIPLICITY-CHECKBOX": "Multiplicity", + "FIELD-TEXT-AREA-TITLE": "Text Area Data", + "FIELD-TEXT-AREA-PLACEHOLDER": "Input Placeholder", + "FIELD-BOOLEAN-DECISION-TITLE": "Boolean Decision Data", + "FIELD-BOOLEAN-DECISION-PLACEHOLDER": "Input Placeholder", + "FIELD-CHECKBOX-TITLE": "Checkbox Data", + "FIELD-CHECKBOX-PLACEHOLDER": "Input Placeholder", + "FIELD-FREE-TEXT-TITLE": "Free Text Data", + "FIELD-FREE-TEXT-PLACEHOLDER": "Input Placeholder", + "FIELD-COMBO-BOX-TYPE": "Type of Combo Box", + "FIELD-WORD-LIST-TITLE": "Word List Data", + "FIELD-WORD-LIST-PLACEHOLDER": "Input Placeholder", + "FIELD-WORD-LIST-LABEL": "Label", + "FIELD-WORD-LIST-VALUE": "Value", + "FIELD-INTERNAL-DMP-ENTITIES-TYPE": "Type of Internal DMP Entity", + "FIELD-RESEARCHERS-TITLE": "Researchers Autocomplete", + "FIELD-RESEARCHERS-PLACEHOLDER": "Input Placeholder", + "FIELD-DATASETS-PLACEHOLDER": "Input Placeholder", + "FIELD-DMPS-PLACEHOLDER": "Input Placeholder", + "FIELD-RADIO-BOX-TITLE": "Radio Box Data", + "FIELD-RADIO-BOX-PLACEHOLDER": "Input Placeholder", + "FIELD-RADIO-BOX-LABEL": "Label", + "FIELD-RADIO-BOX-VALUE": "Value", + "FIELD-AUTOCOMPLETE-TITLE": "Autocomplete Data", + "FIELD-AUTOCOMPLETE-PLACEHOLDER": "Input Placeholder", + "FIELD-AUTOCOMPLETE-LABEL": "Label", + "FIELD-AUTOCOMPLETE-VALUE": "Value", + "FIELD-AUTOCOMPLETE-SOURCE": "Source", + "FIELD-AUTOCOMPLETE-URL": "Url", + "FIELD-AUTOCOMPLETE-OPTIONS-ROOT": "Options Root", + "FIELD-DATE-PICKER-TITLE": "Date Picker", + "FIELD-DATE-PICKER-PLACEHOLDER": "Input Placeholder", + "FIELD-DATE-PICKER-LABEL": "Label", + "FIELD-DATE-PICKER-VALUE": "Value", + "FIELD-MULTIPLE-AUTOCOMPLETE": "Multiple Autocomplete" + }, + "DEFAULT-VALUES": { + "NONE": "None", + "BOOLEAN-DECISION": { + "YES": "Yes", + "NO": "No" + }, + "CHECK-BOX": { + "CHECKED": "Checked", + "UNCHECKED": "Unchecked" + } + }, + "ACTIONS": { + "ADD-RULE": "Add Visibility Rule +" + } + }, + "RULE": { + "FIELDS": { + "RULE-TYPE": "Rule Type", + "TARGET": "Target Field Id", + "VALUE": "Required Value", + "RULE-IF": "If Value is", + "RULE-THEN": "then show Field With Id" + } + } + } + }, + "ACTIONS": { + "SAVE": "Save", + "FINALIZE": "Finalize", + "UPDATE": "Update", + "CANCEL": "Cancel", + "DELETE": "Delete", + "ADD-PAGE": "Add Page +", + "ADD-SECTION": "Add Section +" + } + }, + "GRANT-LISTING": { + "TITLE": "Grants", + "SUBTITLE": "Grant Subtitle", + "ACTIONS": { + "NEW": "New Grant" + } + }, + "DMP-LISTING": { + "TITLE": "Data Management Plans", + "OWNER": "Owner", + "MEMBER": "Member", + "COLUMNS": { + "NAME": "Name", + "GRANT": "Grant", + "PROFILE": "Template", + "CREATION-TIME": "Creation Time", + "ORGANISATIONS": "Organizations", + "LATEST_VERSION": "Latest Version", + "ACTIONS": "Actions", + "DATASETS": "Dataset Descriptions", + "STATUS": "Status", + "PEOPLE": "People", + "VERSION": "Version" + }, + "ACTIONS": { + "NEW": "New DMP", + "NEW-WITH-WIZARD": "New DMP using the wizard", + "EDIT": "Edit", + "INVITE": "Invite Contributors", + "ADD-DATASET": "Add Dataset Description To DMP", + "DATASETS": "List All DMP Dataset Descriptions", + "NEW-VERSION": "New Version", + "VIEW-VERSION": "All DMP Versions", + "CLONE": "Clone", + "DELETE": "Delete", + "EXPORT": "Export", + "PUBLISH": "Publish", + "FINALIZE": "Finalize", + "ADV-EXP": "Advanced Export", + "EXP-AS": "Export As", + "DOWNLOAD-XML": "Download XML", + "DOWNLOAD-DOCX": "Download Document", + "DOWNLOAD-PDF": "Download PDF", + "SETTINGS": "Settings", + "GETDOI": "Get DOI" + }, + "TOOLTIP": { + "DMP-STATUS": { + "DRAFT": "Private access - Editable DMP", + "FINALIZED": "Private access - Closed DMP", + "PUBLISHED": "Public access - Closed DMP" + }, + "LEVEL-OF-ACCESS": "Level of Access", + "INVOLVED-DATASETS": "Involved Dataset Descriptions", + "TEMPLATES-INVOLVED": "Dataset Description Templates Involved" + }, + "VIEW-ALL-VERSIONS": "All versions of" + }, + "DMP-PUBLIC-LISTING": { + "TITLE": "Published Data Management Plans", + "OWNER": "Owner", + "MEMBER": "Member", + "VIEW-ONLY": "View Only", + "TOOLTIP": { + "PUBLISHED": "Public access - Closed DMP", + "INVOLVED-DATASETS": "Involved Dataset Descriptions", + "TEMPLATES-INVOLVED": "Dataset Description Templates Involved" + } + }, + "DMP-UPLOAD": { + "TITLE": "Import Data Management Plan", + "UPLOAD-BUTTON": "Upload", + "ACTIONS": { + "IMPORT": "Import", + "CANCEL": "Cancel" + }, + "PLACEHOLDER": "DMP title" + }, + "DATASET-WIZARD": { + "TITLE": { + "NEW": "New Dataset Description" + }, + "EDITOR": { + "FIELDS": { + "EXTERNAL-DATASET-TYPE": "Type", + "EXTERNAL-AUTOCOMPLETE-SUBTITLE": "Source: ", + "EXTERNAL-AUTOCOMPLETE-NO-SOURCE": "Source not provided" + } + }, + "FIRST-STEP": { + "TITLE": "Dataset Description Information", + "DMP": "Data Management Plan", + "PROFILE": "Dataset Description Template", + "SUB-TITLE": "Created At: " + }, + "SECOND-STEP": { + "TITLE": "External References", + "EXTERNAL-HINT": "List of values provided by external source(s)" + }, + "THIRD-STEP": { + "TITLE": "Description" + }, + "ACTIONS": { + "NEXT": "Next", + "BACK": "Back", + "DELETE": "Delete", + "GO-TO-GRANT": "Go to Dataset Description's Grant", + "GO-TO-DMP": "Go to Dataset Description's DMP", + "SAVE": "Save", + "SAVE-AND-FINALISE": "Save and Finalize", + "FINALIZE": "Finalize", + "REVERSE": "Undo Finalization", + "INFO": "Datasets of finalized DMPs can't revert to unfinalized", + "DOWNLOAD-PDF": "Download PDF", + "DOWNLOAD-XML": "Download XML", + "DOWNLOAD-DOCX": "Download DOCX", + "COPY-DATASET": "Copy Dataset Description", + "UPDATE-DATASET-PROFILE": "Update Template" + }, + "MESSAGES": { + "DATASET-NOT-FOUND": "Dataset Description does not exist", + "SUCCESS-UPDATE-DATASET-PROFILE": "Dataset Description Template updated successfully" + }, + "UPLOAD": { + "UPLOAD-XML": "Import", + "UPLOAD-XML-FILE-TITLE": "Import Dataset Description Template", + "UPLOAD-XML-NAME": "Name Of Dataset Description Template", + "UPLOAD-XML-IMPORT": "File", + "UPLOAD-XML-FILE-CANCEL": "Cancel" + }, + "DIALOGUE": { + "TITLE": "Copy Dataset Description to DMP", + "DMP-SEARCH": { + "PLACEHOLDER": "Search DMP" + }, + "COPY": "Copy", + "CANCEL": "Cancel", + "ERROR-MESSAGE": "Does not contain this Dataset Description Template" + } + }, + "DMP-OVERVIEW": { + "RESEARCHERS": "Researchers", + "COLLABORATORS": "Collaborators", + "TOOLTIP": { + "LEVEL-OF-ACCESS": "Level of Access", + "INVOLVED-DATASETS": "Involved Dataset Descriptions", + "TEMPLATES-INVOLVED": "Dataset Description Templates Involved" + }, + "ERROR": { + "DELETED-DMP": "The requested DMP is deleted" + } + }, + "DATASET-LISTING": { + "TITLE": "Dataset Descriptions", + "SELECT-DATASETS-TO-CLONE": "Select which datasets to include in the new DMP. Selected datasets will be editable.", + "SELECT-DATASETS-NONE": "Not available Dataset Descriptions for this DMP.", + "COLUMNS": { + "NAME": "Name", + "REFERNCE": "Reference", + "GRANT": "Grant", + "URI": "Uri", + "STATUS": "Status", + "DESCRIPTION": "Description", + "CREATED": "Created", + "PUBLISHED": "Published", + "FINALIZED": "Finalized", + "LAST-EDITED": "Last Edited", + "ACTIONS": "Actions", + "DMP": "DMP", + "PROFILE": "Template", + "DATAREPOSITORIES": "Data Repositories", + "REGISTRIES": "Registries", + "SERVICES": "Services" + }, + "ACTIONS": { + "EDIT": "Edit", + "MAKE-IT-PUBLIC": "Make it public", + "VIEW": "View", + "NEW": "New Dataset Description", + "CREATE-NEW": "Create new Dataset Description" + }, + "TOOLTIP": { + "DATASET-STATUS": { + "DRAFT": "Private access - Editable Dataset Description", + "FINALIZED": "Private access - Closed Dataset Description" + }, + "DMP": "DMP", + "GRANT": "Grant", + "TEMPLATES-INVOLVED": "Dataset Description Template", + "VERSION": "DMP Version" + } + }, + "DATASET-PUBLIC-LISTING": { + "TITLE": "Published Dataset Descriptions", + "TOOLTIP": { + "FINALIZED": "Private access - Closed Dataset Description", + "DMP": "DMP", + "GRANT": "Grant", + "TEMPLATES-INVOLVED": "Dataset Description Template" + } + }, + "DATASET-PROFILE-LISTING": { + "TITLE": "Dataset Description Templates", + "COLUMNS": { + "NAME": "Name", + "REFERNCE": "Reference", + "GRANT": "Grant", + "URI": "Uri", + "ROLE": "Role", + "TEMPLATE": "Template", + "ORGANIZATION": "Organization", + "STATUS": "Status", + "VISITED": "Visited", + "EDITED": "Edited", + "DESCRIPTION": "Description", + "CREATED": "Created", + "ACTIONS": "Actions", + "DMP": "DMP", + "PROFILE": "Template", + "DATAREPOSITORIES": "Data Repositories", + "REGISTRIES": "Registries", + "SERVICES": "Services" + }, + "ACTIONS": { + "EDIT": "Edit", + "MAKE-IT-PUBLIC": "Make it public", + "VIEW": "View", + "CLONE": "Clone", + "NEW-VERSION": "New Version", + "VIEW-VERSIONS": "All Dataset Description Template Versions" + } + }, + "DATASET-UPLOAD": { + "TITLE": "Import Dataset Description", + "UPLOAD-BUTTON": "Upload", + "ACTIONS": { + "IMPORT": "Import", + "CANCEL": "Cancel" + }, + "PLACEHOLDER": "Dataset Description Title", + "DATASET-PROFILE": { + "SELECT": "Select Dataset Description Template" + }, + "SNACK-BAR": { + "SUCCESSFUL-CREATION": "Imported Successfully", + "UNSUCCESSFUL": "Something went wrong" + } + }, + "DMP-PROFILE-EDITOR": { + "TITLE": { + "NEW": "New DMP Template", + "EDIT": "Edit" + }, + "FIELDS": { + "TITLE": "Fields", + "LABEL": "Name", + "TYPE": "Type", + "DATATYPE": "Data Type", + "REQUIRED": "Required", + "EXTERNAL-AUTOCOMPLETE": { + "TITLE": "Autocomplete Data", + "MULTIPLE-AUTOCOMPLETE": "Multiple Autocomplete", + "PLACEHOLDER": "Input Placeholder", + "URL": "Url", + "OPTIONS-ROOT": "Options Root", + "LABEL": "Label", + "VALUE": "Value" + } + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "FINALIZE": "Finalize", + "DOWNLOAD-XML": "Download XML" + } + }, + "GRANT-EDITOR": { + "TITLE": { + "NEW": "New Grant", + "EDIT": "Edit" + }, + "FIELDS": { + "LABEL": "Title", + "ABBREVIATION": "Abbreviation", + "URI": "URL", + "START": "Start", + "END": "End", + "DESCRIPTION": "Description", + "LOGO": "Grant Logo" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "GO-TO-DMPS": "Go To DMPs", + "VISIT-WEBSITE": "Visit Website" + } + }, + "DMP-EDITOR": { + "TITLE": { + "NEW": "New Data Management Plan", + "EDIT": "Edit", + "SUBTITLE": "DOI" + }, + "FIELDS": { + "NAME": "Title", + "RELATED-GRANT": "Related Grant", + "DESCRIPTION": "Description", + "ORGANISATIONS": "Organizations", + "ORGANISATIONS-HINT": "Add here the names of the organizations contributing to the creation and revision of the DMPs", + "RESEARCHERS": "Researchers", + "TEMPLATES": "Templates", + "TEMPLATE": "DMP Template", + "DATASET-TEMPLATES": "Related Dataset Description Templates", + "PROFILE": "DMP Template", + "PROJECT": "Project", + "GRANT": "Grant", + "FUNDER": "Funder", + "STATUS": "DMP Status", + "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)", + "COLLABORATORS": "Collaborators" + }, + "ACTIONS": { + "GO-TO-GRANT": "Go To DMP Grant", + "GO-TO-DATASETS": "Go To Dataset Descriptions", + "SAVE-CHANGES": "Save Changes", + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "FINALISE": "Finalize" + }, + "SNACK-BAR": { + "UNSUCCESSFUL-DOI": "Unsuccessful DOI creation", + "SUCCESSFUL-DOI": "Successful DOI creation", + "UNSUCCESSFUL-FINALIZE": "Unsuccessful DMP finalization" + }, + "DATASET-TEMPLATE-LIST": { + "TITLE": "Available Dataset Templates", + "TEXT": "Dataset Profiles selected: ", + "OK": "OK" + } + }, + "DMP-PROFILE-LISTING": { + "TITLE": "DMP Templates", + "COLUMNS": { + "NAME": "Name", + "STATUS": "Status", + "CREATED": "Created", + "PUBLISHED": "Published", + "LAST-EDITED": "Last Edited" + }, + "UPLOAD": { + "UPLOAD-XML": "Import", + "UPLOAD-XML-FILE-TITLE": "Import Data Management Plan Template", + "UPLOAD-XML-NAME": "Name Of DMP Template", + "UPLOAD-XML-IMPORT": "File", + "UPLOAD-XML-FILE-CANCEL": "Cancel" + } + }, + "DYNAMIC-FORM": { + "FIELDS": { + "LABEL": "Label" + }, + "ACTIONS": { + "PREVIEW": "Preview", + "ADD-PAGE": "Add Page +", + "ADD-SECTION": "Add Section +" + } + }, + "CRITERIA": { + "FILTERS": "Filters", + "GRANTS": { + "LIKE": "Search", + "PERIOD-FROM": "Grant Start", + "PERIOD-TO": "Grant End", + "GRANT-STATE-TYPE": "Grant Status", + "TYPES": { + "NONE": "-", + "ON-GOING": "On Going", + "FINISHED": "Finished" + } + }, + "DATASET-PROFILE": { + "LIKE": "Search" + }, + "DATA-SETS": { + "PERIOD-FROM": "Start", + "PERIOD-TO": "End", + "STATUS": "Status", + "NONE": "-", + "TAGS": "Tags", + "SELECT-TAGS": "Select Tags", + "LIKE": "Search Dataset Descriptions", + "SELECT-GRANTS": "Select Grants", + "ROLE": "Role", + "ORGANIZATION": "Organization", + "SELECT-ORGANIZATIONS": "Select Organizations", + "SELECT-SPEC": "Select Dataset Description Specification", + "RELATED-GRANT": "Related Grant", + "SELECT-DMP": "Select DMP", + "RELATED-DMP": "Related DMPs", + "SELECT-COLLABORATORS": "Select Collaborators", + "RELATED-COLLABORATORS": "Related Collaborators", + "SELECT-DATASET-TEMPLATES": "Select Dataset Description Templates", + "RELATED-DATASET-TEMPLATES": "Related Dataset Description Templates", + "ALL-VERSIONS": "From All Versions" + }, + "DMP": { + "LIKE": "Search DMPs", + "GRANTS": "Grants", + "SELECT-GRANTS": "Select Grants", + "SELECT-COLLABORATORS": "Select Collaborators", + "RELATED-COLLABORATORS": "Related Collaborators", + "SELECT-DATASET-TEMPLATES": "Select Dataset Description Templates", + "RELATED-DATASET-TEMPLATES": "Related Dataset Description Templates" + }, + "USERS": { + "LABEL": "Search", + "ROLE": "Role" + }, + "SELECT": "Select an option" + }, + "DATASET-EDITOR": { + "TITLE": { + "NEW": "New Data Management Plan", + "EDIT": "Edit" + }, + "FIELDS": { + "NAME": "Name of the Dataset Description", + "DESCRIPTION": "Description", + "PROFILE": "Template", + "URI": "Uri", + "DMP": "DMP", + "DATAREPOSITORIES": "Data Repositories", + "REGISTRIES": "Registries", + "SERVICES": "Services", + "EXTERNAL-DATASETS": "External Datasets", + "EXTERNAL-DATASETS-DESCRIPTION": "Datasets related to the one being described in the DMP, either utilized for its production or being a derivative or byproduct of its utilization", + "EXTERNAL-DATASET-TYPE": "External Dataset Type", + "EXTERNAL-DATASET-INFO": "External Dataset Info", + "DATAREPOSITORIES-INFO": "Data Repositories Info", + "TAGS": "Tags", + "CREATE": "Create New" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete" + }, + "VERSION-DIALOG": { + "ABOUT": "Versioning is automated.", + "QUESTION": "It seems your Dataset Description Template is outdated. Do you want to update it to the latest version?" + } + }, + "DATASET-CREATE-WIZARD": { + "ACTIONS": { + "NEXT": "Next", + "BACK": "Back", + "SAVE": "Save" + }, + "FIRST-STEP": { + "TITLE": "DMP", + "PLACEHOLDER": "Pick an existing DMP" + } + }, + "INVITATION-EDITOR": { + "TITLE": "Send Invitations for ", + "AUTOCOMPLETE-USER": "User", + "AUTOCOMPLETE-EMAIL": "Email", + "ACTIONS": { + "SEND-INVITATION": "Send Invitations", + "CANCEL": "Cancel" + } + }, + "USERS": { + "LISTING": { + "TITLE": "Users", + "EMAIL": "Email", + "LAST-LOGGED-IN": "Last Logged In", + "LABEL": "Label", + "ROLES": "Roles", + "NAME": "Name", + "PERMISSIONS": "Permissions" + } + }, + "TYPES": { + "APP-ROLE": { + "ADMIN": "Admin", + "USER": "User", + "MANAGER": "Manager" + }, + "DMP-PROFILE-FIELD": { + "DATA-TYPE": { + "DATE": "Date", + "NUMBER": "Number", + "TEXT": "Text", + "EXTERNAL-AUTOCOMPLETE": "External AutoComplete" + }, + "TYPE": { + "INPUT": "Input" + } + }, + "DATASET-STATUS": { + "DRAFT": "Draft", + "FINALISED": "Finalized", + "ANY": "Any", + "DRAFT-DESC": "Draft Registrations" + }, + "DATASET-ROLE": { + "OWNER": "Owner", + "MEMBER": "Member", + "ANY": "Any" + }, + "EXTERNAL-DATASET-TYPE": { + "SOURCE": "Source", + "SOURCES": "Sources", + "SOURCE:": "Source: ", + "NO-SOURCE": "Not bind with source", + "OUTPUT": "Output" + }, + "DMP": { + "FINALISED": "Finalized", + "DRAFT": "Draft" + }, + "DMP-VISIBILITY": { + "VISIBILITY": "Visibility", + "PUBLIC": "Published", + "FINALIZED": "Finalized", + "DRAFT": "Draft", + "ANY": "Any" + }, + "DATASET-PROFILE-FIELD-VALIDATION-TYPE": { + "NONE": "None", + "REQUIRED": "Required" + }, + "DATASET-PROFILE-FIELD-VIEW-STYLE": { + "BOOLEAN-DECISION": "Boolean Decision", + "CHECKBOX": "Checkbox", + "COMBO-BOX": "Combo Box", + "INTERNAL-DMP-ENTITIES": "Internal DMP Entities", + "FREE-TEXT": "Free Text", + "RADIO-BOX": "Radio Box", + "TEXT-AREA": "Text Area", + "DATE-PICKER": "Date Picker" + }, + "DATASET-PROFILE-COMBO-BOX-TYPE": { + "WORD-LIST": "Word List", + "AUTOCOMPLETE": "Autocomplete", + "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)", + "ACTIONS": { + "YES": "Yes", + "NO": "No" + } + }, + "DATASET-PROFILE-INTERNAL-DMP-ENTITIES-TYPE": { + "RESEARCHERS": "Researchers", + "DMPS": "DMPs", + "DATASETS": "Dataset Descriptions", + "EXTERNAL-SOURCE-HINT": "List of values provided by external source(s)" + } + }, + "ADDRESEARCHERS-EDITOR": { + "TITLE": "Add a Researcher", + "FIRST_NAME": "First Name", + "LAST_NAME": "Last Name", + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel" + } + }, + "DMP-WIZARD": { + "FIRST-STEP": { + "DMP": "DMP Editor", + "DATASETS": "Dataset Descriptions" + }, + "ACTIONS": { + "NEXT": "Next", + "BACK": "Back", + "SAVE": "Save" + } + }, + "DMP-RELATED-GRANT": { + "RELATED-GRANT": "Related Grant" + }, + "DMP-RELATED-COLLABORATOR": { + "RELATED-COLLABORATOR": "Related Collaborator", + "SELECT-COLLABORATORS": "Select Collaborators" + }, + "DMP-RELATED-ORGANIZATION": { + "RELATED-ORGANIZATION": "Organization", + "SELECT-ORGANIZATIONS": "Select Organizations" + }, + "DATASET-PROFILE": { + "PREVIEW": "Preview", + "FORM-DESCRIPTION": "Form Description", + "PAGES-DESCRIPTION": "Pages Description" + }, + "RECENT-ACTIVITY": { + "MY-TITLE-GRANT": "My Recent Grant Activity", + "MY-TITLE-DMP": "My Recent DMP Activity", + "MY-TITLE-DATASET": "My Recent Dataset Description Activity", + "LAST-VISITED-DMP": "Last Visited Data Management Plan", + "LAST-EDITED-DMP": "Last Edited Data Management Plan", + "LICENSE": "The DMPs below are public under the ## license of" + }, + "FILE-UPLOADER": { + "DEFAULT": "Choose a file", + "GRANT": "", + "UPLOAD": "Upload" + }, + "URL-LISTING-COMPONENT": { + "SHOW-MORE": "Show more" + }, + "HOMEPAGE": { + "OPEN-DMPS": { + "STATS": "ARGOS Dashboard" + }, + "MY-DMPS": { + "STATS": "My Dashboard" + } + }, + "ABOUT": { + "TITLE": "-About-", + "MAIN-CONTENT": "Our goal is to make your research data FAIR, that is findable, accessible,interoperable and re-usable. These principles precede implementation choices and do not necessarily suggest any specific technology, standard, or implementation solution.", + "CONTRIBUTORS": "Contributors", + "WELCOME": "Welcome to ARGOS", + "WELCOME-MESSAGE": "Create, Link, Share Data Management Plans" + }, + "FOOTER": { + "CONTACT-SUPPORT": "Contact Support", + "FAQ": "FAQ", + "GLOSSARY": "Glossary", + "TERMS-OF-SERVICE": "Terms Of Service", + "PRIVACY-POLICY": "Privacy Policy" + }, + "GLOSSARY": { + "TITLE": "Glossary", + "TITLE-DASHED": "-Glossary-", + "CLOSE": "Close" + }, + "FAQ": { + "TITLE": "FAQ", + "TITLE-DASHED": "-FAQ-", + "CLOSE": "Close" + }, + "PRIVACY-POLICY": { + "TITLE": "-Privacy Policy-", + "MAIN-CONTENT": "" + }, + "TERMS-OF-SERVICE": { + "TITLE": "-Terms Of Service-", + "MAIN-CONTENT": "" + }, + "CONTACT": { + "SUPPORT": { + "TITLE": "Contact Support", + "SUBTITLE": "How can we help you?", + "SUBJECT": "Subject", + "DESCRIPTION": "Description", + "CANCEL": "Cancel", + "SEND": "Send" + }, + "TITLE-DASHED": "-Contact Support-", + "GUIDE": "Guide", + "HELP": "Help", + "GLOSSARY": "Glossary" + }, + "DASHBOARD": { + "MY-GRANTS": "My Grants", + "GRANTS": "Grants", + "MY-DMPS": "My DMPs", + "TITLE": "What is ARGOS?", + "INFO-TEXT": "ARGOS is an open extensible service that simplifies the management, validation, monitoring and maintenance and of Data Management Plans. It allows actors (researchers, managers, supervisors etc) to create actionable DMPs that may be freely exchanged among infrastructures for carrying out specific aspects of the Data management process in accordance with the intentions and commitment of Data owners.", + "ORGANIZATIONS": "Related Organizations", + "DMPS": "DMPs", + "MY-DATASETS": "My Dataset Descriptions", + "DATASETS": "Dataset Descriptions", + "SEARCH": "SEARCH...", + "DATA-MANAGEMENT-PLANS": "DATA MANAGEMENT PLANS" + }, + "USER-DIALOG": { + "USER-PROFILE": "My Profile", + "EXIT": "Exit ", + "LOG-OUT": "Log Out" + }, + "USER-PROFILE": { + "SETTINGS": { + "TITLE": "Settings", + "TIMEZONE": "Time Zone", + "CULTURE": "Culture", + "LANGUAGE": "Lengua" + }, + "ASSOCIATED-DMPS": "Associated DMPs", + "DMPS": { + "SHOW-ALL": "Show All", + "CREATOR": "Creator", + "MEMBER": "Member" + } + }, + "DATASET-REFERENCED-MODELS": { + "SERVICES": { + "TITLE": "Add New Service", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation", + "URI": "Uri" + }, + "DATA-REPOSITORY": { + "TITLE": "Add New Data Repository", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation", + "URI": "Uri" + }, + "EXTERNAL-DATASET": { + "TITLE": "Add New External Dataset Description", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation" + }, + "REGISTRY": { + "TITLE": "Add New Registry", + "LABEL": "Label", + "ABBREVIATION": "Abbreviation", + "URI": "Uri" + } + }, + "FACET-SEARCH": { + "FILTER": "Filter", + "GRANT-STATUS": { + "TITLE": "Grant Status", + "OPTIONS": { + "ANY": "Any", + "ACTIVE": "Active", + "INACTIVE": "Inactive" + } + }, + "GRANT": { + "TITLE": "Related Grant", + "FILTER": "Filter Grants" + }, + "PROFILES": { + "TITLE": "Dataset specification" + }, + "ROLE": { + "TITLE": "Role", + "ANY": "Any", + "OWNER": "Owner", + "MEMBER": "Member" + }, + "DMP-ORGANISATIONS": { + "TITLE": "Organization", + "FILTER": "Filter Organizations" + } + }, + "DMP-FINALISE-DIALOG": { + "DMP": "DMP", + "DATASETS": "Dataset Descriptions", + "EMPTY": "No Dataset Descriptions for this DMP so far", + "SUBMIT": "Submit", + "FINALISE-TITLE": "Do you want to finalize any of the following Draft Dataset Descriptions?", + "ALREADY-FINALISED-DATASETS": "Already Finalized Dataset Descriptions", + "NONE": "None", + "VALIDATION": { + "AT-LEAST-ONE-DATASET-FINALISED": "You need to have at least one Dataset Description Finalized" + }, + "IMPACT": "This action will finalize your DMP, and you won't be able to edit it again.", + "AFTER-FINALIZATION": "After finalizing your DMP you can Publish it, and it'll be publicly available to the ARGOS tool." + }, + "DRAFTS": { + "FOR-DMP": "For DMP:", + "FOR-GRANT": "For Grant:" + }, + "QUICKWIZARD": { + "CREATE-ADD": { + "CREATE": { + "TITLE": "Create new DMP", + "SUBTITLE": "Create a new DMP and describe your Dataset Description(s) guided step by step by our wizard through the most essential elements of a DMP definition.", + "QUICKWIZARD_CREATE": { + "TITLE": "DMP Wizard", + "POST-SELECTION-INFO": "This wizard allows you to create a new DMP supplying just the most essential information required for it and then describe one or more Dataset Descriptions that are managed under this DMP. After finishing through the wizard you will be able to further edit the DMP, accessing its advanced properties, via the full DMP editor, and even add more Dataset Descriptions or editing the previous ones.", + "ACTIONS": { + "DELETE": "Delete", + "SAVE": "Save", + "SAVE-AND-FINALIZE": "Save and Finalize", + "NEXT": "Next", + "BACK": "Back", + "CREATE-NEW-GRANT": "Add Grant", + "EXIST-GRANT": "Use Existing Grant", + "CREATE-NEW-FUNDER": "Add Funder", + "EXIST-FUNDER": "Use Existing Funder", + "CREATE-NEW-PROJECT": "Add Project", + "EXIST-PROJECT": "Use Existing Project" + }, + "FIRST-STEP": { + "TITLE": "Grant", + "ABOUT-GRANT": "Find the grant that your DMP is associated with and link it to funders' information. If the grant is not listed or you are creating a DMP for a grant proposal or for other purposes, use \"Add Grant\"", + "ABOUT-NEW-GRANT": "If you are creating a DMP for a grant proposal, institutional or research community use or training and educational purposes, add information below by creating a new grant.", + "ABOUT-FUNDER": "Find the funder that you wish to associate with the DMP that will be created and then select a grant that funder is linked with. If the funder is not listed, use \"Add Funder\"", + "ABOUT-NEW-FUNDER": "If you you are creating a DMP for a grant proposal, institutional or research community use or training and educational purposes and you wish to associate it with a funder that is not listed then create a new funder", + "ABOUT-PROJECT": "Find the project that your DMP is associated with. If the project is not listed, use \"Add Project\"", + "ABOUT-NEW-PROJECT": "", + "OR": "or", + "FIELDS": { + "SELECT-GRANT": "Select the grant that the DMP is associated with", + "SELECT-FUNDER": "Select the funder of the grant that the DMP is associated with", + "SELECT-PROJECT": "Select the project that the DMP is associated with", + "GRANT-LABEL": "Grant Name", + "FUNDER-LABEL": "Funder Name", + "PROJECT-LABEL": "Project Name", + "LABEL-HINT": "Add the name of the grant as it appears in the call for grant proposal", + "DESCRIPTION": "Description", + "DESCRIPTION-HINT": "Briefly explain the aims and objectives of the grant" + } + }, + "SECOND-STEP": { + "TITLE": "DMP Profile", + "ABOUT": "A Data Management Plan consists of a set of questions that you should answer with a level of detail appropriate to the grant or with relevance to the purpose that you are creating the DMP. Contents of each DMP vary depending on the selected Dataset Description Template(s) which contain(s) a set of tailored questions in response to policy requirements of funders, institutions, research communities.", + "NEW-TITLE": "", + "DMP-NAME": "DMP For Grant : ", + "FIELDS": { + "NAME": "Title of the DMP", + "DESCRIPTION": "Summary", + "DESCRIPTION-HINT": "Briefly describe the context and purpose of the DMP", + "PROFILE": "Dataset Description Template", + "PROFILE-HINT": "Select a template to describe your Dataset Description(s). If you want to select multiple Dataset Description Templates use \"New DMP (Expert)\". You can also add new Dataset Descriptions at any time after the DMP creation.", + "HELP": "If you can't find a template or if you want to create a personalized template for your institution, research community or training needs, please contact us." + } + }, + "THIRD-STEP": { + "TITLE": "Dataset Description", + "NEW-TITLE": "", + "DATASET-LABEL": "Dataset Description Title", + "DATASET-NAME": "Dataset Description: ", + "DATASET-NAME-FOR": " For DMP: ", + "LIST-BUTTON-TOOLTIP": "Dataset Descriptions List", + "ADD-BUTTON-TOOLTIP": "Add Dataset Description" + } + } + }, + "ADD": { + "TITLE": "Add a Dataset Description into an existing DMP", + "DATASET-WIZARD": "Dataset Description Wizard", + "POST-SELECTION-INFO": "This wizard simplifies the process of adding new Dataset Descriptions into existing DMPs, guiding you through and requesting only the most essential pieces of information for completing the task. Full access to the attributes of a Dataset Description can be obtained afterwards via the Dataset Description access menus of the System.", + "SUBTITLE": "This wizard allows you to describe additional Dataset Descriptions managed in the context of a DMP providing only the essential information for their description.", + "CREATED": "Created on" + } + }, + "SAVE-DIALOG": { + "TITLE": "Would you like to add another Dataset Description?", + "ACTIONS": { + "AFFIRMATIVE": "Yes", + "NEGATIVE": "No" + } + }, + "HINT": "(Suggested Default Name)" + } +} diff --git a/dmp-frontend/src/assets/i18n/gr.json b/dmp-frontend/src/assets/i18n/gr.json index 0d5810d52..8004fbc3d 100644 --- a/dmp-frontend/src/assets/i18n/gr.json +++ b/dmp-frontend/src/assets/i18n/gr.json @@ -2,7 +2,15 @@ "GENERAL": { "VALIDATION": { "REQUIRED": "Required" - } + }, + "ACTIONS": { + "LOG-IN": "Είσοδος" + }, + "LANGUAGES": { + "ENGLISH": "Αγγλικά", + "GREEK": "Ελληνικά", + "SPANISH": "Ισπανικά" + } }, "USER-PROFILE": { "SETTINGS": { diff --git a/dmp-frontend/src/assets/images/profile-placeholder.png b/dmp-frontend/src/assets/images/profile-placeholder.png new file mode 100644 index 000000000..c13e0c32f Binary files /dev/null and b/dmp-frontend/src/assets/images/profile-placeholder.png differ diff --git a/dmp-frontend/src/assets/resources/language.json b/dmp-frontend/src/assets/resources/language.json index 4bbfac0ab..e337c2308 100644 --- a/dmp-frontend/src/assets/resources/language.json +++ b/dmp-frontend/src/assets/resources/language.json @@ -1,10 +1,14 @@ [ { - "label": "English", + "label": "GENERAL.LANGUAGES.ENGLISH", "value": "en" }, { - "label": "Greek", + "label": "GENERAL.LANGUAGES.GREEK", "value": "gr" + }, + { + "label": "GENERAL.LANGUAGES.SPANISH", + "value": "es" } ] diff --git a/dmp-frontend/src/common/base/base-enum-utils.service.ts b/dmp-frontend/src/common/base/base-enum-utils.service.ts new file mode 100644 index 000000000..0d5654137 --- /dev/null +++ b/dmp-frontend/src/common/base/base-enum-utils.service.ts @@ -0,0 +1,17 @@ +import { BaseService } from '@common/base/base.service'; + +export abstract class BaseEnumUtilsService extends BaseService { + + public getEnumValues(T): Array { + + //getting all numeric values + const numericValues: T[] = Object.keys(T).map(key => T[key]).filter(value => typeof (value) === 'number'); + if (numericValues.length > 0) { return numericValues; } + + //getting all string values + const stringValues: T[] = Object.keys(T).map(key => T[key]).filter(value => typeof (value) === 'string'); + if (stringValues.length > 0) { return stringValues; } + + return []; + } +} diff --git a/dmp-frontend/src/common/base/base-form-editor-model.ts b/dmp-frontend/src/common/base/base-form-editor-model.ts new file mode 100644 index 000000000..4f414abd5 --- /dev/null +++ b/dmp-frontend/src/common/base/base-form-editor-model.ts @@ -0,0 +1,8 @@ +import { FormBuilder } from '@angular/forms'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; + +export abstract class BaseFormEditorModel { + + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + protected formBuilder: FormBuilder = new FormBuilder(); +} diff --git a/dmp-frontend/src/common/base/base-form-editor.ts b/dmp-frontend/src/common/base/base-form-editor.ts new file mode 100644 index 000000000..9ef8bbc80 --- /dev/null +++ b/dmp-frontend/src/common/base/base-form-editor.ts @@ -0,0 +1,111 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { FormGroup } from '@angular/forms'; +import { MatDialog } from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; +import { BaseFormEditorModel } from '@common/base/base-form-editor-model'; +import { BasePendingChangesComponent } from '@common/base/base-pending-changes.component'; +import { FormService } from '@common/forms/form-service'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@common/modules/notification/ui-notification-service'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +export abstract class BaseFormEditor extends BasePendingChangesComponent { + + isNew = true; + isDeleted = false; + editorModel: EditorModelType; + serverData: FormModel; //To be used only for presentation purposes + formGroup: FormGroup = null; + + abstract deleteItem(id: Guid); + abstract refreshData(): void; + abstract persistForm(onSuccess?: (response) => void): void; + abstract buildForm(): void; + + constructor( + protected dialog: MatDialog, + protected language: TranslateService, + protected formService: FormService, + protected router: Router, + protected route: ActivatedRoute, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + ) { super(); } + + public isFormValid() { + return this.formGroup.valid; + } + + public delete() { + const value = this.formGroup.value; + if (value.id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + data: { + message: this.language.instant('COMMONS.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.deleteItem(value.id); + } + }); + } + } + + public cancel(): void { + this.router.navigate(['/folders']); + } + + onCallbackSuccess(data?: any): 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.refreshOnNavigateToData(data.id); + } + + onCallbackError(errorResponse: HttpErrorResponse) { + const error: HttpError = this.httpErrorHandlingService.getError(errorResponse); + if (error.statusCode === 400) { + this.editorModel.validationErrorModel.fromJSONObject(errorResponse.error); + this.formService.validateAllFormFields(this.formGroup); + } else { + this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning); + } + } + + canDeactivate(): boolean | Observable { + return this.formGroup ? !this.formGroup.dirty : true; + } + + formSubmit(): void { + this.formService.removeAllBackEndErrors(this.formGroup); + this.formService.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { + return; + } + + this.persistForm(complete => { + this.refreshOnNavigateToData(complete.id); + }); + } + + private refreshOnNavigateToData(id: Guid): void { + if (this.isNew) { + this.formGroup.markAsPristine(); + this.router.navigate(['../' + (id)], { relativeTo: this.route }); + } else { this.internalRefreshData(); } + } + + private internalRefreshData(): void { + setTimeout(() => { + this.formGroup = null; + this.editorModel = null; + }); + this.refreshData(); + } +} diff --git a/dmp-frontend/src/common/base/base-http.service.ts b/dmp-frontend/src/common/base/base-http.service.ts new file mode 100644 index 000000000..7ac3735fe --- /dev/null +++ b/dmp-frontend/src/common/base/base-http.service.ts @@ -0,0 +1,39 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +@Injectable() +export class BaseHttpService { + constructor( + protected http: HttpClient + ) { + } + + get(url: string, options?: Object): Observable { + return this.http.get(url, options); + } + + post(url: string, body: any, options?: Object): Observable { + return this.http.post(url, body, options); + } + + put(url: string, body: any, options?: Object): Observable { + return this.http.put(url, body, options); + } + + delete(url: string, options?: Object): Observable { + return this.http.delete(url, options); + } + + patch(url: string, body: any, options?: Object): Observable { + return this.http.patch(url, body, options); + } + + head(url: string, options?: Object): Observable { + return this.http.head(url, options); + } + + options(url: string, options?: Object): Observable { + return this.http.options(url, options); + } +} diff --git a/dmp-frontend/src/common/base/base-pending-changes.component.ts b/dmp-frontend/src/common/base/base-pending-changes.component.ts new file mode 100644 index 000000000..fbf4a98ea --- /dev/null +++ b/dmp-frontend/src/common/base/base-pending-changes.component.ts @@ -0,0 +1,17 @@ +import { HostListener } from '@angular/core'; +import { BaseComponent } from '@common/base/base.component'; +import { Observable } from 'rxjs'; + +export abstract class BasePendingChangesComponent extends BaseComponent { + + protected constructor() { super(); } + + abstract canDeactivate(): boolean | Observable; + + @HostListener('window:beforeunload', ['$event']) + unloadNotification($event: any) { + if (!this.canDeactivate()) { + $event.returnValue = true; + } + } +} diff --git a/dmp-frontend/src/app/core/common/base/base.component.ts b/dmp-frontend/src/common/base/base.component.ts similarity index 100% rename from dmp-frontend/src/app/core/common/base/base.component.ts rename to dmp-frontend/src/common/base/base.component.ts diff --git a/dmp-frontend/src/common/base/base.guard.ts b/dmp-frontend/src/common/base/base.guard.ts new file mode 100644 index 000000000..a4809b6f3 --- /dev/null +++ b/dmp-frontend/src/common/base/base.guard.ts @@ -0,0 +1,14 @@ +import { OnDestroy } from '@angular/core'; +import { Subject } from 'rxjs'; + +export abstract class BaseGuard implements OnDestroy { + + protected _destroyed: Subject = new Subject(); + + protected constructor() { } + + ngOnDestroy(): void { + this._destroyed.next(true); + this._destroyed.complete(); + } +} diff --git a/dmp-frontend/src/common/base/base.pipe.ts b/dmp-frontend/src/common/base/base.pipe.ts new file mode 100644 index 000000000..a36b43efb --- /dev/null +++ b/dmp-frontend/src/common/base/base.pipe.ts @@ -0,0 +1,14 @@ +import { OnDestroy } from '@angular/core'; +import { Subject } from 'rxjs'; + +export abstract class BasePipe implements OnDestroy { + + protected _destroyed: Subject = new Subject(); + + protected constructor() { } + + ngOnDestroy(): void { + this._destroyed.next(true); + this._destroyed.complete(); + } +} diff --git a/dmp-frontend/src/app/core/common/base/base.service.ts b/dmp-frontend/src/common/base/base.service.ts similarity index 100% rename from dmp-frontend/src/app/core/common/base/base.service.ts rename to dmp-frontend/src/common/base/base.service.ts diff --git a/dmp-frontend/src/common/base/tenant-configuration-editor.component.ts b/dmp-frontend/src/common/base/tenant-configuration-editor.component.ts new file mode 100644 index 000000000..46c632d1b --- /dev/null +++ b/dmp-frontend/src/common/base/tenant-configuration-editor.component.ts @@ -0,0 +1,20 @@ +import { FormControl } from '@angular/forms'; +import { BaseComponent } from '@common/base/base.component'; + +export abstract class TenantConfigurationBaseComponent extends BaseComponent { + + readonly secretValue: string = '1784E159-C809-4F3F-AC8F-90F98B04B01D'; + shouldShowEditSecret: Map = new Map(); + + protected constructor() { super(); } + + editSecret(formControl: FormControl, formControlName: string) { + this.shouldShowEditSecret.set(formControlName, true); + formControl.setValue(undefined); + } + + cancelEditSecret(formControl: FormControl, formControlName: string) { + this.shouldShowEditSecret.delete(formControlName); + formControl.setValue(this.secretValue); + } +} diff --git a/dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts b/dmp-frontend/src/common/date/moment-utc-date-adapter.ts similarity index 93% rename from dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts rename to dmp-frontend/src/common/date/moment-utc-date-adapter.ts index 659926878..0b3ca383d 100644 --- a/dmp-frontend/src/app/common/date/moment-utc-date-adapter.ts +++ b/dmp-frontend/src/common/date/moment-utc-date-adapter.ts @@ -36,7 +36,8 @@ export class MomentUtcDateAdapter extends MomentDateAdapter { // manually writing on the textbox parse(value: any, parseFormat: string | string[]): Moment | null { const initialParse = super.parse(value, parseFormat); - if (initialParse === null || !initialParse.isValid()) { return initialParse; } + if (initialParse == null) { return null }; + if (!initialParse.isValid()) { return initialParse; } const result = moment.utc({ year: initialParse.year(), month: initialParse.month(), date: initialParse.date() }).locale(this.locale); return result; diff --git a/dmp-frontend/src/app/common/forms/common-forms.module.ts b/dmp-frontend/src/common/forms/common-forms.module.ts similarity index 55% rename from dmp-frontend/src/app/common/forms/common-forms.module.ts rename to dmp-frontend/src/common/forms/common-forms.module.ts index 13f128841..cea6b2aab 100644 --- a/dmp-frontend/src/app/common/forms/common-forms.module.ts +++ b/dmp-frontend/src/common/forms/common-forms.module.ts @@ -1,5 +1,7 @@ import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { PendingChangesGuard } from '@common/forms/pending-form-changes/pending-form-changes-guard.service'; +import { FormService } from './form-service'; @NgModule({ imports: [ @@ -9,6 +11,10 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; exports: [ FormsModule, ReactiveFormsModule, + ], + providers: [ + FormService, + PendingChangesGuard ] }) export class CommonFormsModule { } diff --git a/dmp-frontend/src/common/forms/form-service.ts b/dmp-frontend/src/common/forms/form-service.ts new file mode 100644 index 000000000..3bb75fa85 --- /dev/null +++ b/dmp-frontend/src/common/forms/form-service.ts @@ -0,0 +1,81 @@ +import { Injectable } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; + +@Injectable() +export class FormService { + + constructor() { + } + + public validateAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.updateValueAndValidity({ emitEvent: false }); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.validateAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.validateAllFormFields(item); + }); + } + } + + public touchAllFormFields(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + formControl.markAsTouched(); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.touchAllFormFields(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.touchAllFormFields(item); + }); + } + } + + public removeAllBackEndErrors(formControl: AbstractControl) { + if (formControl instanceof FormControl) { + this.removeError(formControl, 'backendError'); + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + this.removeAllBackEndErrors(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + this.removeAllBackEndErrors(item); + }); + } + } + + public removeError(control: FormControl, error: string) { + const err = control.errors; + if (err && err[error]) { + delete err[error]; + if (!Object.keys(err).length) { + control.setErrors(null); // Make control Valid again + } else { + control.setErrors(err); // if there are others errors left attach them back to the control + } + } + } + + public getValue(control: AbstractControl) { + return JSON.parse(JSON.stringify(control.value)); //Used to deep copy formGroup. + } + + // TODO + // public reapplyValidators(array: FormArray, validationContext: ValidationContext) { + // if (!Array.isArray(array.controls)) { return; } + // array.controls.forEach((element, index) => { + // const formGroup = element as FormGroup; + // Object.keys(formGroup.controls).forEach(key => { + // formGroup.get(key).setValidators(validationContext.getValidation(key).validators); + // }); + // }); + // } +} diff --git a/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.html b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.html new file mode 100644 index 000000000..1126efc31 --- /dev/null +++ b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.html @@ -0,0 +1,11 @@ +
+

{{'GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.WARNING' | translate}}

+
+
    +
  • {{error}}
  • +
+
+
+ +
+
diff --git a/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.scss b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.scss new file mode 100644 index 000000000..66c7f2cf2 --- /dev/null +++ b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.scss @@ -0,0 +1,5 @@ +#warningText { + color: red; + text-decoration: underline; + text-decoration-color: red; +} \ No newline at end of file diff --git a/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.ts b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.ts new file mode 100644 index 000000000..2e2b31be6 --- /dev/null +++ b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component.ts @@ -0,0 +1,78 @@ +import { Component, Inject } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'app-form-validation-errors-dialog', + templateUrl: './form-validation-errors-dialog.component.html', + styleUrls: ['./form-validation-errors-dialog.component.scss'] +}) +export class FormValidationErrorsDialogComponent { + + formGroup: FormGroup; + errorMessages: string[] = []; + + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private language: TranslateService + ) { + this.formGroup = data.formGroup; + this.errorMessages = this.getErrors(this.formGroup); + } + + onClose(): void { + this.dialogRef.close(); + } + + public getErrors(formControl: AbstractControl): string[] { + const errors: string[] = []; + if (formControl instanceof FormControl) { + if (formControl.invalid && formControl['nativeElement']) { errors.push(...this.getErrorMessage(formControl)); } + } else if (formControl instanceof FormGroup) { + if (formControl.errors) { (errors.push(...Object.values(formControl.errors).map(x => x.message) as string[])); } + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + errors.push(...this.getErrors(control)); + }); + } else if (formControl instanceof FormArray) { + if (formControl.errors) { (errors.push(...Object.values(formControl.errors).map(x => x.message) as string[])); } + formControl.controls.forEach(item => { + errors.push(...this.getErrors(item)); + }); + } + return errors; + } + + getErrorMessage(formControl: FormControl): string[] { + const errors: string[] = []; + Object.keys(formControl.errors).forEach(key => { + if (key === 'required') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED')); } + else if (key === 'email') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.EMAIL')); } + else if (key === 'min') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.MIN-VALUE', { 'min': formControl.getError('min').min })); } + else if (key === 'max') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.MAX-VALUE', { 'max': formControl.getError('max').max })); } + else { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + formControl.errors[key].message); } + }); + return errors; + } + + getPlaceHolder(formControl: any): string { + // if (formControl.nativeElement.localName === 'input') { + // return formControl.nativeElement.getAttribute('placeholder'); + // } else if (formControl.nativeElement.localName === 'mat-select') { + // return formControl.nativeElement.getAttribute('aria-label'); + // } else if (formControl.nativeElement.localName === 'app-single-auto-complete') { + // return (Array.from(formControl.nativeElement.firstChild.children).filter((x: any) => x.localName === 'input')[0] as any).getAttribute('placeholder'); + // } else if (formControl.nativeElement.localName === 'app-multiple-auto-complete') { + // return (Array.from(formControl.nativeElement.firstChild.children).filter((x: any) => x.localName === 'input')[0] as any).getAttribute('placeholder'); + // } + + let result = ''; + try { + result = (Array.from(formControl.nativeElement.parentElement.children).filter((x: any) => Array.from(x.classList).includes('mat-form-field-label-wrapper'))[0] as any).innerText; + result = result.replace(' *', ''); + } catch (error) { } + + return result; + } +} diff --git a/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module.ts b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module.ts new file mode 100644 index 000000000..fad8c4028 --- /dev/null +++ b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core'; +import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component'; +import { FormValidationErrorsDirective } from '@common/forms/form-validation-errors-dialog/form-validation-errors-directive'; +import { CommonUiModule } from '@common/ui/common-ui.module'; + +@NgModule({ + imports: [ + CommonUiModule, + ], + exports: [ + FormValidationErrorsDialogComponent, + FormValidationErrorsDirective + ], + declarations: [ + FormValidationErrorsDialogComponent, + FormValidationErrorsDirective + ], + entryComponents: [ + FormValidationErrorsDialogComponent + ], + providers: [ + FormValidationErrorsDirective + ] +}) +export class FormValidationErrorsDialogModule { } diff --git a/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-directive.ts b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-directive.ts new file mode 100644 index 000000000..60724499a --- /dev/null +++ b/dmp-frontend/src/common/forms/form-validation-errors-dialog/form-validation-errors-directive.ts @@ -0,0 +1,20 @@ +import { Directive, ElementRef, OnInit } from '@angular/core'; +import { NgControl } from '@angular/forms'; + +@Directive({ + selector: '[formControl], [formControlName]' +}) +export class FormValidationErrorsDirective implements OnInit { + get control() { + return this.controlDir.control; + } + + constructor( + private controlDir: NgControl, + private host: ElementRef) { + } + + ngOnInit() { + (this.controlDir.control as any).nativeElement = this.host.nativeElement; + } +} diff --git a/dmp-frontend/src/common/forms/pending-form-changes/pending-form-changes-guard.service.ts b/dmp-frontend/src/common/forms/pending-form-changes/pending-form-changes-guard.service.ts new file mode 100644 index 000000000..c8a5166d9 --- /dev/null +++ b/dmp-frontend/src/common/forms/pending-form-changes/pending-form-changes-guard.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { CanDeactivate } from '@angular/router'; +import { BasePendingChangesComponent } from '@common/base/base-pending-changes.component'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { TranslateService } from '@ngx-translate/core'; +import { from, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +@Injectable() +export class PendingChangesGuard implements CanDeactivate { + + constructor( + private dialog: MatDialog, + private language: TranslateService + ) { + } + + canDeactivate(component: BasePendingChangesComponent): boolean | Observable { + if (component.canDeactivate()) { + return from([true]); + } else { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + data: { + message: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.MESSAGE'), + cancelButton: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.ACTIONS.NO'), + confirmButton: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.ACTIONS.YES') + } + }); + return dialogRef.afterClosed().pipe(map(x => x ? true : false)); + } + } +} diff --git a/dmp-frontend/src/common/forms/validation/custom-validator.ts b/dmp-frontend/src/common/forms/validation/custom-validator.ts new file mode 100644 index 000000000..9854d1d4d --- /dev/null +++ b/dmp-frontend/src/common/forms/validation/custom-validator.ts @@ -0,0 +1,100 @@ +import { AbstractControl, ValidatorFn, Validators } from '@angular/forms'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; +import { isNullOrUndefined } from 'util'; + +export function BackendErrorValidator(errorModel: ValidationErrorModel, propertyName: string): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const error: string = errorModel.getError(propertyName); + return error ? { 'backendError': { message: error } } : null; + }; +} + +export function E164PhoneValidator(): ValidatorFn { + return Validators.pattern('^\\+?[1-9]\\d{1,14}$'); +} + +// Getter is required because the index of each element is not fixed (array does not always follow LIFO) +export function BackendArrayErrorValidator(errorModel: ValidationErrorModel, propertyNameGetter: () => string): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const error: string = errorModel.getError(propertyNameGetter()); + return error ? { 'backendError': { message: error } } : null; + }; +} + +export function CustomErrorValidator(errorModel: ValidationErrorModel, propertyNames: string[]): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const error: string = errorModel.getErrors(propertyNames); + return error ? { 'customError': { message: error } } : null; + }; +} + +export function DateValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + if (control.value) { + const dateString: string[] = control.value.split('-'); + const yearString = dateString.length > 0 ? dateString[0].replace(/_/g, '') : null; + const monthString = dateString.length > 1 ? dateString[1].replace(/_/g, '') : null; + const dayString = dateString.length > 2 ? dateString[2].replace(/_/g, '') : null; + let yearParsed: number = null; + let monthParsed: number = null; + let dayParsed: number = null; + + if (!isNullOrUndefined(yearString) && yearString.length === 4 && Number(yearString) !== NaN) { + yearParsed = Number(yearString); + } + if (!isNullOrUndefined(monthString) && monthString.length > 0 && Number(monthString) !== NaN) { + monthParsed = Number(monthString); + } + if (!isNullOrUndefined(dayString) && dayString.length > 0 && Number(dayString) !== NaN) { + dayParsed = Number(dayString); + } + + if ((dayParsed && (!monthParsed || !yearParsed)) || (monthParsed && !yearParsed) || !yearParsed) { + return { 'invalidDate': true }; + } + + const current_date = new Date(); + yearParsed = yearParsed ? yearParsed : current_date.getFullYear(); + monthParsed = monthParsed ? monthParsed - 1 : current_date.getMonth(); + dayParsed = dayParsed ? dayParsed : 1; + + //due to autocorrection of Date objects + const d = new Date(yearParsed, monthParsed, dayParsed); + if (d.getFullYear() === yearParsed && d.getMonth() === monthParsed && d.getDate() === dayParsed) { + return null; + } + return { 'invalidDate': true }; + } + return null; + }; +} + +export function DateFromToValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + if (control.get('fromTime').value && control.get('toTime').value) { + const fromDate = new Date(control.get('fromTime').value); + const toDate = new Date(control.get('toTime').value); + if (fromDate <= toDate) { return null; } + return { 'invalidFromToDate': true }; + } + return null; + }; +} + +export function EmailMatchValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + return control.get('email').value === control.get('emailConfirm').value ? null : { 'emailMismatch': true }; + }; +} + +export function PasswordMatchValidator(passwordControlName: string, repeatPasswordControlName: string): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + const passwordControl = control.get(passwordControlName); + const passwordRepeatControl = control.get(repeatPasswordControlName); + + if (passwordControl && passwordControl.value && passwordRepeatControl && passwordRepeatControl.value && passwordControl.value !== passwordRepeatControl.value) { + return { 'passwordMismatch': true }; + } + return null; + }; +} diff --git a/dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts b/dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts similarity index 97% rename from dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts rename to dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts index 21eec2772..86dca530e 100644 --- a/dmp-frontend/src/app/common/forms/validation/error-model/validation-error-model.ts +++ b/dmp-frontend/src/common/forms/validation/error-model/validation-error-model.ts @@ -1,4 +1,4 @@ -import { Serializable } from '../../../types/json/serializable'; +import { Serializable } from '@common/types/json/serializable'; export class ValidationErrorModel implements Serializable { public error: string; diff --git a/dmp-frontend/src/app/common/forms/validation/validation-context.ts b/dmp-frontend/src/common/forms/validation/validation-context.ts similarity index 100% rename from dmp-frontend/src/app/common/forms/validation/validation-context.ts rename to dmp-frontend/src/common/forms/validation/validation-context.ts diff --git a/dmp-frontend/src/app/common/http/base-http-params.ts b/dmp-frontend/src/common/http/base-http-params.ts similarity index 100% rename from dmp-frontend/src/app/common/http/base-http-params.ts rename to dmp-frontend/src/common/http/base-http-params.ts diff --git a/dmp-frontend/src/app/common/http/common-http.module.ts b/dmp-frontend/src/common/http/common-http.module.ts similarity index 100% rename from dmp-frontend/src/app/common/http/common-http.module.ts rename to dmp-frontend/src/common/http/common-http.module.ts diff --git a/dmp-frontend/src/common/http/image/secure-image.pipe.ts b/dmp-frontend/src/common/http/image/secure-image.pipe.ts new file mode 100644 index 000000000..61052fdc7 --- /dev/null +++ b/dmp-frontend/src/common/http/image/secure-image.pipe.ts @@ -0,0 +1,16 @@ +import { HttpClient } from '@angular/common/http'; +import { Pipe, PipeTransform } from '@angular/core'; +import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; +import { BasePipe } from '@common/base/base.pipe'; +import { Observable } from 'rxjs'; +import { map, takeUntil } from 'rxjs/operators'; + +@Pipe({ name: 'secureImage' }) +export class SecureImagePipe extends BasePipe implements PipeTransform { + + constructor(private http: HttpClient, private sanitizer: DomSanitizer) { super(); } + + transform(url): Observable { + return this.http.get(url, { responseType: 'blob' }).pipe(takeUntil(this._destroyed), map(val => this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(val)))); + } +} diff --git a/dmp-frontend/src/app/common/http/interceptor-context.ts b/dmp-frontend/src/common/http/interceptor-context.ts similarity index 100% rename from dmp-frontend/src/app/common/http/interceptor-context.ts rename to dmp-frontend/src/common/http/interceptor-context.ts diff --git a/dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts b/dmp-frontend/src/common/http/interceptors/auth-token.interceptor.ts similarity index 91% rename from dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/auth-token.interceptor.ts index 3f37fd4ba..41b5443b9 100644 --- a/dmp-frontend/src/app/common/http/interceptors/auth-token.interceptor.ts +++ b/dmp-frontend/src/common/http/interceptors/auth-token.interceptor.ts @@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { BaseInterceptor } from './base.interceptor'; import { InterceptorType } from './interceptor-type'; -import { AuthService } from '../../../core/services/auth/auth.service'; +import { AuthService } from '../../../app/core/services/auth/auth.service'; @Injectable() export class AuthTokenInterceptor extends BaseInterceptor { diff --git a/dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts b/dmp-frontend/src/common/http/interceptors/base.interceptor.ts similarity index 94% rename from dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/base.interceptor.ts index 7918c5f0a..13374a21f 100644 --- a/dmp-frontend/src/app/common/http/interceptors/base.interceptor.ts +++ b/dmp-frontend/src/common/http/interceptors/base.interceptor.ts @@ -2,7 +2,7 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/c import { Observable } from 'rxjs'; import { BaseHttpParams } from '../base-http-params'; import { InterceptorType } from './interceptor-type'; -import { environment } from '../../../../environments/environment'; +import { environment } from '../../../environments/environment'; export abstract class BaseInterceptor implements HttpInterceptor { diff --git a/dmp-frontend/src/app/common/http/interceptors/interceptor-type.ts b/dmp-frontend/src/common/http/interceptors/interceptor-type.ts similarity index 100% rename from dmp-frontend/src/app/common/http/interceptors/interceptor-type.ts rename to dmp-frontend/src/common/http/interceptors/interceptor-type.ts diff --git a/dmp-frontend/src/app/common/http/interceptors/json.interceptor.ts b/dmp-frontend/src/common/http/interceptors/json.interceptor.ts similarity index 100% rename from dmp-frontend/src/app/common/http/interceptors/json.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/json.interceptor.ts diff --git a/dmp-frontend/src/app/common/http/interceptors/locale.interceptor.ts b/dmp-frontend/src/common/http/interceptors/locale.interceptor.ts similarity index 100% rename from dmp-frontend/src/app/common/http/interceptors/locale.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/locale.interceptor.ts diff --git a/dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts b/dmp-frontend/src/common/http/interceptors/progress-indication.interceptor.ts similarity index 87% rename from dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/progress-indication.interceptor.ts index c472b1e12..939d25f41 100644 --- a/dmp-frontend/src/app/common/http/interceptors/progress-indication.interceptor.ts +++ b/dmp-frontend/src/common/http/interceptors/progress-indication.interceptor.ts @@ -2,7 +2,7 @@ import { HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { finalize } from 'rxjs/operators'; -import { ProgressIndicationService } from '../../../core/services/progress-indication/progress-indication-service'; +import { ProgressIndicationService } from '../../../app/core/services/progress-indication/progress-indication-service'; import { BaseInterceptor } from './base.interceptor'; import { InterceptorType } from './interceptor-type'; diff --git a/dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts b/dmp-frontend/src/common/http/interceptors/request-timing.interceptor.ts similarity index 92% rename from dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/request-timing.interceptor.ts index 869674c69..295701614 100644 --- a/dmp-frontend/src/app/common/http/interceptors/request-timing.interceptor.ts +++ b/dmp-frontend/src/common/http/interceptors/request-timing.interceptor.ts @@ -2,7 +2,7 @@ import { HttpEvent, HttpHandler, HttpRequest, HttpResponse } from '@angular/comm import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; -import { LoggingService } from '../../../core/services/logging/logging-service'; +import { LoggingService } from '../../../app/core/services/logging/logging-service'; import { BaseInterceptor } from './base.interceptor'; import { InterceptorType } from './interceptor-type'; diff --git a/dmp-frontend/src/app/common/http/interceptors/response-payload.interceptor.ts b/dmp-frontend/src/common/http/interceptors/response-payload.interceptor.ts similarity index 100% rename from dmp-frontend/src/app/common/http/interceptors/response-payload.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/response-payload.interceptor.ts diff --git a/dmp-frontend/src/app/common/http/interceptors/status-code.interceptor.ts b/dmp-frontend/src/common/http/interceptors/status-code.interceptor.ts similarity index 100% rename from dmp-frontend/src/app/common/http/interceptors/status-code.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/status-code.interceptor.ts diff --git a/dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts b/dmp-frontend/src/common/http/interceptors/unauthorized-response.interceptor.ts similarity index 97% rename from dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts rename to dmp-frontend/src/common/http/interceptors/unauthorized-response.interceptor.ts index 2417f00dd..542df6dac 100644 --- a/dmp-frontend/src/app/common/http/interceptors/unauthorized-response.interceptor.ts +++ b/dmp-frontend/src/common/http/interceptors/unauthorized-response.interceptor.ts @@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { Observable, throwError } from 'rxjs'; import { catchError, mergeMap, tap } from 'rxjs/operators'; -import { AuthService } from '../../../core/services/auth/auth.service'; +import { AuthService } from '../../../app/core/services/auth/auth.service'; import { BaseInterceptor } from './base.interceptor'; import { InterceptorType } from './interceptor-type'; diff --git a/dmp-frontend/src/app/common/material/material.module.ts b/dmp-frontend/src/common/material/material.module.ts similarity index 100% rename from dmp-frontend/src/app/common/material/material.module.ts rename to dmp-frontend/src/common/material/material.module.ts diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.html b/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.html similarity index 100% rename from dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.html rename to dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.html diff --git a/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.scss b/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.scss new file mode 100644 index 000000000..a0856d4a9 --- /dev/null +++ b/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.scss @@ -0,0 +1,45 @@ +.confirmation-dialog { + .confirmation { + padding-bottom: 20px; + } + + .privacy-policy-names { + font-weight: 700; + padding: 1em; + } + + .close-btn { + margin-left: auto; + cursor: pointer; + } + + .warn-text { + color: #f44336; + } + + .cancel { + background-color: #aaaaaa; + color: #ffffff; + } + + .confirm { + background-color: #2cba6c; + color: #ffffff; + } + + .delete { + background-color: #ba2c2c; + color: #ffffff; + } + + .checkbox-privacy { + padding: 0em 1em; + } + + .required-policy { + padding: 0em 1.2em 1em; + font-size: smaller; + color: #f44336; + } + } + \ No newline at end of file diff --git a/dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.ts b/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.ts similarity index 100% rename from dmp-frontend/src/app/library/confirmation-dialog/confirmation-dialog.component.ts rename to dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.component.ts diff --git a/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.module.ts b/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.module.ts new file mode 100644 index 000000000..124fea2f1 --- /dev/null +++ b/dmp-frontend/src/common/modules/confirmation-dialog/confirmation-dialog.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { CommonUiModule } from '@common/ui/common-ui.module'; + +@NgModule({ + imports: [CommonUiModule, FormsModule], + declarations: [ConfirmationDialogComponent], + exports: [ConfirmationDialogComponent], + entryComponents: [ConfirmationDialogComponent] +}) +export class ConfirmationDialogModule { + constructor() { } +} diff --git a/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts b/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts new file mode 100644 index 000000000..754a6a8c9 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/error-handling/http-error-handling.service.ts @@ -0,0 +1,67 @@ +import { HttpErrorResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +@Injectable() +export class HttpErrorHandlingService { + constructor( + protected language: TranslateService + ) { + } + + getError(errorResponse: HttpErrorResponse): HttpError { + const error: HttpError = new HttpError(); + error.statusCode = errorResponse.status; + error.messages = this.parseMessages(error.statusCode, errorResponse); + + // if (error && error.error && error.error.error) { + // errorMsg = error.error.error; + // // } else if (error && error.message) { + // // errorMsg = error.message; + // // } else if (error) { + // // errorMsg = error; + // } else { + // errorMsg = language.instant('COMMONS.ERRORS.DEFAULT'); + // } + return error; + } + + private parseMessages(httpStatusCode: number, errorPayload: any): string[] { + const result: string[] = []; + switch (httpStatusCode) { + case 400: // Bad Request, Used for validation errors. + if (errorPayload && errorPayload.error && errorPayload.error.error_description) { result.push(errorPayload.error.error_description); } + else if (errorPayload && errorPayload.error && errorPayload.error.error) { result.push(errorPayload.error.error); } + else if (errorPayload && errorPayload.message) { result.push(errorPayload.message); } + break; + case 404: // Not Found + if (errorPayload && errorPayload.error && errorPayload.error.error_description) { result.push(errorPayload.error.error_description); } + else if (errorPayload && errorPayload.error && errorPayload.error.error) { result.push(errorPayload.error.error); } + else if (errorPayload && errorPayload.message) { result.push(errorPayload.message); } + break; + case 500: // Bad Request, Used for validation errors. + if (errorPayload && errorPayload.error && errorPayload.error.error_description) { result.push(errorPayload.error.error_description); } + else if (errorPayload && errorPayload.error && errorPayload.error.error) { result.push(errorPayload.error.error); } + else if (errorPayload && errorPayload.message) { result.push(errorPayload.message); } + break; + default: + if (errorPayload && errorPayload.error && errorPayload.error.error_description) { result.push(errorPayload.error.error_description); } + else if (errorPayload && errorPayload.error && errorPayload.error.error) { result.push(errorPayload.error.error); } + else if (errorPayload && errorPayload.message) { result.push(errorPayload.message); } + break; + } + + if (result.length === 0) { result.push(this.language.instant('COMMONS.ERRORS.DEFAULT')); } + + return result; + } +} + +export class HttpError { + statusCode: number; + messages: string[]; + + getMessagesString(): string { + return this.messages ? this.messages.join(', ') : null; + } +} diff --git a/dmp-frontend/src/common/modules/errors/errors-component/errors.component.html b/dmp-frontend/src/common/modules/errors/errors-component/errors.component.html new file mode 100644 index 000000000..02396e756 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/errors-component/errors.component.html @@ -0,0 +1,34 @@ +
+
+
+
+

ERROR {{ data?.error}}

+
Not found :(
+ +
Go Home
+
+
+ +
+ +

ERROR {{ routeParams?.status }}


+

{{ routeParams?.message }}


+

Error in {{ routeParams?.url }} page, sorry :(

+

This error has been reported to the Administrator with the ID:
{{ routeParams?.id}}

+ +
Go Back to {{routeParams?.url}}
+
+ +
Go Back to home
+
+
+ +
+

Unknown error, sorry :(

+ +
Go Home
+
+
+
+
+
diff --git a/dmp-frontend/src/common/modules/errors/errors-component/errors.component.scss b/dmp-frontend/src/common/modules/errors/errors-component/errors.component.scss new file mode 100644 index 000000000..b4f6062e5 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/errors-component/errors.component.scss @@ -0,0 +1,14 @@ +h1, +h3, +h4, +h5 { + margin-bottom: 0; + margin-top: 10px; +} + +.error-container { + margin-top: auto; + margin-bottom: auto; + text-align: center; + overflow-wrap: break-word; +} diff --git a/dmp-frontend/src/common/modules/errors/errors-component/errors.component.ts b/dmp-frontend/src/common/modules/errors/errors-component/errors.component.ts new file mode 100644 index 000000000..7b6fc0155 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/errors-component/errors.component.ts @@ -0,0 +1,21 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-error', + templateUrl: './errors.component.html', + styleUrls: ['./errors.component.scss'] +}) +export class ErrorsComponent implements OnInit { + routeParams; + data; + + constructor( + private activatedRoute: ActivatedRoute, + ) { } + + ngOnInit() { + this.routeParams = this.activatedRoute.snapshot.queryParams; + this.data = this.activatedRoute.snapshot.data; + } +} diff --git a/dmp-frontend/src/common/modules/errors/errors-handler/errors-handler.ts b/dmp-frontend/src/common/modules/errors/errors-handler/errors-handler.ts new file mode 100644 index 000000000..77b954a4f --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/errors-handler/errors-handler.ts @@ -0,0 +1,51 @@ + +import { HttpErrorResponse } from '@angular/common/http'; +import { ErrorHandler, Injectable, Injector } from '@angular/core'; +import { Router } from '@angular/router'; +import { SnackBarNotificationLevel, UiNotificationService } from '@common/modules/notification/ui-notification-service'; +import { TranslateService } from '@ngx-translate/core'; + +@Injectable() +export class ErrorsHandler implements ErrorHandler { + + private _notificationService; + // private _errorService; + private _router; + private _language; + + constructor( + private injector: Injector, + ) { + + } + + handleError(error: Error | HttpErrorResponse) { + this._notificationService = this.injector.get(UiNotificationService); + // this._errorService = this.injector.get(ErrorService); + this._router = this.injector.get(Router); + this._language = this.injector.get(TranslateService); + + if (error instanceof HttpErrorResponse) { + // Server error happened + if (!navigator.onLine) { + // No Internet connection + return this._notificationService.snackBarNotification(this._language.instant('ERROR-HANDLER.GLOBAL.NO-INTERNET'), SnackBarNotificationLevel.Error); + } + // Http Error + // Send the error to the server + // this._errorService.log(error).subscribe(); + // Show notification to the user + return this._notificationService.snackBarNotification(`${error.status} - ${error.message}`, SnackBarNotificationLevel.Error); + } else { + // Client Error Happend + // Send the error to the server and then + // redirect the user to the page with all the info + // this._errorService + // .log(error) + // .subscribe(errorWithContextInfo => { + // this._router.navigate(['/error'], { queryParams: errorWithContextInfo }); + // }); + } + } +} + diff --git a/dmp-frontend/src/common/modules/errors/errors-routing/errors-routing.module.ts b/dmp-frontend/src/common/modules/errors/errors-routing/errors-routing.module.ts new file mode 100644 index 000000000..c95dd35c7 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/errors-routing/errors-routing.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { ErrorsComponent } from '@common/modules/errors/errors-component/errors.component'; + +const routes: Routes = [ + { path: 'error', component: ErrorsComponent }, + { path: '**', loadChildren: () => import('@common/modules/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule) }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ErrorRoutingModule { } diff --git a/dmp-frontend/src/common/modules/errors/errors.module.ts b/dmp-frontend/src/common/modules/errors/errors.module.ts new file mode 100644 index 000000000..d630e7a17 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/errors.module.ts @@ -0,0 +1,34 @@ +import { CommonModule } from '@angular/common'; +import { HTTP_INTERCEPTORS } from '@angular/common/http'; +import { ErrorHandler, NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +// import { ExternalTracingService } from '@app/core/services/http/external-tracing.service'; +import { ErrorsComponent } from '@common/modules/errors/errors-component/errors.component'; +import { ErrorsHandler } from '@common/modules/errors/errors-handler/errors-handler'; +import { ErrorRoutingModule } from '@common/modules/errors/errors-routing/errors-routing.module'; +import { ServerErrorsInterceptor } from '@common/modules/errors/server-errors-interceptor/server-errors.interceptor'; + +@NgModule({ + imports: [ + CommonModule, + RouterModule, + ErrorRoutingModule, + ], + declarations: [ + ErrorsComponent + ], + providers: [ + // ErrorService, + // ExternalTracingService, + { + provide: ErrorHandler, + useClass: ErrorsHandler, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ServerErrorsInterceptor, + multi: true + }, + ] +}) +export class ErrorsModule { } diff --git a/dmp-frontend/src/common/modules/errors/external-tracing/external-trace-entry.ts b/dmp-frontend/src/common/modules/errors/external-tracing/external-trace-entry.ts new file mode 100644 index 000000000..8af4afb37 --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/external-tracing/external-trace-entry.ts @@ -0,0 +1,20 @@ +export interface ExternalTraceEntry { + eventId: EventId; + level: ExternalTraceLogLevel; + message: string; + data: any; +} + +export interface EventId { + id: number; +} + +export enum ExternalTraceLogLevel { + Trace = 0, + Debug = 1, + Information = 2, + Warning = 3, + Error = 4, + Critical = 5, + None = 6 +} diff --git a/dmp-frontend/src/common/modules/errors/server-errors-interceptor/server-errors.interceptor.ts b/dmp-frontend/src/common/modules/errors/server-errors-interceptor/server-errors.interceptor.ts new file mode 100644 index 000000000..c652d028e --- /dev/null +++ b/dmp-frontend/src/common/modules/errors/server-errors-interceptor/server-errors.interceptor.ts @@ -0,0 +1,13 @@ +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { retry } from 'rxjs/operators'; + +@Injectable() +export class ServerErrorsInterceptor implements HttpInterceptor { + constructor() { } + intercept(request: HttpRequest, next: HttpHandler): Observable> { + + return next.handle(request); //TODO: possibly we want to retry here using: .pipe(retry(5)); + } +} diff --git a/dmp-frontend/src/common/modules/notification/popup/popup-notification.component.html b/dmp-frontend/src/common/modules/notification/popup/popup-notification.component.html new file mode 100644 index 000000000..a06d796e6 --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/popup/popup-notification.component.html @@ -0,0 +1,5 @@ +

{{notification.title}}

+{{notification.message}} + + + diff --git a/dmp-frontend/src/common/modules/notification/popup/popup-notification.component.ts b/dmp-frontend/src/common/modules/notification/popup/popup-notification.component.ts new file mode 100644 index 000000000..04622b096 --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/popup/popup-notification.component.ts @@ -0,0 +1,16 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { PopupNotification } from '@common/modules/notification/ui-notification-service'; + +@Component({ + selector: 'app-popup-notification-dialog', + templateUrl: './popup-notification.component.html' +}) +export class PopupNotificationDialogComponent { + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public notification: PopupNotification + ) { + } +} diff --git a/dmp-frontend/src/common/modules/notification/snack-bar/snack-bar-notification.component.html b/dmp-frontend/src/common/modules/notification/snack-bar/snack-bar-notification.component.html new file mode 100644 index 000000000..75af56131 --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/snack-bar/snack-bar-notification.component.html @@ -0,0 +1 @@ +{{message}} diff --git a/dmp-frontend/src/common/modules/notification/snack-bar/snack-bar-notification.component.ts b/dmp-frontend/src/common/modules/notification/snack-bar/snack-bar-notification.component.ts new file mode 100644 index 000000000..55db60951 --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/snack-bar/snack-bar-notification.component.ts @@ -0,0 +1,15 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar'; +import { SnackBarNotification } from '@common/modules/notification/ui-notification-service'; + +@Component({ + selector: 'app-snack-bar-notification', + templateUrl: './snack-bar-notification.component.html' +}) + +export class SnackBarNotificationComponent { + message: string; + constructor(@Inject(MAT_SNACK_BAR_DATA) public data: SnackBarNotification) { + this.message = data.message; + } +} diff --git a/dmp-frontend/src/common/modules/notification/ui-notification-service.ts b/dmp-frontend/src/common/modules/notification/ui-notification-service.ts new file mode 100644 index 000000000..3219daa45 --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/ui-notification-service.ts @@ -0,0 +1,60 @@ +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; + +@Injectable() +export class UiNotificationService { + + private notificationSubject = new Subject(); + + constructor() { + } + + public snackBarNotification(message: string, level: SnackBarNotificationLevel, duration: number = 5000) { + const notification: SnackBarNotification = new SnackBarNotification(); + notification.level = level; + notification.message = message; + notification.duration = duration; + this.notificationSubject.next(notification); + } + + public popupNotification(title: string, message: string) { + const notification: PopupNotification = new PopupNotification(); + notification.title = title; + notification.message = message; + this.notificationSubject.next(notification); + } + + public getNotificationObservable(): Observable { + return this.notificationSubject.asObservable(); + } +} + +export enum UiNotificationType { + SnackBar = 0, + Popup = 1 +} + +export interface UiNotification { + type: UiNotificationType; + +} + +export enum SnackBarNotificationLevel { + Info = 0, + Warning = 1, + Success = 2, + Error = 3 +} + +export class SnackBarNotification implements UiNotification { + type: UiNotificationType = UiNotificationType.SnackBar; + message: string; + level: SnackBarNotificationLevel; + duration: number; +} + +export class PopupNotification implements UiNotification { + type: UiNotificationType = UiNotificationType.Popup; + message: string; + title: string; +} diff --git a/dmp-frontend/src/common/modules/notification/ui-notification.component.html b/dmp-frontend/src/common/modules/notification/ui-notification.component.html new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/ui-notification.component.html @@ -0,0 +1 @@ + diff --git a/dmp-frontend/src/common/modules/notification/ui-notification.component.scss b/dmp-frontend/src/common/modules/notification/ui-notification.component.scss new file mode 100644 index 000000000..1203c5d5a --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/ui-notification.component.scss @@ -0,0 +1,15 @@ +.snack-bar-notification--success { + background-color: #4CAF50 !important; +} + +.snack-bar-notification--error { + background-color: #B13636 !important; +} + +.snack-bar-notification--warning { + background-color: #B13636 !important; +} + +.snack-bar-notification--info { + background-color: #B13636 !important; +} diff --git a/dmp-frontend/src/common/modules/notification/ui-notification.component.ts b/dmp-frontend/src/common/modules/notification/ui-notification.component.ts new file mode 100644 index 000000000..f4bf6ee0a --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/ui-notification.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { BaseComponent } from '@common/base/base.component'; +import { PopupNotificationDialogComponent } from '@common/modules/notification/popup/popup-notification.component'; +import { SnackBarNotificationComponent } from '@common/modules/notification/snack-bar/snack-bar-notification.component'; +import { PopupNotification, SnackBarNotification, SnackBarNotificationLevel, UiNotificationService, UiNotificationType } from '@common/modules/notification/ui-notification-service'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-ui-notification', + templateUrl: './ui-notification.component.html', + styleUrls: ['./ui-notification.component.scss'] +}) +export class UiNotificationComponent extends BaseComponent implements OnInit { + + constructor( + private snackBar: MatSnackBar, + public dialog: MatDialog, + private uiNotificationService: UiNotificationService + ) { + super(); + } + + ngOnInit() { + this.uiNotificationService.getNotificationObservable().pipe(takeUntil(this._destroyed)).subscribe(notification => { + switch (notification.type) { + case UiNotificationType.SnackBar: + const snackBarNotification: SnackBarNotification = notification as SnackBarNotification; + this.snackBar.openFromComponent(SnackBarNotificationComponent, { + data: snackBarNotification, + duration: snackBarNotification.duration, + panelClass: [this.getSnackBarLevelClass(snackBarNotification.level)] + }); + break; + case UiNotificationType.Popup: + const popupNotification: PopupNotification = notification as PopupNotification; + this.dialog.open(PopupNotificationDialogComponent, { + data: popupNotification + }); + break; + } + }); + } + + private getSnackBarLevelClass(level: SnackBarNotificationLevel): string { + switch (level) { + case SnackBarNotificationLevel.Warning: return 'snack-bar-notification--warning'; + case SnackBarNotificationLevel.Error: return 'snack-bar-notification--error'; + case SnackBarNotificationLevel.Success: return 'snack-bar-notification--success'; + default: return 'snack-bar-notification--info'; + } + + } +} diff --git a/dmp-frontend/src/common/modules/notification/ui-notification.module.ts b/dmp-frontend/src/common/modules/notification/ui-notification.module.ts new file mode 100644 index 000000000..3e57b18bc --- /dev/null +++ b/dmp-frontend/src/common/modules/notification/ui-notification.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { PopupNotificationDialogComponent } from '@common/modules/notification/popup/popup-notification.component'; +import { SnackBarNotificationComponent } from '@common/modules/notification/snack-bar/snack-bar-notification.component'; +import { UiNotificationComponent } from '@common/modules/notification/ui-notification.component'; +import { CommonUiModule } from '@common/ui/common-ui.module'; + +@NgModule({ + imports: [ + CommonUiModule + ], + declarations: [ + UiNotificationComponent, + SnackBarNotificationComponent, + PopupNotificationDialogComponent, + ], + exports: [ + UiNotificationComponent + ], + entryComponents: [ + SnackBarNotificationComponent, + PopupNotificationDialogComponent, + ] +}) +export class UiNotificationModule { + constructor() { } +} diff --git a/dmp-frontend/src/common/modules/page-not-found/page-not-found.component.html b/dmp-frontend/src/common/modules/page-not-found/page-not-found.component.html new file mode 100644 index 000000000..5727cb897 --- /dev/null +++ b/dmp-frontend/src/common/modules/page-not-found/page-not-found.component.html @@ -0,0 +1 @@ +

Page not found

diff --git a/dmp-frontend/src/common/modules/page-not-found/page-not-found.component.ts b/dmp-frontend/src/common/modules/page-not-found/page-not-found.component.ts new file mode 100644 index 000000000..ea7c6f5f9 --- /dev/null +++ b/dmp-frontend/src/common/modules/page-not-found/page-not-found.component.ts @@ -0,0 +1,13 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + templateUrl: './page-not-found.component.html' +}) +export class PageNotFoundComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/dmp-frontend/src/common/modules/page-not-found/page-not-found.module.ts b/dmp-frontend/src/common/modules/page-not-found/page-not-found.module.ts new file mode 100644 index 000000000..0a362cb9b --- /dev/null +++ b/dmp-frontend/src/common/modules/page-not-found/page-not-found.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { PageNotFoundComponent } from '@common/modules/page-not-found/page-not-found.component'; + +@NgModule({ + imports: [ + ], + declarations: [ + PageNotFoundComponent + ], + entryComponents: [] +}) +export class PageNotFoundModule { } diff --git a/dmp-frontend/src/app/common/types/guid.ts b/dmp-frontend/src/common/types/guid.ts similarity index 100% rename from dmp-frontend/src/app/common/types/guid.ts rename to dmp-frontend/src/common/types/guid.ts diff --git a/dmp-frontend/src/app/common/types/json/json-serializer.ts b/dmp-frontend/src/common/types/json/json-serializer.ts similarity index 82% rename from dmp-frontend/src/app/common/types/json/json-serializer.ts rename to dmp-frontend/src/common/types/json/json-serializer.ts index 775a9c2de..96d4ef8ed 100644 --- a/dmp-frontend/src/app/common/types/json/json-serializer.ts +++ b/dmp-frontend/src/common/types/json/json-serializer.ts @@ -1,4 +1,4 @@ -import { Serializable } from './serializable'; +import { Serializable } from '@common/types/json/serializable'; export class JsonSerializer> { constructor(private constructorOfT: { new(): T }) { diff --git a/dmp-frontend/src/app/common/types/json/serializable.ts b/dmp-frontend/src/common/types/json/serializable.ts similarity index 100% rename from dmp-frontend/src/app/common/types/json/serializable.ts rename to dmp-frontend/src/common/types/json/serializable.ts diff --git a/dmp-frontend/src/app/common/types/pair.ts b/dmp-frontend/src/common/types/pair.ts similarity index 100% rename from dmp-frontend/src/app/common/types/pair.ts rename to dmp-frontend/src/common/types/pair.ts diff --git a/dmp-frontend/src/app/common/ui/common-ui.module.ts b/dmp-frontend/src/common/ui/common-ui.module.ts similarity index 62% rename from dmp-frontend/src/app/common/ui/common-ui.module.ts rename to dmp-frontend/src/common/ui/common-ui.module.ts index fe8455d39..5c16efc7b 100644 --- a/dmp-frontend/src/app/common/ui/common-ui.module.ts +++ b/dmp-frontend/src/common/ui/common-ui.module.ts @@ -1,21 +1,23 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; +import { SecureImagePipe } from '@common/http/image/secure-image.pipe'; +import { MaterialModule } from '@common/material/material.module'; import { TranslateModule } from '@ngx-translate/core'; -import { MaterialModule } from '../material/material.module'; -import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ CommonModule, MaterialModule, TranslateModule, - FormsModule + ], + declarations: [ + SecureImagePipe ], exports: [ CommonModule, MaterialModule, TranslateModule, - FormsModule + SecureImagePipe ] }) export class CommonUiModule { } diff --git a/dmp-frontend/src/environments/environment.ts b/dmp-frontend/src/environments/environment.ts index 193d09ace..7fb7fa113 100644 --- a/dmp-frontend/src/environments/environment.ts +++ b/dmp-frontend/src/environments/environment.ts @@ -14,7 +14,6 @@ export const environment = { linkedInConfiguration: { clientId: '', oauthUrl: 'https://www.linkedin.com/oauth/v2/authorization', - redirectUri: 'http://localhost:4200/login/linkedin' redirectUri: 'http://localhost:4200/login/linkedin', state: '987654321' }, diff --git a/dmp-frontend/tsconfig.json b/dmp-frontend/tsconfig.json index bfd2e9604..5d5ba689a 100644 --- a/dmp-frontend/tsconfig.json +++ b/dmp-frontend/tsconfig.json @@ -1,15 +1,30 @@ { + "compileOnSave": false, "compilerOptions": { - "downlevelIteration": true, - "importHelpers": true, - "target": "es2015", + "baseUrl": "./src", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, "module": "esnext", "moduleResolution": "node", - "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "lib": ["es2017", "dom"], - "noImplicitAny": false, - "suppressImplicitAnyIndexErrors": true + "importHelpers": true, + "target": "es2015", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ], + "paths": { + "@app/*": [ + "./app/*" + ], + "@common/*": [ + "./common/*" + ] + } } -} +} \ No newline at end of file