no message

This commit is contained in:
Ioannis Kalyvas 2018-07-11 16:47:36 +03:00
parent efb7af10b5
commit 78b91ee3e0
144 changed files with 5181 additions and 2043 deletions

8
.env
View File

@ -1,6 +1,6 @@
TAG=6.2.1 TAG=6.3.0
ENV=dev ENV=prod
PROFILE=production PROFILE=production
AOT=no-aot AOT=aot
ELASTIC_VERSION=6.2.1 ELASTIC_VERSION=6.3.0
ELASTIC_PASSWORD=changeme ELASTIC_PASSWORD=changeme

2
.gitignore vendored
View File

@ -25,3 +25,5 @@ dmp-backend/web/src/main/ui-resources/static/
dmp-backend/data/target/data-1.0-SNAPSHOT.jar dmp-backend/data/target/data-1.0-SNAPSHOT.jar
dmp-backend/data/target/ dmp-backend/data/target/
dmp-backend/queryable/target/ dmp-backend/queryable/target/
dmp-backend/elastic/target/
dmp-backend/queryengine/target/

View File

@ -1,3 +1,3 @@
TAG=6.2.1 TAG=6.3.1
ELASTIC_VERSION=6.2.1 ELASTIC_VERSION=6.3.1
ELASTIC_PASSWORD=changeme ELASTIC_PASSWORD=changeme

View File

@ -100,7 +100,72 @@ services:
networks: ['stack'] networks: ['stack']
depends_on: ['kibana'] depends_on: ['kibana']
#volumes:
##########################DOCSBOX######################################################################
web:
restart: always
build: ./docsbox-master/docsbox
expose:
- "8000"
links:
- redis:redis
volumes:
- docsbox:/home/docsbox
- media:/home/docsbox/media
command: gunicorn -b :8000 docsbox:app
networks: ['stack']
rqworker:
restart: always
build: ./docsbox-master/docsbox
links:
- redis:redis
volumes:
- web
command: rq worker -c docsbox.settings
networks: ['stack']
rqscheduler:
restart: always
build: ./docsbox-master/docsbox
links:
- redis:redis
volumes:
- web
command: rqscheduler -H redis -p 6379 -d 0
networks: ['stack']
nginx:
restart: always
build: ./docsbox-master/nginx/
ports:
- "81:80"
volumes:
- web
links:
- web:web
networks: ['stack']
redis:
restart: always
image: redis:latest
expose:
- "6379"
volumes:
- redisdata:/data
networks: ['stack']
##########################SETTIGNS######################################################################
volumes:
#esdata: #esdata:
# driver: local #driver: local
redisdata:
driver: local
docsbox:
driver: local
media:
driver: local
networks: {stack: {}} networks: {stack: {}}

View File

@ -1,5 +1,11 @@
FROM openjdk:8-jdk-alpine FROM openjdk:8-jdk-alpine
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
VOLUME /tmp VOLUME /tmp
ARG PROFILE=dev ARG PROFILE=production
ENV PROF $PROFILE
ADD web/src/main/resources/ProjectConfiguration.xml /tmp/ProjectConfiguration.xml
ADD web/src/main/resources/ExternalUrls.xml /tmp/ExternalUrls.xml
ADD web/target/web-1.0-SNAPSHOT.jar app.jar ADD web/target/web-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=${PROFILE}","-jar","/app.jar"] ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom" ,"-Dspring.profiles.active=${PROF}","-jar","/app.jar"]

View File

@ -21,5 +21,10 @@
<artifactId>queryable</artifactId> <artifactId>queryable</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>eu.eudat</groupId>
<artifactId>elastic</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,6 +1,7 @@
package eu.eudat.data.dao.criteria; package eu.eudat.data.dao.criteria;
import eu.eudat.data.entities.Dataset; import eu.eudat.data.entities.Dataset;
import eu.eudat.elastic.entities.Tag;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -12,8 +13,10 @@ public class DatasetCriteria extends Criteria<Dataset> {
private Date periodStart; private Date periodStart;
private Date periodEnd; private Date periodEnd;
private List<UUID> dmpIds; private List<UUID> dmpIds;
private List<Tag> tags;
private boolean allVersions; private boolean allVersions;
public boolean getAllVersions() { public boolean getAllVersions() {
return allVersions; return allVersions;
} }
@ -53,4 +56,12 @@ public class DatasetCriteria extends Criteria<Dataset> {
public void setDmpIds(List<UUID> dmpIds) { public void setDmpIds(List<UUID> dmpIds) {
this.dmpIds = dmpIds; this.dmpIds = dmpIds;
} }
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
} }

View File

@ -14,15 +14,23 @@ import java.util.stream.Collectors;
@NamedEntityGraphs({ @NamedEntityGraphs({
@NamedEntityGraph( @NamedEntityGraph(
name = "datasetListingModel", name = "datasetListingModel",
attributeNodes = {@NamedAttributeNode("services"), @NamedAttributeNode("datasetDataRepositories"), @NamedAttributeNode("datasetExternalDatasets"), @NamedAttributeNode("registries"), attributeNodes = {@NamedAttributeNode("services"), @NamedAttributeNode(value = "datasetDataRepositories", subgraph = "datasetDataRepositories"), @NamedAttributeNode("datasetExternalDatasets"), @NamedAttributeNode("registries"),
@NamedAttributeNode(value = "dmp", subgraph = "dmp"), @NamedAttributeNode("profile"), @NamedAttributeNode("creator")}, @NamedAttributeNode(value = "dmp", subgraph = "dmp"), @NamedAttributeNode("profile"), @NamedAttributeNode("creator")},
subgraphs = @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users")})), subgraphs = {
@NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users")}),
@NamedSubgraph(name = "datasetDataRepositories", attributeNodes = {@NamedAttributeNode("dataRepository")})
}),
@NamedEntityGraph( @NamedEntityGraph(
name = "datasetWizardModel", name = "datasetWizardModel",
attributeNodes = {@NamedAttributeNode("services"), @NamedAttributeNode("datasetDataRepositories"), @NamedAttributeNode("datasetExternalDatasets"), @NamedAttributeNode("registries"), attributeNodes = {@NamedAttributeNode("services"), @NamedAttributeNode("datasetDataRepositories"), @NamedAttributeNode("datasetExternalDatasets"), @NamedAttributeNode("registries"),
@NamedAttributeNode("dmp"), @NamedAttributeNode("profile"), @NamedAttributeNode("creator")}), @NamedAttributeNode("dmp"), @NamedAttributeNode("profile"), @NamedAttributeNode("creator")}),
@NamedEntityGraph( @NamedEntityGraph(
name = "datasetRecentActivity", name = "datasetRecentActivity",
attributeNodes = {@NamedAttributeNode(value = "dmp", subgraph = "dmp")},
subgraphs = @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("users")})),
@NamedEntityGraph(
name = "datasetDataRepositories",
attributeNodes = {@NamedAttributeNode(value = "dmp", subgraph = "dmp"), @NamedAttributeNode("creator")}, attributeNodes = {@NamedAttributeNode(value = "dmp", subgraph = "dmp"), @NamedAttributeNode("creator")},
subgraphs = @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users")})) subgraphs = @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users")}))
}) })
@ -291,10 +299,10 @@ public class Dataset implements DataEntity<Dataset, UUID> {
@Override @Override
public void update(Dataset entity) { public void update(Dataset entity) {
this.setRegistries(entity.getRegistries()); this.setRegistries(entity.getRegistries());
if(this.getDatasetDataRepositories()==null) this.setDatasetDataRepositories(new HashSet<>()); if (this.getDatasetDataRepositories() == null) this.setDatasetDataRepositories(new HashSet<>());
if(!this.getDatasetDataRepositories().containsAll(entity.getDatasetDataRepositories())){ if (!this.getDatasetDataRepositories().containsAll(entity.getDatasetDataRepositories())) {
this.getDatasetDataRepositories().removeAll(this.getDatasetDataRepositories()); this.getDatasetDataRepositories().removeAll(this.getDatasetDataRepositories());
this.getDatasetDataRepositories().addAll(entity.getDatasetDataRepositories().stream().map(item->{ this.getDatasetDataRepositories().addAll(entity.getDatasetDataRepositories().stream().map(item -> {
item.setDataset(this); item.setDataset(this);
return item; return item;
}).collect(Collectors.toList())); }).collect(Collectors.toList()));
@ -302,8 +310,8 @@ public class Dataset implements DataEntity<Dataset, UUID> {
this.setDescription(entity.getDescription()); this.setDescription(entity.getDescription());
this.setLabel(entity.getLabel()); this.setLabel(entity.getLabel());
this.setProperties(entity.getProperties()); this.setProperties(entity.getProperties());
if(this.getDatasetExternalDatasets()==null) this.setDatasetExternalDatasets(new HashSet<>()); if (this.getDatasetExternalDatasets() == null) this.setDatasetExternalDatasets(new HashSet<>());
if(!this.getDatasetExternalDatasets().containsAll(entity.getDatasetExternalDatasets())) { if (!this.getDatasetExternalDatasets().containsAll(entity.getDatasetExternalDatasets())) {
this.getDatasetExternalDatasets().removeAll(this.getDatasetExternalDatasets()); this.getDatasetExternalDatasets().removeAll(this.getDatasetExternalDatasets());
this.getDatasetExternalDatasets().addAll(entity.getDatasetExternalDatasets().stream().map(item -> { this.getDatasetExternalDatasets().addAll(entity.getDatasetExternalDatasets().stream().map(item -> {
item.setDataset(this); item.setDataset(this);

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dmp-backend</artifactId>
<groupId>eu.eudat</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>elastic</artifactId>
</project>

View File

@ -0,0 +1,7 @@
package eu.eudat.elastic.criteria;
/**
* Created by ikalyvas on 7/5/2018.
*/
public abstract class Criteria {
}

View File

@ -0,0 +1,20 @@
package eu.eudat.elastic.criteria;
import eu.eudat.elastic.entities.Tag;
import java.util.List;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class DatasetCriteria extends Criteria {
public List<Tag> tags;
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
}

View File

@ -0,0 +1,7 @@
package eu.eudat.elastic.criteria;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class TagCriteria extends Criteria {
}

View File

@ -0,0 +1,60 @@
package eu.eudat.elastic.entities;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class Dataset implements ElasticEntity<Dataset> {
private String id;
private List<Tag> tags = new LinkedList<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
@Override
public XContentBuilder toElasticEntity(XContentBuilder builder) throws IOException {
builder.startObject();
builder.field("id", this.id);
builder.startArray("tags");
this.tags.forEach(x -> {
try {
x.toElasticEntity(builder);
} catch (IOException e) {
e.printStackTrace();
}
});
builder.endArray();
builder.endObject();
return builder;
}
@Override
public Dataset fromElasticEntity(Map<String, Object> fields) {
if (fields != null) {
this.id = (String) fields.get("id");
this.tags = ((List<Tag>) fields.get("tags"));
}
return this;
}
}

View File

@ -0,0 +1,15 @@
package eu.eudat.elastic.entities;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Map;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface ElasticEntity<T> {
XContentBuilder toElasticEntity(XContentBuilder builder) throws IOException;
T fromElasticEntity(Map<String, Object> fields);
}

View File

@ -0,0 +1,45 @@
package eu.eudat.elastic.entities;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Map;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class Tag implements ElasticEntity {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public XContentBuilder toElasticEntity(XContentBuilder builder) throws IOException {
builder.startObject();
builder.field("id", this.id);
builder.field("name", this.name);
builder.endObject();
return builder;
}
@Override
public Object fromElasticEntity(Map fields) {
return null;
}
}

View File

@ -0,0 +1,72 @@
package eu.eudat.elastic.repository;
import eu.eudat.elastic.criteria.DatasetCriteria;
import eu.eudat.elastic.entities.Dataset;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
/**
* Created by ikalyvas on 7/5/2018.
*/
@Service("datasetRepository")
public class DatasetRepository extends ElasticRepository<Dataset, DatasetCriteria> {
@Autowired
public DatasetRepository(RestHighLevelClient client) {
super(client);
}
@Override
public Dataset createOrUpdate(Dataset entity) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder();
IndexRequest request = new IndexRequest("datasets", "doc", entity.getId()).source(entity.toElasticEntity(builder));
this.getClient().index(request);
return entity;
}
@Override
public Dataset findDocument(String id) throws IOException {
GetRequest request = new GetRequest("datasets","doc",id);
GetResponse response = this.getClient().get(request);
return new Dataset().fromElasticEntity(response.getSourceAsMap());
}
@Override
public List<Dataset> query(DatasetCriteria criteria) throws ExecutionException, InterruptedException, IOException {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.termsQuery("tags.name.keyword", criteria.getTags().stream().map(x -> x.getName()).collect(Collectors.toList())));
searchSourceBuilder.query(boolQuery);
searchRequest.source(searchSourceBuilder);
SearchResponse response = this.getClient().search(searchRequest);
return Arrays.stream(response.getHits().getHits()).map(x -> this.transformFromString(x.getSourceAsString(), Dataset.class)).collect(Collectors.toList());
}
@Override
public boolean exists() throws IOException {
GetIndexRequest request = new GetIndexRequest();
request.indices("datasets");
return this.getClient().indices().exists(request);
}
}

View File

@ -0,0 +1,36 @@
package eu.eudat.elastic.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.elastic.criteria.Criteria;
import eu.eudat.elastic.entities.ElasticEntity;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import java.io.IOException;
/**
* Created by ikalyvas on 7/5/2018.
*/
public abstract class ElasticRepository<T extends ElasticEntity,C extends Criteria> implements Repository<T,C> {
private RestHighLevelClient client;
public RestHighLevelClient getClient() {
return client;
}
public ElasticRepository(RestHighLevelClient client) {
this.client = client;
}
public <T> T transformFromString(String value, Class<T> tClass) {
ObjectMapper mapper = new ObjectMapper();
T item = null;
try {
item = mapper.readValue(value, tClass);
} catch (IOException e) {
e.printStackTrace();
}
return item;
}
}

View File

@ -0,0 +1,22 @@
package eu.eudat.elastic.repository;
import eu.eudat.elastic.criteria.Criteria;
import eu.eudat.elastic.entities.ElasticEntity;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface Repository<ET extends ElasticEntity, C extends Criteria> {
ET createOrUpdate(ET entity) throws IOException;
ET findDocument(String id) throws IOException;
List<ET> query(C criteria) throws ExecutionException, InterruptedException, IOException;
boolean exists() throws IOException;
}

View File

@ -18,7 +18,8 @@
<module>web</module> <module>web</module>
<module>data</module> <module>data</module>
<module>logging</module> <module>logging</module>
<module>queryengine</module>
<module>elastic</module>
</modules> </modules>
<properties> <properties>
@ -65,6 +66,19 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.3.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.3.1</version>
</dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
@ -172,6 +186,11 @@
<artifactId>hibernate-jpamodelgen</artifactId> <artifactId>hibernate-jpamodelgen</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.3.0</version>
</dependency>
</dependencies> </dependencies>
@ -188,7 +207,7 @@
<profile> <profile>
<id>production</id> <id>production</id>
<properties> <properties>
<packaging.type>war</packaging.type> <packaging.type>jar</packaging.type>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dmp-backend</artifactId>
<groupId>eu.eudat</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>query-engine</artifactId>
<dependencies>
<dependency>
<groupId>eu.eudat</groupId>
<artifactId>data</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,14 @@
import eu.eudat.data.entities.DataRepository;
import eu.eudat.query.engine.builder.QueryBuilder;
import eu.eudat.query.engine.builder.QueryBuilderImpl;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class Main {
public void Test(){
QueryBuilder<DataRepository> queryBuilder = new QueryBuilderImpl<>();
queryBuilder.where((entity, comparisonExpression) -> comparisonExpression.field("id").greaterThan(5));
//queryBuilder.and(((entity, expression) -> expression.field("id").greaterThan(4)),((entity, expression) -> expression.field("id").greaterThan(5)));
}
}

View File

@ -0,0 +1,16 @@
package eu.eudat.query.engine.builder;
import eu.eudat.query.engine.expressions.Expression;
import eu.eudat.query.engine.predicates.AndPredicate;
import eu.eudat.query.engine.predicates.ComparisonPredicate;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface QueryBuilder<T> {
Expression where(ComparisonPredicate<T> wherePredicate);
Expression and(AndPredicate<T> andPredicate);
}

View File

@ -0,0 +1,22 @@
package eu.eudat.query.engine.builder;
import eu.eudat.query.engine.expressions.Expression;
import eu.eudat.query.engine.predicates.AndPredicate;
import eu.eudat.query.engine.predicates.ComparisonPredicate;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class QueryBuilderImpl<T> implements QueryBuilder<T> {
@Override
public Expression where(ComparisonPredicate wherePredicate) {
return null;
}
@Override
public Expression and(AndPredicate<T> andPredicate) {
return null;
}
}

View File

@ -0,0 +1,17 @@
package eu.eudat.query.engine.expressions;
/**
* Created by ikalyvas on 7/5/2018.
*/
public abstract class AbstractFieldExpression<T extends AbstractFieldExpression<T>> {
private String field;
protected String getField() {
return field;
}
public T field(String field) {
this.field = field;
return (T)this;
}
}

View File

@ -0,0 +1,43 @@
package eu.eudat.query.engine.expressions;
import eu.eudat.query.engine.types.expression.comparison.ComparisonExpressionType;
/**
* Created by ikalyvas on 7/5/2018.
*/
public class ComparisonExpression extends AbstractFieldExpression<ComparisonExpression> implements Expression {
private ComparisonExpressionType type;
private Object value;
public <T> Expression greaterThan(T value){
this.value = value;
this.type = ComparisonExpressionType.GREATER_THAN;
return this;
}
public <T> Expression greaterThanOrEqual(T value){
this.value = value;
this.type = ComparisonExpressionType.GREATER_OR_EQUAL_THAN;
return this;
}
public <T> Expression equal(T value){
this.value = value;
this.type = ComparisonExpressionType.EQUAL;
return this;
}
public <T> Expression lessThan(T value){
this.value = value;
this.type = ComparisonExpressionType.LESS_THAN;
return this;
}
public <T> Expression lessOrEqualThan(T value){
this.value = value;
this.type = ComparisonExpressionType.LESS_OR_EQUAL_THAN;
return this;
}
}

View File

@ -0,0 +1,7 @@
package eu.eudat.query.engine.expressions;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface Expression {
}

View File

@ -0,0 +1,11 @@
package eu.eudat.query.engine.predicates;
import eu.eudat.query.engine.expressions.ComparisonExpression;
import eu.eudat.query.engine.expressions.Expression;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface AndPredicate<T> {
<E extends Expression> Expression and(ComparisonPredicate<T>... predicates);
}

View File

@ -0,0 +1,9 @@
package eu.eudat.query.engine.predicates;
import eu.eudat.query.engine.expressions.ComparisonExpression;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface ComparisonPredicate<T> extends Predicate<T, ComparisonExpression> {
}

View File

@ -0,0 +1,11 @@
package eu.eudat.query.engine.predicates;
import eu.eudat.query.engine.expressions.Expression;
/**
* Created by ikalyvas on 7/5/2018.
*/
public interface Predicate<T,E extends Expression> {
Expression where(T entity, E expression);
}

View File

@ -0,0 +1,8 @@
package eu.eudat.query.engine.types.expression.comparison;
/**
* Created by ikalyvas on 7/5/2018.
*/
public enum ComparisonExpressionType {
EQUAL, GREATER_THAN, GREATER_OR_EQUAL_THAN, LESS_THAN, LESS_OR_EQUAL_THAN
}

View File

@ -31,6 +31,15 @@
<artifactId>queryable</artifactId> <artifactId>queryable</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>eu.eudat</groupId>
<artifactId>elastic</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>

View File

@ -32,6 +32,7 @@ public class ResponsesCache {
caches.add(new GuavaCache("organisations", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); caches.add(new GuavaCache("organisations", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build()));
caches.add(new GuavaCache("registries", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); caches.add(new GuavaCache("registries", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build()));
caches.add(new GuavaCache("services", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); caches.add(new GuavaCache("services", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build()));
caches.add(new GuavaCache("tags", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build()));
caches.add(new GuavaCache("researchers", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build())); caches.add(new GuavaCache("researchers", CacheBuilder.newBuilder().expireAfterAccess(HOW_MANY, TIME_UNIT).build()));
simpleCacheManager.setCaches(caches); simpleCacheManager.setCaches(caches);
System.out.println("OK"); System.out.println("OK");

View File

@ -0,0 +1,39 @@
package eu.eudat.configurations;
import org.apache.http.HttpHost;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
/**
* Created by ikalyvas on 7/5/2018.
*/
@Configuration
public class ElasticSearchConfiguration {
private Environment environment;
@Autowired
public ElasticSearchConfiguration(Environment environment) {
this.environment = environment;
}
@Bean
public RestHighLevelClient client() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost(this.environment.getProperty("elasticsearch.host"),
Integer.parseInt(this.environment.getProperty("elasticsearch.port")), "http")));
return client;
}
}

View File

@ -14,6 +14,7 @@ import javax.xml.bind.Unmarshaller;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.Paths;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -47,7 +48,7 @@ public class DynamicProjectConfigurationProdImpl implements DynamicProjectConfig
JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
is = new URL("file:///" + System.getenv("CATALINA_HOME") + fileUrl).openStream(); is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream();
this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();

View File

@ -74,7 +74,8 @@ public class DatasetWizardController extends BaseController {
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<DatasetWizardModel>> getSingle(@PathVariable String id, Principal principal) { ResponseEntity<ResponseItem<DatasetWizardModel>> getSingle(@PathVariable String id, Principal principal) {
try { try {
DatasetWizardModel dataset = new DatasetManager().getSingle(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(), id); DatasetWizardModel dataset = new DatasetManager().getSingle(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(),this.getApiContext().getOperationsContext().getDatasetRepository()
,id);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();

View File

@ -0,0 +1,67 @@
package eu.eudat.controllers;
import eu.eudat.elastic.criteria.TagCriteria;
import eu.eudat.elastic.entities.Dataset;
import eu.eudat.elastic.entities.Tag;
import eu.eudat.elastic.repository.Repository;
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.external.TagExternalSourcesModel;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.types.ApiMessageCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* Created by ikalyvas on 7/5/2018.
*/
@RestController
@CrossOrigin
@RequestMapping(value = {"/api"})
public class TagController extends BaseController{
private Repository<Dataset,TagCriteria> datasetRepository;
@Autowired
public TagController(ApiContext apiContext, Repository tagRepository) {
super(apiContext);
this.datasetRepository = tagRepository;
}
@Transactional
@RequestMapping(method = RequestMethod.POST, value = {"/tag/create"}, consumes = "application/json", produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<Dataset>> create(@RequestBody Dataset dataset) {
try {
Dataset tagEntity = this.datasetRepository.createOrUpdate(dataset);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Dataset>().payload(dataset).status(ApiMessageCode.SUCCESS_MESSAGE));
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Dataset>().status(ApiMessageCode.SUCCESS_MESSAGE).message(e.getMessage()));
}
}
@RequestMapping(method = RequestMethod.GET, value = {"/external/tags"}, produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<TagExternalSourcesModel>> listExternalTagModel(
@RequestParam(value = "query", required = false) String query,@RequestParam(value = "type", required = false) String type) {
try {
List<Map<String, String>> remoteRepos = this.getApiContext().getOperationsContext().getRemoteFetcher().getTags(query,type);
TagExternalSourcesModel researchersExternalSourcesModel = new TagExternalSourcesModel().fromExternalItem(remoteRepos);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<TagExternalSourcesModel>().payload(researchersExternalSourcesModel).status(ApiMessageCode.NO_MESSAGE));
} catch (NoURLFound ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<TagExternalSourcesModel>().status(ApiMessageCode.ERROR_MESSAGE).message("External Url Not Found"));
} catch (HugeResultSet ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<TagExternalSourcesModel>().status(ApiMessageCode.ERROR_MESSAGE).message("Huge Result Set"));
} catch (Exception ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<TagExternalSourcesModel>().status(ApiMessageCode.ERROR_MESSAGE).message(ex.getMessage()));
}
}
}

View File

@ -20,6 +20,8 @@ public class CommonsManager {
.map(item-> new ExternalSourcesConfiguration.ExternalSourcesUrlModel(item.getKey(),item.getLabel())).collect(Collectors.toList())); .map(item-> new ExternalSourcesConfiguration.ExternalSourcesUrlModel(item.getKey(),item.getLabel())).collect(Collectors.toList()));
externalSourcesConfiguration.setServices(configLoader.getExternalUrls().getServices().getUrls().stream() externalSourcesConfiguration.setServices(configLoader.getExternalUrls().getServices().getUrls().stream()
.map(item-> new ExternalSourcesConfiguration.ExternalSourcesUrlModel(item.getKey(),item.getLabel())).collect(Collectors.toList())); .map(item-> new ExternalSourcesConfiguration.ExternalSourcesUrlModel(item.getKey(),item.getLabel())).collect(Collectors.toList()));
externalSourcesConfiguration.setTags(configLoader.getExternalUrls().getTags().getUrls().stream()
.map(item-> new ExternalSourcesConfiguration.ExternalSourcesUrlModel(item.getKey(),item.getLabel())).collect(Collectors.toList()));
return externalSourcesConfiguration; return externalSourcesConfiguration;
} }
} }

View File

@ -1,25 +1,27 @@
package eu.eudat.logic.managers; package eu.eudat.logic.managers;
import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.data.dao.entities.*;
import eu.eudat.data.entities.*;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
import eu.eudat.logic.utilities.documents.word.WordBuilder;
import eu.eudat.logic.utilities.documents.xml.ExportXmlBuilder;
import eu.eudat.models.HintedModelFactory;
import eu.eudat.data.dao.criteria.DataRepositoryCriteria; import eu.eudat.data.dao.criteria.DataRepositoryCriteria;
import eu.eudat.data.dao.criteria.ExternalDatasetCriteria; import eu.eudat.data.dao.criteria.ExternalDatasetCriteria;
import eu.eudat.data.dao.criteria.RegistryCriteria; import eu.eudat.data.dao.criteria.RegistryCriteria;
import eu.eudat.data.dao.criteria.ServiceCriteria; import eu.eudat.data.dao.criteria.ServiceCriteria;
import eu.eudat.data.dao.entities.*;
import eu.eudat.data.entities.*;
import eu.eudat.data.query.items.table.dataset.DatasetTableRequest; import eu.eudat.data.query.items.table.dataset.DatasetTableRequest;
import eu.eudat.elastic.criteria.DatasetCriteria;
import eu.eudat.elastic.repository.DatasetRepository;
import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.forms.VisibilityRuleService;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
import eu.eudat.logic.utilities.documents.word.WordBuilder;
import eu.eudat.logic.utilities.documents.xml.ExportXmlBuilder;
import eu.eudat.models.HintedModelFactory;
import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.common.DataTableData;
import eu.eudat.models.data.listingmodels.DatasetListingModel; import eu.eudat.models.data.listingmodels.DatasetListingModel;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.models.data.user.composite.PagedDatasetProfile;
import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.QueryableList;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.forms.VisibilityRuleService;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.json.JSONObject; import org.json.JSONObject;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -35,6 +37,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
@ -42,8 +45,19 @@ import java.util.zip.ZipInputStream;
public class DatasetManager { public class DatasetManager {
public DataTableData<DatasetListingModel> getPaged(ApiContext apiContext, DatasetTableRequest datasetTableRequest, Principal principal) throws Exception { public DataTableData<DatasetListingModel> getPaged(ApiContext apiContext, DatasetTableRequest datasetTableRequest, Principal principal) throws Exception {
DatasetCriteria datasetCriteria = new DatasetCriteria();
datasetCriteria.setTags(datasetTableRequest.getCriteria().getTags());
List<eu.eudat.elastic.entities.Dataset> datasets = apiContext.getOperationsContext().getDatasetRepository().exists() ?
apiContext.getOperationsContext().getDatasetRepository().query(datasetCriteria) : new LinkedList<>();
UserInfo userInfo = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build(); UserInfo userInfo = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build();
QueryableList<eu.eudat.data.entities.Dataset> items = apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(datasetTableRequest.getCriteria()).withHint(HintedModelFactory.getHint(DatasetListingModel.class)); QueryableList<eu.eudat.data.entities.Dataset> items = apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(datasetTableRequest.getCriteria()).withHint(HintedModelFactory.getHint(DatasetListingModel.class));
if (datasetTableRequest.getCriteria().getTags() != null && !datasetTableRequest.getCriteria().getTags().isEmpty()) {
if (!datasets.isEmpty())
items.where((builder, root) -> root.get("id").in(datasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList())));
else
items.where((builder, root) -> root.get("id").in(new UUID[]{UUID.randomUUID()}));
}
QueryableList<eu.eudat.data.entities.Dataset> authItems = apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getAuthenticated(items, userInfo); QueryableList<eu.eudat.data.entities.Dataset> authItems = apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getAuthenticated(items, userInfo);
QueryableList<eu.eudat.data.entities.Dataset> pagedItems = PaginationManager.applyPaging(authItems, datasetTableRequest); QueryableList<eu.eudat.data.entities.Dataset> pagedItems = PaginationManager.applyPaging(authItems, datasetTableRequest);
DataTableData<DatasetListingModel> dataTable = new DataTableData<DatasetListingModel>(); DataTableData<DatasetListingModel> dataTable = new DataTableData<DatasetListingModel>();
@ -62,11 +76,14 @@ public class DatasetManager {
return dataTable; return dataTable;
} }
public DatasetWizardModel getSingle(DatasetDao datatasetRepository, String id) throws InstantiationException, IllegalAccessException { public DatasetWizardModel getSingle(DatasetDao datatasetRepository, DatasetRepository elasticDatasetRepository, String id) throws InstantiationException, IllegalAccessException, IOException {
DatasetWizardModel dataset = new DatasetWizardModel(); DatasetWizardModel dataset = new DatasetWizardModel();
eu.eudat.data.entities.Dataset datasetEntity = datatasetRepository.find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class)); eu.eudat.data.entities.Dataset datasetEntity = datatasetRepository.find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class));
eu.eudat.elastic.entities.Dataset datasetElastic = elasticDatasetRepository.exists() ?
elasticDatasetRepository.findDocument(id) : new eu.eudat.elastic.entities.Dataset();
dataset.setDatasetProfileDefinition(getPagedProfile(dataset, datasetEntity)); dataset.setDatasetProfileDefinition(getPagedProfile(dataset, datasetEntity));
dataset.fromDataModel(datasetEntity); dataset.fromDataModel(datasetEntity);
dataset.setTags(datasetElastic.getTags());
return dataset; return dataset;
} }
@ -75,7 +92,7 @@ public class DatasetManager {
datasetprofile.setStatus(dataset.getStatus()); datasetprofile.setStatus(dataset.getStatus());
if (datasetEntity.getProperties() != null) { if (datasetEntity.getProperties() != null) {
JSONObject jobject = new JSONObject(datasetEntity.getProperties()); JSONObject jobject = new JSONObject(datasetEntity.getProperties());
Map<String, Object> properties = (Map<String, Object>) jobject.toMap(); Map<String, Object> properties = jobject.toMap();
datasetprofile.fromJsonObject(properties); datasetprofile.fromJsonObject(properties);
} }
PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile();
@ -180,15 +197,16 @@ public class DatasetManager {
return newFile; return newFile;
} }
public static eu.eudat.data.entities.Dataset createOrUpdate(ApiContext apiContext, DatasetWizardModel profile, Principal principal) throws Exception { public static eu.eudat.data.entities.Dataset createOrUpdate(ApiContext apiContext, DatasetWizardModel datasetWizardModel, Principal principal) throws Exception {
eu.eudat.data.entities.Dataset dataset = profile.toDataModel(); eu.eudat.data.entities.Dataset dataset = datasetWizardModel.toDataModel();
propertiesModelToString(profile, dataset); propertiesModelToString(datasetWizardModel, dataset);
UserInfo userInfo = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build(); UserInfo userInfo = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build();
dataset.setCreator(userInfo); dataset.setCreator(userInfo);
updateTags(apiContext.getOperationsContext().getDatasetRepository(), datasetWizardModel);
createRegistriesIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getRegistryDao(), dataset); createRegistriesIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getRegistryDao(), dataset);
createDataRepositoriesIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getDataRepositoryDao(), dataset); createDataRepositoriesIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getDataRepositoryDao(), dataset);
createServicesIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getDatasetServiceDao(),apiContext.getOperationsContext().getDatabaseRepository().getServiceDao(), dataset); createServicesIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getDatasetServiceDao(), apiContext.getOperationsContext().getDatabaseRepository().getServiceDao(), dataset);
createExternalDatasetsIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getDatasetExternalDatasetDao(),apiContext.getOperationsContext().getDatabaseRepository().getExternalDatasetDao(), dataset); createExternalDatasetsIfTheyDontExist(apiContext.getOperationsContext().getDatabaseRepository().getDatasetExternalDatasetDao(), apiContext.getOperationsContext().getDatabaseRepository().getExternalDatasetDao(), dataset);
return apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().createOrUpdate(dataset); return apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().createOrUpdate(dataset);
} }
@ -200,6 +218,15 @@ public class DatasetManager {
dataset.setProperties(jobject.toString()); dataset.setProperties(jobject.toString());
} }
private static void updateTags(DatasetRepository datasetRepository, DatasetWizardModel datasetWizardModel) throws IOException {
if (datasetWizardModel.getTags() != null && !datasetWizardModel.getTags().isEmpty()) {
eu.eudat.elastic.entities.Dataset dataset = new eu.eudat.elastic.entities.Dataset();
dataset.setId(datasetWizardModel.getId().toString());
dataset.setTags(datasetWizardModel.getTags());
datasetRepository.createOrUpdate(dataset);
}
}
private static void createRegistriesIfTheyDontExist(RegistryDao registryDao, eu.eudat.data.entities.Dataset dataset) { private static void createRegistriesIfTheyDontExist(RegistryDao registryDao, eu.eudat.data.entities.Dataset dataset) {
if (dataset.getRegistries() != null && !dataset.getRegistries().isEmpty()) { if (dataset.getRegistries() != null && !dataset.getRegistries().isEmpty()) {
@ -226,8 +253,7 @@ public class DatasetManager {
datasetDataRepository.getDataRepository().setId(entries.get(0).getId()); datasetDataRepository.getDataRepository().setId(entries.get(0).getId());
datasetDataRepository.setDataset(dataset); datasetDataRepository.setDataset(dataset);
dataset.getDatasetDataRepositories().add(datasetDataRepository); dataset.getDatasetDataRepositories().add(datasetDataRepository);
} } else {
else {
DataRepository dataRepository = dataRepositoryDao.createOrUpdate(datasetDataRepository.getDataRepository()); DataRepository dataRepository = dataRepositoryDao.createOrUpdate(datasetDataRepository.getDataRepository());
datasetDataRepository.setDataRepository(dataRepository); datasetDataRepository.setDataRepository(dataRepository);
dataset.getDatasetDataRepositories().add(datasetDataRepository); dataset.getDatasetDataRepositories().add(datasetDataRepository);
@ -236,7 +262,7 @@ public class DatasetManager {
} }
} }
private static void createServicesIfTheyDontExist(DatasetServiceDao datasetServiceDao,ServiceDao serviceDao, eu.eudat.data.entities.Dataset dataset) { private static void createServicesIfTheyDontExist(DatasetServiceDao datasetServiceDao, ServiceDao serviceDao, eu.eudat.data.entities.Dataset dataset) {
Set<DatasetService> services = dataset.getServices(); Set<DatasetService> services = dataset.getServices();
dataset.setServices(new HashSet<>()); dataset.setServices(new HashSet<>());
if (services != null && !services.isEmpty()) { if (services != null && !services.isEmpty()) {
@ -244,21 +270,20 @@ public class DatasetManager {
ServiceCriteria criteria = new ServiceCriteria(); ServiceCriteria criteria = new ServiceCriteria();
criteria.setLike(datasetService.getService().getLabel()); criteria.setLike(datasetService.getService().getLabel());
List<eu.eudat.data.entities.Service> entries = serviceDao.getWithCriteria(criteria).toList(); List<eu.eudat.data.entities.Service> entries = serviceDao.getWithCriteria(criteria).toList();
if (entries != null && !entries.isEmpty()){ if (entries != null && !entries.isEmpty()) {
datasetService.getService().setId(entries.get(0).getId()); datasetService.getService().setId(entries.get(0).getId());
datasetService.setDataset(dataset); datasetService.setDataset(dataset);
dataset.getServices().add(datasetService); dataset.getServices().add(datasetService);
} } else {
else {
Service service = serviceDao.createOrUpdate(datasetService.getService()); Service service = serviceDao.createOrUpdate(datasetService.getService());
datasetService.setService(service ); datasetService.setService(service);
dataset.getServices().add(datasetService); dataset.getServices().add(datasetService);
} }
} }
} }
} }
private static void createExternalDatasetsIfTheyDontExist(DatasetExternalDatasetDao datasetExternalDatasetDao,ExternalDatasetDao externalDatasetDao, eu.eudat.data.entities.Dataset dataset) { private static void createExternalDatasetsIfTheyDontExist(DatasetExternalDatasetDao datasetExternalDatasetDao, ExternalDatasetDao externalDatasetDao, eu.eudat.data.entities.Dataset dataset) {
Set<DatasetExternalDataset> externalDatasets = dataset.getDatasetExternalDatasets(); Set<DatasetExternalDataset> externalDatasets = dataset.getDatasetExternalDatasets();
dataset.setDatasetExternalDatasets(new HashSet<>()); dataset.setDatasetExternalDatasets(new HashSet<>());
if (externalDatasets != null && !externalDatasets.isEmpty()) { if (externalDatasets != null && !externalDatasets.isEmpty()) {
@ -270,8 +295,7 @@ public class DatasetManager {
datasetExternalDataset.getExternalDataset().setId(entries.get(0).getId()); datasetExternalDataset.getExternalDataset().setId(entries.get(0).getId());
datasetExternalDataset.setDataset(dataset); datasetExternalDataset.setDataset(dataset);
dataset.getDatasetExternalDatasets().add(datasetExternalDataset); dataset.getDatasetExternalDatasets().add(datasetExternalDataset);
} } else {
else {
ExternalDataset externalDataset = externalDatasetDao.createOrUpdate(datasetExternalDataset.getExternalDataset()); ExternalDataset externalDataset = externalDatasetDao.createOrUpdate(datasetExternalDataset.getExternalDataset());
datasetExternalDataset.setExternalDataset(externalDataset); datasetExternalDataset.setExternalDataset(externalDataset);
dataset.getDatasetExternalDatasets().add(datasetExternalDataset); dataset.getDatasetExternalDatasets().add(datasetExternalDataset);

View File

@ -23,6 +23,7 @@ public class ExternalUrls implements Serializable {
ResearcherUrls researchers; ResearcherUrls researchers;
OrganisationUrls organisations; OrganisationUrls organisations;
DatasetUrls datasets; DatasetUrls datasets;
TagUrls tags;
public RegistryUrls getRegistries() { public RegistryUrls getRegistries() {
@ -59,6 +60,15 @@ public class ExternalUrls implements Serializable {
return researchers; return researchers;
} }
public TagUrls getTags() {
return tags;
}
@XmlElement(name = "tags")
public void setTags(TagUrls tags) {
this.tags = tags;
}
@XmlElement(name = "researchers") @XmlElement(name = "researchers")
public void setResearchers(ResearcherUrls researchers) { public void setResearchers(ResearcherUrls researchers) {
this.researchers = researchers; this.researchers = researchers;

View File

@ -11,6 +11,7 @@ import javax.xml.bind.Unmarshaller;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.Paths;
/** /**
* Created by ikalyvas on 2/9/2018. * Created by ikalyvas on 2/9/2018.
@ -34,7 +35,7 @@ public class ProductionConfigLoader implements ConfigLoader {
JAXBContext jaxbContext = JAXBContext.newInstance(ExternalUrls.class); JAXBContext jaxbContext = JAXBContext.newInstance(ExternalUrls.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
is = new URL("file:///" + System.getenv("CATALINA_HOME") + fileUrl).openStream(); is = new URL(Paths.get(fileUrl).toUri().toURL().toString()).openStream();
externalUrls = (ExternalUrls) jaxbUnmarshaller.unmarshal(is); externalUrls = (ExternalUrls) jaxbUnmarshaller.unmarshal(is);
} catch (Exception ex) { } catch (Exception ex) {

View File

@ -0,0 +1,35 @@
package eu.eudat.logic.proxy.config.entities;
import eu.eudat.logic.proxy.config.FetchStrategy;
import eu.eudat.logic.proxy.config.UrlConfiguration;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import java.util.List;
/**
* Created by ikalyvas on 7/9/2018.
*/
public class TagUrls {
List<UrlConfiguration> urls;
FetchStrategy fetchMode;
public List<UrlConfiguration> getUrls() {
return urls;
}
@XmlElementWrapper
@XmlElement(name = "urlConfig")
public void setUrls(List<UrlConfiguration> urls) {
this.urls = urls;
}
public FetchStrategy getFetchMode() {
return fetchMode;
}
@XmlElement(name = "fetchMode")
public void setFetchMode(FetchStrategy fetchMode) {
this.fetchMode = fetchMode;
}
}

View File

@ -85,6 +85,15 @@ public class RemoteFetcher {
return getAll(urlConfigs, fetchStrategy, query); return getAll(urlConfigs, fetchStrategy, query);
} }
@Cacheable("tags")
public List<Map<String, String>> getTags(String query, String key) throws NoURLFound, HugeResultSet {
List<UrlConfiguration> urlConfigs =
key != null && !key.isEmpty() ? configLoader.getExternalUrls().getTags().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList())
: configLoader.getExternalUrls().getTags().getUrls();
FetchStrategy fetchStrategy = configLoader.getExternalUrls().getTags().getFetchMode();
return getAll(urlConfigs, fetchStrategy, query);
}
@Cacheable("datasets") @Cacheable("datasets")
public List<Map<String, String>> getDatasets(String query, String key) throws NoURLFound, HugeResultSet { public List<Map<String, String>> getDatasets(String query, String key) throws NoURLFound, HugeResultSet {
List<UrlConfiguration> urlConfigs = List<UrlConfiguration> urlConfigs =

View File

@ -3,6 +3,7 @@ package eu.eudat.logic.services;
import eu.eudat.logic.services.helpers.HelpersService; import eu.eudat.logic.services.helpers.HelpersService;
import eu.eudat.logic.services.operations.OperationsContext; import eu.eudat.logic.services.operations.OperationsContext;
import eu.eudat.logic.services.utilities.UtilitiesService; import eu.eudat.logic.services.utilities.UtilitiesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -13,6 +14,7 @@ public class ApiContextImpl implements ApiContext {
private HelpersService helpersService; private HelpersService helpersService;
private UtilitiesService utilitiesService; private UtilitiesService utilitiesService;
@Autowired
public ApiContextImpl(OperationsContext operationsContext, HelpersService helpersService, UtilitiesService utilitiesService) { public ApiContextImpl(OperationsContext operationsContext, HelpersService helpersService, UtilitiesService utilitiesService) {
this.operationsContext = operationsContext; this.operationsContext = operationsContext;
this.helpersService = helpersService; this.helpersService = helpersService;

View File

@ -1,5 +1,6 @@
package eu.eudat.logic.services.operations; package eu.eudat.logic.services.operations;
import eu.eudat.elastic.repository.DatasetRepository;
import eu.eudat.logic.builders.BuilderFactory; import eu.eudat.logic.builders.BuilderFactory;
import eu.eudat.logic.proxy.fetching.RemoteFetcher; import eu.eudat.logic.proxy.fetching.RemoteFetcher;
import eu.eudat.logic.services.helpers.FileStorageService; import eu.eudat.logic.services.helpers.FileStorageService;
@ -20,4 +21,5 @@ public interface OperationsContext {
FileStorageService getFileStorageService(); FileStorageService getFileStorageService();
DatasetRepository getDatasetRepository();
} }

View File

@ -1,5 +1,6 @@
package eu.eudat.logic.services.operations; package eu.eudat.logic.services.operations;
import eu.eudat.elastic.repository.DatasetRepository;
import eu.eudat.logic.builders.BuilderFactory; import eu.eudat.logic.builders.BuilderFactory;
import eu.eudat.logic.proxy.fetching.RemoteFetcher; import eu.eudat.logic.proxy.fetching.RemoteFetcher;
import eu.eudat.logic.services.helpers.FileStorageService; import eu.eudat.logic.services.helpers.FileStorageService;
@ -18,15 +19,17 @@ public class OperationsContextImpl implements OperationsContext {
private RemoteFetcher remoteFetcher; private RemoteFetcher remoteFetcher;
private BuilderFactory builderFactory; private BuilderFactory builderFactory;
private FileStorageService fileStorageService; private FileStorageService fileStorageService;
private DatasetRepository datasetRepository;
@Autowired @Autowired
public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcher remoteFetcher public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcher remoteFetcher
, BuilderFactory builderFactory, FileStorageService fileStorageService) { , BuilderFactory builderFactory, FileStorageService fileStorageService,DatasetRepository datasetRepository) {
this.databaseRepository = databaseRepository; this.databaseRepository = databaseRepository;
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
this.remoteFetcher = remoteFetcher; this.remoteFetcher = remoteFetcher;
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.fileStorageService = fileStorageService; this.fileStorageService = fileStorageService;
this.datasetRepository = datasetRepository;
} }
@Override @Override
@ -53,4 +56,13 @@ public class OperationsContextImpl implements OperationsContext {
public FileStorageService getFileStorageService() { public FileStorageService getFileStorageService() {
return fileStorageService; return fileStorageService;
} }
@Override
public DatasetRepository getDatasetRepository() {
return datasetRepository;
}
public void setDatasetRepository(DatasetRepository datasetRepository) {
this.datasetRepository = datasetRepository;
}
} }

View File

@ -1,6 +1,7 @@
package eu.eudat.models.data.datasetwizard; package eu.eudat.models.data.datasetwizard;
import eu.eudat.data.entities.*; import eu.eudat.data.entities.*;
import eu.eudat.elastic.entities.Tag;
import eu.eudat.models.DataModel; import eu.eudat.models.DataModel;
import eu.eudat.models.data.dataset.DataRepository; import eu.eudat.models.data.dataset.DataRepository;
import eu.eudat.models.data.dataset.Registry; import eu.eudat.models.data.dataset.Registry;
@ -29,6 +30,7 @@ public class DatasetWizardModel implements DataModel<Dataset, DatasetWizardModel
private List<Registry> registries; private List<Registry> registries;
private List<Service> services; private List<Service> services;
private List<DataRepository> dataRepositories; private List<DataRepository> dataRepositories;
private List<Tag> tags;
private List<ExternalDatasetListingModel> externalDatasets; private List<ExternalDatasetListingModel> externalDatasets;
private DatasetProfileListingModel profile; private DatasetProfileListingModel profile;
@ -144,6 +146,14 @@ public class DatasetWizardModel implements DataModel<Dataset, DatasetWizardModel
this.externalDatasets = externalDatasets; this.externalDatasets = externalDatasets;
} }
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
@Override @Override
public DatasetWizardModel fromDataModel(Dataset entity) { public DatasetWizardModel fromDataModel(Dataset entity) {
this.id = entity.getId(); this.id = entity.getId();

View File

@ -0,0 +1,22 @@
package eu.eudat.models.data.external;
import java.util.List;
import java.util.Map;
/**
* Created by ikalyvas on 7/9/2018.
*/
public class TagExternalSourcesModel extends ExternalListingItem<TagExternalSourcesModel> {
@Override
public TagExternalSourcesModel fromExternalItem(List<Map<String, String>> values) {
for (Map<String, String> item : values) {
ExternalSourcesItemModel model = new ExternalSourcesItemModel();
model.setId(item.get("pid"));
model.setUri(item.get("label"));
model.setName(item.get("name"));
this.add(model);
}
return this;
}
}

View File

@ -37,6 +37,15 @@ public class ExternalSourcesConfiguration {
private List<ExternalSourcesUrlModel> dataRepositories; private List<ExternalSourcesUrlModel> dataRepositories;
private List<ExternalSourcesUrlModel> services; private List<ExternalSourcesUrlModel> services;
private List<ExternalSourcesUrlModel> externalDatasets; private List<ExternalSourcesUrlModel> externalDatasets;
private List<ExternalSourcesUrlModel> tags;
public List<ExternalSourcesUrlModel> getTags() {
return tags;
}
public void setTags(List<ExternalSourcesUrlModel> tags) {
this.tags = tags;
}
public List<ExternalSourcesUrlModel> getRegistries() { public List<ExternalSourcesUrlModel> getRegistries() {
return registries; return registries;

View File

@ -44,6 +44,45 @@
<fetchMode>FIRST</fetchMode> <!-- EITHER 'FIRST' OR 'ALL' --> <fetchMode>FIRST</fetchMode> <!-- EITHER 'FIRST' OR 'ALL' -->
</registries> </registries>
<tags>
<urls>
<urlConfig>
<key>cristin</key>
<label>Cristin</label>
<ordinal>1</ordinal>
<url>https://eestore.paas2.uninett.no/api/tags/</url>
<data>
<path>$['data'][*]['attributes']</path>
<fields>
<id>'pid'</id>
<name>'name'</name>
<uri>'uri'</uri>
<description>'description'</description>
</fields>
</data>
<paginationpath>$['meta']['pagination']['page','pages','count']</paginationpath>
</urlConfig>
<urlConfig>
<key>openAire</key>
<label>OpenAIRE</label>
<ordinal>1</ordinal>
<url>https://eestore.paas2.uninett.no/api/tags/</url>
<data>
<path>$['data'][*]['attributes']</path>
<fields>
<id>'pid'</id>
<name>'name'</name>
<uri>'uri'</uri>
<description>'description'</description>
</fields>
</data>
<paginationpath>$['meta']['pagination']['page','pages','count']</paginationpath>
</urlConfig>
</urls>
<fetchMode>FIRST</fetchMode> <!-- EITHER 'FIRST' OR 'ALL' -->
</tags>
<projects> <projects>

View File

@ -15,8 +15,8 @@ production.database.password=dmpt00lu$r
##########################/Persistence########################################## ##########################/Persistence##########################################
###################Allowed Proxy Service Host ############################ ###################Allowed Proxy Service Host ############################
eu.eudat.logic.proxy.allowed.host=https://eestore.paas2.uninett.no eu.eudat.logic.proxy.allowed.host=https://eestore.paas2.uninett.no
configuration.externalUrls=/classes/ExternalUrls.xml configuration.externalUrls=/tmp/ExternalUrls.xml
configuration.dynamicProjectUrl=/classes/ProjectConfiguration.xml configuration.dynamicProjectUrl=/tmp/ProjectConfiguration.xml
####################################################### #######################################################
########################/Email############################# ########################/Email#############################
@ -59,7 +59,7 @@ b2access.externallogin.redirect_uri=http://dmp.eudat.org:4200/api/oauth/authoriz
b2access.externallogin.clientid=eudatdmptool b2access.externallogin.clientid=eudatdmptool
b2access.externallogin.clientSecret=A3b*1*92 b2access.externallogin.clientSecret=A3b*1*92
################################################################################# #################################################################################
pdf.converter.url=http://localhost/ pdf.converter.url=http://localhost:81/
files.storage.temp = temp files.storage.temp = temp
files.storage.final = final files.storage.final = final
################################################################################# #################################################################################
@ -70,3 +70,6 @@ project.configuration.grant.name = Grant
http-logger.initial-delay = 0 http-logger.initial-delay = 0
http-logger.delay = 10 http-logger.delay = 10
http-logger.server-address = http://logstash:31311 http-logger.server-address = http://logstash:31311
#############################Elastic Search######################################
elasticsearch.host = localhost
elasticsearch.port = 9201

View File

@ -1,60 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "dmp-frontend"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.scss"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json",
"exclude": "**/node_modules/**"
},
{
"project": "src/tsconfig.spec.json",
"exclude": "**/node_modules/**"
},
{
"project": "e2e/tsconfig.e2e.json",
"exclude": "**/node_modules/**"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"component": {}
}
}

View File

@ -5,7 +5,9 @@ RUN npm cache clear --force && npm install
COPY ./ /app/ COPY ./ /app/
ARG env=dev ARG env=dev
ARG aot=--no-aot ARG aot=--no-aot
RUN ng build --$env --$aot RUN echo $env
RUN echo $aot
RUN if [ "$env" = "prod" ]; then ng build --$env --$aot; else ng build --$aot; fi
# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx # Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx
FROM nginx:1.13 FROM nginx:1.13

132
dmp-frontend/angular.json Normal file
View File

@ -0,0 +1,132 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"dmp-frontend": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "dmp-frontend:build"
},
"configurations": {
"production": {
"browserTarget": "dmp-frontend:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "dmp-frontend:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [],
"styles": [
"src/styles.scss"
],
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"dmp-frontend-e2e": {
"root": "",
"sourceRoot": "e2e",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "dmp-frontend:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "dmp-frontend",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"styleext": "css"
},
"@schematics/angular:directive": {
"prefix": "app"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -12,32 +12,33 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^5.2.0", "@angular/animations": "6.0.7",
"@angular/cdk": "^5.2.4", "@angular/cdk": "6.1.0",
"@angular/common": "^5.2.0", "@angular/common": "6.0.7",
"@angular/compiler": "^5.2.0", "@angular/compiler": "6.0.7",
"@angular/core": "^5.2.0", "@angular/core": "6.0.7",
"@angular/flex-layout": "5.0.0-beta.14", "@angular/flex-layout": "6.0.0-beta.16",
"@angular/forms": "^5.2.0", "@angular/forms": "6.0.7",
"@angular/http": "^5.2.0", "@angular/http": "6.0.7",
"@angular/material": "^5.2.4", "@angular/material": "6.1.0",
"@angular/platform-browser": "^5.2.0", "@angular/platform-browser": "6.0.7",
"@angular/platform-browser-dynamic": "^5.2.0", "@angular/platform-browser-dynamic": "6.0.7",
"@angular/router": "^5.2.0", "@angular/router": "6.0.7",
"@covalent/core": "1.0.0", "@covalent/core": "2.0.0-beta.2",
"@ngx-translate/core": "10.0.1", "@ngx-translate/core": "10.0.1",
"@ngx-translate/http-loader": "3.0.1", "@ngx-translate/http-loader": "3.0.1",
"@swimlane/ngx-datatable": "^11.3.2", "@swimlane/ngx-datatable": "13.0.1",
"@types/file-saver": "1.3.0", "@types/file-saver": "1.3.0",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"file-saver": "1.3.3", "file-saver": "1.3.3",
"rxjs": "^5.6.0-forward-compat.4", "rxjs": "^6.2.1",
"zone.js": "^0.8.19" "rxjs-compat": "^6.1.0",
"zone.js": "^0.8.26"
}, },
"devDependencies": { "devDependencies": {
"@angular/cli": "~1.7.4", "@angular/cli": "^6.0.8",
"@angular/compiler-cli": "^5.2.0", "@angular/compiler-cli": "6.0.7",
"@angular/language-service": "^5.2.0", "@angular/language-service": "6.0.7",
"@types/jasmine": "~2.8.3", "@types/jasmine": "~2.8.3",
"@types/jasminewd2": "~2.0.2", "@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60", "@types/node": "~6.0.60",
@ -52,6 +53,7 @@
"protractor": "^5.3.2", "protractor": "^5.3.2",
"ts-node": "~4.1.0", "ts-node": "~4.1.0",
"tslint": "~5.9.1", "tslint": "~5.9.1",
"typescript": "~2.5.3" "typescript": "2.7.2",
"@angular-devkit/build-angular": "~0.6.8"
} }
} }

View File

@ -1,4 +1,4 @@
<app-navigation [(sidenavOpen)]="sideNavOpen"></app-navigation> <app-navigation></app-navigation>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">

View File

@ -1,6 +1,3 @@
.example-container { .example-container {
width: 400px; background: rgb(250, 248, 248);
height: 200px;
margin: 10px;
border: 1px solid #555;
} }

View File

@ -38,11 +38,10 @@ import { RecentActivityComponent } from './users/activity/recent-activity.compon
import { LanguageResolverService } from './services/language-resolver/language-resolver.service'; import { LanguageResolverService } from './services/language-resolver/language-resolver.service';
import { LanguageService } from './services/language/language.service'; import { LanguageService } from './services/language/language.service';
import { UsersModule } from './users/users.module'; import { UsersModule } from './users/users.module';
import { HelpContentComponent } from './shared/help-content/help-content.component'; import { HelpContentComponent, AsideHelpContentComponent } from './shared/help-content/help-content.component';
import { AuthGuard } from './shared/guards/auth.guard'; import { AuthGuard } from './shared/guards/auth.guard';
import { UrlUtilities } from './utilities/UrlUtilities'; import { UrlUtilities } from './utilities/UrlUtilities';
import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service'; import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service';
import { McBreadcrumbsModule } from 'ngx-breadcrumbs';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -52,12 +51,12 @@ import { McBreadcrumbsModule } from 'ngx-breadcrumbs';
RecentActivityComponent, RecentActivityComponent,
WelcomepageComponent, WelcomepageComponent,
HelpContentComponent, HelpContentComponent,
AsideHelpContentComponent,
B2AccessLoginComponent, B2AccessLoginComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
ReactiveFormsModule, ReactiveFormsModule,
McBreadcrumbsModule.forRoot(),
FormsModule, FormsModule,
HttpModule, HttpModule,
HttpClientModule, HttpClientModule,

View File

@ -1,45 +1,45 @@
<div> <div>
<div [formGroup]="form"> <div [formGroup]="form">
<div class="row"> <div class="row">
<mat-form-field> <mat-form-field>
<input matInput placeholder='Id' type="text" formControlName="id"> <input matInput placeholder='Id' type="text" formControlName="id">
</mat-form-field> </mat-form-field>
<div> <div>
<div formGroupName="viewStyle"> <div formGroupName="viewStyle">
<mat-form-field> <mat-form-field>
<mat-select placeholder="View Style" formControlName="renderStyle" (change)="onchangeCombo($event)"> <mat-select placeholder="View Style" formControlName="renderStyle" (change)="onchangeCombo()">
<mat-option value="textarea">textarea</mat-option> <mat-option value="textarea">textarea</mat-option>
<mat-option value="booleanDecision">booleanDecision</mat-option> <mat-option value="booleanDecision">booleanDecision</mat-option>
<mat-option value='combobox'>combobox</mat-option> <mat-option value='combobox'>combobox</mat-option>
<mat-option value="checkBox">checkBox</mat-option> <mat-option value="checkBox">checkBox</mat-option>
<mat-option value="freetext">freetext</mat-option> <mat-option value="freetext">freetext</mat-option>
<mat-option value="radiobox">radiobox</mat-option> <mat-option value="radiobox">radiobox</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div>
</div>
</div> </div>
<div class="form" [ngSwitch]="form.get('viewStyle').get('renderStyle').value"> </div>
<div *ngSwitchCase="'combobox'"> </div>
<combobox-component [form]="form" [dataModel]="dataModel"></combobox-component> <div class="form" [ngSwitch]="form.get('viewStyle').get('renderStyle').value">
</div> <div *ngSwitchCase="'combobox'">
<div *ngSwitchCase="'radiobox'"> <combobox-component [form]="form" [dataModel]="dataModel"></combobox-component>
<radiobox-component [form]="form" [dataModel]="dataModel"></radiobox-component> </div>
</div> <div *ngSwitchCase="'radiobox'">
<div *ngSwitchCase="'freetext'"> <radiobox-component [form]="form" [dataModel]="dataModel"></radiobox-component>
<freetext-component [form]="form" [dataModel]="dataModel"></freetext-component> </div>
</div> <div *ngSwitchCase="'freetext'">
<div *ngSwitchCase="'textarea'"> <freetext-component [form]="form" [dataModel]="dataModel"></freetext-component>
<textarea-component [form]="form" [dataModel]="dataModel"></textarea-component> </div>
</div> <div *ngSwitchCase="'textarea'">
<div *ngSwitchCase="'booleanDecision'"> <textarea-component [form]="form" [dataModel]="dataModel"></textarea-component>
<booleanDecision-component [form]="form" [dataModel]="dataModel"></booleanDecision-component> </div>
</div> <div *ngSwitchCase="'booleanDecision'">
<div *ngSwitchCase="'checkBox'"> <booleanDecision-component [form]="form" [dataModel]="dataModel"></booleanDecision-component>
<checkbox-component [form]="form" [dataModel]="dataModel"></checkbox-component> </div>
</div> <div *ngSwitchCase="'checkBox'">
</div> <checkbox-component [form]="form" [dataModel]="dataModel"></checkbox-component>
<!-- <div class="row"> </div>
</div>
<!-- <div class="row">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label>description</label> <label>description</label>
<input type="text" class="form-control" formControlName="description"> <input type="text" class="form-control" formControlName="description">
@ -49,57 +49,57 @@
<input type="text" class="form-control" formControlName="extendedDescription"> <input type="text" class="form-control" formControlName="extendedDescription">
</div> </div>
</div> --> </div> -->
<div class="row"> <div class="row">
<div *ngIf="isFieldMultiplicityEnabled" formGroupName="multiplicity"> <div *ngIf="isFieldMultiplicityEnabled" formGroupName="multiplicity">
<div> <div>
<h5>Multiplicity</h5> <h5>Multiplicity</h5>
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="number" placeholder="Min" formControlName="min"> <input matInput type="number" placeholder="Min" formControlName="min">
</mat-form-field> </mat-form-field>
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="number" placeholder="Max" formControlName="max"> <input matInput type="number" placeholder="Max" formControlName="max">
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="number" placeholder="Ordinal" formControlName="ordinal"> <input matInput type="number" placeholder="Ordinal" formControlName="ordinal">
</mat-form-field> </mat-form-field>
<div formGroupName="defaultValue"> <div formGroupName="defaultValue">
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="text" placeholder="Default Value" formControlName="value"> <input matInput type="text" placeholder="Default Value" formControlName="value">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-5"> <div class="col-md-5">
<div formArrayName="validations"> <div formArrayName="validations">
<div *ngFor="let validation of form.controls.validations.controls; let i=index"> <div *ngFor="let validation of form['controls']['validations']['controls']; let i=index">
<mat-form-field> <mat-form-field>
<mat-select placeholder='Validation' [formControlName]="i"> <mat-select placeholder='Validation' [formControlName]="i">
<mat-option *ngFor="let option of validationsOptions" [value]="option.key">{{option.value}}</mat-option> <mat-option *ngFor="let option of validationsOptions" [value]="option.key">{{option.value}}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
</div>
</div>
</div> </div>
</div>
<mat-checkbox *ngIf="showMultiplicity" [(ngModel)]="isFieldMultiplicityEnabled" (ngModelChange)="onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled)">Multiplicity</mat-checkbox>
<mat-expansion-panel *ngFor="let rule of dataModel.visible.rules let i=index;">
<mat-expansion-panel-header>
<mat-panel-title>{{i + 1}}. Rule {{i + 1}}</mat-panel-title>
<div class="btn-group pull-right"> </div>
<button type="button" class="btn btn-sm" style="margin-left:5px;" (click)="DeleteRule(i);"> </div>
<span class="glyphicon glyphicon-erase"></span> </div>
</button> <mat-checkbox *ngIf="showMultiplicity" [(ngModel)]="isFieldMultiplicityEnabled" (ngModelChange)="onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled)">Multiplicity</mat-checkbox>
</div> <mat-expansion-panel *ngFor="let rule of dataModel.visible.rules let i=index;">
</mat-expansion-panel-header> <mat-expansion-panel-header>
<rule-form [form]="form.get('visible').get('rules').get(''+i)" [dataModel]="rule"></rule-form> <mat-panel-title>{{i + 1}}. Rule {{i + 1}}</mat-panel-title>
</mat-expansion-panel>
<a (click)="addNewRule()" style="cursor: pointer"> <div class="btn-group pull-right">
Add Rule + <button type="button" class="btn btn-sm" style="margin-left:5px;" (click)="DeleteRule(i);">
</a> <span class="glyphicon glyphicon-erase"></span>
</button>
</div>
</mat-expansion-panel-header>
<rule-form [form]="form.get('visible').get('rules').get(''+i)" [dataModel]="rule"></rule-form>
</mat-expansion-panel>
<a (click)="addNewRule()" style="cursor: pointer">
Add Rule +
</a>
</div> </div>

View File

@ -1,78 +1,78 @@
<div> <div>
<div class="row" [formGroup]="form"> <div class="row" [formGroup]="form">
<div class="col-md-6"> <div class="col-md-6">
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="text" placeholder="Title" formControlName="title"> <input matInput type="text" placeholder="Title" formControlName="title">
</mat-form-field> </mat-form-field>
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="text" placeholder="Id" formControlName="id"> <input matInput type="text" placeholder="Id" formControlName="id">
</mat-form-field> </mat-form-field>
<mat-form-field class="full-width"> <mat-form-field class="full-width">
<input matInput type="number" placeholder="Ordinal" formControlName="ordinal"> <input matInput type="number" placeholder="Ordinal" formControlName="ordinal">
</mat-form-field> </mat-form-field>
</div>
<div class="col-md-6">
<mat-form-field class="full-width">
<mat-select placeholder='Page' formControlName="page">
<mat-option *ngFor="let pageGroup of form.root.get('pages').controls;" [value]="pageGroup.get('id').value">{{pageGroup.get('title').value}}</mat-option>
</mat-select>
<!-- <div *ngIf="form.get('page').invalid && (form.get('page').dirty || form.get('page').touched)" class="alert alert-danger">Page is required</div> -->
</mat-form-field>
<label>Default Visibility</label>
<mat-radio-group formControlName="defaultVisibility" class="full-width">
<mat-radio-button [value]="true">true</mat-radio-button>
<mat-radio-button [value]="false">false</mat-radio-button>
</mat-radio-group>
</div>
</div> </div>
<div class="col-md-6">
<mat-form-field class="full-width">
<mat-select placeholder='Page' formControlName="page">
<mat-option *ngFor="let pageGroup of form.root.get('pages')['controls'];" [value]="pageGroup.get('id').value">{{pageGroup.get('title').value}}</mat-option>
</mat-select>
<!-- <div *ngIf="form.get('page').invalid && (form.get('page').dirty || form.get('page').touched)" class="alert alert-danger">Page is required</div> -->
</mat-form-field>
<label>Default Visibility</label>
<mat-radio-group formControlName="defaultVisibility" class="full-width">
<mat-radio-button [value]="true">true</mat-radio-button>
<mat-radio-button [value]="false">false</mat-radio-button>
</mat-radio-group>
<div *ngIf="dataModel.sections.length > 0">
<mat-expansion-panel *ngFor="let section of dataModel.sections; let i=index;">
<mat-expansion-panel-header>
<mat-panel-title *ngIf="form.get('sections').get(''+i).get('title').value">{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}</mat-panel-title>
<div class="btn-group pull-right">
<button type="button" class="btn btn-sm" style="margin-left:5px;" (click)="DeleteSectionInSection(i);">
<span class="glyphicon glyphicon-erase"></span>
</button>
</div>
</mat-expansion-panel-header>
<div id="{{indexPath + 's' + i}}">
<section-form [form]="form.get('sections').get(''+i)" [dataModel]="section" [indexPath]="indexPath + 's' + i"></section-form>
</div>
</mat-expansion-panel>
</div> </div>
</div>
<div *ngIf="dataModel.sections.length > 0">
<mat-expansion-panel *ngFor="let section of dataModel.sections; let i=index;">
<mat-expansion-panel-header>
<mat-panel-title *ngIf="form.get('sections').get(''+i).get('title').value">{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}</mat-panel-title>
<div class="btn-group pull-right">
<button type="button" class="btn btn-sm" style="margin-left:5px;" (click)="DeleteSectionInSection(i);">
<span class="glyphicon glyphicon-erase"></span>
</button>
</div>
</mat-expansion-panel-header>
<div id="{{indexPath + 's' + i}}">
<section-form [form]="form.get('sections').get(''+i)" [dataModel]="section" [indexPath]="indexPath + 's' + i"></section-form>
</div>
</mat-expansion-panel>
</div>
<!-- <div *ngFor="let fieldGroup of dataModel.fieldGroups let i=index;"> <!-- <div *ngFor="let fieldGroup of dataModel.fieldGroups let i=index;">
<groupfield-form [form]="form.get('fieldGroups').get(''+i)" [dataModel]="fieldGroup" [indexPath]="indexPath + 'g' + i"></groupfield-form> <groupfield-form [form]="form.get('fieldGroups').get(''+i)" [dataModel]="fieldGroup" [indexPath]="indexPath + 'g' + i"></groupfield-form>
</div> --> </div> -->
<div> <div>
<mat-expansion-panel *ngFor="let field of dataModel.fieldSets let i=index;" class="panel panel-default"> <mat-expansion-panel *ngFor="let field of dataModel.fieldSets let i=index;" class="panel panel-default">
<mat-expansion-panel-header> <mat-expansion-panel-header>
<!-- <a *ngIf="form.get('compositeFields').get(''+i).get('title').value" data-toggle="collapse" href="#{{'compositeFieldCollapse' + i}}" <!-- <a *ngIf="form.get('compositeFields').get(''+i).get('title').value" data-toggle="collapse" href="#{{'compositeFieldCollapse' + i}}"
class="panel-title pull-left" style="padding-top: 7.5px;">{{i + 1}}. {{form.get('compositeFields').get(''+i).get('title').value}}</a> class="panel-title pull-left" style="padding-top: 7.5px;">{{i + 1}}. {{form.get('compositeFields').get(''+i).get('title').value}}</a>
<a *ngIf="!form.get('compositeFields').get(''+i).get('title').value" data-toggle="collapse" href="#{{'compositeFieldCollapse' + i}}" <a *ngIf="!form.get('compositeFields').get(''+i).get('title').value" data-toggle="collapse" href="#{{'compositeFieldCollapse' + i}}"
class="panel-title pull-left" style="padding-top: 7.5px;">{{i + 1}}. Field {{i + 1}}</a> --> class="panel-title pull-left" style="padding-top: 7.5px;">{{i + 1}}. Field {{i + 1}}</a> -->
<mat-panel-title>{{i + 1}}. Field {{i + 1}}</mat-panel-title> <mat-panel-title>{{i + 1}}. Field {{i + 1}}</mat-panel-title>
<div> <div>
<button type="button" class="btn btn-sm" style="margin-left:5px;" (click)="DeleteFieldSet(i);"> <button type="button" class="btn btn-sm" style="margin-left:5px;" (click)="DeleteFieldSet(i);">
<span class="glyphicon glyphicon-erase"></span> <span class="glyphicon glyphicon-erase"></span>
</button> </button>
</div> </div>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<compositefield-form [form]="form.get('fieldSets').get(''+i)" [dataModel]="field" [indexPath]="indexPath + 'cf' + i"></compositefield-form> <compositefield-form [form]="form.get('fieldSets').get(''+i)" [dataModel]="field" [indexPath]="indexPath + 'cf' + i"></compositefield-form>
</mat-expansion-panel> </mat-expansion-panel>
</div> </div>
<!-- <!--
<div *ngIf="dataModel.fieldGroups" class="panel-group" style="margin-top:10px;"> <div *ngIf="dataModel.fieldGroups" class="panel-group" style="margin-top:10px;">
<div *ngFor="let fieldGroup of dataModel.fieldGroups let i=index;" class="panel panel-default"> <div *ngFor="let fieldGroup of dataModel.fieldGroups let i=index;" class="panel panel-default">
<div class="panel-heading clearfix"> <div class="panel-heading clearfix">
@ -93,19 +93,19 @@
</div> </div>
</div> </div>
</div> --> </div> -->
<!-- <div> <!-- <div>
<a (click)="addGroupField()" style="cursor: pointer"> <a (click)="addGroupField()" style="cursor: pointer">
Add Group + Add Group +
</a> </a>
</div> --> </div> -->
<div> <div>
<a (click)="addField()" style="cursor: pointer"> <a (click)="addField()" style="cursor: pointer">
Add Field + Add Field +
</a> </a>
</div> </div>
<div> <div>
<a (click)="addSectioninSection()" style="cursor: pointer"> <a (click)="addSectioninSection()" style="cursor: pointer">
Add Section + Add Section +
</a> </a>
</div> </div>
</div> </div>

View File

@ -13,15 +13,11 @@
<button mat-raised-button color="primary" *ngIf="datasetWizardModel&&datasetWizardModel?.status == 1" style="margin-top: 15px;margin-bottom: 15px;margin-right: 15px;" <button mat-raised-button color="primary" *ngIf="datasetWizardModel&&datasetWizardModel?.status == 1" style="margin-top: 15px;margin-bottom: 15px;margin-right: 15px;"
(click)="downloadXML();" type="button">Download XML</button> (click)="downloadXML();" type="button">Download XML</button>
<div class="fill-space"></div> <div class="fill-space"></div>
<mat-menu #actionsMenu="matMenu"> <button mat-button (click)="redirectToProject()">
<button mat-menu-item (click)="redirectToProject()"> <mat-icon>arrow_right_alt</mat-icon>{{'DATASET-WIZARD.ACTIONS.GO-TO-PROJECT' | translate}}</button>
<mat-icon>arrow_right_alt</mat-icon>{{'DATASET-WIZARD.ACTIONS.GO-TO-PROJECT' | translate}}</button> <button mat-button (click)="redirectToDmp()">
<button mat-menu-item (click)="redirectToDmp()"> <mat-icon>arrow_right_alt</mat-icon>{{'DATASET-WIZARD.ACTIONS.GO-TO-DMP' | translate}}</button>
<mat-icon>arrow_right_alt</mat-icon>{{'DATASET-WIZARD.ACTIONS.GO-TO-DMP' | translate}}</button>
</mat-menu>
<button mat-icon-button type="button" style="margin-top: 15px;margin-bottom: 15px;margin-right: 15px;" [matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon>
</button>
</div> </div>
<mat-horizontal-stepper [linear]="isLinear" #stepper> <mat-horizontal-stepper [linear]="isLinear" #stepper>
<mat-step [stepControl]="formGroup"> <mat-step [stepControl]="formGroup">
@ -54,8 +50,9 @@
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('dataRepositories') && dataRepositoriesTemplate && externalSourcesConfiguration" <app-external-item-listing *ngIf="formGroup.get('dataRepositories') && dataRepositoriesTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.dataRepositories" placeholder="{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}" [options]="externalSourcesConfiguration.dataRepositories" placeholder="{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}"
[parentTemplate]='dataRepositoriesTemplate' [displayFunction]='dataRepositoryDisplayFunc' [formGroup]="formGroup.get('dataRepositories')" [parentTemplate]='dataRepositoriesTemplate' [displayFunction]='dataRepositoryDisplayFunc' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc'
[autoCompleteConfiguration]="dataRepositoriesAutoCompleteConfiguration" (onItemChange)="dataRepositoriesOnItemChange($event)"> [formGroup]="formGroup.get('dataRepositories')" [autoCompleteConfiguration]="dataRepositoriesAutoCompleteConfiguration"
(onItemChange)="dataRepositoriesOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
@ -86,8 +83,9 @@
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('externalDatasets') && externalDatasetsTemplate && externalSourcesConfiguration" <app-external-item-listing *ngIf="formGroup.get('externalDatasets') && externalDatasetsTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.externalDatasets" placeholder="{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}" [options]="externalSourcesConfiguration.externalDatasets" placeholder="{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}"
[parentTemplate]='externalDatasetsTemplate' [displayFunction]='externalDatasetDisplayFunc' [formGroup]="formGroup.get('externalDatasets')" [parentTemplate]='externalDatasetsTemplate' [displayFunction]='externalDatasetDisplayFunc' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc'
[autoCompleteConfiguration]="externalDatasetAutoCompleteConfiguration" (onItemChange)="externalDatasetsOnItemChange($event)"> [formGroup]="formGroup.get('externalDatasets')" [autoCompleteConfiguration]="externalDatasetAutoCompleteConfiguration"
(onItemChange)="externalDatasetsOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
@ -128,7 +126,8 @@
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('registries') && registriesTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.registries" <app-external-item-listing *ngIf="formGroup.get('registries') && registriesTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.registries"
placeholder="{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}" [parentTemplate]='registriesTemplate' [displayFunction]='registriesDisplayFunc' placeholder="{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}" [parentTemplate]='registriesTemplate' [displayFunction]='registriesDisplayFunc'
[formGroup]="formGroup.get('registries')" [autoCompleteConfiguration]="registriesAutoCompleteConfiguration" (onItemChange)="registriesOnItemChange($event)"> [formGroup]="formGroup.get('registries')" [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [autoCompleteConfiguration]="registriesAutoCompleteConfiguration"
(onItemChange)="registriesOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
@ -154,7 +153,8 @@
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('services') && servicesTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.services" <app-external-item-listing *ngIf="formGroup.get('services') && servicesTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.services"
placeholder="{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}" [parentTemplate]='servicesTemplate' [displayFunction]='servicesDisplayFunc' placeholder="{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}" [parentTemplate]='servicesTemplate' [displayFunction]='servicesDisplayFunc'
[formGroup]="formGroup.get('services')" [autoCompleteConfiguration]="servicesAutoCompleteConfiguration" (onItemChange)="servicesOnItemChange($event)"> [formGroup]="formGroup.get('services')" [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [autoCompleteConfiguration]="servicesAutoCompleteConfiguration"
(onItemChange)="servicesOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
@ -172,6 +172,33 @@
</ng-template> </ng-template>
</mat-card> </mat-card>
<mat-card>
<mat-card-header>
<mat-card-title class="thick">
{{'DATASET-EDITOR.FIELDS.TAG' | translate}}
</mat-card-title>
</mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('tags') && tagsTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.tags"
placeholder="{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}" [parentTemplate]='tagsTemplate' [displayFunction]='tagsDisplayFunc'
[formGroup]="formGroup.get('tags')" [subtitleFunction]='tagsDisplaySubtitleFunc' [autoCompleteConfiguration]="tagsAutoCompleteConfiguration"
(onItemChange)="tagsOnItemChange($event)">
</app-external-item-listing>
<ng-template #tagsTemplate let-suggestion let-i="index" let-callback="function">
<div>
<p>
{{i+1}}) {{suggestion.get('name').value}}
</p>
</div>
<div>
<button mat-button (click)="callback(i)">
<mat-icon>close</mat-icon>
</button>
</div>
</ng-template>
</mat-card>
<div class="navigation-buttons-container"> <div class="navigation-buttons-container">
<button matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' | translate}}</button> <button matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' | translate}}</button>
<button matStepperNext mat-raised-button color="primary" style="float:right;" (click)="getDefinition()">{{'DATASET-WIZARD.ACTIONS.NEXT' | translate}}</button> <button matStepperNext mat-raised-button color="primary" style="float:right;" (click)="getDefinition()">{{'DATASET-WIZARD.ACTIONS.NEXT' | translate}}</button>

View File

@ -33,6 +33,8 @@ import { ExternalSourcesConfiguration } from '../../models/external-sources/Exte
import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item';
import { TagsCriteria } from '../../models/criteria/tags/TagsCriteria';
import { TagModel } from '../../models/tags/TagModel';
@Component({ @Component({
selector: 'app-dataset-wizard-component', selector: 'app-dataset-wizard-component',
@ -45,16 +47,26 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
@ViewChild('stepper') stepper: MatStepper; @ViewChild('stepper') stepper: MatStepper;
//autocomplete Display Functions; //autocomplete Display Functions;
externalDatasetDisplayFunc = (item) => item ? item.label + " (" + item.tag + ")" : null; externalDatasetDisplayFunc = (item) => item ? item.label : null;
registriesDisplayFunc = (item) => item ? item.label + " (" + item.tag + ")" : null; registriesDisplayFunc = (item) => item ? item.label : null;
dataRepositoryDisplayFunc = (item) => item ? (item.name + " (" + item.tag + ")") : null; dataRepositoryDisplayFunc = (item) => item ? item.name : null;
servicesDisplayFunc = (item) => item ? item.label + " (" + item.tag + ")" : null; servicesDisplayFunc = (item) => item ? item.label : null;
tagsDisplayFunc = (item) => item ? item.name : null;
//autocomplete Display Functions;
externalDatasetDisplaySubtitleFunc = (item) => item ? item.tag : null;
registriesDisplaySubtitleFunc = (item) => item ? item.tag : null;
dataRepositoryDisplaySubtitleFunc = (item) => item ? item.tag : null;
servicesDisplaySubtitleFunc = (item) => item ? item.tag : null;
tagsDisplaySubtitleFunc = (item) => item ? item.tag : null;
//autocomplete Configurations; //autocomplete Configurations;
externalDatasetAutoCompleteConfiguration: AutoCompleteConfiguration; externalDatasetAutoCompleteConfiguration: AutoCompleteConfiguration;
registriesAutoCompleteConfiguration: AutoCompleteConfiguration; registriesAutoCompleteConfiguration: AutoCompleteConfiguration;
dataRepositoriesAutoCompleteConfiguration: AutoCompleteConfiguration; dataRepositoriesAutoCompleteConfiguration: AutoCompleteConfiguration;
servicesAutoCompleteConfiguration: AutoCompleteConfiguration; servicesAutoCompleteConfiguration: AutoCompleteConfiguration;
tagsAutoCompleteConfiguration: AutoCompleteConfiguration;
externalSourcesConfiguration: ExternalSourcesConfiguration; externalSourcesConfiguration: ExternalSourcesConfiguration;
datasetWizardModel: DatasetWizardModel; datasetWizardModel: DatasetWizardModel;
@ -103,12 +115,17 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
servicesRequestItem.criteria = new ServicesCriteria(); servicesRequestItem.criteria = new ServicesCriteria();
this.servicesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetService.bind(this.externalSourcesService), servicesRequestItem) this.servicesAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetService.bind(this.externalSourcesService), servicesRequestItem)
let tagsRequestItem: RequestItem<TagsCriteria> = new RequestItem();
tagsRequestItem.criteria = new TagsCriteria();
this.tagsAutoCompleteConfiguration = new AutoCompleteConfiguration(this.externalSourcesService.searchDatasetTags.bind(this.externalSourcesService), tagsRequestItem)
this.externalSourcesConfigurationService.getExternalSourcesConfiguration().subscribe(result => { this.externalSourcesConfigurationService.getExternalSourcesConfiguration().subscribe(result => {
this.externalSourcesConfiguration = result; this.externalSourcesConfiguration = result;
this.externalSourcesConfiguration.dataRepositories.push({ key: '', label: "All" }) this.externalSourcesConfiguration.dataRepositories.push({ key: '', label: "All" })
this.externalSourcesConfiguration.externalDatasets.push({ key: '', label: "All" }) this.externalSourcesConfiguration.externalDatasets.push({ key: '', label: "All" })
this.externalSourcesConfiguration.registries.push({ key: '', label: "All" }) this.externalSourcesConfiguration.registries.push({ key: '', label: "All" })
this.externalSourcesConfiguration.services.push({ key: '', label: "All" }) this.externalSourcesConfiguration.services.push({ key: '', label: "All" })
this.externalSourcesConfiguration.tags.push({ key: '', label: "All" })
}) })
let dmpAutoCompleteConfiguration = {} let dmpAutoCompleteConfiguration = {}
this.route.params.subscribe((params: Params) => { this.route.params.subscribe((params: Params) => {
@ -243,7 +260,6 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
} }
@ -316,6 +332,12 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
(<FormArray>this.formGroup.get("services")).push(serviceModel.buildForm()); (<FormArray>this.formGroup.get("services")).push(serviceModel.buildForm());
} }
tagsOnItemChange(event) {
let serviceModel = new TagModel(event.id, event.name);
(<FormArray>this.formGroup.get("tags")).push(serviceModel.buildForm());
}
dataRepositoriesOnItemChange(event) { dataRepositoriesOnItemChange(event) {
let dataRepositoryModel = new DataRepositoryModel(event.id, event.name, event.pid, event.uri); let dataRepositoryModel = new DataRepositoryModel(event.id, event.name, event.pid, event.uri);
(<FormArray>this.formGroup.get("dataRepositories")).push(dataRepositoryModel.buildForm()); (<FormArray>this.formGroup.get("dataRepositories")).push(dataRepositoryModel.buildForm());

View File

@ -88,7 +88,6 @@ export class DataManagementPlanProfileEditorComponent implements AfterViewInit {
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
this.router.navigate(['/dmp-profiles']); this.router.navigate(['/dmp-profiles']);
} }

View File

@ -31,6 +31,7 @@ import { RouterModule } from '@angular/router';
import { ResearcherService } from '../services/researchers/researchers.service'; import { ResearcherService } from '../services/researchers/researchers.service';
import { InvitationService } from '../services/invitation/invitation.service'; import { InvitationService } from '../services/invitation/invitation.service';
import { DatasetService } from '../services/dataset/dataset.service'; import { DatasetService } from '../services/dataset/dataset.service';
import { FlexLayoutModule } from '@angular/flex-layout';
@NgModule({ @NgModule({
imports: [ imports: [

View File

@ -11,19 +11,28 @@
<h3>{{formGroup.get('label').value}} </h3> <h3>{{formGroup.get('label').value}} </h3>
</mat-card-title> </mat-card-title>
<div class="fill-space"></div> <div class="fill-space"></div>
<mat-menu #actionsMenu="matMenu"> <div *ngIf="!isNew" flexLayout="row">
<button mat-menu-item (click)="redirectToProject()"> <div fxFlex>
<mat-icon>arrow_right_alt</mat-icon>{{'DMP-EDITOR.ACTIONS.GO-TO-PROJECT' | translate}}</button> <button mat-button type="button" (click)="redirectToProject()">
<button mat-menu-item (click)="redirectToDatasets()"> <mat-icon>arrow_right_alt</mat-icon>{{'DMP-EDITOR.ACTIONS.GO-TO-PROJECT' | translate}}</button>
<mat-icon>arrow_right_alt</mat-icon>{{'DMP-EDITOR.ACTIONS.GO-TO-DATASETS' | translate}}</button> </div>
<button mat-menu-item (click)="newVersion(this.dataManagementPlan.id, this.dataManagementPlan.label)"> <div fxFlex>
<mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}</button> <button mat-button type="button" (click)="redirectToDatasets()">
<button mat-menu-item (click)="clone(this.dataManagementPlan.id)"> <mat-icon>arrow_right_alt</mat-icon>{{'DMP-EDITOR.ACTIONS.GO-TO-DATASETS' | translate}}</button>
<mat-icon>filter_none</mat-icon>{{'DMP-LISTING.ACTIONS.CLONE' | translate}}</button> </div>
</mat-menu> <mat-menu #actionsMenu="matMenu">
<button mat-icon-button type="button" [matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon> <button mat-menu-item (click)="newVersion(this.dataManagementPlan.id, this.dataManagementPlan.label)">
</button> <mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}</button>
<button mat-menu-item (click)="clone(this.dataManagementPlan.id)">
<mat-icon>filter_none</mat-icon>{{'DMP-LISTING.ACTIONS.CLONE' | translate}}</button>
</mat-menu>
<div fxFlex>
<button fxFlex mat-icon-button type="button" [matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon>
</button>
</div>
</div>
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<mat-form-field class="full-width"> <mat-form-field class="full-width">
@ -97,7 +106,7 @@
<mat-progress-bar [style.height.px]="2" *ngIf="filteringResearchersAsync" mode="indeterminate"></mat-progress-bar> <mat-progress-bar [style.height.px]="2" *ngIf="filteringResearchersAsync" mode="indeterminate"></mat-progress-bar>
</td-chips> </td-chips>
<button style="display:inline-block;" mat-icon-button (click)="addResearcher()"> <button style="display:inline-block;" mat-icon-button type="button" (click)="addResearcher()">
<mat-icon aria-label="Example icon-button with a heart icon">add_circle</mat-icon> <mat-icon aria-label="Example icon-button with a heart icon">add_circle</mat-icon>
</button> </button>
</div> </div>

View File

@ -154,7 +154,6 @@ export class DataManagementPlanEditorComponent implements AfterViewInit, IBreadC
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
this.router.navigate(['/dmps']); this.router.navigate(['/dmps']);
} }

View File

@ -1,19 +1,19 @@
<div class="dmp-wizard"> <div class="dmp-wizard">
<mat-horizontal-stepper [linear]="isLinear" #stepper> <mat-horizontal-stepper #stepper>
<mat-step> <mat-step>
<ng-template matStepLabel>{{'DMP-WIZARD.FIRST-STEP.DMP' | translate}}</ng-template> <ng-template matStepLabel>{{'DMP-WIZARD.FIRST-STEP.DMP' | translate}}</ng-template>
<app-dmp-wizard-editor-component [formGroup]="formGroup" *ngIf="formGroup"></app-dmp-wizard-editor-component> <app-dmp-wizard-editor-component [formGroup]="formGroup" *ngIf="formGroup"></app-dmp-wizard-editor-component>
<div class="navigation-buttons-container"> <div class="navigation-buttons-container">
<button style="float:right;" matStepperNext mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.NEXT' | translate}}</button> <button style="float:right;" matStepperNext mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.NEXT' | translate}}</button>
</div> </div>
</mat-step> </mat-step>
<mat-step> <mat-step>
<ng-template matStepLabel>{{'DMP-WIZARD.FIRST-STEP.DATASETS' | translate}}</ng-template> <ng-template matStepLabel>{{'DMP-WIZARD.FIRST-STEP.DATASETS' | translate}}</ng-template>
<app-dataset-wizard-listing-component [formGroup]="formGroup" [dmpId]="formGroup.get('id').value" *ngIf="formGroup"></app-dataset-wizard-listing-component> <app-dataset-wizard-listing-component [formGroup]="formGroup" [dmpId]="formGroup.get('id').value" *ngIf="formGroup"></app-dataset-wizard-listing-component>
<div class="navigation-buttons-container"> <div class="navigation-buttons-container">
<button matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' | translate}}</button> <button matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' | translate}}</button>
<button style="float:right;" matStepperNext mat-raised-button (click)='submit()' color="primary">{{'DMP-WIZARD.ACTIONS.SAVE' | translate}}</button> <button style="float:right;" matStepperNext mat-raised-button (click)='submit()' color="primary">{{'DMP-WIZARD.ACTIONS.SAVE' | translate}}</button>
</div> </div>
</mat-step> </mat-step>
</mat-horizontal-stepper> </mat-horizontal-stepper>
</div> </div>

View File

@ -26,10 +26,10 @@ export class DataManagementPlanWizardComponent implements OnInit, IBreadCrumbCom
private router: Router private router: Router
) { } ) { }
itemId: string public itemId: string
dataManagementPlan: DataManagementPlanModel; public dataManagementPlan: DataManagementPlanModel;
formGroup: FormGroup public formGroup: FormGroup
isClone: boolean public isClone: boolean
ngOnInit(): void { ngOnInit(): void {
@ -65,7 +65,6 @@ export class DataManagementPlanWizardComponent implements OnInit, IBreadCrumbCom
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
this.router.navigate(['/dmps']); this.router.navigate(['/dmps']);
} }

View File

@ -100,7 +100,6 @@ export class DataManagementPlanWizardEditorComponent implements AfterViewInit {
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
this.router.navigate(['/dmps']); this.router.navigate(['/dmps']);
} }

View File

@ -23,11 +23,11 @@ export class AutocompleteRemoteComponent implements OnInit/* , ControlValueAcces
@Input() disabled = false @Input() disabled = false
@Input() form: FormGroup; @Input() form: FormGroup;
private autoCompleteConfiguration: AutoCompleteConfiguration; public autoCompleteConfiguration: AutoCompleteConfiguration;
private loading: boolean; public loading: boolean;
private datasetId; public datasetId;
values: any[] = new Array(); public values: any[] = new Array();
typeaheadMS: number = 1400; public typeaheadMS: number = 1400;
constructor(private datasetProfileService: DatasetProfileService, route: ActivatedRoute) { constructor(private datasetProfileService: DatasetProfileService, route: ActivatedRoute) {
this.datasetId = route.snapshot.params['id']; this.datasetId = route.snapshot.params['id'];

View File

@ -12,7 +12,7 @@
<div *ngSwitchCase="'freetext'"> <div *ngSwitchCase="'freetext'">
<mat-form-field> <mat-form-field>
<input matInput formControlName="value" placeholder="{{field.data.label}}" [required]="field.validationRequired"> <input matInput formControlName="value" placeholder="{{field.data.label}}" [required]="field.validationRequired">
<mat-error *ngIf="form.get('value').errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="form.get('value')['errors'] && form.get('value')['errors']['required']">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
@ -33,11 +33,12 @@
<div *ngSwitchCase="'textarea'"> <div *ngSwitchCase="'textarea'">
<mat-form-field> <mat-form-field>
<textarea matInput formControlName="value" matTextareaAutosize matAutosizeMinRows="2" matAutosizeMaxRows="10" [required]="field.validationRequired"> </textarea> <textarea matInput formControlName="value" matTextareaAutosize matAutosizeMinRows="2" matAutosizeMaxRows="10" [required]="field.validationRequired">
</textarea>
<button mat-button *ngIf="form.get('value').value" matSuffix mat-icon-button aria-label="Clear" (click)="this.form.patchValue({'value': ''})"> <button mat-button *ngIf="form.get('value').value" matSuffix mat-icon-button aria-label="Clear" (click)="this.form.patchValue({'value': ''})">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
<mat-error *ngIf="form.get('value').errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="form.get('value')['errors'] && form.get('value')['errors']['required']">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -21,7 +21,7 @@ export class DynamicFormFieldComponent implements OnInit {
@Input() pathName: string; @Input() pathName: string;
@Input() path: string; @Input() path: string;
constructor(private route: ActivatedRoute, private visibilityRulesService: VisibilityRulesService) { } constructor(private route: ActivatedRoute, public visibilityRulesService: VisibilityRulesService) { }
ngOnInit() { ngOnInit() {
this.form.get('value').valueChanges.subscribe(item => { this.form.get('value').valueChanges.subscribe(item => {

View File

@ -21,7 +21,7 @@ export class DynamicFormGroupComponent implements OnInit {
@Input() path: string; @Input() path: string;
constructor(private visibilityRulesService: VisibilityRulesService) { constructor(public visibilityRulesService: VisibilityRulesService) {
} }
ngOnInit() { ngOnInit() {

View File

@ -19,7 +19,7 @@ export class DynamicFormSectionComponent implements OnInit {
@Input() form: FormGroup; @Input() form: FormGroup;
@Input() pathName: string; @Input() pathName: string;
@Input() path: string; @Input() path: string;
constructor(private visibilityRulesService: VisibilityRulesService) { } constructor(public visibilityRulesService: VisibilityRulesService) { }
ngOnInit() { ngOnInit() {
} }

View File

@ -1,5 +1,5 @@
<!-- <p-progressBar [value]="value" [style]="{'height': '30px'}" [styleClass]="'alwaysVisible'"></p-progressBar> --> <!-- <p-progressBar [value]="value" [style]="{'height': '30px'}" [styleClass]="'alwaysVisible'"></p-progressBar> -->
<div class="demo-progress-bar-container"> <div class="demo-progress-bar-container">
<mat-progress-bar class="form-progress-bar" mode="determinate" [value]="value" [color]="color"></mat-progress-bar> <mat-progress-bar class="form-progress-bar" mode="determinate" [value]="value"></mat-progress-bar>
</div> </div>

View File

@ -16,7 +16,7 @@ export class ProgressBarComponent implements OnInit {
constructor(private visibilityRulesService: VisibilityRulesService) { } constructor(private visibilityRulesService: VisibilityRulesService) { }
private value: number = 0; public value: number = 0;
ngOnInit() { ngOnInit() {
this.calculateValueForProgressbar() this.calculateValueForProgressbar()
this.formGroup this.formGroup

View File

@ -1,7 +1,7 @@
<!-- All contents in the first page --> <!-- All contents in the first page -->
<ul> <ul>
<li *ngFor="let section of model.sections let i = index"> <li *ngFor="let section of model['sections'] let i = index">
<!-- && field.label for sections without field label as data summery --> <!-- && field.label for sections without field label as data summery -->
<table-of-contents-section [page]='section.page' [model]="section" [index]="i+1" [path]="i+1"> </table-of-contents-section> <table-of-contents-section [page]='section.page' [model]="section" [index]="i+1" [path]="i+1"> </table-of-contents-section>
</li> </li>
</ul> </ul>

View File

@ -9,17 +9,18 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
selector: 'table-of-content', selector: 'table-of-content',
templateUrl: './table-of-contents.component.html', templateUrl: './table-of-contents.component.html',
styleUrls: ['./toc.component.css'], styleUrls: ['./toc.component.css'],
providers: [] providers: []
}) })
export class TableOfContentsComponent implements OnInit{ export class TableOfContentsComponent implements OnInit {
@Input() model:DatasetProfileDefinitionModel; @Input()
public path:string=""; public model: DatasetProfileDefinitionModel;
public path: string = "";
/* @Output() /* @Output()
setPage:EventEmitter<number> = new EventEmitter<number>(); setPage:EventEmitter<number> = new EventEmitter<number>();
*/ ngOnInit(){ */ ngOnInit() {
} }
} }

View File

@ -12,8 +12,8 @@ import { AuthService } from '../services/auth/auth.service';
}) })
export class HomepageComponent implements OnInit { export class HomepageComponent implements OnInit {
private userInfo: any; public userInfo: any;
private dashboardStatisticsData: DashboardStatisticsModel = new DashboardStatisticsModel(); public dashboardStatisticsData: DashboardStatisticsModel = new DashboardStatisticsModel();
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,

View File

@ -1,7 +1,9 @@
import { BaseCriteria } from "../BaseCriteria"; import { BaseCriteria } from "../BaseCriteria";
import { ExternalSourcesItemModel } from "../../external-sources/ExternalSourcesItemModel";
export class DatasetCriteria extends BaseCriteria { export class DatasetCriteria extends BaseCriteria {
public status: Number; public status: Number;
public dmpIds: String[] = []; public dmpIds: String[] = [];
public allVersions: boolean; public tags: ExternalSourcesItemModel[] = [];
public allVersions: boolean;
} }

View File

@ -0,0 +1,6 @@
import { BaseCriteria } from "../BaseCriteria";
import { ExternalSourcesItemModel } from "../../external-sources/ExternalSourcesItemModel";
export class TagsCriteria extends BaseCriteria {
public type: string;
}

View File

@ -12,6 +12,7 @@ import { JsonSerializer } from "../../utilities/JsonSerializer";
import { RegisterModel } from "../registers/RegisterModel"; import { RegisterModel } from "../registers/RegisterModel";
import { DataRepositoryModel } from "../dataRepositories/DataRepositoryModel"; import { DataRepositoryModel } from "../dataRepositories/DataRepositoryModel";
import { ExternalDatasetModel } from '../../models/external-dataset/ExternalDatasetModel'; import { ExternalDatasetModel } from '../../models/external-dataset/ExternalDatasetModel';
import { TagModel } from '../tags/TagModel';
export class DatasetWizardModel implements Serializable<DatasetWizardModel> { export class DatasetWizardModel implements Serializable<DatasetWizardModel> {
public id: string; public id: string;
@ -23,6 +24,7 @@ export class DatasetWizardModel implements Serializable<DatasetWizardModel> {
public services: ServiceModel[] = []; public services: ServiceModel[] = [];
public registries: RegisterModel[] = []; public registries: RegisterModel[] = [];
public dataRepositories: DataRepositoryModel[] = []; public dataRepositories: DataRepositoryModel[] = [];
public tags: TagModel[] = [];
public externalDatasets: ExternalDatasetModel[] = []; public externalDatasets: ExternalDatasetModel[] = [];
public dmp: DataManagementPlanModel = new DataManagementPlanModel(); public dmp: DataManagementPlanModel = new DataManagementPlanModel();
public datasetProfileDefinition; public datasetProfileDefinition;
@ -42,6 +44,7 @@ export class DatasetWizardModel implements Serializable<DatasetWizardModel> {
this.profile = JsonSerializer.fromJSONObject(item.profile, DatasetProfileModel); this.profile = JsonSerializer.fromJSONObject(item.profile, DatasetProfileModel);
this.externalDatasets = JsonSerializer.fromJSONArray(item.externalDatasets, ExternalDatasetModel); this.externalDatasets = JsonSerializer.fromJSONArray(item.externalDatasets, ExternalDatasetModel);
this.datasetProfileDefinition = JsonSerializer.fromJSONObject(item.datasetProfileDefinition, DatasetProfileDefinitionModel); this.datasetProfileDefinition = JsonSerializer.fromJSONObject(item.datasetProfileDefinition, DatasetProfileDefinitionModel);
this.tags = JsonSerializer.fromJSONArray(item.tags, TagModel);
return this; return this;
} }
@ -54,7 +57,7 @@ export class DatasetWizardModel implements Serializable<DatasetWizardModel> {
uri: [{ value: this.uri, disabled: disabled }, context.getValidation('uri').validators], uri: [{ value: this.uri, disabled: disabled }, context.getValidation('uri').validators],
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
dmp: [{ value: this.dmp, disabled: disabled }, context.getValidation('dmp').validators] dmp: [{ value: this.dmp, disabled: disabled }, context.getValidation('dmp').validators],
}); });
const externalDatasetsFormArray = new Array<FormGroup>(); const externalDatasetsFormArray = new Array<FormGroup>();
@ -67,6 +70,16 @@ export class DatasetWizardModel implements Serializable<DatasetWizardModel> {
} }
formGroup.addControl('externalDatasets', formBuilder.array(externalDatasetsFormArray)); formGroup.addControl('externalDatasets', formBuilder.array(externalDatasetsFormArray));
const tagsFormArray = new Array<FormGroup>();
if (this.tags && this.tags.length > 0) {
this.tags.forEach(item => {
tagsFormArray.push(item.buildForm(context.getValidation('tags').descendantValidations, disabled))
})
} else {
//externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
}
formGroup.addControl('tags', formBuilder.array(tagsFormArray));
const registriesFormArray = new Array<FormGroup>(); const registriesFormArray = new Array<FormGroup>();
if (this.registries && this.registries.length > 0) { if (this.registries && this.registries.length > 0) {
this.registries.forEach(item => { this.registries.forEach(item => {
@ -116,6 +129,7 @@ export class DatasetWizardModel implements Serializable<DatasetWizardModel> {
baseContext.validation.push({ key: 'externalDatasets', validators: [BackendErrorValidator(this.errorModel, 'externalDatasets')] }); baseContext.validation.push({ key: 'externalDatasets', validators: [BackendErrorValidator(this.errorModel, 'externalDatasets')] });
baseContext.validation.push({ key: 'dmp', validators: [BackendErrorValidator(this.errorModel, 'dmp')] }); //TODO baseContext.validation.push({ key: 'dmp', validators: [BackendErrorValidator(this.errorModel, 'dmp')] }); //TODO
baseContext.validation.push({ key: 'datasetProfileDefinition', validators: [BackendErrorValidator(this.errorModel, 'datasetProfileDefinition')] }); //TODO baseContext.validation.push({ key: 'datasetProfileDefinition', validators: [BackendErrorValidator(this.errorModel, 'datasetProfileDefinition')] }); //TODO
baseContext.validation.push({ key: 'tags', validators: [BackendErrorValidator(this.errorModel, 'datasetProfileDefinition')] }); //TODO
return baseContext; return baseContext;
} }

View File

@ -1,8 +1,9 @@
import { ExternalSourcesUrlModel } from "./ExternalSourcesUrlModel"; import { ExternalSourcesUrlModel } from "./ExternalSourcesUrlModel";
export class ExternalSourcesConfiguration { export class ExternalSourcesConfiguration {
public registries: Array<ExternalSourcesUrlModel> public registries: Array<ExternalSourcesUrlModel>
public dataRepositories: Array<ExternalSourcesUrlModel> public dataRepositories: Array<ExternalSourcesUrlModel>
public services: Array<ExternalSourcesUrlModel> public services: Array<ExternalSourcesUrlModel>
public externalDatasets: Array<ExternalSourcesUrlModel> public externalDatasets: Array<ExternalSourcesUrlModel>
public tags: Array<ExternalSourcesUrlModel>
} }

View File

@ -0,0 +1,27 @@
import { Serializable } from "../Serializable";
import { ValidationContext } from "../../utilities/validators/ValidationContext";
import { FormGroup, FormBuilder } from "@angular/forms";
export class TagModel implements Serializable<TagModel> {
public id: string;
public name: string;
constructor(id?: string, name?: string) {
this.id = id;
this.name = name;
}
fromJSONObject(item: any): TagModel {
this.id = item.id;
this.name = item.name;
return this;
}
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
return new FormBuilder().group({
id: [this.id],
name: [this.name]
})
}
}

View File

@ -93,7 +93,6 @@ export class ProjectEditorComponent implements OnInit, IBreadCrumbComponent {
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language }, data: { message: this.isNew ? 'GENERAL.SNACK-BAR.SUCCESSFUL-CREATION' : 'GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
this.router.navigate(['/projects']); this.router.navigate(['/projects']);
} }

View File

@ -34,11 +34,11 @@ export class ProjectListingComponent implements OnInit, IBreadCrumbComponent {
displayedColumns: String[] = ['avatar', 'name', 'abbreviation', 'start', 'end', "dmps"]; displayedColumns: String[] = ['avatar', 'name', 'abbreviation', 'start', 'end', "dmps"];
constructor( constructor(
private projectService: ProjectService, public projectService: ProjectService,
private router: Router, public router: Router,
private languageService: TranslateService, public languageService: TranslateService,
public snackBar: MatSnackBar, public snackBar: MatSnackBar,
private languageResolverService: LanguageResolverService public languageResolverService: LanguageResolverService
) { ) {
} }

View File

@ -133,7 +133,6 @@ export class AuthService {
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language }, data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-success']
}) })
this.router.navigate(['/login']); this.router.navigate(['/login']);
} }
@ -142,7 +141,6 @@ export class AuthService {
this.snackBar.openFromComponent(SnackBarNotificationComponent, { this.snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGOUT', language: this.language }, data: { message: 'GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGOUT', language: this.language },
duration: 3000, duration: 3000,
extraClasses: ['snackbar-warning']
}) })
this.router.navigate(['/login']); this.router.navigate(['/login']);
} }

View File

@ -12,6 +12,7 @@ import { ExternalDatasetCriteria } from '../../models/criteria/external-dataset/
import { RegistryCriteria } from '../../models/criteria/registry/RegistryCriteria'; import { RegistryCriteria } from '../../models/criteria/registry/RegistryCriteria';
import { DataRepositoryCriteria } from '../../models/criteria/data-repository/DataRepositoryCriteria'; import { DataRepositoryCriteria } from '../../models/criteria/data-repository/DataRepositoryCriteria';
import { ServicesCriteria } from '../../models/criteria/services/ServicesCriteria'; import { ServicesCriteria } from '../../models/criteria/services/ServicesCriteria';
import { TagsCriteria } from '../../models/criteria/tags/TagsCriteria';
@Injectable() @Injectable()
@ -41,6 +42,20 @@ export class ExternalSourcesService {
return this.http.get<ExternalSourcesItemModel[]>(this.actionUrl + "services" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers }); return this.http.get<ExternalSourcesItemModel[]>(this.actionUrl + "services" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers });
} }
public searchDatasetTags(requestItem: RequestItem<TagsCriteria>): Observable<ExternalSourcesItemModel[]> {
return Observable.of([
{ id: "1", name: "Tag 1", description: "" },
{ id: "2", name: "Tag 2", description: "" },
{ id: "3", name: "Tag 3", description: "" },
{ id: "4", name: "Tag 4", description: "" },
{ id: "5", name: "Tag 5", description: "" },
{ id: "6", name: "Tag 6", description: "" },
{ id: "7", name: "Tag 7", description: "" },
{ id: "8", name: "Tag 8", description: "" },
])
//return this.http.get<ExternalSourcesItemModel[]>(this.actionUrl + "tags" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers });
}
public searchDatasetSExternalDatasetservice(requestItem: RequestItem<ExternalDatasetCriteria>): Observable<ExternalSourcesItemModel[]> { public searchDatasetSExternalDatasetservice(requestItem: RequestItem<ExternalDatasetCriteria>): Observable<ExternalSourcesItemModel[]> {
return this.http.get<ExternalSourcesItemModel[]>(this.actionUrl + "datasets" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers }); return this.http.get<ExternalSourcesItemModel[]>(this.actionUrl + "datasets" + "?query=" + requestItem.criteria.like + "&type=" + requestItem.criteria.type, { headers: this.headers });
} }

View File

@ -14,7 +14,7 @@ import { ResearcherService } from '../../../services/researchers/researchers.ser
}) })
export class AddResearchersComponent implements OnInit { export class AddResearchersComponent implements OnInit {
private formGroup: FormGroup; public formGroup: FormGroup;
constructor( constructor(
private researcherService: ResearcherService, private researcherService: ResearcherService,

View File

@ -7,7 +7,9 @@
<mat-progress-spinner matSuffix mode="indeterminate" *ngIf="loading" [diameter]="22"></mat-progress-spinner> <mat-progress-spinner matSuffix mode="indeterminate" *ngIf="loading" [diameter]="22"></mat-progress-spinner>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFunction" (optionSelected)="this.optionSelected($event)"> <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFunction" (optionSelected)="this.optionSelected($event)">
<mat-option *ngFor="let option of options" [value]="option"> <mat-option *ngFor="let option of options" [value]="option">
{{ this.printText(option) }} {{ this.printText(option) }} |
<small *ngIf="_subtitleFn">{{subtitleFn(option)}}</small>
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
</mat-form-field> </mat-form-field>

View File

@ -17,6 +17,8 @@ export class AutoCompleteComponent implements OnInit, ErrorStateMatcher {
@Input() formCtrl: FormControl; @Input() formCtrl: FormControl;
@Input() required = false; @Input() required = false;
@Input() displayFunction: Function; @Input() displayFunction: Function;
@Input() _subtitleFn: Function;
@Input() assignValueFunction: Function; @Input() assignValueFunction: Function;
@Input() transformFunction: Function; @Input() transformFunction: Function;
@Input() inputData: AutoCompleteConfiguration; @Input() inputData: AutoCompleteConfiguration;
@ -86,6 +88,10 @@ export class AutoCompleteComponent implements OnInit, ErrorStateMatcher {
else return item; else return item;
} }
subtitleFn(item) {
return this._subtitleFn(item);
}
getValue(item: any): string { getValue(item: any): string {
if (this.assignValueFunction) { if (this.assignValueFunction) {
if (this.transformFunction) return this.assignValueFunction(this.transformFunction(item)) if (this.transformFunction) return this.assignValueFunction(this.transformFunction(item))

View File

@ -25,17 +25,16 @@
</div> --> </div> -->
<mat-form-field> <mat-form-field>
<input matInput [matAutocomplete]="auto" [formControl]="control" placeholder="{{placeholder}}" [required]="required" > <input matInput [matAutocomplete]="auto" [formControl]="control" placeholder="{{placeholder}}" [required]="required">
<mat-error *ngIf="control.errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="control['errors'] && control['errors']['required']">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="validationErrorString">{{errorString}}</mat-error> <mat-progress-spinner matSuffix mode="indeterminate" *ngIf="loading" [diameter]="22"></mat-progress-spinner>
<mat-progress-spinner matSuffix mode="indeterminate" *ngIf="loading" [diameter]="22"></mat-progress-spinner> <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayWith.bind(this)" (optionSelected)="this.optionSelected($event)">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayWith.bind(this)" (optionSelected)="this.optionSelected($event)"> <mat-option *ngFor="let item of filteredItems " [value]="item">
<mat-option *ngFor="let item of filteredItems " [value]="item"> <span *ngIf="titleKey">{{item[titleKey]}}</span>
<span *ngIf="titleKey">{{item[titleKey]}}</span> <span *ngIf="subtitleKey">{{item[subtitleKey]}}</span>
<span *ngIf="subtitleKey">{{item[subtitleKey]}}</span> </mat-option>
</mat-option> <!-- <mat-option *ngIf="filteredItems.length == 0" value="das">
<!-- <mat-option *ngIf="filteredItems.length == 0" value="das">
<span>{{'GENERAL.AUTOCOMPLETE.NO-ITEMS' | translate}}</span> <span>{{'GENERAL.AUTOCOMPLETE.NO-ITEMS' | translate}}</span>
</mat-option> --> </mat-option> -->
</mat-autocomplete> </mat-autocomplete>
</mat-form-field> </mat-form-field>

View File

@ -1,22 +1,21 @@
<mat-form-field> <mat-form-field>
<mat-chip-list #chipList [required]="required"> <mat-chip-list #chipList [required]="required">
<mat-chip *ngFor="let item of selectedItems" (remove)="remove(item)"> <mat-chip *ngFor="let item of selectedItems" (remove)="remove(item)">
{{item.name}} {{item.name}}
<mat-icon matChipRemove>cancel</mat-icon> <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip> </mat-chip>
<input matInput [matChipInputFor]="chipList" [matAutocomplete]="auto" [formControl]="control" <input matInput [matChipInputFor]="chipList" [matAutocomplete]="auto" [formControl]="control" placeholder="{{placeholder}}"
placeholder="{{placeholder}}" [required]="required" #chipInput> [required]="required" #chipInput>
</mat-chip-list> </mat-chip-list>
<mat-error *ngIf="control.errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="control['errors']['required']">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="validationErrorString">{{errorString}}</mat-error> <mat-progress-spinner matSuffix mode="indeterminate" *ngIf="loading" [diameter]="22"></mat-progress-spinner>
<mat-progress-spinner matSuffix mode="indeterminate" *ngIf="loading" [diameter]="22"></mat-progress-spinner> <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayWith.bind(this)" (optionSelected)="this.optionSelected($event)">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayWith.bind(this)" (optionSelected)="this.optionSelected($event)"> <mat-option *ngFor="let item of filteredItems " [value]="item">
<mat-option *ngFor="let item of filteredItems " [value]="item"> <span *ngIf="titleKey">{{item[titleKey]}}</span>
<span *ngIf="titleKey">{{item[titleKey]}}</span> <span *ngIf="subtitleKey">{{item[subtitleKey]}}</span>
<span *ngIf="subtitleKey">{{item[subtitleKey]}}</span> </mat-option>
</mat-option> <!-- <mat-option *ngIf="filteredItems.length == 0" value="das">
<!-- <mat-option *ngIf="filteredItems.length == 0" value="das">
<span>{{'GENERAL.AUTOCOMPLETE.NO-ITEMS' | translate}}</span> <span>{{'GENERAL.AUTOCOMPLETE.NO-ITEMS' | translate}}</span>
</mat-option> --> </mat-option> -->
</mat-autocomplete> </mat-autocomplete>
</mat-form-field> </mat-form-field>

View File

@ -15,9 +15,9 @@ import { DatasetProfileModule } from '../../../dataset-profile-form/dataset-prof
}) })
export class AvailableProfilesComponent implements OnInit { export class AvailableProfilesComponent implements OnInit {
private formGroup: FormGroup; public formGroup: FormGroup;
private profiles: DatasetProfileModel[] = []; public profiles: DatasetProfileModel[] = [];
private selectedProfiles: DatasetProfileModel[] = []; public selectedProfiles: DatasetProfileModel[] = [];
constructor( constructor(
private datasetService: DatasetService, private datasetService: DatasetService,

View File

@ -2,13 +2,13 @@
<mat-card-content aria-label="breadcrumb"> <mat-card-content aria-label="breadcrumb">
<ol class="no-style" fxLayout="row"> <ol class="no-style" fxLayout="row">
<div fxFlex="nogrow" *ngFor="let breadcrumb of buildBreadCrumb(this.activatedRoute) | async ; let i = index; let length = count "> <div fxFlex="nogrow" *ngFor="let breadcrumb of buildBreadCrumb(this.activatedRoute) | async ; let i = index; let length = count ">
<div fxLayout="row" fxLayoutAlign="start center"> <div fxLayout="row">
<li fxFlex> <li fxFlex="nogrow">
<a fxFlex [routerLink]="[breadcrumb.url]" [queryParams]="breadcrumb.params"> <a [routerLink]="[breadcrumb.url]" [queryParams]="breadcrumb.params">
{{ breadcrumb.label }} {{ breadcrumb.label }}
</a> </a>
</li> </li>
<mat-icon fxFlex *ngIf="length > 1 && i != ( length - 1 )">chevron_right</mat-icon> <mat-icon fxFlex="nogrow" *ngIf="length > 1 && i != ( length - 1 )">chevron_right</mat-icon>
</div> </div>
</div> </div>
</ol> </ol>

View File

@ -3,100 +3,100 @@ import { FormControl, FormGroup, NgForm, FormArray, AbstractControl } from '@ang
import { BaseCriteriaErrorModel } from '../../../../models/criteria/BaseCriteriaErrorModel'; import { BaseCriteriaErrorModel } from '../../../../models/criteria/BaseCriteriaErrorModel';
@Component({ @Component({
selector: 'base-criteria-component', selector: 'base-criteria-component',
template: '', template: '',
providers: [ providers: [
] ]
}) })
export class BaseCriteriaComponent implements OnInit { export class BaseCriteriaComponent implements OnInit {
public refreshCallback: Function = null; public refreshCallback: Function = null;
public formGroup: FormGroup = null; public formGroup: FormGroup = null;
constructor( constructor(
public baseErrorModel?: BaseCriteriaErrorModel, public baseErrorModel?: BaseCriteriaErrorModel,
) { ) {
} }
ngOnInit() { ngOnInit() {
if (this.baseErrorModel == null) { this.baseErrorModel = new BaseCriteriaErrorModel(); } if (this.baseErrorModel == null) { this.baseErrorModel = new BaseCriteriaErrorModel(); }
} }
controlModified(): void { controlModified(): void {
this.clearErrorModel(); this.clearErrorModel();
if (!this.isFormValid()) { return; } if (!this.isFormValid()) { return; }
if (this.refreshCallback != null) { this.refreshCallback(); } if (this.refreshCallback != null) { this.refreshCallback(); }
} }
public isFormValid(): boolean { public isFormValid(): boolean {
this.touchAllFormFields(this.formGroup); this.touchAllFormFields(this.formGroup);
this.validateAllFormFields(this.formGroup); this.validateAllFormFields(this.formGroup);
return this.formGroup.valid; return this.formGroup.valid;
} }
public getFormData(): any { public getFormData(): any {
return this.formGroup.value; return this.formGroup.value;
} }
public getFormControl(controlName: string): AbstractControl { public getFormControl(controlName: string): AbstractControl {
return this.formGroup.get(controlName); return this.formGroup.get(controlName);
} }
public disableFormFields(formControl: AbstractControl) { public disableFormFields(formControl: AbstractControl) {
formControl.disable(); formControl.disable();
} }
public validateAllFormFields(formControl: AbstractControl) { public validateAllFormFields(formControl: AbstractControl) {
if (formControl instanceof FormControl) { if (formControl instanceof FormControl) {
formControl.updateValueAndValidity({ emitEvent: false }) formControl.updateValueAndValidity({ emitEvent: false })
} else if (formControl instanceof FormGroup) { } else if (formControl instanceof FormGroup) {
Object.keys(formControl.controls).forEach(item => { Object.keys(formControl.controls).forEach(item => {
const control = formControl.get(item); const control = formControl.get(item);
this.validateAllFormFields(control); this.validateAllFormFields(control);
}) })
} else if (formControl instanceof FormArray) { } else if (formControl instanceof FormArray) {
formControl.controls.forEach(item => { formControl.controls.forEach(item => {
this.validateAllFormFields(item); this.validateAllFormFields(item);
}) })
} }
} }
public touchAllFormFields(formControl: AbstractControl) { public touchAllFormFields(formControl: AbstractControl) {
if (formControl instanceof FormControl) { if (formControl instanceof FormControl) {
formControl.markAsTouched(); formControl.markAsTouched();
} else if (formControl instanceof FormGroup) { } else if (formControl instanceof FormGroup) {
Object.keys(formControl.controls).forEach(item => { Object.keys(formControl.controls).forEach(item => {
const control = formControl.get(item); const control = formControl.get(item);
this.touchAllFormFields(control); this.touchAllFormFields(control);
}) })
} else if (formControl instanceof FormArray) { } else if (formControl instanceof FormArray) {
formControl.controls.forEach(item => { formControl.controls.forEach(item => {
this.touchAllFormFields(item); this.touchAllFormFields(item);
}) })
} }
} }
setRefreshCallback(callback: Function): void { setRefreshCallback(callback: Function): void {
this.refreshCallback = callback; this.refreshCallback = callback;
} }
onCallbackError(error: any) { onCallbackError(error: any) {
this.setErrorModel(error.error); this.setErrorModel(error.error);
this.validateAllFormFields(this.formGroup); this.validateAllFormFields(this.formGroup);
} }
public setErrorModel(errorModel: BaseCriteriaErrorModel) { public setErrorModel(errorModel: BaseCriteriaErrorModel) {
Object.keys(errorModel).forEach(item => { Object.keys(errorModel).forEach(item => {
(<any>this.baseErrorModel)[item] = (<any>errorModel)[item]; (<any>this.baseErrorModel)[item] = (<any>errorModel)[item];
}) })
} }
public clearErrorModel() { public clearErrorModel() {
Object.keys(this.baseErrorModel).forEach(item => { Object.keys(this.baseErrorModel).forEach(item => {
(<any>this.baseErrorModel)[item] = ''; (<any>this.baseErrorModel)[item] = '';
}) })
} }
} }

View File

@ -69,11 +69,6 @@ export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent i
this.projectService.get(requestItem).subscribe(items => { this.projectService.get(requestItem).subscribe(items => {
this.filteredProjects = items; this.filteredProjects = items;
this.filteringProjectsAsync = false; this.filteringProjectsAsync = false;
// this.filteredProjects = items.filter((filteredObj: any) => {
// return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true;
// });
}); });
} }
} }

View File

@ -20,14 +20,14 @@
<mat-datepicker #periodStartPicker></mat-datepicker> <mat-datepicker #periodStartPicker></mat-datepicker>
</mat-form-field> </mat-form-field>
</div> --> </div> -->
<div class="col-md-6"> <div class="col-md-4">
<mat-form-field> <mat-form-field>
<input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="datasetCriteriaName" [(ngModel)]="criteria.like" <input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="datasetCriteriaName" [(ngModel)]="criteria.like"
(ngModelChange)="controlModified()"> (ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel?.name">{{baseErrorModel['Criteria.like']}}</mat-error> <mat-error *ngIf="baseErrorModel['name']">{{baseErrorModel['Criteria.like']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-6"> <div class="col-md-4">
<mat-form-field> <mat-form-field>
<mat-select placeholder=" {{'CRITERIA.DATA-SETS.STATUS'| translate}}" name="datasetCriteriastatus" [(ngModel)]="criteria.status" <mat-select placeholder=" {{'CRITERIA.DATA-SETS.STATUS'| translate}}" name="datasetCriteriastatus" [(ngModel)]="criteria.status"
(ngModelChange)="controlModified()"> (ngModelChange)="controlModified()">
@ -35,9 +35,24 @@
{{status.viewValue}} {{status.viewValue}}
</mat-option> </mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="baseErrorModel?.status">{{baseErrorModel['Criteria.status']}}</mat-error> <mat-error *ngIf="baseErrorModel['status']">{{baseErrorModel['Criteria.status']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-4">
<td-chips color="accent" [items]="filteredTags" [(ngModel)]="criteria.tags" (ngModelChange)="controlModified()" placeholder="{{'CRITERIA.DATA-SETS.TAGS' | translate}}"
(inputChange)="filterTags($event)" name="tags" requireMatch>
<ng-template td-chip let-chip="chip">
<div class="tc-grey-100 bgc-teal-700" td-chip-avatar>{{chip.name.substring(0, 1).toUpperCase()}}</div>
{{chip.name}}
</ng-template>
<ng-template td-autocomplete-option let-option="option">
<div layout="row" layout-align="start center">
{{option.name}}
</div>
</ng-template>
<mat-progress-bar [style.height.px]="2" *ngIf="filteringTagsAsync" mode="indeterminate"></mat-progress-bar>
</td-chips>
</div>
</div> </div>
</mat-card> </mat-card>
</form> </form>

View File

@ -6,52 +6,78 @@ import { ValidationContext, Validation } from '../../../../utilities/validators/
import { BackendErrorValidator } from '../../../../utilities/validators/BackendErrorValidator'; import { BackendErrorValidator } from '../../../../utilities/validators/BackendErrorValidator';
import { DatasetCriteriaErrorModel } from '../../../../models/criteria/dataset/DatasetCriteriaErrorModel'; import { DatasetCriteriaErrorModel } from '../../../../models/criteria/dataset/DatasetCriteriaErrorModel';
import { DatasetCriteria } from '../../../../models/criteria/dataset/DatasetCriteria'; import { DatasetCriteria } from '../../../../models/criteria/dataset/DatasetCriteria';
import { TagsCriteria } from '../../../../models/criteria/tags/TagsCriteria';
import { ExternalSourcesService } from '../../../../services/external-sources/external-sources.service';
import { RequestItem } from '../../../../models/criteria/RequestItem';
import { TagModel } from '../../../../models/tags/TagModel';
import { ExternalSourcesItemModel } from '../../../../models/external-sources/ExternalSourcesItemModel';
@Component({ @Component({
selector: 'app-datasets-criteria-component', selector: 'app-datasets-criteria-component',
templateUrl: './datasets-criteria.component.html', templateUrl: './datasets-criteria.component.html',
styleUrls: ['./datasets-criteria.component.scss'], styleUrls: ['./datasets-criteria.component.scss'],
providers: [ providers: [
] ExternalSourcesService
]
}) })
export class DatasetCriteriaComponent extends BaseCriteriaComponent implements OnInit { export class DatasetCriteriaComponent extends BaseCriteriaComponent implements OnInit {
// public form: ProjectType; // public form: ProjectType;
// public formStatus: ProjectStatus; // public formStatus: ProjectStatus;
public criteria: DatasetCriteria= new DatasetCriteria(); public criteria: DatasetCriteria = new DatasetCriteria();
public filteringTagsAsync: boolean = false;
public filteredTags: ExternalSourcesItemModel[];
statuses = [ statuses = [
{value: '0', viewValue: 'Saved'}, { value: '0', viewValue: 'Saved' },
{value: '1', viewValue: 'Finalised'} { value: '1', viewValue: 'Finalised' }
]; ];
constructor( constructor(
public language: TranslateService, public language: TranslateService,
public formBuilder: FormBuilder public formBuilder: FormBuilder,
) { public externalSourcesService: ExternalSourcesService
super(new DatasetCriteriaErrorModel()); ) {
} super(new DatasetCriteriaErrorModel());
}
ngOnInit() { ngOnInit() {
super.ngOnInit(); super.ngOnInit();
if (this.criteria == null) { this.criteria = new DatasetCriteria(); } if (this.criteria == null) { this.criteria = new DatasetCriteria(); }
} }
setCriteria(criteria: DatasetCriteria): void { setCriteria(criteria: DatasetCriteria): void {
this.criteria = criteria; this.criteria = criteria;
} }
onCallbackError(error: any) { onCallbackError(error: any) {
this.setErrorModel(error.error); this.setErrorModel(error.error);
} }
controlModified(): void { controlModified(): void {
this.clearErrorModel(); this.clearErrorModel();
if (this.refreshCallback != null && if (this.refreshCallback != null &&
(this.criteria.like == null || this.criteria.like.length == 0 || this.criteria.like.length > 2) (this.criteria.like == null || this.criteria.like.length == 0 || this.criteria.like.length > 2)
) { ) {
this.refreshCallback(); this.refreshCallback();
} }
} }
filterTags(value: string): void {
this.filteredTags = undefined;
if (value) {
this.filteringTagsAsync = true;
let requestItem: RequestItem<TagsCriteria> = new RequestItem();
let criteria: TagsCriteria = new TagsCriteria();
criteria.like = value;
requestItem.criteria = criteria;
this.externalSourcesService.searchDatasetTags(requestItem).subscribe(items => {
this.filteredTags = items;
this.filteringTagsAsync = false;
});
}
}
} }

View File

@ -27,7 +27,7 @@
<mat-form-field> <mat-form-field>
<input matInput (focus)="periodEndPicker.open()" (click)="periodEndPicker.open()" name="projectCriteriaPeriodEnd" placeholder=" {{this.languageResolver.getBy('criteriaEnd')| translate}}" <input matInput (focus)="periodEndPicker.open()" (click)="periodEndPicker.open()" name="projectCriteriaPeriodEnd" placeholder=" {{this.languageResolver.getBy('criteriaEnd')| translate}}"
[matDatepicker]="periodEndPicker" [(ngModel)]="criteria.periodEnd" (ngModelChange)="controlModified()"> [matDatepicker]="periodEndPicker" [(ngModel)]="criteria.periodEnd" (ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel?.criteria?.periodEnd">{{baseErrorModel['criteria.periodEnd']}}</mat-error> <mat-error *ngIf="baseErrorModel['criteria.periodEnd']">{{baseErrorModel['criteria.periodEnd']}}</mat-error>
<mat-datepicker-toggle matSuffix [for]="periodEndPicker"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="periodEndPicker"></mat-datepicker-toggle>
<mat-datepicker #periodEndPicker></mat-datepicker> <mat-datepicker #periodEndPicker></mat-datepicker>
</mat-form-field> </mat-form-field>

Some files were not shown because too many files have changed in this diff Show More