Merge commit '180e02c829a8fb35056124d5afdbec3835a94b62'

This commit is contained in:
Diamantis Tziotzios 2023-02-28 16:08:32 +02:00
commit 7185b5d117
129 changed files with 3019 additions and 1251 deletions

View File

@ -12,4 +12,4 @@ RUN mvn package
FROM adoptopenjdk/openjdk11:alpine-jre
WORKDIR /app
COPY --from=MAVEN_BUILD /build/web/target/web-1.0-SNAPSHOT.jar /app/app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dspring.profiles.active=${PROF}", "-Dspring.config.additional-location=/files/config/", "-jar","/app/app.jar"]
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dspring.profiles.active=${PROF}", "-Dspring.config.additional-location=/files/config/", "-cp", "/app/app.jar", "-Dloader.path=/files/repo-jars", "org.springframework.boot.loader.PropertiesLauncher"]

View File

@ -87,7 +87,7 @@ public class DMPDaoImpl extends DatabaseAccess<DMP> implements DMPDao {
}
if (criteria.hasDoi()) {
query.where((builder, root) -> builder.not(builder.isNull(root.get("doi"))));
query.where((builder, root) -> builder.not(builder.isNull(root.join("dois").get("id"))));
}
query.where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue()));
return query;

View File

@ -80,7 +80,7 @@ public class DatasetDaoImpl extends DatabaseAccess<Dataset> implements DatasetDa
query.where((builder, root) -> root.get("profile").get("id").in(criteria.getDatasetTemplates()));
if (criteria.hasDoi()) {
query.where((builder, root) -> builder.not(builder.isNull(root.get("dmp").get("doi"))));
query.where((builder, root) -> builder.not(builder.isNull(root.join("dmp").join("dois").get("id"))));
}
query.where((builder, root) -> builder.notEqual(root.get("status"), Dataset.Status.DELETED.getValue()));
query.where((builder, root) -> builder.notEqual(root.get("status"), Dataset.Status.CANCELED.getValue()));

View File

@ -0,0 +1,10 @@
package eu.eudat.data.dao.entities;
import eu.eudat.data.dao.DatabaseAccessLayer;
import eu.eudat.data.entities.EntityDoi;
import java.util.UUID;
public interface EntityDoiDao extends DatabaseAccessLayer<EntityDoi, UUID> {
EntityDoi findFromDoi(String doi);
}

View File

@ -0,0 +1,56 @@
package eu.eudat.data.dao.entities;
import eu.eudat.data.dao.DatabaseAccess;
import eu.eudat.data.dao.databaselayer.service.DatabaseService;
import eu.eudat.data.entities.EntityDoi;
import eu.eudat.queryable.QueryableList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@Component("EntityDoiDao")
public class EntityDoiDaoImpl extends DatabaseAccess<EntityDoi> implements EntityDoiDao {
@Autowired
public EntityDoiDaoImpl(DatabaseService<EntityDoi> databaseService){
super(databaseService);
}
@Override
public EntityDoi createOrUpdate(EntityDoi item) {
return this.getDatabaseService().createOrUpdate(item, EntityDoi.class);
}
@Override
public CompletableFuture<EntityDoi> createOrUpdateAsync(EntityDoi item) {
return CompletableFuture.supplyAsync(() -> this.createOrUpdate(item));
}
@Override
public EntityDoi find(UUID id) {
return this.getDatabaseService().getQueryable(EntityDoi.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle();
}
@Override
public EntityDoi findFromDoi(String doi) {
return this.getDatabaseService().getQueryable(EntityDoi.class).where((builder, root) -> builder.equal(root.get("doi"), doi)).getSingle();
}
@Override
public EntityDoi find(UUID id, String hint) {
return null;
}
@Override
public void delete(EntityDoi item) {
this.getDatabaseService().delete(item);
}
@Override
public QueryableList<EntityDoi> asQueryable() {
return this.getDatabaseService().getQueryable(EntityDoi.class);
}
}

View File

@ -3,7 +3,9 @@ package eu.eudat.data.dao.entities;
import eu.eudat.data.dao.DatabaseAccessLayer;
import eu.eudat.data.entities.FileUpload;
import java.util.List;
import java.util.UUID;
public interface FileUploadDao extends DatabaseAccessLayer<FileUpload, UUID> {
List<FileUpload> getFileUploads(UUID entityId);
}

View File

@ -7,6 +7,7 @@ import eu.eudat.queryable.QueryableList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@ -33,6 +34,11 @@ public class FileUploadDaoImpl extends DatabaseAccess<FileUpload> implements Fil
return getDatabaseService().getQueryable(FileUpload.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle();
}
@Override
public List<FileUpload> getFileUploads(UUID entityId) {
return this.getDatabaseService().getQueryable(FileUpload.class).where((builder, root) -> builder.equal(root.get("entityId"), entityId)).toList();
}
@Override
public FileUpload find(UUID id, String hint) {
return null;

View File

@ -181,8 +181,8 @@ public class DMP implements DataEntity<DMP, UUID> {
@Convert(converter = DateToUTCConverter.class)
private Date publishedAt;
@Column(name = "\"DOI\"")
private String doi;
@OneToMany(mappedBy = "entityId", fetch = FetchType.LAZY)
private Set<EntityDoi> dois;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "\"Project\"")
@ -339,12 +339,12 @@ public class DMP implements DataEntity<DMP, UUID> {
this.publishedAt = publishedAt;
}
public String getDoi() {
return doi;
}
public void setDoi(String doi) {
this.doi = doi;
}
public Set<EntityDoi> getDois() {
return dois;
}
public void setDois(Set<EntityDoi> dois) {
this.dois = dois;
}
public Project getProject() {
return project;
@ -380,7 +380,7 @@ public class DMP implements DataEntity<DMP, UUID> {
if (entity.getStatus().equals(DMPStatus.FINALISED.getValue())) this.setFinalizedAt(new Date());
if (entity.isPublic) this.setPublishedAt(new Date());
if (entity.getUsers() != null) this.users = entity.getUsers();
if (entity.getDoi() != null && entity.getDoi().trim().isEmpty()) this.doi = entity.doi;
this.dois = entity.getDois();
this.extraProperties = entity.getExtraProperties();
}

View File

@ -0,0 +1,121 @@
package eu.eudat.data.entities;
import eu.eudat.data.converters.DateToUTCConverter;
import eu.eudat.data.entities.helpers.EntityBinder;
import eu.eudat.queryable.queryableentity.DataEntity;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Entity
@Table(name = "\"EntityDoi\"")
public class EntityDoi implements DataEntity<EntityDoi, UUID> {
public enum EntityType {
DMP
}
@Id
@Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)")
private UUID id;
@Enumerated(EnumType.STRING)
@Type(type = "eu.eudat.configurations.typedefinition.PostgreSQLEnumType")
@Column(name = "\"EntityType\"", nullable = false)
private EntityType entityType;
@Column(name = "\"RepositoryId\"", nullable = false)
private String repositoryId;
@Column(name = "\"Doi\"", nullable = false)
private String doi;
@Column(name = "\"CreatedAt\"", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date createdAt;
@Column(name = "\"UpdatedAt\"", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date updatedAt;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "\"EntityId\"", nullable = false)
private DMP entityId;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public EntityType getEntityType() {
return entityType;
}
public void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getDoi() {
return doi;
}
public void setDoi(String doi) {
this.doi = doi;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public DMP getEntityId() {
return entityId;
}
public void setEntityId(DMP entityId) {
this.entityId = entityId;
}
@Override
public void update(EntityDoi doi) {
this.entityType = doi.getEntityType();
this.repositoryId = doi.getRepositoryId();
this.doi = doi.getDoi();
this.createdAt = doi.getCreatedAt();
this.updatedAt = doi.getUpdatedAt();
this.entityId = doi.getEntityId();
}
@Override
public UUID getKeys() {
return this.id;
}
@Override
public EntityDoi buildFromTuple(List<Tuple> tuple, List<String> fields, String base) {
String currentBase = base.isEmpty() ? "" : base + ".";
if (fields.contains(currentBase + "id")) this.id = EntityBinder.fromTuple(tuple, currentBase + "id");
if (fields.contains(currentBase + "entityId"))
this.entityId = tuple.stream().map(x -> new DMP().buildFromTuple(Arrays.asList(x), fields , base.isEmpty() ? "entityId" : base + "." + "entityId")).collect(Collectors.toList()).get(0);
return this;
}
}

View File

@ -57,7 +57,7 @@ public class Dmp implements ElasticEntity<Dmp> {
private Date modified;
private Date finalizedAt;
private Date publishedAt;
private String doi;
private List<Doi> dois;
public UUID getId() {
return id;
@ -203,12 +203,12 @@ public class Dmp implements ElasticEntity<Dmp> {
this.publishedAt = publishedAt;
}
public String getDoi() {
return doi;
public List<Doi> getDois() {
return dois;
}
public void setDoi(String doi) {
this.doi = doi;
public void setDois(List<Doi> dois) {
this.dois = dois;
}
@Override
@ -280,7 +280,17 @@ public class Dmp implements ElasticEntity<Dmp> {
builder.field(MapKey.MODIFIED.getName(), this.modified);
builder.field(MapKey.FINALIZEDAT.getName(), this.finalizedAt);
builder.field(MapKey.PUBLISHEDAT.getName(), this.publishedAt);
builder.field(MapKey.DOI.getName(), this.doi);
if (this.dois != null && !this.dois.isEmpty()) {
builder.startArray(MapKey.DOIS.getName());
this.dois.forEach(doi -> {
try {
doi.toElasticEntity(builder);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
});
builder.endArray();
}
builder.endObject();
return builder;
}
@ -329,8 +339,8 @@ public class Dmp implements ElasticEntity<Dmp> {
if (fields.get(MapKey.PUBLISHEDAT.getName()) != null) {
this.publishedAt = Date.from(Instant.parse(fields.get(MapKey.PUBLISHEDAT.getName()).toString()));
}
if (fields.get(MapKey.DOI.getName()) != null) {
this.doi = fields.get(MapKey.DOI.getName()).toString();
if (fields.get(MapKey.DOIS.getName()) != null) {
this.dois = ((List<HashMap<String, Object>>) fields.get(MapKey.DOIS.getName())).stream().map(map -> new Doi().fromElasticEntity(map)).collect(Collectors.toList());
}
}
return this;
@ -355,7 +365,7 @@ public class Dmp implements ElasticEntity<Dmp> {
MODIFIED ("modified"),
FINALIZEDAT ("finalizedAt"),
PUBLISHEDAT ("publishedAt"),
DOI ("doi");
DOIS ("dois");
private final String name;

View File

@ -0,0 +1,65 @@
package eu.eudat.elastic.entities;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
public class Doi implements ElasticEntity<Doi>{
private UUID id;
private String repositoryId;
private String doi;
private UUID dmp;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getDoi() {
return doi;
}
public void setDoi(String doi) {
this.doi = doi;
}
public UUID getDmp() {
return dmp;
}
public void setDmp(UUID dmp) {
this.dmp = dmp;
}
@Override
public XContentBuilder toElasticEntity(XContentBuilder builder) throws IOException {
builder.startObject();
builder.field("id", this.id.toString());
builder.field("repositoryId", this.repositoryId);
builder.field("doi", this.doi);
builder.field("dmp", this.dmp.toString());
builder.endObject();
return builder;
}
@Override
public Doi fromElasticEntity(Map<String, Object> fields) {
if (fields == null || fields.isEmpty()) {
return null;
}
this.id = UUID.fromString((String) fields.get("id"));
this.repositoryId = (String) fields.get("repositoryId");
this.doi = (String) fields.get("doi");
this.dmp = UUID.fromString((String) fields.get("dmp"));
return this;
}
}

View File

@ -30,6 +30,7 @@ public abstract class ElasticRepository<T extends ElasticEntity,C extends Criter
}
} catch (IOException e) {
logger.warn("Unable to connect to Elastic Services");
logger.error(e.getMessage(), e);
this.client = null;
}
}

View File

@ -327,6 +327,18 @@
<packaging.type>jar</packaging.type>
</properties>
</profile>
<profile>
<id>intellij-properties-launcher</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
<version>2.5.2</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>production</id>
<properties>

View File

@ -26,13 +26,16 @@
<artifactId>queryable</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>eu.eudat</groupId>
<artifactId>elastic</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>gr.cite.opendmp</groupId>
<artifactId>repositorydepositbase</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
@ -221,6 +224,39 @@
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.9.RELEASE</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>eu.eudat.EuDatApplication</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dependency-jars/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@ -8,7 +8,7 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@SpringBootApplication(scanBasePackages = {"eu.eudat", "eu.eudat.depositinterface"})
@EnableAsync
public class EuDatApplication extends SpringBootServletInitializer {
private static final Logger logger = LoggerFactory.getLogger(EuDatApplication.class);

View File

@ -4,6 +4,7 @@ import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
@ -72,29 +73,34 @@ public class ElasticSearchConfiguration {
RestHighLevelClient client;
if(this.environment.getProperty("elasticsearch.usingssl", Boolean.class)){
Path caCertificatePath = Paths.get(this.environment.getProperty("elasticsearch.certPath"));
CertificateFactory factory =
CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = Files.newInputStream(caCertificatePath)) {
trustedCa = factory.generateCertificate(is);
}
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
// Path caCertificatePath = Paths.get(this.environment.getProperty("elasticsearch.certPath"));
// CertificateFactory factory =
// CertificateFactory.getInstance("X.509");
// Certificate trustedCa;
// try (InputStream is = Files.newInputStream(caCertificatePath)) {
// trustedCa = factory.generateCertificate(is);
// }
// KeyStore trustStore = KeyStore.getInstance("pkcs12");
// trustStore.load(null, null);
// trustStore.setCertificateEntry("ca", trustedCa);
//
// TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// tmf.init(trustStore);
//
// SSLContext sslContext = SSLContext.getInstance("TLS");
// sslContext.init(null, tmf.getTrustManagers(), null);
SSLContextBuilder sslBuilder = SSLContexts.custom()
.loadTrustMaterial(null, (x509Certificates, s) -> true);
final SSLContext sslContext = sslBuilder.build();
client = new RestHighLevelClient(
RestClient.builder(
new HttpHost(this.environment.getProperty("elasticsearch.host"),
Integer.parseInt(this.environment.getProperty("elasticsearch.port")), "https"))
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider).setSSLContext(sslContext)));
.setDefaultCredentialsProvider(credentialsProvider).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSSLContext(sslContext))
.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(5000).setSocketTimeout(120000))
);
}
else {
client = new RestHighLevelClient(

View File

@ -0,0 +1,84 @@
package eu.eudat.controllers;
import eu.eudat.logic.managers.DepositManager;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.doi.DepositCode;
import eu.eudat.models.data.doi.DepositRequest;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.doi.RepositoryConfig;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.ApiMessageCode;
import eu.eudat.types.Authorities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping(value = {"/api/deposit/"})
public class DepositController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(DepositController.class);
private DepositManager depositManager;
@Autowired
public DepositController(ApiContext apiContext, DepositManager depositManager){
super(apiContext);
this.depositManager = depositManager;
}
@RequestMapping(method = RequestMethod.GET, value = {"/repos"})
public @ResponseBody
ResponseEntity<ResponseItem<List<RepositoryConfig>>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
List<RepositoryConfig> ids = this.depositManager.getAvailableRepos();
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<RepositoryConfig>>().status(ApiMessageCode.NO_MESSAGE).payload(ids));
}
@RequestMapping(method = RequestMethod.POST, value = {"/getAccessToken"})
public @ResponseBody
ResponseEntity<ResponseItem<String>> getAccessToken(@RequestBody DepositCode depositCode, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception {
String accessToken = this.depositManager.authenticate(depositCode.getRepositoryId(), depositCode.getCode());
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.NO_MESSAGE).payload(accessToken));
}
@RequestMapping(method = RequestMethod.POST, value = {"/createDoi"})
public @ResponseBody
ResponseEntity<ResponseItem<Doi>> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
try {
Doi doi = this.depositManager.deposit(depositRequest, principal);
if(doi != null){
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Doi>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi));
}
else{
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Doi>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan"));
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Doi>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage()));
}
}
@RequestMapping(method = RequestMethod.GET, value = {"/logo/{repositoryId}"})
public @ResponseBody
ResponseEntity<ResponseItem<String>> getLogo(@PathVariable("repositoryId") String repositoryId, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
try {
String encodedLogo = this.depositManager.getRepositoryLogo(repositoryId);
if(encodedLogo != null){
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully loaded " + repositoryId + "'s logo.").payload(encodedLogo));
}
else{
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message(repositoryId + " has no logo").payload(null));
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to load " + repositoryId + "'s logo: " + e.getMessage()));
}
}
}

View File

@ -15,6 +15,8 @@ import eu.eudat.data.enumeration.notification.NotifyState;
import eu.eudat.data.query.items.table.dataset.DatasetTableRequest;
import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem;
import eu.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest;
import eu.eudat.depositinterface.models.DMPDepositModel;
import eu.eudat.depositinterface.repository.RepositoryDeposit;
import eu.eudat.elastic.criteria.DmpCriteria;
import eu.eudat.elastic.entities.Collaborator;
import eu.eudat.elastic.entities.Dmp;
@ -29,6 +31,7 @@ import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.logic.mapper.elastic.DmpMapper;
import eu.eudat.logic.mapper.elastic.criteria.DmpCriteriaMapper;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.forms.VisibilityRuleService;
import eu.eudat.logic.services.forms.VisibilityRuleServiceImpl;
@ -45,6 +48,8 @@ import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel;
import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized;
import eu.eudat.models.data.dmp.*;
import eu.eudat.models.data.doi.DepositRequest;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field;
@ -57,11 +62,10 @@ import eu.eudat.models.data.project.ProjectDMPEditorModel;
import eu.eudat.models.data.security.Principal;
import eu.eudat.models.data.user.composite.PagedDatasetProfile;
import eu.eudat.models.data.userinfo.UserListingModel;
import eu.eudat.models.deposit.zenodo.ZenodoDeposit;
import eu.eudat.models.deposit.zenodo.mapper.DMPToZenodoMapper;
import eu.eudat.queryable.QueryableList;
import eu.eudat.types.Authorities;
import eu.eudat.types.MetricNames;
import org.apache.commons.io.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
@ -70,11 +74,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
@ -86,6 +87,7 @@ import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@ -93,6 +95,8 @@ import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Component
public class DataManagementPlanManager {
@ -114,9 +118,11 @@ public class DataManagementPlanManager {
private UserManager userManager;
private final MetricsManager metricsManager;
private final ConfigLoader configLoader;
private List<RepositoryDeposit> repositoriesDeposit;
@Autowired
public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager, MetricsManager metricsManager, ConfigLoader configLoader) {
public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager,
MetricsManager metricsManager, ConfigLoader configLoader, List<RepositoryDeposit> repositoriesDeposit) {
this.apiContext = apiContext;
this.datasetManager = datasetManager;
this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository();
@ -126,6 +132,7 @@ public class DataManagementPlanManager {
this.metricsManager = metricsManager;
this.configLoader = configLoader;
this.objectMapper = new ObjectMapper();
this.repositoriesDeposit = repositoriesDeposit;
}
/*
@ -749,7 +756,7 @@ public class DataManagementPlanManager {
metricsManager.decreaseValue(MetricNames.DMP, 1, MetricNames.DRAFT);
break;
case 1:
if (oldDmp.getDoi() != null) {
if (oldDmp.getDois() != null && !oldDmp.getDois().isEmpty()) {
metricsManager.decreaseValue(MetricNames.DMP, 1, MetricNames.DOIED);
}
if (oldDmp.isPublic()) {
@ -1057,9 +1064,9 @@ public class DataManagementPlanManager {
});
UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId());
sendNotification(dmp, user, NotificationType.DMP_PUBLISH);
if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) {
this.createZenodoDoi(dmp.getId(), principal, true);
}
// if (dmp.getDois() != null && !dmp.getDois().isEmpty()) {
// this.createZenodoDoi(dmp.getId(), principal, true);
// }
}
@Transactional
@ -1151,6 +1158,10 @@ public class DataManagementPlanManager {
throw new Exception("User does not have the privilege to do this action.");
if (dmp.getStatus().equals(DMP.DMPStatus.ACTIVE.getValue()))
throw new Exception("DMP is already Active");
if (dmp.isPublic())
throw new Exception("DMP is publicly available");
if (!dmp.getDois().isEmpty())
throw new Exception("DMP is deposited");
dmp.setStatus(DMP.DMPStatus.ACTIVE.getValue());
apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
UUID dmpId = dmp.getId();
@ -2006,23 +2017,28 @@ public class DataManagementPlanManager {
* DOI Generation
* */
private String getPreviousDOI(UUID groupId, UUID selfId) {
private String getPreviousDOI(UUID groupId, UUID selfId, String repositoryId) {
DataManagementPlanCriteria criteria = new DataManagementPlanCriteria();
List<UUID> groupIds = new ArrayList<>();
groupIds.add(groupId);
criteria.setGroupIds(groupIds);
criteria.setAllVersions(true);
List<DMP> dmps = this.databaseRepository.getDmpDao().getWithCriteria(criteria).toList();
String doi = null;
dmps.sort((DMP d1, DMP d2) -> d2.getVersion() - d1.getVersion());
for (DMP dmp: dmps) {
if (!dmp.getId().equals(selfId)) {
if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) {
doi = dmp.getDoi();
if (dmp.getDois() != null && !dmp.getDois().isEmpty()) {
for (Iterator<EntityDoi> it = dmp.getDois().iterator(); it.hasNext(); ) {
EntityDoi entityDoi = it.next();
if(entityDoi.getRepositoryId().equals(repositoryId)){
return entityDoi.getDoi();
}
}
}
}
}
return doi;
return null;
}
private String getUnpublishedDOI(String DOI, String token, Integer version) {
@ -2064,6 +2080,22 @@ public class DataManagementPlanManager {
/*if (dmp.getDoi() != null)
throw new Exception("DMP already has a DOI");*/
FileEnvelope file = getWordDocument(id.toString(), principal, configLoader);
String name = file.getFilename().substring(0, file.getFilename().length() - 5);
File pdfFile = PDFUtils.convertToPDF(file, environment);
String fileName = name + ".pdf";
ResponseEntity<byte[]> jsonFile;
try {
jsonFile = getRDAJsonDocument(id.toString(), principal);
} catch (Exception e) {
throw e;
}
String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId(), "Zenodo");
File supportingFilesZip = this.createSupportingFilesZip(dmp);
DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfFile, fileName, jsonFile, supportingFilesZip, previousDOI);
String zenodoToken = "";
try {
if (this.userManager.isDOITokenValid(principal)) {
@ -2072,136 +2104,126 @@ public class DataManagementPlanManager {
} catch (NonValidTokenException e) {
zenodoToken = this.environment.getProperty("zenodo.access_token");
}
// First step, post call to Zenodo, to create the entry.
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
ZenodoDeposit deposit = DMPToZenodoMapper.fromDMP(dmp, environment, configLoader);
//if (Objects.requireNonNull(environment.getProperty("spring.profiles.active")).contains("devel")) {
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(deposit);
logger.info(json);
//}
HttpEntity<ZenodoDeposit> request = new HttpEntity<>(deposit, headers);
Map createResponse;
LinkedHashMap<String, String> links;
String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId());
String unpublishedUrl = null;
String publishUrl;
String finalDoi;
try {
if (previousDOI == null) {
String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + zenodoToken;
createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody();
links = (LinkedHashMap<String, String>) createResponse.get("links");
finalDoi = (String) createResponse.get("conceptdoi");
} else {
unpublishedUrl = this.getUnpublishedDOI(previousDOI, zenodoToken, dmp.getVersion());
if (unpublishedUrl == null) {
//It requires more than one step to create a new version
//First, get the deposit related to the concept DOI
String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
ResponseEntity<Map[]> listResponses = restTemplate.getForEntity(listUrl, Map[].class);
createResponse = listResponses.getBody()[0];
links = (LinkedHashMap<String, String>) createResponse.get("links");
//Second, make the new version (not in the links?)
String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken;
createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class);
links = (LinkedHashMap<String, String>) createResponse.get("links");
//Third, get the new deposit
String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken;
createResponse = restTemplate.getForObject(latestDraftUrl, Map.class);
links = (LinkedHashMap<String, String>) createResponse.get("links");
finalDoi = (String) createResponse.get("conceptdoi");
//At this point it might fail to perform the next requests so enclose them with try catch
try {
//Forth, update the new deposit's metadata
String updateUrl = links.get("self") + "?access_token=" + zenodoToken;
restTemplate.put(updateUrl, request);
//And finally remove pre-existing files from it
String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken;
ResponseEntity<Map[]> fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class);
for (Map file : fileListResponse.getBody()) {
String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken;
restTemplate.delete(fileDeleteUrl);
}
} catch (Exception e) {
//In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed)
restTemplate.delete(latestDraftUrl);
throw e;
}
}
else {
String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
ResponseEntity<Map[]> listResponses = restTemplate.getForEntity(listUrl, Map[].class);
createResponse = listResponses.getBody()[0];
links = (LinkedHashMap<String, String>) createResponse.get("links");
String finalDoi = null;
for(RepositoryDeposit repo: this.repositoriesDeposit) { //temp
if(repo.getConfiguration().getRepositoryId().equals("Zenodo")) {
finalDoi = repo.deposit(dmpDepositModel, zenodoToken);
if (finalDoi != null) {
EntityDoi doiEntity = new EntityDoi();
doiEntity.setId(UUID.randomUUID());
doiEntity.setEntityType(EntityDoi.EntityType.DMP);
doiEntity.setDoi(finalDoi);
doiEntity.setRepositoryId("Zenodo");
Date now = new Date();
doiEntity.setCreatedAt(now);
doiEntity.setUpdatedAt(now);
doiEntity.setEntityId(dmp);
apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity);
dmp.getDois().add(doiEntity);
apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
}
}
if (!update) {
if (unpublishedUrl == null) {
// Second step, add the file to the entry.
FileEnvelope file = getWordDocument(id.toString(), principal, configLoader);
String name = file.getFilename().substring(0, file.getFilename().length() - 5);
File pdfFile = PDFUtils.convertToPDF(file, environment);
String fileName = name + ".pdf";
FileSystemResource fileSystemResource = new FileSystemResource(pdfFile);
HttpEntity<FileSystemResource> addFileMapRequest = new HttpEntity<>(fileSystemResource, null);
String addFileUrl = links.get("bucket") + "/" + fileName + "?access_token=" + zenodoToken;
restTemplate.put(addFileUrl, addFileMapRequest);
Files.deleteIfExists(file.getFile().toPath());
ResponseEntity<byte[]> jsonFile;
try {
jsonFile = getRDAJsonDocument(id.toString(), principal);
} catch (Exception e) {
throw e;
}
UUID jsonFileUUID = UUID.randomUUID();
File tempJsonFile = new File(this.environment.getProperty("temp.temp") + jsonFileUUID.toString() + ".json");
try (FileOutputStream jsonFos = new FileOutputStream(tempJsonFile)) {
jsonFos.write(jsonFile.getBody());
jsonFos.flush();
}
fileSystemResource = new FileSystemResource(tempJsonFile);
HttpHeaders jsonHeaders = new HttpHeaders();
jsonHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
addFileMapRequest = new HttpEntity<>(fileSystemResource, jsonHeaders);
String jsonFileName = jsonFile.getHeaders().get("Content-Disposition").get(0).substring(jsonFile.getHeaders().get("Content-Disposition").get(0).lastIndexOf('=') + 1);
addFileUrl = links.get("bucket") + "/" + jsonFileName + "?access_token=" + zenodoToken;
restTemplate.put(addFileUrl, addFileMapRequest);
Files.deleteIfExists(tempJsonFile.toPath());
// Third post call to Zenodo to publish the entry and return the DOI.
publishUrl = links.get("publish") + "?access_token=" + zenodoToken;
} else {
publishUrl = unpublishedUrl + "?access_token=" + zenodoToken;
}
// if (dmp.isPublic()) {
Map<String, Object> publishResponce = restTemplate.postForObject(publishUrl, "", Map.class);
finalDoi = (String) publishResponce.get("conceptdoi");
// }
} else {
Map<String, Object> editResponce = restTemplate.postForObject(links.get("edit") + "?access_token=" + zenodoToken, "", Map.class);
restTemplate.put(links.get("self") + "?access_token=" + zenodoToken, request);
Map<String, Object> publishResponce = restTemplate.postForObject(links.get("publish") + "?access_token=" + zenodoToken, "", Map.class);
finalDoi = (String) publishResponce.get("conceptdoi");
}
if (finalDoi != null) {
dmp.setDoi(finalDoi);
apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
}
return finalDoi;
} catch (HttpClientErrorException | HttpServerErrorException ex) {
//ObjectMapper ob = new ObjectMapper();
Map<String, String> parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), HashMap.class);
throw new IOException(parsedException.get("message"), ex);
}
if(supportingFilesZip != null) {
Files.deleteIfExists(supportingFilesZip.toPath());
}
Files.deleteIfExists(pdfFile.toPath());
Files.deleteIfExists(file.getFile().toPath());
return finalDoi;
}
public Doi createDoi(DepositRequest depositRequest, Principal principal) throws Exception {
DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId()));
if (!isUserOwnerOfDmp(dmp, principal))
throw new Exception("User is not authorized to invoke this action");
if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue()))
throw new Exception("DMP is not finalized");
/*if (dmp.getDoi() != null)
throw new Exception("DMP already has a DOI");*/
FileEnvelope file = getWordDocument(depositRequest.getDmpId(), principal, configLoader);
String name = file.getFilename().substring(0, file.getFilename().length() - 5).replaceAll("[^a-zA-Z0-9_+ ]", "").replace(" ", "_").replace(",", "_");
File pdfFile = PDFUtils.convertToPDF(file, environment);
String fileName = name + ".pdf";
ResponseEntity<byte[]> jsonFile;
try {
jsonFile = getRDAJsonDocument(depositRequest.getDmpId(), principal);
} catch (Exception e) {
throw e;
}
String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId(), depositRequest.getRepositoryId());
File supportingFilesZip = this.createSupportingFilesZip(dmp);
DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfFile, fileName, jsonFile, supportingFilesZip, previousDOI);
Optional<RepositoryDeposit> repo = this.repositoriesDeposit.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(depositRequest.getRepositoryId())).findFirst();
String finalDoi = repo.map(r -> {
try {
return r.deposit(dmpDepositModel, depositRequest.getAccessToken());
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}).orElse(null);
Doi doiModel = null;
if (finalDoi != null) {
EntityDoi doiEntity = new EntityDoi();
doiEntity.setId(UUID.randomUUID());
doiEntity.setEntityType(EntityDoi.EntityType.DMP);
doiEntity.setDoi(finalDoi);
doiEntity.setRepositoryId(depositRequest.getRepositoryId());
Date now = new Date();
doiEntity.setCreatedAt(now);
doiEntity.setUpdatedAt(now);
doiEntity.setEntityId(dmp);
apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity);
dmp.getDois().add(doiEntity);
apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
doiModel = new Doi().fromDataModel(doiEntity);
}
if(supportingFilesZip != null) {
Files.deleteIfExists(supportingFilesZip.toPath());
}
Files.deleteIfExists(pdfFile.toPath());
Files.deleteIfExists(file.getFile().toPath());
return doiModel;
}
private File createSupportingFilesZip(DMP dmp) throws IOException {
FileOutputStream fout = new FileOutputStream(this.environment.getProperty("temp.temp") + "supportingFiles.zip");
ZipOutputStream zout = new ZipOutputStream(fout);
boolean hasFileUploaded = false;
Set<Dataset> datasets = dmp.getDataset();
for (Dataset dataset : datasets) {
List<FileUpload> files = this.apiContext.getOperationsContext().getDatabaseRepository().getFileUploadDao().getFileUploads(dataset.getId());
for (FileUpload f : files) {
if(!f.getIsDeleted()){
File exportFile = new File(this.environment.getProperty("file.storage") + f.getId());
String filename = f.getName().replace(" ", "_").replace(",", "_");
byte[] content = Files.readAllBytes(exportFile.toPath());
ZipEntry ze = new ZipEntry(filename);
zout.putNextEntry(ze);
zout.write(content, 0, content.length);
zout.closeEntry();
hasFileUploaded = true;
}
}
}
zout.close();
if(!hasFileUploaded){
Files.deleteIfExists(new File(this.environment.getProperty("temp.temp") + "supportingFiles.zip").toPath());
}
return hasFileUploaded ? new File(this.environment.getProperty("temp.temp") + "supportingFiles.zip") : null;
}
/*

View File

@ -0,0 +1,58 @@
package eu.eudat.logic.managers;
import eu.eudat.depositinterface.repository.RepositoryDeposit;
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
import eu.eudat.models.data.doi.DepositRequest;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.doi.RepositoryConfig;
import eu.eudat.models.data.security.Principal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Component
public class DepositManager {
private static final Logger logger = LoggerFactory.getLogger(DepositManager.class);
private List<RepositoryDeposit> repositories;
private DataManagementPlanManager dataManagementPlanManager;
@Autowired
public DepositManager(List<RepositoryDeposit> repositories, DataManagementPlanManager dataManagementPlanManager){
this.repositories = repositories;
this.dataManagementPlanManager = dataManagementPlanManager;
}
public List<RepositoryConfig> getAvailableRepos() {
List<RepositoryConfig> reposConfigModel = new ArrayList<>();
for (RepositoryDeposit r: this.repositories) {
RepositoryConfig repoModel = new RepositoryConfig();
RepositoryDepositConfiguration repoConf = r.getConfiguration();
if(repoConf != null) {
reposConfigModel.add(repoModel.toModel(repoConf));
}
}
return reposConfigModel;
}
public String authenticate(String id, String code) {
Optional<RepositoryDeposit> repo = repositories.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(id)).findFirst();
return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null);
}
public Doi deposit(DepositRequest depositRequest, Principal principal) throws Exception {
return this.dataManagementPlanManager.createDoi(depositRequest, principal);
}
public String getRepositoryLogo(String repositoryId){
Optional<RepositoryDeposit> repo = repositories.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(repositoryId)).findFirst();
return repo.map(repositoryDeposit ->
(repositoryDeposit.getConfiguration().isHasLogo()) ? repositoryDeposit.getLogo() : null
).orElse(null);
}
}

View File

@ -1,27 +0,0 @@
package eu.eudat.logic.proxy.config;
import com.fasterxml.jackson.annotation.JsonProperty;
public class DOIFunder {
@JsonProperty("Funder")
private String funder;
@JsonProperty("DOI")
private String DOI;
public String getFunder() {
return funder;
}
public void setFunder(String funder) {
this.funder = funder;
}
public String getDOI() {
return DOI;
}
public void setDOI(String DOI) {
this.DOI = DOI;
}
}

View File

@ -1,6 +1,5 @@
package eu.eudat.logic.proxy.config.configloaders;
import eu.eudat.logic.proxy.config.DOIFunder;
import eu.eudat.logic.proxy.config.ExternalUrls;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
@ -15,5 +14,4 @@ public interface ConfigLoader {
XWPFDocument getDatasetDocument();
ConfigurableProviders getConfigurableProviders();
Map<String, String> getKeyToSourceMap();
List<DOIFunder> getDOIFunders();
}

View File

@ -2,7 +2,6 @@ package eu.eudat.logic.proxy.config.configloaders;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.logic.proxy.config.DOIFunder;
import eu.eudat.logic.proxy.config.ExternalUrls;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
@ -41,7 +40,6 @@ public class DefaultConfigLoader implements ConfigLoader {
private XWPFDocument datasetDocument;
private ConfigurableProviders configurableProviders;
private Map<String, String> keyToSourceMap;
private List<DOIFunder> doiFunders = new ArrayList<>();
@Autowired
private Environment environment;
@ -207,18 +205,6 @@ public class DefaultConfigLoader implements ConfigLoader {
return keyToSourceMap;
}
@Override
public List<DOIFunder> getDOIFunders() {
if (doiFunders == null || doiFunders.isEmpty()) {
try {
List<Map<String, Object>> tempdoiFunders = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.doi_funder")), List.class);
doiFunders = tempdoiFunders.stream().map(map -> mapper.convertValue(map, DOIFunder.class) ).collect(Collectors.toList());
} catch (IOException e) {
logger.error(e.getLocalizedMessage(), e);
}
}
return doiFunders;
}
private Document getXmlDocumentFromFilePath(String filePath) {
InputStream is = null;

View File

@ -0,0 +1,74 @@
package eu.eudat.logic.security.repositorydeposit.mapper;
import eu.eudat.data.entities.*;
import eu.eudat.depositinterface.models.*;
import org.springframework.http.ResponseEntity;
import java.io.File;
import java.util.stream.Collectors;
public class DMPToDepositMapper {
public static DMPDepositModel fromDMP(DMP entity, File pdfFile, String fileName, ResponseEntity<byte[]> jsonFile, File supportingFilesZip, String previousDOI) {
DMPDepositModel deposit = new DMPDepositModel();
deposit.setId(entity.getId());
deposit.setVersion(entity.getVersion());
deposit.setLabel(entity.getLabel());
deposit.setDescription(entity.getDescription());
deposit.setPublic(entity.isPublic());
deposit.setUsers(entity.getUsers().stream().map(DMPToDepositMapper::fromUserDMP).collect(Collectors.toSet()));
deposit.setOrganisations(entity.getOrganisations().stream().map(DMPToDepositMapper::fromOrganisation).collect(Collectors.toSet()));
deposit.setResearchers(entity.getResearchers().stream().map(DMPToDepositMapper::fromResearcher).collect(Collectors.toSet()));
deposit.setGrant(fromGrant(entity.getGrant()));
deposit.setPdfFile(pdfFile);
deposit.setPdfFileName(fileName);
deposit.setRdaJson(jsonFile);
deposit.setSupportingFilesZip(supportingFilesZip);
deposit.setPreviousDOI(previousDOI);
deposit.setExtraProperties(entity.getExtraProperties());
return deposit;
}
private static UserDMPDepositModel fromUserDMP(UserDMP entity){
UserDMPDepositModel deposit = new UserDMPDepositModel();
deposit.setUser(fromUserInfo(entity.getUser()));
deposit.setRole(entity.getRole());
return deposit;
}
private static UserInfoDepositModel fromUserInfo(UserInfo entity){
UserInfoDepositModel deposit = new UserInfoDepositModel();
deposit.setName(entity.getName());
deposit.setEmail(entity.getEmail());
return deposit;
}
private static OrganisationDepositModel fromOrganisation(Organisation entity){
OrganisationDepositModel deposit = new OrganisationDepositModel();
deposit.setLabel(entity.getLabel());
return deposit;
}
private static ResearcherDepositModel fromResearcher(Researcher entity){
ResearcherDepositModel deposit = new ResearcherDepositModel();
deposit.setLabel(entity.getLabel());
deposit.setReference(entity.getReference());
return deposit;
}
private static GrantDepositModel fromGrant(Grant entity){
GrantDepositModel deposit = new GrantDepositModel();
deposit.setId(entity.getId());
deposit.setReference(entity.getReference());
deposit.setFunder(fromFunder(entity.getFunder()));
return deposit;
}
private static FunderDepositModel fromFunder(Funder entity){
FunderDepositModel deposit = new FunderDepositModel();
deposit.setLabel(entity.getLabel());
return deposit;
}
}

View File

@ -60,5 +60,7 @@ public interface DatabaseRepository {
FileUploadDao getFileUploadDao();
EntityDoiDao getEntityDoiDao();
<T> void detachEntity(T entity);
}

View File

@ -39,6 +39,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
private LockDao lockDao;
private NotificationDao notificationDao;
private FileUploadDao fileUploadDao;
private EntityDoiDao entityDoiDao;
private EntityManager entityManager;
@ -317,6 +318,15 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
this.fileUploadDao = fileUploadDao;
}
@Override
public EntityDoiDao getEntityDoiDao() {
return entityDoiDao;
}
@Autowired
public void setEntityDoiDao(EntityDoiDao entityDoiDao) {
this.entityDoiDao = entityDoiDao;
}
public <T> void detachEntity(T entity) {
this.entityManager.detach(entity);

View File

@ -25,6 +25,14 @@ public class HtmlToWorldBuilder implements NodeVisitor {
private BigInteger numberingLevel;
private XmlCursor cursor;
public static HtmlToWorldBuilder convertInTable(XWPFTableCell document, Document htmlDocument, float indentation) {
XWPFParagraph paragraph = document.addParagraph();
paragraph.setIndentFromLeft(Math.round(400 * indentation));
HtmlToWorldBuilder htmlToWorldBuilder = new HtmlToWorldBuilder(paragraph, indentation, null);
NodeTraversor.traverse(htmlToWorldBuilder, htmlDocument);
return htmlToWorldBuilder;
}
public static HtmlToWorldBuilder convert(XWPFDocument document, Document htmlDocument, float indentation) {
XWPFParagraph paragraph = document.createParagraph();
paragraph.setIndentFromLeft(Math.round(400 * indentation));

View File

@ -65,6 +65,7 @@ public class WordBuilder {
).collect(Collectors.toMap(objects -> (String)objects[0], o -> (Integer)o[1]));
private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, Object, XWPFParagraph>> options = new HashMap<>();
private Map<ParagraphStyle, ApplierWithValue<XWPFTableCell, Object, XWPFParagraph>> optionsInTable = new HashMap<>();
private CTAbstractNum cTAbstractNum;
private BigInteger numId;
private Integer indent;
@ -78,6 +79,42 @@ public class WordBuilder {
this.imageCount = 0;
this.mapper = new ObjectMapper();
this.buildOptions(environment);
this.buildOptionsInTable(environment);
}
private void buildOptionsInTable(Environment environment) {
this.optionsInTable.put(ParagraphStyle.TEXT, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.addParagraph();
XWPFRun run = paragraph.createRun();
if (item != null)
run.setText("" + item);
run.setFontSize(11);
return paragraph;
});
this.optionsInTable.put(ParagraphStyle.HTML, (mainDocumentPart, item) -> {
Document htmlDoc = Jsoup.parse(((String)item).replaceAll("\n", "<br>"));
HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convertInTable(mainDocumentPart, htmlDoc, 0);
return htmlToWorldBuilder.getParagraph();
});
this.optionsInTable.put(ParagraphStyle.TITLE, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.addParagraph();
paragraph.setStyle("Title");
paragraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run = paragraph.createRun();
run.setText((String)item);
run.setBold(true);
run.setFontSize(14);
return paragraph;
});
this.optionsInTable.put(ParagraphStyle.IMAGE, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.addParagraph();
XWPFRun run = paragraph.createRun();
if (item != null)
run.setText(((Map<String, String>)item).get("name"));
run.setFontSize(11);
run.setItalic(true);
return paragraph;
});
}
private void buildOptions(Environment environment) {
@ -91,7 +128,6 @@ public class WordBuilder {
});
this.options.put(ParagraphStyle.HTML, (mainDocumentPart, item) -> {
Document htmlDoc = Jsoup.parse(((String)item).replaceAll("\n", "<br>"));
// HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convert(mainDocumentPart, htmlDoc, indent > 0 ? (indent/2.0F) * 0.8F : 0.8F);
HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convert(mainDocumentPart, htmlDoc, this.indent);
return htmlToWorldBuilder.getParagraph();
});
@ -287,6 +323,7 @@ public class WordBuilder {
if (createListing) this.addListing(mainDocumentPart, indent, true, true);
boolean hasValue = false;
boolean returnedValue = false;
for (FieldSet compositeField: compositeFields) {
if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) {
char c = 'a';
@ -299,14 +336,30 @@ public class WordBuilder {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent));
paragraphPos = mainDocumentPart.getPosOfParagraph(paragraph);
if(compositeField.getMultiplicityItems() != null && !compositeField.getMultiplicityItems().isEmpty()){
if(!compositeField.getMultiplicity().getTableView() && compositeField.getMultiplicityItems() != null && !compositeField.getMultiplicityItems().isEmpty()){
XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
paragraphPosInner = mainDocumentPart.getPosOfParagraph(paragraphInner);
hasMultiplicityItems = true;
multiplicityItems++;
}
}
hasValue = createFields(compositeField.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems);
XWPFTable tbl = null;
XWPFTableRow row = null;
int numOfRows = 0;
if(compositeField.getMultiplicity().getTableView()) {
tbl = mainDocumentPart.createTable();
tbl.setTableAlignment(TableRowAlign.CENTER);
mainDocumentPart.createParagraph();
createHeadersInTable(compositeField.getFields(), tbl, visibilityRuleService);
numOfRows = tbl.getRows().size();
row = tbl.createRow();
}
if(compositeField.getMultiplicity().getTableView()) {
hasValue = createFieldsInTable(compositeField.getFields(), row, indent, createListing, visibilityRuleService, hasMultiplicityItems, numOfRows);
numOfRows++;
} else {
hasValue = createFields(compositeField.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems);
}
if(hasValue){
returnedValue = true;
} else if(paragraphPosInner > -1){
@ -318,7 +371,7 @@ public class WordBuilder {
List<FieldSet> list = compositeField.getMultiplicityItems().stream().sorted(Comparator.comparingInt(FieldSet::getOrdinal)).collect(Collectors.toList());
for (FieldSet multiplicityFieldset : list) {
paragraphPosInner = -1;
if(!createListing){
if(!compositeField.getMultiplicity().getTableView() && !createListing){
c++;
// addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.HEADER6, numId);
XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
@ -327,7 +380,14 @@ public class WordBuilder {
multiplicityItems++;
}
// hasValue = createFields(multiplicityFieldset.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService, hasMultiplicityItems);
boolean hasValueInner = createFields(multiplicityFieldset.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems);
boolean hasValueInner = false;
if(compositeField.getMultiplicity().getTableView()) {
row = tbl.createRow();
hasValueInner = createFieldsInTable(multiplicityFieldset.getFields(), row, indent, createListing, visibilityRuleService, hasMultiplicityItems, numOfRows);
numOfRows++;
} else {
hasValueInner = createFields(multiplicityFieldset.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems);
}
// if(hasValue){
if(hasValueInner){
hasValue = true;
@ -355,9 +415,159 @@ public class WordBuilder {
}
}
}
return returnedValue;
}
private void createHeadersInTable(List<Field> fields, XWPFTable table, VisibilityRuleService visibilityRuleService) {
boolean atLeastOneHeader = false;
List<Field> tempFields = fields.stream().sorted(Comparator.comparingInt(Field::getOrdinal)).collect(Collectors.toList());
int index = 0;
XWPFTableRow row = table.getRow(0);
for (Field field: tempFields) {
if (visibilityRuleService.isElementVisible(field.getId()) && field.getExport()) {
XWPFTableCell cell;
if(index == 0) {
cell = row.getCell(0);
} else {
cell = row.createCell();
}
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.valueOf("CENTER"));
String label = ((FieldData) field.getData()).getLabel();
if(label != null && label != "") {
XWPFParagraph paragraph = cell.getParagraphs().get(0);
paragraph.setIndentationFirstLine(50);
XWPFRun run = paragraph.createRun();
run.setText(label);
run.setBold(true);
run.setFontSize(12);
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.setSpacingBefore(100);
atLeastOneHeader = true;
}
}
index++;
}
if(!atLeastOneHeader) {
table.removeRow(0);
}
}
private Boolean createFieldsInTable(List<Field> fields, XWPFTableRow mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService, boolean hasMultiplicityItems, int numOfRows) {
int numOfCells = 0;
boolean hasValue = false;
List<Field> tempFields = fields.stream().sorted(Comparator.comparingInt(Field::getOrdinal)).collect(Collectors.toList());
for (Field field: tempFields) {
if (visibilityRuleService.isElementVisible(field.getId()) && field.getExport()) {
if (!createListing) {
try {
if(field.getViewStyle().getRenderStyle().equals("upload")){
boolean isImage = false;
for(UploadData.Option type: ((UploadData)field.getData()).getTypes()){
String fileFormat = type.getValue();
if(IMAGE_TYPE_MAP.containsKey(fileFormat)){
isImage = true;
break;
}
}
if(isImage){
if (field.getValue() != null && !field.getValue().toString().isEmpty()) {
XWPFParagraph paragraph = addCellContent(mapper.convertValue(field.getValue(), Map.class), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0, numOfRows, numOfCells, 0);
if (paragraph != null) {
hasValue = true;
}
if(hasMultiplicityItems){
hasMultiplicityItems = false;
}
}
}
}
else if (field.getValue() != null && !field.getValue().toString().isEmpty()) {
this.indent = indent;
String format = this.formatter(field);
if (field.getViewStyle().getRenderStyle().equals("tags")) {
format = getCommaSeparatedFormatsFromJson(format, "name");
} else if (field.getViewStyle().getRenderStyle().equals("combobox") && field.getData() instanceof AutoCompleteData) {
format = getCommaSeparatedFormatsFromJson(format, "label");
}
boolean isResearcher = field.getViewStyle().getRenderStyle().equals("researchers");
if(format != null && !format.isEmpty()){
Object hasMultiAutoComplete = mapper.convertValue(field.getData(), Map.class).get("multiAutoComplete");
boolean isMultiAutoComplete = hasMultiAutoComplete != null && (boolean)hasMultiAutoComplete;
boolean arrayStringFormat = format.charAt(0) == '[';
if(arrayStringFormat || isMultiAutoComplete){
List<String> values = (arrayStringFormat) ? Arrays.asList(format.substring(1, format.length() - 1).split(",[ ]*")) : Arrays.asList(format.split(",[ ]*"));
if(values.size() > 1) {
boolean orcidResearcher;
int numOfValuesInCell = 0;
for (String val : values) {
orcidResearcher = false;
String orcId = null;
if(isResearcher && val.contains("orcid:")){
orcId = val.substring(val.indexOf(':') + 1, val.indexOf(')'));
val = val.substring(0, val.indexOf(':') + 1) + " ";
orcidResearcher = true;
}
format = "" + val;
if(hasMultiplicityItems){
XWPFParagraph paragraph = mainDocumentPart.getCell(mainDocumentPart.getTableCells().size()).addParagraph();
paragraph.createRun().setText(format);
if(orcidResearcher){
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
hasMultiplicityItems = false;
}
else{
XWPFParagraph paragraph = addCellContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent, numOfRows, numOfCells, numOfValuesInCell);
numOfValuesInCell++;
if(orcidResearcher){
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
if (paragraph != null) {
hasValue = true;
}
}
format = null;
}
}
else if(values.size() == 1){
format = values.get(0);
}
}
}
if(hasMultiplicityItems && format != null){
XWPFParagraph paragraph = mainDocumentPart.getCell(mainDocumentPart.getTableCells().size()).addParagraph();
paragraph.createRun().setText(format);
hasMultiplicityItems = false;
hasValue = true;
}
else{
XWPFParagraph paragraph = addCellContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent, numOfRows, numOfCells, 0);
if (paragraph != null) {
hasValue = true;
}
}
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
numOfCells++;
}
}
return hasValue;
}
private Boolean createFields(List<Field> fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService, boolean hasMultiplicityItems) {
if (createListing) this.addListing(mainDocumentPart, indent, false, false);
boolean hasValue = false;
@ -491,6 +701,36 @@ public class WordBuilder {
}
}
public XWPFParagraph addCellContent(Object content, XWPFTableRow mainDocumentPart, ParagraphStyle style, BigInteger numId, int indent, int numOfRows, int numOfCells, int numOfValuesInCell) {
if (content != null) {
if (content instanceof String && ((String)content).isEmpty()) {
return null;
}
this.indent = indent;
XWPFTableCell cell;
if(numOfRows > 0 || numOfValuesInCell > 0) {
cell = mainDocumentPart.getCell(numOfCells);
} else {
cell = mainDocumentPart.createCell();
}
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.valueOf("CENTER"));
if(numOfValuesInCell == 0) {
cell.removeParagraph(0);
}
XWPFParagraph paragraph = this.optionsInTable.get(style).apply(cell, content);
if (paragraph != null) {
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.setSpacingBefore(100);
if (numId != null) {
paragraph.setNumID(numId);
}
return paragraph;
}
}
return null;
}
public XWPFParagraph addParagraphContent(Object content, XWPFDocument mainDocumentPart, ParagraphStyle style, BigInteger numId, int indent) {
// this.indent = 0;
if (content != null) {
@ -796,9 +1036,8 @@ public class WordBuilder {
r.setText(text, 0);
}
if(text.contains("{ARGOS.DMP.DOI}")){
String doi = dmpEntity.getDoi();
if(doi != null)
text = text.replace("{ARGOS.DMP.DOI}", doi);
if(dmpEntity.getDois() != null && !dmpEntity.getDois().isEmpty())
text = text.replace("{ARGOS.DMP.DOI}", dmpEntity.getDois().iterator().next().getDoi());
else
text = text.replace("{ARGOS.DMP.DOI}", "-");
r.setText(text, 0);

View File

@ -121,6 +121,7 @@ public class ExportXmlBuilderDatasetProfile {
multiplicity.setAttribute("max", "" + field.getMultiplicity().getMax());
multiplicity.setAttribute("min", "" + field.getMultiplicity().getMin());
multiplicity.setAttribute("placeholder", field.getMultiplicity().getPlaceholder());
multiplicity.setAttribute("tableView", String.valueOf(field.getMultiplicity().getTableView()));
composite.appendChild(multiplicity);
}
if (field.getTitle() != null && !field.getTitle().isEmpty()) {

View File

@ -9,6 +9,7 @@ public class Multiplicity {
private int max;
private int min;
private String placeholder;
private boolean tableView;
@XmlAttribute(name = "max")
public int getMax() {
@ -37,11 +38,21 @@ public class Multiplicity {
this.placeholder = placeholder;
}
@XmlAttribute(name = "tableView")
public boolean getTableView() {
return tableView;
}
public void setTableView(boolean tableView) {
this.tableView = tableView;
}
public eu.eudat.models.data.components.commons.Multiplicity toAdminCompositeModelSection() {
eu.eudat.models.data.components.commons.Multiplicity multiplicityEntity = new eu.eudat.models.data.components.commons.Multiplicity();
multiplicityEntity.setMax(max);
multiplicityEntity.setMin(min);
multiplicityEntity.setPlaceholder(placeholder);
multiplicityEntity.setTableView(tableView);
return multiplicityEntity;
}
}

View File

@ -5,6 +5,7 @@ public class Multiplicity {
private int min;
private int max;
private String placeholder;
private boolean tableView;
public int getMin() {
return min;
@ -29,4 +30,12 @@ public class Multiplicity {
public void setPlaceholder(String placeholder) {
this.placeholder = placeholder;
}
public boolean getTableView() {
return tableView;
}
public void setTableView(boolean tableView) {
this.tableView = tableView;
}
}

View File

@ -4,6 +4,7 @@ import eu.eudat.data.entities.*;
import eu.eudat.logic.utilities.builders.XmlBuilder;
import eu.eudat.models.DataModel;
import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile;
import eu.eudat.models.data.funder.Funder;
@ -40,7 +41,7 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
private List<DynamicFieldWithValue> dynamicFields;
private Map<String, Object> properties;
private List<UserInfoListingModel> users;
private String doi;
private List<Doi> dois;
private Project project;
private Funder funder;
private Boolean isPublic;
@ -194,11 +195,11 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
this.users = users;
}
public String getDoi() {
return doi;
public List<Doi> getDois() {
return dois;
}
public void setDoi(String doi) {
this.doi = doi;
public void setDois(List<Doi> dois) {
this.dois = dois;
}
public Project getProject() {
@ -280,7 +281,7 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
this.status = entity.getStatus();
this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>();
this.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>();
this.doi = entity.getDoi();
this.dois = entity.getDois() != null ? entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()): new ArrayList<>();
if (entity.getProject() != null) {
this.project = new Project();
@ -376,7 +377,7 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
this.status = entity.getStatus();
this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>();
this.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>();
this.doi = entity.getDoi();
this.dois = entity.getDois() != null ? entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()): new ArrayList<>();
this.grant.fromDataModel(entity.getGrant());
if (entity.getProject() != null) {

View File

@ -0,0 +1,21 @@
package eu.eudat.models.data.doi;
public class DepositCode {
private String repositoryId;
private String code;
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@ -0,0 +1,29 @@
package eu.eudat.models.data.doi;
public class DepositRequest {
private String repositoryId;
private String dmpId;
private String accessToken;
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getDmpId() {
return dmpId;
}
public void setDmpId(String dmpId) {
this.dmpId = dmpId;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}

View File

@ -0,0 +1,85 @@
package eu.eudat.models.data.doi;
import eu.eudat.data.entities.EntityDoi;
import eu.eudat.models.DataModel;
import eu.eudat.models.data.dmp.DataManagementPlan;
import java.util.Date;
import java.util.UUID;
public class Doi implements DataModel<EntityDoi, Doi> {
private UUID id;
private String repositoryId;
private String doi;
private Date createdAt;
private Date updatedAt;
private DataManagementPlan dmp;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getDoi() {
return doi;
}
public void setDoi(String doi) {
this.doi = doi;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public DataManagementPlan getDmp() {
return dmp;
}
public void setDmp(DataManagementPlan dmp) {
this.dmp = dmp;
}
@Override
public Doi fromDataModel(EntityDoi entity) {
this.id = entity.getId();
this.repositoryId = entity.getRepositoryId();
this.doi = entity.getDoi();
this.createdAt = entity.getCreatedAt();
this.updatedAt = entity.getUpdatedAt();
return this;
}
@Override
public EntityDoi toDataModel() throws Exception {
EntityDoi entityDoi = new EntityDoi();
entityDoi.setId(this.id);
entityDoi.setRepositoryId(this.repositoryId);
entityDoi.setDoi(this.doi);
entityDoi.setCreatedAt(this.createdAt);
entityDoi.setUpdatedAt(this.updatedAt);
return entityDoi;
}
@Override
public String getHint() {
return null;
}
}

View File

@ -0,0 +1,74 @@
package eu.eudat.models.data.doi;
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
public class RepositoryConfig {
private int depositType;
private String repositoryId;
private String repositoryAuthorizationUrl;
private String repositoryRecordUrl;
private String repositoryClientId;
private String redirectUri;
private boolean hasLogo;
public int getDepositType() {
return depositType;
}
public void setDepositType(int depositType) {
this.depositType = depositType;
}
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getRepositoryAuthorizationUrl() {
return repositoryAuthorizationUrl;
}
public void setRepositoryAuthorizationUrl(String repositoryAuthorizationUrl) {
this.repositoryAuthorizationUrl = repositoryAuthorizationUrl;
}
public String getRepositoryRecordUrl() {
return repositoryRecordUrl;
}
public void setRepositoryRecordUrl(String repositoryRecordUrl) {
this.repositoryRecordUrl = repositoryRecordUrl;
}
public String getRepositoryClientId() {
return repositoryClientId;
}
public void setRepositoryClientId(String repositoryClientId) {
this.repositoryClientId = repositoryClientId;
}
public String getRedirectUri() {
return redirectUri;
}
public void setRedirectUri(String redirectUri) {
this.redirectUri = redirectUri;
}
public boolean isHasLogo() {
return hasLogo;
}
public void setHasLogo(boolean hasLogo) {
this.hasLogo = hasLogo;
}
public RepositoryConfig toModel(RepositoryDepositConfiguration r){
this.setDepositType(r.getDepositType());
this.setRepositoryId(r.getRepositoryId());
this.setRepositoryAuthorizationUrl(r.getRepositoryAuthorizationUrl());
this.setRepositoryRecordUrl(r.getRepositoryRecordUrl());
this.setRepositoryClientId(r.getRepositoryClientId());
this.setRedirectUri(r.getRedirectUri());
this.setHasLogo(r.isHasLogo());
return this;
}
}

View File

@ -122,6 +122,7 @@ public class FieldSet implements DatabaseViewStyleDefinition, XmlSerializable<Fi
multiplicity.setAttribute("min", "" + this.multiplicity.getMin());
multiplicity.setAttribute("max", "" + this.multiplicity.getMax());
multiplicity.setAttribute("placeholder", this.multiplicity.getPlaceholder());
multiplicity.setAttribute("tableView", String.valueOf(this.multiplicity.getTableView()));
Element commentField = doc.createElement("commentField");
commentField.setAttribute("hasCommentField", "" + this.hasCommentField);
@ -185,6 +186,7 @@ public class FieldSet implements DatabaseViewStyleDefinition, XmlSerializable<Fi
this.multiplicity.setMin(Integer.parseInt(multiplicity.getAttribute("min")));
this.multiplicity.setMax(Integer.parseInt(multiplicity.getAttribute("max")));
this.multiplicity.setPlaceholder(multiplicity.getAttribute("placeholder"));
this.multiplicity.setTableView(Boolean.parseBoolean(multiplicity.getAttribute("tableView")));
return this;
}

View File

@ -8,6 +8,7 @@ import eu.eudat.models.data.dataset.DatasetOverviewModel;
import eu.eudat.models.data.dmp.AssociatedProfile;
import eu.eudat.models.data.dmp.Organisation;
import eu.eudat.models.data.dmp.Researcher;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.grant.GrantOverviewModel;
import java.util.Date;
@ -35,7 +36,7 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
private String description;
private boolean isPublic;
private Date publishedAt;
private String doi;
private List<Doi> dois;
public String getId() {
@ -164,11 +165,11 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
this.publishedAt = publishedAt;
}
public String getDoi() {
return doi;
public List<Doi> getDois() {
return dois;
}
public void setDoi(String doi) {
this.doi = doi;
public void setDois(List<Doi> dois) {
this.dois = dois;
}
@Override
@ -180,6 +181,9 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
if (entity.getResearchers() != null) {
this.researchers = entity.getResearchers().stream().map(item -> new Researcher().fromDataModel(item)).collect(Collectors.toList());
}
if(entity.getDois() != null){
this.dois = entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList());
}
return this;
}
@ -208,7 +212,7 @@ public class DataManagementPlanOverviewModel implements DataModel<DMP, DataManag
}
this.isPublic = entity.isPublic();
this.publishedAt = entity.getPublishedAt();
this.doi = entity.getDoi();
this.dois = entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList());
return this;
}

View File

@ -1,9 +1,6 @@
package eu.eudat.models.data.rda;
import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.Dataset;
import eu.eudat.data.entities.UserDMP;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.*;
import eu.eudat.logic.managers.DatasetManager;
import eu.eudat.models.data.security.Principal;
@ -146,8 +143,17 @@ public class DmpRDAExportModel {
dmpRda.dataset.add(new DatasetRDAExportModel().fromDataModel(dataset, datasetManager, principal));
}
dmpRda.description = entity.getDescription().replace("\n", " ");
if (entity.getDoi() != null) {
dmpRda.dmp_id = new IdRDAExportModel(entity.getDoi(), "zenodo");
if (entity.getDois() != null && !entity.getDois().isEmpty()) {
boolean zenodoDoi = false;
for(EntityDoi doi: entity.getDois()){
if(doi.getRepositoryId().equals("Zenodo")){
dmpRda.dmp_id = new IdRDAExportModel(doi.getDoi(), "zenodo");
zenodoDoi = true;
}
}
if(!zenodoDoi){
dmpRda.dmp_id = new IdRDAExportModel(entity.getId().toString(), "other");
}
}
else {
dmpRda.dmp_id = new IdRDAExportModel(entity.getId().toString(), "other");

View File

@ -1,18 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonValue;
public enum ZenodoAccessRight {
RESTRICTED("restricted"), EMBARGOED("embargoed"), OPEN("open");
private final String value;
ZenodoAccessRight(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
}

View File

@ -1,19 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoComunity {
private String identifier;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
}

View File

@ -1,45 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoContributor {
private String name;
private String type;
private String affiliation;
private String orcid;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAffiliation() {
return affiliation;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public String getOrcid() {
return orcid;
}
public void setOrcid(String orcid) {
this.orcid = orcid;
}
}

View File

@ -1,19 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoDeposit {
private ZenodoDepositMetadata metadata;
public ZenodoDepositMetadata getMetadata() {
return metadata;
}
public void setMetadata(ZenodoDepositMetadata metadata) {
this.metadata = metadata;
}
}

View File

@ -1,159 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoDepositMetadata {
private String title;
@JsonProperty("upload_type")
private String uploadType;
@JsonProperty("publication_type")
private String publicationType;
private String description;
private String version;
private List<ZenodoComunity> communities;
@JsonProperty("access_right")
private ZenodoAccessRight accessRight;
@JsonProperty("access_conditions")
private String accessConditions;
@JsonProperty("embargo_date")
private String embargoDate;
private String license;
@JsonProperty("related_identifiers")
private List<ZenodoRelator> relatedIdentifiers;
private List<ZenodoContributor> contributors;
private List<ZenodoGrant> grants;
private List<ZenodoContributor> creators;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUploadType() {
return uploadType;
}
public void setUploadType(String uploadType) {
this.uploadType = uploadType;
}
public String getPublicationType() {
return publicationType;
}
public void setPublicationType(String publicationType) {
this.publicationType = publicationType;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public List<ZenodoComunity> getCommunities() {
return communities;
}
public void setCommunities(List<ZenodoComunity> communities) {
this.communities = communities;
}
public ZenodoAccessRight getAccessRight() {
return accessRight;
}
public void setAccessRight(ZenodoAccessRight accessRight) {
this.accessRight = accessRight;
}
public String getAccessConditions() {
return accessConditions;
}
public void setAccessConditions(String accessConditions) {
this.accessConditions = accessConditions;
}
public String getEmbargoDate() {
return embargoDate;
}
public void setEmbargoDate(String embargoDate) {
this.embargoDate = embargoDate;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public List<ZenodoRelator> getRelatedIdentifiers() {
return relatedIdentifiers;
}
public void setRelatedIdentifiers(List<ZenodoRelator> relatedIdentifiers) {
this.relatedIdentifiers = relatedIdentifiers;
}
public List<ZenodoContributor> getContributors() {
return contributors;
}
public void setContributors(List<ZenodoContributor> contributors) {
this.contributors = contributors;
}
public List<ZenodoGrant> getGrants() {
return grants;
}
public void setGrants(List<ZenodoGrant> grants) {
this.grants = grants;
}
public List<ZenodoContributor> getCreators() {
return creators;
}
public void setCreators(List<ZenodoContributor> creators) {
this.creators = creators;
}
}

View File

@ -1,18 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoGrant {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@ -1,28 +0,0 @@
package eu.eudat.models.deposit.zenodo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoRelator {
private String identifier;
private String relation;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getRelation() {
return relation;
}
public void setRelation(String relation) {
this.relation = relation;
}
}

View File

@ -1,115 +0,0 @@
package eu.eudat.models.deposit.zenodo.mapper;
import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.Organisation;
import eu.eudat.data.entities.UserDMP;
import eu.eudat.logic.proxy.config.DOIFunder;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.models.deposit.zenodo.*;
import org.springframework.core.env.Environment;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
public class DMPToZenodoMapper {
public static ZenodoDeposit fromDMP(DMP dmp, Environment environment, ConfigLoader configLoader) {
Map<String, Object> extraProperties = dmp.getExtraProperties() != null ? new org.json.JSONObject(dmp.getExtraProperties()).toMap() : new HashMap<>();
ZenodoDeposit deposit = new ZenodoDeposit();
deposit.setMetadata(new ZenodoDepositMetadata());
deposit.getMetadata().setTitle(dmp.getLabel());
deposit.getMetadata().setUploadType("publication");
deposit.getMetadata().setPublicationType("datamanagementplan");
deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "<p></p>"));
deposit.getMetadata().setVersion(dmp.getVersion().toString());
ZenodoComunity community = new ZenodoComunity();
community.setIdentifier(environment.getProperty("zenodo.community"));
deposit.getMetadata().setCommunities(Collections.singletonList(community));
if (extraProperties.get("visible") == null) {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
deposit.getMetadata().setAccessConditions("");
} else {
if (((Boolean) extraProperties.get("visible"))) {
Instant publicationDate = Instant.parse(extraProperties.get("publicDate").toString());
if (publicationDate.isBefore(Instant.now())) {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.OPEN);
} else {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.EMBARGOED);
deposit.getMetadata().setEmbargoDate(publicationDate.toString());
}
if (extraProperties.get("license") != null) {
deposit.getMetadata().setLicense(((Map<?, ?>) extraProperties.get("license")).get("pid").toString());
}
} else {
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
deposit.getMetadata().setAccessConditions("");
}
}
if (dmp.isPublic()) {
ZenodoRelator relator = new ZenodoRelator();
relator.setIdentifier((environment.getProperty("dmp.domain") + "/external/zenodo/" + dmp.getId().toString()));
relator.setRelation("isIdenticalTo");
deposit.getMetadata().setRelatedIdentifiers(Collections.singletonList(relator));
}
deposit.getMetadata().setContributors(new LinkedList<>());
List<ZenodoContributor> contributors = dmp.getUsers().stream().map(userDMP -> {
ZenodoContributor contributor = new ZenodoContributor();
contributor.setName(userDMP.getUser().getName());
contributor.setType("ProjectMember");
if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) {
contributor.setAffiliation(dmp.getOrganisations()
.stream().map(Organisation::getLabel).collect(Collectors.joining(", ")));
} else {
contributor.setAffiliation(environment.getProperty("zenodo.affiliation"));
}
return contributor;
}).collect(Collectors.toList());
List<ZenodoContributor> researchers = dmp.getResearchers().stream().map(researcher -> {
ZenodoContributor contributor = new ZenodoContributor();
contributor.setName(researcher.getLabel());
contributor.setType("Researcher");
String referenceHead = researcher.getReference().split(":")[0];
String referenceTail = researcher.getReference().replace(referenceHead + ":", "");
contributor.setAffiliation(referenceHead);
if (referenceHead.equalsIgnoreCase("ORCID")) {
contributor.setOrcid(referenceTail);
}
return contributor;
}).collect(Collectors.toList());
deposit.getMetadata().getContributors().addAll(contributors);
deposit.getMetadata().getContributors().addAll(researchers);
if (dmp.getGrant().getReference() == null) {
dmp.getGrant().setReference("dmp:" + dmp.getGrant().getId());
}
String grantReferenceHead = dmp.getGrant().getReference().split(":")[0];
if (grantReferenceHead.equals("openaire")) {
String grantReferenceTail = dmp.getGrant().getReference().split(":")[3];
DOIFunder doiFunder = configLoader.getDOIFunders().stream()
.filter(doiFunder1 -> dmp.getGrant().getFunder().getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(dmp.getGrant().getFunder().getLabel()))
.findFirst().orElse(null);
if (doiFunder != null) {
String finalId = doiFunder.getDOI() + "::" + grantReferenceTail;
ZenodoGrant grant = new ZenodoGrant();
grant.setId(finalId);
deposit.getMetadata().setGrants(Collections.singletonList(grant));
}
}
ZenodoContributor creator = new ZenodoContributor();
creator.setName(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName());
if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) {
creator.setAffiliation(dmp.getOrganisations()
.stream().map(Organisation::getLabel).collect(Collectors.joining(", ")));
} else {
creator.setAffiliation(environment.getProperty("zenodo.affiliation"));
}
deposit.getMetadata().setCreators(Collections.singletonList(creator));
return deposit;
}
}

View File

@ -47,8 +47,12 @@ public class DmpRDAMapper {
}
}
Dmp rda = new Dmp();
if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) {
rda.setDmpId(DmpIdRDAMapper.toRDA(dmp.getDoi()));
if (dmp.getDois() != null && !dmp.getDois().isEmpty()) {
for(EntityDoi doi: dmp.getDois()){
if(doi.getRepositoryId().equals("Zenodo")){
rda.setDmpId(DmpIdRDAMapper.toRDA(doi.getDoi()));
}
}
} else {
rda.setDmpId(DmpIdRDAMapper.toRDA(dmp.getId()));
}
@ -105,7 +109,10 @@ public class DmpRDAMapper {
DMP entity = new DMP();
entity.setLabel(rda.getTitle());
if (rda.getDmpId().getType() == DmpId.Type.DOI) {
entity.setDoi(rda.getDmpId().getIdentifier());
EntityDoi doi = apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().findFromDoi(rda.getDmpId().getIdentifier());
Set<EntityDoi> dois = new HashSet<>();
dois.add(doi);
entity.setDois(dois);
}
if (((List<String>) rda.getAdditionalProperties().get("templates")) != null && !((List<String>) rda.getAdditionalProperties().get("templates")).isEmpty()) {
entity.setAssociatedDmps(((List<String>) rda.getAdditionalProperties().get("templates")).stream().map(this::getProfile).filter(Objects::nonNull).collect(Collectors.toSet()));

View File

@ -0,0 +1,61 @@
package eu.eudat.publicapi.models.doi;
import eu.eudat.data.entities.EntityDoi;
import eu.eudat.logic.utilities.helpers.LabelGenerator;
import eu.eudat.models.DataModel;
import java.util.UUID;
public class DoiPublicModel implements DataModel<EntityDoi, DoiPublicModel>, LabelGenerator {
private UUID id;
private String repositoryId;
private String doi;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
public String getDoi() {
return doi;
}
public void setDoi(String doi) {
this.doi = doi;
}
@Override
public DoiPublicModel fromDataModel(EntityDoi entity) {
this.id = entity.getId();
this.repositoryId = entity.getRepositoryId();
this.doi = entity.getDoi();
return this;
}
@Override
public EntityDoi toDataModel() throws Exception {
EntityDoi entity = new EntityDoi();
entity.setId(this.getId());
entity.setRepositoryId(this.getRepositoryId());
entity.setDoi(this.getDoi());
return entity;
}
@Override
public String generateLabel() {
return this.getDoi();
}
@Override
public String getHint() {
return null;
}
}

View File

@ -7,6 +7,7 @@ import eu.eudat.logic.utilities.builders.XmlBuilder;
import eu.eudat.models.DataModel;
import eu.eudat.models.data.user.composite.PagedDatasetProfile;
import eu.eudat.publicapi.models.associatedprofile.AssociatedProfilePublicModel;
import eu.eudat.publicapi.models.doi.DoiPublicModel;
import eu.eudat.publicapi.models.grant.GrantPublicOverviewModel;
import eu.eudat.publicapi.models.organisation.OrganizationPublicModel;
import eu.eudat.publicapi.models.researcher.ResearcherPublicModel;
@ -35,7 +36,7 @@ public class DataManagementPlanPublicModel implements DataModel<DMP, DataManagem
private List<UserInfoPublicModel> users;
private String description;
private Date publishedAt;
private String doi;
private List<DoiPublicModel> dois;
public String getId() {
@ -150,11 +151,11 @@ public class DataManagementPlanPublicModel implements DataModel<DMP, DataManagem
this.publishedAt = publishedAt;
}
public String getDoi() {
return doi;
public List<DoiPublicModel> getDois() {
return dois;
}
public void setDoi(String doi) {
this.doi = doi;
public void setDois(List<DoiPublicModel> dois) {
this.dois = dois;
}
@Override
@ -198,7 +199,7 @@ public class DataManagementPlanPublicModel implements DataModel<DMP, DataManagem
}
}
this.publishedAt = entity.getPublishedAt();
this.doi = entity.getDoi();
this.dois = entity.getDois().stream().map(item -> new DoiPublicModel().fromDataModel(item)).collect(Collectors.toList());
return this;
}

View File

@ -926,6 +926,27 @@ CREATE TABLE public."FileUpload"
ALTER TABLE public."FileUpload" OWNER TO :POSTGRES_USER;
--
-- Name: EntityDoi; Type: TABLE; Schema: public; Owner: :POSTGRES_USER
--
CREATE TYPE DoiEntityType AS ENUM ('DMP');
CREATE TABLE public."EntityDoi"
(
"ID" uuid NOT NULL,
"EntityType" DoiEntityType NOT NULL,
"RepositoryId" character varying(150) NOT NULL,
"Doi" character varying(50) NOt NULL,
"CreatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL,
"UpdatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL,
"EntityId" uuid NOT NULL,
CONSTRAINT "Doi_pkey" PRIMARY KEY ("ID"),
CONSTRAINT fk_doi_entityId FOREIGN KEY ("EntityId") REFERENCES public."DMP"("ID")
);
ALTER TABLE public."EntityDoi" OWNER TO :POSTGRES_USER;
--
-- Name: Content Content_pkey; Type: CONSTRAINT; Schema: public; Owner: :POSTGRES_USER
--

View File

@ -0,0 +1,26 @@
DO $$DECLARE
this_version CONSTANT varchar := '00.00.010';
BEGIN
PERFORM * FROM "DBVersion" WHERE version = this_version;
IF FOUND THEN RETURN; END IF;
CREATE TYPE DoiEntityType AS ENUM ('DMP');
CREATE TABLE public."EntityDoi"
(
"ID" uuid NOT NULL,
"EntityType" DoiEntityType NOT NULL,
"RepositoryId" character varying(150) NOT NULL,
"Doi" character varying(50) NOt NULL,
"CreatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL,
"UpdatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL,
"EntityId" uuid NOT NULL,
CONSTRAINT "Doi_pkey" PRIMARY KEY ("ID"),
CONSTRAINT fk_doi_entityId FOREIGN KEY ("EntityId") REFERENCES public."DMP"("ID")
);
/*ALTER TABLE public."EntityDoi" OWNER TO :POSTGRES_USER;*/
INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.010', '2022-10-27 10:50:00.000000+02', now(), 'Add Doi Table for depositions');
END$$;

View File

@ -0,0 +1,14 @@
DO $$DECLARE
this_version CONSTANT varchar := '00.00.011';
BEGIN
PERFORM * FROM "DBVersion" WHERE version = this_version;
IF FOUND THEN RETURN; END IF;
INSERT INTO public."EntityDoi" ("ID", "EntityType", "RepositoryId", "Doi", "CreatedAt", "UpdatedAt", "EntityId")
SELECT uuid_generate_v4(), 'DMP', 'Zenodo', public."DMP"."DOI", now(), now(), public."DMP"."ID"
FROM public."DMP"
WHERE public."DMP"."DOI" IS NOT NULL;
INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.011', '2022-10-27 10:50:00.000000+02', now(), 'Migrate DMP.DOI to EntityDoi table');
END$$;

View File

@ -0,0 +1,11 @@
DO $$DECLARE
this_version CONSTANT varchar := '00.00.012';
BEGIN
PERFORM * FROM "DBVersion" WHERE version = this_version;
IF FOUND THEN RETURN; END IF;
ALTER TABLE public."DMP" DROP COLUMN "DOI";
INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.012', '2022-10-27 10:50:00.000000+02', now(), 'Delete doi column from dmp table');
END$$;

View File

@ -0,0 +1,5 @@
export enum DepositConfigurationStatus {
System = 0,
User = 1,
BothSystemAndUser = 2
}

View File

@ -46,6 +46,7 @@ import { CollectionUtils } from './services/utilities/collection-utils.service';
import { TypeUtils } from './services/utilities/type-utils.service';
import { SpecialAuthGuard } from './special-auth-guard.service';
import {PrefillingService} from "@app/core/services/prefilling.service";
import { DepositRepositoriesService } from './services/deposit-repositories/deposit-repositories.service';
//
//
// This is shared module that provides all the services. Its imported only once on the AppModule.
@ -89,6 +90,7 @@ export class CoreServiceModule {
FunderService,
GrantFileUploadService,
DmpService,
DepositRepositoriesService,
DmpProfileService,
ExternalSourcesService,
ExternalSourcesConfigurationService,

View File

@ -7,6 +7,8 @@ import { TimezoneInfoDisplayPipe } from './pipes/timezone-info-display.pipe';
import { EnumUtils } from './services/utilities/enum-utils.service';
import { JsonParserPipe } from './pipes/json-parser.pipe';
import { DateTimeCultureFormatPipe } from './pipes/date-time-culture-format.pipe';
import {FieldValuePipe} from "@app/core/pipes/field-value.pipe";
import {ColumnClassPipe} from "@app/core/pipes/column-class.pipe";
//
//
@ -21,7 +23,9 @@ import { DateTimeCultureFormatPipe } from './pipes/date-time-culture-format.pipe
DateFormatPipe,
DateTimeFormatPipe,
DateTimeCultureFormatPipe,
JsonParserPipe
JsonParserPipe,
FieldValuePipe,
ColumnClassPipe
],
exports: [
NgForLimitPipe,
@ -29,7 +33,9 @@ import { DateTimeCultureFormatPipe } from './pipes/date-time-culture-format.pipe
DateFormatPipe,
DateTimeFormatPipe,
DateTimeCultureFormatPipe,
JsonParserPipe
JsonParserPipe,
FieldValuePipe,
ColumnClassPipe
],
providers: [
EnumUtils,
@ -39,7 +45,9 @@ import { DateTimeCultureFormatPipe } from './pipes/date-time-culture-format.pipe
DateFormatPipe,
DateTimeFormatPipe,
DateTimeCultureFormatPipe,
JsonParserPipe
JsonParserPipe,
FieldValuePipe,
ColumnClassPipe
]
})
export class FormattingModule { }

View File

@ -45,6 +45,7 @@ export interface Multiplicity {
min: number;
max: number;
placeholder: string;
tableView: boolean;
}
export interface Field {

View File

@ -4,5 +4,6 @@ export interface Multiplicity {
min: number;
max: number;
placeholder: string;
tableView: boolean;
}

View File

@ -0,0 +1,11 @@
import { DepositConfigurationStatus } from "@app/core/common/enum/deposit-configuration-status";
export class DepositConfigurationModel {
depositType: DepositConfigurationStatus;
repositoryId: string;
repositoryAuthorizationUrl: string;
repositoryRecordUrl: string;
repositoryClientId: string;
redirectUri: string;
hasLogo: boolean;
}

View File

@ -0,0 +1,10 @@
export class DepositRequest {
repositoryId: string;
dmpId: string;
accessToken: string;
}
export class DepositCode {
repositoryId: string;
code: string;
}

View File

@ -4,6 +4,7 @@ import { DmpAssociatedProfileModel } from "../dmp-profile/dmp-associated-profile
import { ResearcherModel } from "../researcher/researcher";
import { GrantOverviewModel } from "../grant/grant-overview";
import { DatasetOverviewModel } from "../dataset/dataset-overview";
import { DoiModel } from "../doi/doi";
export interface DmpOverviewModel {
id: string;
@ -26,4 +27,5 @@ export interface DmpOverviewModel {
finalizedAt: Date;
publishedAt: Date;
doi: string;
dois: DoiModel[];
}

View File

@ -0,0 +1,7 @@
export interface DoiModel {
id: string;
repositoryId: string;
doi: string;
createdAt: Date;
updatedAt: Date;
}

View File

@ -0,0 +1,11 @@
import {Pipe, PipeTransform} from "@angular/core";
@Pipe({
name: 'columnClass'
})
export class ColumnClassPipe implements PipeTransform{
transform(value: number): any {
return 'col-' + Math.ceil(12/value);
}
}

View File

@ -0,0 +1,85 @@
import {Pipe, PipeTransform} from "@angular/core";
import {DatePipe} from "@angular/common";
import {DatasetProfileFieldViewStyle} from "@app/core/common/enum/dataset-profile-field-view-style";
@Pipe({
name: 'fieldValue'
})
export class FieldValuePipe implements PipeTransform {
constructor(private date: DatePipe) {
}
transform(controlValue: any): string | null {
let value = controlValue.value;
let renderStyle = controlValue.viewStyle?.renderStyle;
if (renderStyle && value) {
switch (renderStyle) {
case DatasetProfileFieldViewStyle.Currency:
if (value) {
return JSON.parse(value).name;
}
break;
case DatasetProfileFieldViewStyle.BooleanDecision:
return value == 'true' ? 'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.BOOLEAN-DECISION.YES' : 'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.BOOLEAN-DECISION.NO';
case DatasetProfileFieldViewStyle.CheckBox:
return value ? 'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.BOOLEAN-DECISION.YES' : 'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.BOOLEAN-DECISION.NO';
case DatasetProfileFieldViewStyle.RadioBox:
if (value && controlValue.data.options) {
return controlValue.data.options.find(option => option.value === value).label;
}
break;
case DatasetProfileFieldViewStyle.DatePicker:
return this.date.transform(controlValue.value, 'dd/MM/yyyy');
case DatasetProfileFieldViewStyle.FreeText:
return value;
case DatasetProfileFieldViewStyle.ComboBox:
if (value && controlValue.data.options && !controlValue.data.multiList) {
return controlValue.data.options.find(option => value == option.value).label;
} else if (value && controlValue.data.options && controlValue.data.multiList) {
return controlValue.data.options.filter(option => value.includes(option.value)).map(option => option.label).join(',');
}
break;
case DatasetProfileFieldViewStyle.RichTextArea:
if(value) {
return value.replace(/&nbsp;/g, ' ').replace(/(\r\n|\n|\r| +(?= ))|\s\s+/gm, " ").replace(/<[^>]*>/g, '');
}
break;
case DatasetProfileFieldViewStyle.TextArea:
return value;
case DatasetProfileFieldViewStyle.Registries:
case DatasetProfileFieldViewStyle.Services:
case DatasetProfileFieldViewStyle.Researchers:
case DatasetProfileFieldViewStyle.Organizations:
case DatasetProfileFieldViewStyle.ExternalDatasets:
case DatasetProfileFieldViewStyle.DataRepositories:
case DatasetProfileFieldViewStyle.PubRepositories:
case DatasetProfileFieldViewStyle.JournalRepositories:
case DatasetProfileFieldViewStyle.Taxonomies:
case DatasetProfileFieldViewStyle.Licenses:
case DatasetProfileFieldViewStyle.Publications:
case DatasetProfileFieldViewStyle.Tags:
return this.parseJson(value);
case DatasetProfileFieldViewStyle.InternalDmpEntities:
return this.parseJson(value, 'label');
case DatasetProfileFieldViewStyle.DatasetIdentifier:
case DatasetProfileFieldViewStyle.Validation:
if(value && value.identifier) {
return value.identifier;
}
break;
default:
return null;
}
}
return null;
}
public parseJson(value: any, field: string = 'name') {
if(Array.isArray(value)) {
return value.map(element => JSON.parse(element)[field]).join(',');
} else {
return JSON.parse(value)[field];
}
}
}

View File

@ -66,11 +66,6 @@ export class ConfigurationService extends BaseComponent {
return this._allowOrganizationCreator;
}
private _doiLink: string;
get doiLink(): string {
return this._doiLink;
}
private _useSplash: string;
get useSplash(): string {
return this._useSplash;
@ -137,7 +132,6 @@ export class ConfigurationService extends BaseComponent {
this._lockInterval = config.lockInterval;
this._guideAssets = config.guideAssets;
this._allowOrganizationCreator = config.allowOrganizationCreator;
this._doiLink = config.doiLink;
this._useSplash = config.useSplash;
this._orcidPath = config.orcidPath;
if (config.matomo) {

View File

@ -0,0 +1,43 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration';
import { DepositCode, DepositRequest } from '@app/core/model/deposit/deposit-request';
import { DoiModel } from '@app/core/model/doi/doi';
import { Observable } from 'rxjs';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpService } from '../http/base-http.service';
@Injectable()
export class DepositRepositoriesService {
private actionUrl: string;
private headers = new HttpHeaders();
constructor(private http: BaseHttpService, private httpClient: HttpClient, private configurationService: ConfigurationService) {
this.actionUrl = configurationService.server + 'deposit/';
}
getAvailableRepos(): Observable<DepositConfigurationModel[]> {
return this.http.get<DepositConfigurationModel[]>(this.actionUrl + 'repos', { headers: this.headers });
}
getAccessToken(repositoryId: string, code: string): Observable<string> {
const depositCode = new DepositCode();
depositCode.repositoryId = repositoryId;
depositCode.code = code;
return this.http.post<string>(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers });
}
createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable<DoiModel> {
const depositRequest = new DepositRequest();
depositRequest.repositoryId = repositoryId;
depositRequest.dmpId = dmpId;
depositRequest.accessToken = accessToken;
return this.http.post<DoiModel>(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers });
}
getLogo(repositoryId: string): Observable<string> {
return this.http.get<string>(this.actionUrl + 'logo/' + repositoryId, { headers: this.headers });
}
}

View File

@ -36,4 +36,15 @@ export class MatomoService {
this.matomoTracker.trackSiteSearch(keyword, category, resultsCount);
}
}
trackDownload(category: "dmps"|"datasets", type: "docx"|"pdf"|"xml"|"json", id: string): void {
if (this.configurationService.matomoEnabled) {
var principal = this.authService.current();
if (principal != null) { this.matomoTracker.setUserId(principal.id); }
this.matomoTracker.trackLink(this.configurationService.server + category + "/" + type + "/" + id, "download");
// this.matomoTracker.trackLink(url, "download");
// this.matomoTracker.trackEvent(category, "Downloaded", type);
}
}
}

View File

@ -43,6 +43,9 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
}
private _configuration: MultipleAutoCompleteConfiguration;
@Input()
separatorKeysCodes = [];
// Selected Option Event
@Output() optionSelected: EventEmitter<any> = new EventEmitter();
@Output() optionRemoved: EventEmitter<any> = new EventEmitter();
@ -69,7 +72,6 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
_groupedItems: Observable<AutoCompleteGroup[]>;
selectable = false;
removable = true;
separatorKeysCodes = [ENTER, COMMA];
get empty() { return (!this.value || this.value.length === 0) && (!this.inputValue || this.inputValue.length === 0); }
@ -377,7 +379,7 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
//Chip Functions
_addItem(event: MatChipInputEvent): void {
console.log(this._items)
const input = event.input;
const value = event.value;
// Add our fruit

View File

@ -6,11 +6,13 @@ export class MultiplicityEditorModel extends BaseFormModel {
public min: number;
public max: number;
public placeholder: string;
public tableView: boolean;
fromModel(item: Multiplicity): MultiplicityEditorModel {
this.min = item.min;
this.max = item.max;
this.placeholder = item.placeholder;
this.tableView = item.tableView;
return this;
}
@ -21,7 +23,8 @@ export class MultiplicityEditorModel extends BaseFormModel {
placeholder: [{
value: this.placeholder,
disabled: (disabled && !skipDisable.includes('MultiplicityEditorModel.placeholder'))
}]
}],
tableView: [{value: this.tableView, disabled: (disabled && !skipDisable.includes('MultiplicityEditorModel.tableView'))}]
});
}
}

View File

@ -117,6 +117,12 @@
type="text" [formControl]="form.get('multiplicity').get('placeholder')">
</mat-form-field>
</div>
<div class="row">
<mat-checkbox *ngIf="isMultiplicityEnabled" appearance="legacy" class="col pl-0 underline-line-field fieldset-checkbox-action-dataset-profile-editor"
[formControl]="form.get('multiplicity').get('tableView')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.MULTIPLICITY-TABLEVIEW' | translate}}
</mat-checkbox>
</div>
</div>
@ -198,7 +204,7 @@
</div>
<div [id]="'preview_container'+ form.get('id').value" class="w-100" style="margin-right: -15px; margin-left: -15px;" >
<div *ngIf="previewForm && showPreview && firstField?.get('viewStyle').get('renderStyle').value" [@fade-in-fast]>
<app-form-section-inner [form]="previewForm">
<app-form-section-inner [form]="previewForm" [tableView]="form.getRawValue().multiplicity?.tableView">
</app-form-section-inner>
</div>
</div>

View File

@ -261,7 +261,8 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i
description: formValue.description,
hasCommentField: formValue.hasCommentField,
commentFieldValue: '',
multiplicity: {max: formValue.multiplicity.max, min: formValue.multiplicity.min, placeholder: formValue.multiplicity.placeholder},
multiplicity: {max: formValue.multiplicity.max, min: formValue.multiplicity.min,
placeholder: formValue.multiplicity.placeholder, tableView: formValue.multiplicity.tableView},
multiplicityItems:null,
fields: fields.map(editorField=>{
const model = new DatasetDescriptionFieldEditorModel().fromModel(editorField);

View File

@ -468,9 +468,20 @@
<ng-template #actions>
<div>
<button mat-raised-button class="template_action_btn mr-3" (click)="discardChanges()">{{'DATASET-WIZARD.ACTIONS.CLOSE' | translate}}</button>
<button *ngIf="!viewOnly && form.get('status').value!=1" mat-raised-button class="template_action_btn save-btn" (click)="onSubmit()" [disabled]="!form.valid">
{{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' |translate}}
<mat-icon (click)="$event.stopPropagation();" style="width: 14px;" [matMenuTriggerFor]="menuSave">expand_more</mat-icon>
<!-- <button *ngIf="!viewOnly && form.get('status').value!=1" mat-raised-button class="template_action_btn save-btn" (click)="onSubmit()" [disabled]="!form.valid">-->
<!-- {{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' |translate}}-->
<!-- <mat-icon (click)="$event.stopPropagation();" style="width: 14px;" [matMenuTriggerFor]="menuSave">expand_more</mat-icon>-->
<!-- </button>-->
<button *ngIf="!viewOnly && form.get('status').value!=1" [disabled]="!form.valid"
mat-raised-button class="template_action_btn save-btn" type="button">
<span class="d-flex flex-row row">
<span (click)="onSubmit()" class="col">{{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' |translate}}</span>
<mat-divider [vertical]="true"></mat-divider>
<span class="align-items-center justify-content-center col-4 d-flex"
(click)="$event.stopPropagation();" [matMenuTriggerFor]="menuSave">
<mat-icon >expand_more</mat-icon>
</span>
</span>
</button>
<mat-menu #menuSave="matMenu">
<button [disabled]="!form.valid" mat-menu-item (click)="onSubmit(true)" type="button">{{ 'DATASET-PROFILE-EDITOR.ACTIONS.SAVE-AND-CLOSE' | translate }}</button>

View File

@ -133,17 +133,19 @@ $blue-color-light: #5cf7f2;
border-radius: 30px;
border: 1px solid #129D99;
background: transparent;
padding-left: 2em;
padding-right: 2em;
//padding-left: 2em;
//padding-right: 2em;
height: 2.5em;
min-width: 110px;
width: auto;
box-shadow: 0px 3px 6px #1E202029;
color: #129D99;
flex: 0 0 auto;
&.save-btn{
background-color: #f7dd72;
border: 1px solid transparent;
padding-left: 2em;
padding-right: 2em;
//padding-left: 2em;
//padding-right: 2em;
box-shadow: 0px 3px 6px #1E202029;
color: #212121;

View File

@ -263,6 +263,7 @@ export class DraftsComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "pdf", dataset.id);
});
}
@ -274,6 +275,7 @@ export class DraftsComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "docx", dataset.id);
});
}
@ -286,6 +288,7 @@ export class DraftsComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "xml", dataset.id);
});
}

View File

@ -425,6 +425,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "xml", id);
});
}
@ -436,6 +437,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "docx", id);
});
}
@ -447,6 +449,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "pdf", id);
});
}
@ -457,6 +460,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const blob = new Blob([response.body], { type: 'application/json' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "json", id);
}, async error => {
this.onExportCallbackError(error);
});
@ -476,6 +480,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "pdf", dataset.id);
});
}
@ -487,6 +492,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "docx", dataset.id);
});
}
@ -499,6 +505,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "xml", dataset.id);
});
}

View File

@ -27,6 +27,7 @@ import { Location } from '@angular/common';
import { LockService } from '@app/core/services/lock/lock.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { HttpClient } from '@angular/common/http';
import {ConfigurationService} from "@app/core/services/configuration/configuration.service";
@Component({
selector: 'app-recent-edited-dataset-activity',
@ -61,7 +62,8 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen
private location: Location,
private lockService: LockService,
private httpClient: HttpClient,
private matomoService: MatomoService
private matomoService: MatomoService,
private configurationService: ConfigurationService
) {
super();
}
@ -304,6 +306,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "pdf", dataset.id);
});
}
@ -315,6 +318,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "docx", dataset.id);
});
}
@ -327,6 +331,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "xml", dataset.id);
});
}

View File

@ -369,6 +369,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "xml", id);
});
}
@ -380,6 +381,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "docx", id);
});
}
@ -391,6 +393,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "pdf", id);
});
}
@ -401,6 +404,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O
const blob = new Blob([response.body], { type: 'application/json' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "json", id);
}, async error => {
this.onExportCallbackError(error);
});

View File

@ -27,15 +27,52 @@
</div>
</div>
<div class="row">
<div class="col-auto d-flex align-items-center p-0" *ngIf="!viewOnly">
<button [disabled]="saving" *ngIf="isDirty()" type="button" mat-raised-button class="dataset-discard-btn" (click)="discardChanges()">
<div class="col-auto d-flex align-items-center">
<button *ngIf="formGroup.get('id').value" [disabled]="isDirty()" [matTooltipDisabled]="!isDirty()"
mat-raised-button class="dataset-export-btn" type="button"
[matMenuTriggerFor]="exportMenu" (click)="$event.stopPropagation();"
[matTooltip]="'DATASET-EDITOR.ACTIONS.DISABLED-EXPORT' | translate">
{{ 'DMP-LISTING.ACTIONS.EXPORT' | translate }}
<mat-icon [disabled]="isDirty()" style="width: 14px;">expand_more</mat-icon>
</button>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="downloadPDF(formGroup.get('id').value)">
<i class="fa fa-file-pdf-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.PDF' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadDOCX(formGroup.get('id').value)">
<i class="fa fa-file-word-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.DOC' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadXML(formGroup.get('id').value)">
<i class="fa fa-file-code-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.XML' | translate}}</span>
</button>
</mat-menu>
</div>
<mat-divider *ngIf="formGroup.get('id').value && (!viewOnly || (!lockStatus && !viewOnly) || lockStatus || (hasReversableStatus() && !lockStatus))"
[vertical]="true" class="ml-2 mr-2"></mat-divider>
<div *ngIf="isDirty() && !viewOnly" class="col-auto d-flex align-items-center pr-0">
<button [disabled]="saving" type="button" mat-raised-button class="dataset-discard-btn" (click)="discardChanges()">
{{'DMP-EDITOR.ACTIONS.DISCARD' | translate}}
</button>
</div>
<div class="col-auto d-flex align-items-center">
<button [disabled]="saving" *ngIf="!lockStatus && !viewOnly" mat-raised-button class="dataset-save-btn mr-2" type="button" (click)="save()">
{{ 'DATASET-WIZARD.ACTIONS.SAVE' | translate }}
<mat-icon [disabled]="saving" (click)="$event.stopPropagation();" style="width: 14px;" [matMenuTriggerFor]="menu">expand_more</mat-icon>
<button [disabled]="saving" *ngIf="!lockStatus && !viewOnly" mat-raised-button
class="dataset-save-btn mr-2" type="button">
<span class="d-flex flex-row row">
<span (click)="!saving?save():null" class="col">{{ 'DATASET-WIZARD.ACTIONS.SAVE' | translate }}</span>
<mat-divider [vertical]="true"></mat-divider>
<span *ngIf="!saving" class="align-items-center justify-content-center col-4 d-flex"
(click)="$event.stopPropagation();" [matMenuTriggerFor]="menu">
<mat-icon >expand_more</mat-icon>
</span>
<span *ngIf="saving" class="align-items-center justify-content-center col-4 d-flex">
<mat-icon >expand_more</mat-icon>
</span>
</span>
</button>
<mat-menu #menu="matMenu">
<button [disabled]="saving" mat-menu-item (click)="save(saveAnd.close)" type="button">{{ 'DATASET-WIZARD.ACTIONS.SAVE-AND-CLOSE' | translate }}</button>

View File

@ -208,7 +208,7 @@
align-items: center;
}
.dataset-save-btn {
.dataset-save-btn, .dataset-export-btn {
background: #ffffff 0% 0% no-repeat padding-box;
border-radius: 30px;
opacity: 1;

View File

@ -532,7 +532,6 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
if (profiledId && profiledId.length > 0) {
this.formGroup.removeControl('datasetProfileDefinition');
this.getDefinition(profiledId);
console.log(this.table0fContents.tocentries.length + 1);
}
}
@ -660,7 +659,7 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
// }
submit(saveType?: SaveType) {
submit(saveType?: SaveType, onSuccess: Function = null, onError: Function = null) {
this.scrollTop = document.getElementById('dataset-editor-form').scrollTop;
this.tocScrollTop = document.getElementById('stepper-options').scrollTop;
this.datasetWizardService.createDataset(this.formGroup.getRawValue())
@ -670,8 +669,16 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
this.hasChanges = false;
this.datasetIsOnceSaved = true;
this.onCallbackSuccess(data, saveType);
if(onSuccess) {
onSuccess();
}
},
error => this.onCallbackError(error));
error => {
if(onError) {
onError();
}
this.onCallbackError(error)
});
}
@ -841,16 +848,27 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
.pipe(
filter(x => x),
takeUntil(this._destroyed)
).subscribe(_ => {
this.viewOnly = false;
this.datasetWizardModel.status = DatasetStatus.Draft;
setTimeout(x => {
this.formGroup = null;
});
setTimeout(x => {
this.formGroup = this.datasetWizardModel.buildForm();
this.registerFormListeners();
});
).subscribe(result => {
if (result) {
// if (!this.isFormValid()) { return; }
this.formGroup.get('status').setValue(DatasetStatus.Draft);
this.submit(SaveType.finalize, () => {
this.viewOnly = false;
this.datasetWizardModel.status = DatasetStatus.Draft;
setTimeout(x => {
this.formGroup = null;
});
setTimeout(x => {
this.formGroup = this.datasetWizardModel.buildForm();
this.registerFormListeners();
});
}, () => {
this.formGroup.get('status').setValue(DatasetStatus.Finalized);
this.viewOnly = true;
});
} else {
this.saving = false;
}
});
@ -886,7 +904,11 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
if (result) {
// if (!this.isFormValid()) { return; }
this.formGroup.get('status').setValue(DatasetStatus.Finalized);
this.submit(SaveType.finalize);
this.submit(SaveType.finalize, null, () => {
this.formGroup.get('status').setValue(DatasetStatus.Draft);
});
} else {
this.saving = false;
}
});
}
@ -958,37 +980,40 @@ export class DatasetWizardComponent extends CheckDeactivateBaseComponent impleme
});
}
downloadPDF(): void {
this.datasetWizardService.downloadPDF(this.downloadDocumentId)
downloadPDF(id: string): void {
this.datasetWizardService.downloadPDF(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], {type: 'application/pdf'});
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "pdf", id);
});
}
downloadDOCX(): void {
this.datasetWizardService.downloadDOCX(this.downloadDocumentId)
downloadDOCX(id: string): void {
this.datasetWizardService.downloadDOCX(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], {type: 'application/msword'});
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "docx", id);
});
}
downloadXML(): void {
this.datasetWizardService.downloadXML(this.downloadDocumentId)
downloadXML(id: string): void {
this.datasetWizardService.downloadXML(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], {type: 'application/xml'});
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "xml", id);
});
}

View File

@ -99,6 +99,7 @@ export class DatasetListingItemComponent extends BaseComponent implements OnInit
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "pdf", dataset.id);
});
}
@ -110,6 +111,7 @@ export class DatasetListingItemComponent extends BaseComponent implements OnInit
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "docx", dataset.id);
});
}
@ -122,6 +124,7 @@ export class DatasetListingItemComponent extends BaseComponent implements OnInit
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "xml", dataset.id);
});
}

View File

@ -340,6 +340,7 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "pdf", id);
});
}
@ -351,6 +352,7 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "docx", id);
});
}
@ -362,6 +364,7 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('datasets', "xml", id);
});
}

View File

@ -1,54 +1,61 @@
import { NgModule } from '@angular/core';
import { FormattingModule } from '@app/core/formatting.module';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module';
import { ExportMethodDialogModule } from '@app/library/export-method-dialog/export-method-dialog.module';
import { UrlListingModule } from '@app/library/url-listing/url-listing.module';
import { DmpCloneComponent } from '@app/ui/dmp/clone/dmp-clone.component';
import { DmpRoutingModule } from '@app/ui/dmp/dmp.routing';
import { AddResearcherComponent } from '@app/ui/dmp/editor/add-researcher/add-researcher.component';
import { AvailableProfilesComponent } from '@app/ui/dmp/editor/available-profiles/available-profiles.component';
import { DatasetsTabComponent } from '@app/ui/dmp/editor/datasets-tab/datasets-tab.component';
import { DmpEditorComponent } from '@app/ui/dmp/editor/dmp-editor.component';
import { DmpFinalizeDialogComponent } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { DynamicDmpFieldResolverComponent } from '@app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component';
import { DynamicFieldGrantComponent } from '@app/ui/dmp/editor/dynamic-fields-grant/dynamic-field-grant/dynamic-field-grant.component';
import { DynamicFieldsGrantComponent } from '@app/ui/dmp/editor/dynamic-fields-grant/dynamic-fields-grant.component';
import { GeneralTabComponent } from '@app/ui/dmp/editor/general-tab/general-tab.component';
import { GrantTabComponent } from '@app/ui/dmp/editor/grant-tab/grant-tab.component';
import { PeopleTabComponent } from '@app/ui/dmp/editor/people-tab/people-tab.component';
import { InvitationAcceptedComponent } from '@app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component';
import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation-dialog.component';
import { DmpCriteriaComponent } from '@app/ui/dmp/listing/criteria/dmp-criteria.component';
import { DmpUploadDialogue } from '@app/ui/dmp/listing/upload-dialogue/dmp-upload-dialogue.component';
import { DmpListingComponent } from '@app/ui/dmp/listing/dmp-listing.component';
import { DmpListingItemComponent } from '@app/ui/dmp/listing/listing-item/dmp-listing-item.component';
import { DmpOverviewModule } from '@app/ui/dmp/overview/dmp-overview.module';
import { DmpWizardComponent } from '@app/ui/dmp/wizard/dmp-wizard.component';
import { DmpWizardEditorComponent } from '@app/ui/dmp/wizard/editor/dmp-wizard-editor.component';
import { DmpWizardDatasetListingComponent } from '@app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component';
import { CommonFormsModule } from '@common/forms/common-forms.module';
import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module';
import { CommonUiModule } from '@common/ui/common-ui.module';
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
import { AddOrganizationComponent } from './editor/add-organization/add-organization.component';
import { AddCostComponent } from './editor/cost-editor/add-cost/add-cost.component';
import { CostListingComponent } from './editor/cost-editor/cost-listing/cost-listing.component';
import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dialog.component';
import { StartNewDmpDialogComponent } from './start-new-dmp-dialogue/start-new-dmp-dialog.component';
import { MainInfoComponent } from './editor/main-info/main-info.component';
import { FundingInfoComponent } from './editor/funding-info/funding-info.component';
import { DatasetInfoComponent } from './editor/dataset-info/dataset-info.component';
import { DatasetEditorDetailsModule } from './editor/dataset-editor-details/dataset-editor-details.module';
import { DatasetEditorDetailsComponent } from './editor/dataset-editor-details/dataset-editor-details.component';
import { DatasetDescriptionFormModule } from '../misc/dataset-description-form/dataset-description-form.module';
import { LicenseInfoComponent } from './editor/license-info/license-info.component';
import { StartNewDatasetDialogComponent } from './start-new-dataset-dialogue/start-new-dataset-dialog.component';
import { NgxDropzoneModule } from 'ngx-dropzone';
import { DmpToDatasetDialogComponent } from './dmp-to-dataset/dmp-to-dataset-dialog.component';
import { FormProgressIndicationComponent } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component';
import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module';
import { DatasetPreviewDialogComponent } from './dataset-preview/dataset-preview-dialog.component';
import {NgModule} from '@angular/core';
import {FormattingModule} from '@app/core/formatting.module';
import {AutoCompleteModule} from '@app/library/auto-complete/auto-complete.module';
import {ConfirmationDialogModule} from '@common/modules/confirmation-dialog/confirmation-dialog.module';
import {ExportMethodDialogModule} from '@app/library/export-method-dialog/export-method-dialog.module';
import {UrlListingModule} from '@app/library/url-listing/url-listing.module';
import {DmpCloneComponent} from '@app/ui/dmp/clone/dmp-clone.component';
import {DmpRoutingModule} from '@app/ui/dmp/dmp.routing';
import {AddResearcherComponent} from '@app/ui/dmp/editor/add-researcher/add-researcher.component';
import {AvailableProfilesComponent} from '@app/ui/dmp/editor/available-profiles/available-profiles.component';
import {DatasetsTabComponent} from '@app/ui/dmp/editor/datasets-tab/datasets-tab.component';
import {DmpEditorComponent} from '@app/ui/dmp/editor/dmp-editor.component';
import {DmpFinalizeDialogComponent} from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import {
DynamicDmpFieldResolverComponent
} from '@app/ui/dmp/editor/dynamic-field-resolver/dynamic-dmp-field-resolver.component';
import {
DynamicFieldGrantComponent
} from '@app/ui/dmp/editor/dynamic-fields-grant/dynamic-field-grant/dynamic-field-grant.component';
import {DynamicFieldsGrantComponent} from '@app/ui/dmp/editor/dynamic-fields-grant/dynamic-fields-grant.component';
import {GeneralTabComponent} from '@app/ui/dmp/editor/general-tab/general-tab.component';
import {GrantTabComponent} from '@app/ui/dmp/editor/grant-tab/grant-tab.component';
import {PeopleTabComponent} from '@app/ui/dmp/editor/people-tab/people-tab.component';
import {InvitationAcceptedComponent} from '@app/ui/dmp/invitation/accepted/dmp-invitation-accepted.component';
import {DmpInvitationDialogComponent} from '@app/ui/dmp/invitation/dmp-invitation-dialog.component';
import {DmpCriteriaComponent} from '@app/ui/dmp/listing/criteria/dmp-criteria.component';
import {DmpUploadDialogue} from '@app/ui/dmp/listing/upload-dialogue/dmp-upload-dialogue.component';
import {DmpListingComponent} from '@app/ui/dmp/listing/dmp-listing.component';
import {DmpListingItemComponent} from '@app/ui/dmp/listing/listing-item/dmp-listing-item.component';
import {DmpOverviewModule} from '@app/ui/dmp/overview/dmp-overview.module';
import {DmpWizardComponent} from '@app/ui/dmp/wizard/dmp-wizard.component';
import {DmpWizardEditorComponent} from '@app/ui/dmp/wizard/editor/dmp-wizard-editor.component';
import {DmpWizardDatasetListingComponent} from '@app/ui/dmp/wizard/listing/dmp-wizard-dataset-listing.component';
import {CommonFormsModule} from '@common/forms/common-forms.module';
import {
FormValidationErrorsDialogModule
} from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module';
import {CommonUiModule} from '@common/ui/common-ui.module';
import {MultipleChoiceDialogModule} from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
import {AddOrganizationComponent} from './editor/add-organization/add-organization.component';
import {AddCostComponent} from './editor/cost-editor/add-cost/add-cost.component';
import {CostListingComponent} from './editor/cost-editor/cost-listing/cost-listing.component';
import {DmpCriteriaDialogComponent} from './listing/criteria/dmp-criteria-dialog.component';
import {StartNewDmpDialogComponent} from './start-new-dmp-dialogue/start-new-dmp-dialog.component';
import {MainInfoComponent} from './editor/main-info/main-info.component';
import {FundingInfoComponent} from './editor/funding-info/funding-info.component';
import {DatasetInfoComponent} from './editor/dataset-info/dataset-info.component';
import {DatasetEditorDetailsModule} from './editor/dataset-editor-details/dataset-editor-details.module';
import {DatasetEditorDetailsComponent} from './editor/dataset-editor-details/dataset-editor-details.component';
import {DatasetDescriptionFormModule} from '../misc/dataset-description-form/dataset-description-form.module';
import {LicenseInfoComponent} from './editor/license-info/license-info.component';
import {StartNewDatasetDialogComponent} from './start-new-dataset-dialogue/start-new-dataset-dialog.component';
import {NgxDropzoneModule} from 'ngx-dropzone';
import {DmpToDatasetDialogComponent} from './dmp-to-dataset/dmp-to-dataset-dialog.component';
import {
FormProgressIndicationModule
} from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module';
import {DatasetPreviewDialogComponent} from './dataset-preview/dataset-preview-dialog.component';
import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-editor.module";
@NgModule({

View File

@ -0,0 +1,13 @@
<div [matMenuTriggerFor]="depositMenu" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">archive</mat-icon>
</button>
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.DEPOSIT' | translate }}</p>
</div>
<mat-menu #depositMenu="matMenu">
<button mat-menu-item *ngFor="let repo of inputRepos" (click)="deposit(repo)">
<img *ngIf="repo.hasLogo" class="logo" [src]="logos.get(repo.repositoryId)">
<img *ngIf="!repo.hasLogo" class="logo" src="assets/images/repository-placeholder.png">
<span>{{ repo.repositoryId }}</span>
</button>
</mat-menu>

View File

@ -0,0 +1,36 @@
.frame-btn {
border: 1px solid #212121;
color: black;
background: #ffffff;
box-shadow: 0px 2px 6px #00000029;
display: flex;
justify-content: center;
align-items: center;
}
.frame-txt {
color: #000000;
font-size: 0.75em;
font-weight: bold;
letter-spacing: 0px;
text-transform: uppercase;
cursor: pointer;
}
.mat-mini-fab {
width: 2.5em;
height: 2.5em;
}
.mat-mini-fab-icon {
font-size: 1.2em;
display: flex;
justify-content: center;
align-items: center;
}
.logo {
margin-right: 16px;
max-width: 24px;
max-height: 24px;
}

View File

@ -0,0 +1,139 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {DepositConfigurationStatus} from '@app/core/common/enum/deposit-configuration-status';
import {DepositConfigurationModel} from '@app/core/model/deposit/deposit-configuration';
import {DmpOverviewModel} from '@app/core/model/dmp/dmp-overview';
import {DoiModel} from '@app/core/model/doi/doi';
import {DepositRepositoriesService} from '@app/core/services/deposit-repositories/deposit-repositories.service';
import {
SnackBarNotificationLevel,
UiNotificationService
} from '@app/core/services/notification/ui-notification-service';
import {Oauth2DialogService} from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service';
import {BaseComponent} from '@common/base/base.component';
import {MultipleChoiceDialogComponent} from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component';
import {TranslateService} from '@ngx-translate/core';
import {takeUntil} from 'rxjs/operators';
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";
@Component({
selector: 'app-dmp-deposit-dropdown',
templateUrl: './dmp-deposit-dropdown.component.html',
styleUrls: ['./dmp-deposit-dropdown.component.scss']
})
export class DmpDepositDropdown extends BaseComponent implements OnInit {
@Input()
inputRepos: DepositConfigurationModel[];
@Input()
dmp: DmpOverviewModel;
outputRepos = [];
logos: Map<string, SafeResourceUrl> = new Map<string, SafeResourceUrl>();
@Output()
outputReposEmitter: EventEmitter<DoiModel[]> = new EventEmitter<DoiModel[]>();
private oauthLock: boolean;
constructor(
private depositRepositoriesService: DepositRepositoriesService,
private dialog: MatDialog,
private language: TranslateService,
private translate: TranslateService,
private uiNotificationService: UiNotificationService,
private oauth2DialogService: Oauth2DialogService,
private sanitizer: DomSanitizer
) {
super();
}
hasDoi(repo, dois, i) {
return repo.repositoryId !== dois[i].repositoryId;
}
ngOnInit(): void {
for (var i = 0; i < this.dmp.dois.length; i++) {
this.inputRepos = this.inputRepos.filter(r => this.hasDoi(r, this.dmp.dois, i));
}
this.inputRepos.forEach(repo => {
if(repo.hasLogo) {
this.depositRepositoriesService.getLogo(repo.repositoryId).subscribe(logo => {
this.logos.set(repo.repositoryId, this.sanitizer.bypassSecurityTrustResourceUrl('data:image/png;base64, ' + logo));
})
}
})
}
deposit(repo: DepositConfigurationModel) {
if (repo.depositType == DepositConfigurationStatus.BothSystemAndUser) {
const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, {
maxWidth: '600px',
restoreFocus: false,
data: {
message: this.language.instant('DMP-OVERVIEW.DEPOSIT.ACCOUNT-LOGIN'),
titles: [this.language.instant('DMP-OVERVIEW.DEPOSIT.LOGIN', {'repository': repo.repositoryId}), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')]
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
switch (result) {
case 0:
this.showOauth2Dialog(repo.repositoryAuthorizationUrl + '?client_id=' + repo.repositoryClientId
+ '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri='
+ repo.redirectUri, repo, this.dmp);
break;
case 1:
this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null)
.pipe(takeUntil(this._destroyed))
.subscribe(doi => {
this.onDOICallbackSuccess();
this.outputRepos.push(doi);
this.outputReposEmitter.emit(this.outputRepos);
}, error => this.onDOICallbackError(error));
break;
}
});
} else if (repo.depositType == DepositConfigurationStatus.System) {
this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null)
.pipe(takeUntil(this._destroyed))
.subscribe(doi => {
this.onDOICallbackSuccess();
this.outputRepos.push(doi);
this.outputReposEmitter.emit(this.outputRepos);
}, error => this.onDOICallbackError(error));
}
}
onDOICallbackSuccess(): void {
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success);
}
onDOICallbackError(error) {
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error);
}
showOauth2Dialog(url: string, repo: DepositConfigurationModel, dmp: DmpOverviewModel) {
this.oauth2DialogService.login(url)
.pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (result !== undefined) {
if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) {
this.depositRepositoriesService.getAccessToken(repo.repositoryId, result.oauthCode)
.pipe(takeUntil(this._destroyed))
.subscribe(token => {
this.depositRepositoriesService.createDoi(repo.repositoryId, dmp.id, token)
.pipe(takeUntil(this._destroyed))
.subscribe(doi => {
this.onDOICallbackSuccess();
this.outputRepos.push(doi);
this.outputReposEmitter.emit(this.outputRepos);
}, error => this.onDOICallbackError(error));
});
this.oauthLock = true;
}
} else {
this.oauthLock = false;
}
});
}
}

View File

@ -11,6 +11,38 @@
<div class="subtitle">{{ formGroup.get('label').value }} <span *ngIf="isDirty()" class="changes">({{'DMP-EDITOR.CHANGES' | translate}})</span></div>
</div>
<div class="ml-auto d-flex flex-row">
<div class="col-auto d-flex align-items-center">
<button *ngIf="formGroup.get('id').value" [disabled]="isDirty()" [matTooltipDisabled]="!isDirty()"
mat-raised-button class="dmp-export-btn" type="button"
[matMenuTriggerFor]="exportMenu" (click)="$event.stopPropagation();"
[matTooltip]="'DMP-EDITOR.ACTIONS.DISABLED-EXPORT' | translate">
{{ 'DMP-LISTING.ACTIONS.EXPORT' | translate }}
<mat-icon [disabled]="isDirty()" style="width: 14px;">expand_more</mat-icon>
</button>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="downloadPDF(formGroup.get('id').value)">
<i class="fa fa-file-pdf-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.PDF' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadDocx(formGroup.get('id').value)">
<i class="fa fa-file-word-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.DOC' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadXml(formGroup.get('id').value)">
<i class="fa fa-file-code-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.XML' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadJson(formGroup.get('id').value)">
<i class="fa fa-file-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.JSON' | translate}}</span>
</button>
</mat-menu>
</div>
<mat-divider *ngIf="formGroup.get('id').value && (isDirty() || isNew || (!isNew && formGroup.enabled && !lockStatus) || lockStatus)"
[vertical]="true" class="ml-2 mr-2"></mat-divider>
<div class="col-auto d-flex align-items-center">
<button [disabled]="saving" *ngIf="isDirty()" type="button" mat-raised-button class="discard-btn mr-3" (click)="discardChanges()">
{{'DMP-EDITOR.ACTIONS.DISCARD' | translate}}
</button>
@ -23,6 +55,7 @@
</button>
</div>
<button *ngIf="lockStatus" mat-raised-button disabled class="dataset-save-btn cursor-default" type="button">{{ 'DMP-OVERVIEW.LOCKED' | translate}}</button>
</div>
</div>
</div>
</div>

View File

@ -157,8 +157,8 @@ a:hover {
align-items: center;
}
.save-btn {
background: #ffffff 0% 0% no-repeat padding-box;
.save-btn, .dmp-export-btn {
background: #ffffff 0% 0% no-repeat padding-box !important;
border-radius: 30px;
opacity: 1;
width: 110px;

View File

@ -699,6 +699,7 @@ export class DmpEditorComponent extends CheckDeactivateBaseComponent implements
const blob = new Blob([response.body], { type: 'application/xml' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "xml", id);
});
}
@ -709,6 +710,7 @@ export class DmpEditorComponent extends CheckDeactivateBaseComponent implements
const blob = new Blob([response.body], { type: 'application/msword' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "docx", id);
});
}
@ -719,6 +721,7 @@ export class DmpEditorComponent extends CheckDeactivateBaseComponent implements
const blob = new Blob([response.body], { type: 'application/pdf' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "pdf", id);
});
}
@ -729,6 +732,7 @@ export class DmpEditorComponent extends CheckDeactivateBaseComponent implements
const blob = new Blob([response.body], { type: 'application/json' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "json", id);
}, async error => {
this.onExportCallbackError(error);
});
@ -980,7 +984,8 @@ export class DmpEditorComponent extends CheckDeactivateBaseComponent implements
dmpDescription: this.formGroup.get('description').value,
datasets: this.formGroup.get('datasets').value.map(x => {
return { label: x.label, id: x.id, status: x.status };
})
}),
accessRights: false
}
const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, {

View File

@ -64,8 +64,11 @@
<div class="row pt-2 pb-2 pl-4 pr-4">
{{ 'DMP-FINALISE-DIALOG.IMPACT' | translate }}
</div>
<div class="row pl-4 pr-4">
{{ 'DMP-FINALISE-DIALOG.AFTER-FINALIZATION' | translate }}
<div *ngIf="inputModel.accessRights" class="row pl-4 pr-4">
{{ 'DMP-FINALISE-DIALOG.AFTER-FINALIZATION-PUBLISH' | translate }}
</div>
<div *ngIf="!inputModel.accessRights" class="row pl-4 pr-4">
{{ 'DMP-FINALISE-DIALOG.AFTER-FINALIZATION-RESTRICT-ACCESS' | translate }}
</div>
</div>

View File

@ -95,6 +95,7 @@ export interface DmpFinalizeDialogInput {
dmpLabel: string;
dmpDescription: string;
datasets: DmpFinalizeDialogDataset[];
accessRights: boolean;
}
export interface DmpFinalizeDialogDataset {

View File

@ -10,7 +10,7 @@
<mat-form-field class="col pt-0 pb-2 mb-4 search">
<!-- <mat-label>{{'INVITATION-EDITOR.AUTOCOMPLETE-USER-EMAIL' | translate}}</mat-label> -->
<app-multiple-auto-complete [formControl]="formGroup.get('users')" placeholder="{{'INVITATION-EDITOR.AUTOCOMPLETE-USER-EMAIL' | translate}}"
[configuration]="usersAutoCompleteConfiguration" [showNoResultsLabel]="false"
[configuration]="usersAutoCompleteConfiguration" [showNoResultsLabel]="false" [separatorKeysCodes]="separatorKeysCodes"
[minLength]="3">
</app-multiple-auto-complete>
</mat-form-field>

View File

@ -32,7 +32,6 @@ export class DmpInvitationDialogComponent extends BaseComponent implements OnIni
public filteredUsers: DmpInvitationUser[];
public emails: string[] = [];
public roles = Role;
visible = true;
selectable = true;
removable = true;

View File

@ -226,6 +226,7 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "xml", id);
});
}
@ -237,6 +238,7 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "docx", id);
});
}
@ -248,6 +250,7 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "pdf", id);
});
}
@ -258,6 +261,7 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
const blob = new Blob([response.body], { type: 'application/json' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "json", id);
}, async error => {
this.onExportCallbackError(error);
});

View File

@ -112,23 +112,49 @@
</div>
<div class="col-md-4 col-lg-4 p-0">
<div *ngIf="!hasDoi(dmp)" class="row d-flex flex-column ml-0 mr-0 mb-3">
<p class="doi-label">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}</p>
<div class="doi-panel">
<p *ngIf="!hasDoi(dmp)" class="mb-0 ml-3">
<textarea #doi class="doi-txt">{{ dmp.doi }}</textarea>
</p>
<div class="d-flex justify-content-end">
<button (click)="copyDoi(doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<div class="d-flex align-items-center doi-label">
<span class="mr-3">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}: </span>
<ng-container *ngIf="selectedModel">
<mat-select class="max-width-80 select-repo" [placeholder]="selectedModel.repositoryId">
<mat-option *ngFor="let doi of dmp.dois" (click)="selectDoi(doi)">
{{doi.repositoryId}}
</mat-option>
</mat-select>
</ng-container>
</div>
<div *ngIf="dmp.dois && selectedModel" class="doi-panel">
<span class="ml-3 mr-3">{{selectedModel.doi}}</span>
<div class="d-flex justify-content-end ml-3">
<button (click)="copyDoi(selectedModel.doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
</button>
<button mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<a [href]="createDoiLink(dmp.doi)" class="doi-link" target="_blank">
<button *ngIf="depositRepos?.length > 0" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<a [href]="createDoiLink(selectedModel)" class="doi-link" target="_blank">
<mat-icon class="mat-mini-fab-icon">launch</mat-icon>
</a>
</button>
</div>
</div>
</div>
<!-- <div *ngIf="!hasDoi(dmp)" class="row d-flex flex-column ml-0 mr-0 mb-3">
<p class="doi-label">{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}</p>
<div class="doi-panel">
<p *ngIf="!hasDoi(dmp)" class="mb-0 ml-3">
<textarea #doi class="doi-txt">{{ dmp.dois[0].doi }}</textarea>
</p>
<div class="d-flex justify-content-end">
<button (click)="copyDoi(doi)" mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'DMP-LISTING.ACTIONS.COPY' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">content_copy</mat-icon>
</button>
<button mat-mini-fab class="mr-2 d-flex justify-content-center align-items-center" matTooltip="{{'GRANT-EDITOR.ACTIONS.VISIT-WEBSITE' | translate}}" matTooltipPosition="above">
<a [href]="createDoiLink(dmp.dois[0].doi)" class="doi-link" target="_blank">
<mat-icon class="mat-mini-fab-icon">launch</mat-icon>
</a>
</button>
</div>
</div>
</div> -->
<div class="frame mb-3 pt-4 pl-3 pr-5 pb-1">
<div *ngIf="isDraftDmp(dmp) && isUserOwner && !lockStatus">
<div class="row ml-0 mr-0 pl-4 d-flex align-items-center" (click)="finalize(dmp)">
@ -141,13 +167,8 @@
<hr class="hr-line">
</div>
</div>
<div *ngIf="hasDoi(dmp) && isFinalizedDmp(dmp) && !this.isPublicView && isUserOwner" (click)="getDoi(dmp)" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">archive</mat-icon>
</button>
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.DEPOSIT' | translate }}</p>
</div>
<div *ngIf="isFinalizedDmp(dmp) && hasDoi(dmp) && !isPublishedDMP(dmp) && isUserOwner" (click)="reverse(dmp)" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<app-dmp-deposit-dropdown *ngIf="(hasDoi(dmp) || moreDeposit()) && isFinalizedDmp(dmp) && !this.isPublicView && isUserOwner" [inputRepos]="inputRepos" [dmp]="dmp" (outputReposEmitter)="afterDeposit($event)"></app-dmp-deposit-dropdown>
<div *ngIf="isFinalizedDmp(dmp) && hasDoi(dmp) && !isPublishedDMP(dmp) && isUserOwner" (click)="reverse()" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
</button>
@ -167,12 +188,12 @@
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.START-NEW-VERSION' | translate }}
</p>
</div>
<div *ngIf="!dmp.isPublic && showPublishButton(dmp) && isUserOwner" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center" (click)="publish(dmp.id)">
<!-- <div *ngIf="!dmp.isPublic && showPublishButton(dmp) && isUserOwner" class="row ml-0 mr-0 pl-4 pb-3 d-flex align-items-center" (click)="publish(dmp.id)">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">public</mat-icon>
</button>
<p class="mb-0 pl-2 frame-txt">{{ 'DMP-LISTING.ACTIONS.MAKE-PUBLIC' | translate }}</p>
</div>
</div> -->
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="downloadPDF(dmp.id)">
<i class="fa fa-file-pdf-o pr-2"></i>

View File

@ -195,8 +195,7 @@
.doi-label {
font-size: 1em;
color: #212121;
opacity: 0.6;
color: rgba(33, 33, 33, 0.6);
margin-bottom: 0.3em;
}
@ -337,6 +336,10 @@
padding: 0rem 0rem 0.4rem 0rem !important;
}
.select-repo {
border-bottom: 1px solid #212121;
}
// .card-content {
// display: flex;
// justify-content: center;

View File

@ -1,46 +1,52 @@
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { Principal } from '@app/core/model/auth/principal';
import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview';
import { DatasetsToBeFinalized } from '@app/core/model/dataset/datasets-toBeFinalized';
import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput, DmpFinalizeDialogOutput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component';
import { TranslateService } from '@ngx-translate/core';
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {DatasetStatus} from '@app/core/common/enum/dataset-status';
import {DmpStatus} from '@app/core/common/enum/dmp-status';
import {Principal} from '@app/core/model/auth/principal';
import {DatasetOverviewModel} from '@app/core/model/dataset/dataset-overview';
import {DatasetsToBeFinalized} from '@app/core/model/dataset/datasets-toBeFinalized';
import {DmpOverviewModel} from '@app/core/model/dmp/dmp-overview';
import {UserInfoListingModel} from '@app/core/model/user/user-info-listing';
import {AuthService} from '@app/core/services/auth/auth.service';
import {DmpService} from '@app/core/services/dmp/dmp.service';
import {
SnackBarNotificationLevel,
UiNotificationService
} from '@app/core/services/notification/ui-notification-service';
import {ConfirmationDialogComponent} from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import {
DmpFinalizeDialogComponent,
DmpFinalizeDialogInput,
DmpFinalizeDialogOutput
} from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import {BreadcrumbItem} from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import {BaseComponent} from '@common/base/base.component';
import {TranslateService} from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { Observable, of as observableOf, interval } from 'rxjs';
import { takeUntil, map } from 'rxjs/operators';
import { Role } from "@app/core/common/enum/role";
import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation-dialog.component';
import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service';
import { UserService } from '@app/core/services/user/user.service';
import { Location } from '@angular/common';
import { FormGroup, FormArray, FormControl } from '@angular/forms';
import { LockService } from '@app/core/services/lock/lock.service';
import { VersionListingModel } from '@app/core/model/version/version-listing.model';
import { CloneDialogComponent } from '../clone/clone-dialog/clone-dialog.component';
import { DmpModel } from '@app/core/model/dmp/dmp';
import { DmpEditorModel } from '../editor/dmp-editor.model';
import { FunderFormModel } from '../editor/grant-tab/funder-form-model';
import { ProjectFormModel } from '../editor/grant-tab/project-form-model';
import { GrantTabModel } from '../editor/grant-tab/grant-tab-model';
import { ExtraPropertiesFormModel } from '../editor/general-tab/extra-properties-form.model';
import { StartNewDmpDialogComponent } from '../start-new-dmp-dialogue/start-new-dmp-dialog.component';
import { HttpClient } from '@angular/common/http';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component';
import {Observable, of as observableOf} from 'rxjs';
import {map, takeUntil} from 'rxjs/operators';
import {Role} from "@app/core/common/enum/role";
import {DmpInvitationDialogComponent} from '../invitation/dmp-invitation-dialog.component';
import {ConfigurationService} from '@app/core/services/configuration/configuration.service';
import {Location} from '@angular/common';
import {FormGroup} from '@angular/forms';
import {LockService} from '@app/core/services/lock/lock.service';
import {VersionListingModel} from '@app/core/model/version/version-listing.model';
import {CloneDialogComponent} from '../clone/clone-dialog/clone-dialog.component';
import {DmpModel} from '@app/core/model/dmp/dmp';
import {DmpEditorModel} from '../editor/dmp-editor.model';
import {FunderFormModel} from '../editor/grant-tab/funder-form-model';
import {ProjectFormModel} from '../editor/grant-tab/project-form-model';
import {GrantTabModel} from '../editor/grant-tab/grant-tab-model';
import {ExtraPropertiesFormModel} from '../editor/general-tab/extra-properties-form.model';
import {StartNewDmpDialogComponent} from '../start-new-dmp-dialogue/start-new-dmp-dialog.component';
import {MatomoService} from '@app/core/services/matomo/matomo-service';
import {PopupNotificationDialogComponent} from '@app/library/notification/popup/popup-notification.component';
import {DepositRepositoriesService} from '@app/core/services/deposit-repositories/deposit-repositories.service';
import {DepositConfigurationModel} from '@app/core/model/deposit/deposit-configuration';
import {DoiModel} from '@app/core/model/doi/doi';
import {isNullOrUndefined} from '@app/utilities/enhancers/utils';
@Component({
selector: 'app-dmp-overview',
@ -63,28 +69,28 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
textMessage: any;
versions: VersionListingModel[];
version: VersionListingModel;
private oauthLock: boolean;
selectedModel: DoiModel;
@ViewChild('doi')
doi: ElementRef;
depositRepos: DepositConfigurationModel[] = [];
formGroup: FormGroup;
constructor(
private route: ActivatedRoute,
private router: Router,
private dmpService: DmpService,
private depositRepositoriesService: DepositRepositoriesService,
private translate: TranslateService,
private authentication: AuthService,
private dialog: MatDialog,
private language: TranslateService,
private uiNotificationService: UiNotificationService,
private configurationService: ConfigurationService,
private oauth2DialogService: Oauth2DialogService,
private userService: UserService,
private location: Location,
private lockService: LockService,
private httpClient: HttpClient,
private matomoService: MatomoService
) {
super();
@ -105,6 +111,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
if(!this.hasDoi()) {
this.selectedModel = this.dmp.dois[0];
}
this.checkLockStatus(this.dmp.id);
this.setIsUserOwner();
this.getAllVersions(this.dmp);
@ -129,6 +138,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
if(!this.hasDoi()) {
this.selectedModel = this.dmp.dois[0];
}
// this.checkLockStatus(this.dmp.id);
this.getAllVersions(this.dmp);
const breadCrumbs = [];
@ -145,6 +157,13 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
});
}
});
this.depositRepositoriesService.getAvailableRepos()
.pipe(takeUntil(this._destroyed))
.subscribe(
repos => {
this.depositRepos = repos;
},
error => this.depositRepos = []);
}
onFetchingDeletedCallbackError(redirectRoot: string) {
@ -324,6 +343,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "xml", id);
});
}
@ -335,6 +355,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "docx", id);
});
}
@ -346,6 +367,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "pdf", id);
});
}
@ -356,6 +378,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
const blob = new Blob([complete.body], { type: 'application/json' });
const filename = this.getFilenameFromContentDispositionHeader(complete.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.matomoService.trackDownload('dmps', "json", id);
}, async error => {
this.onExportCallbackError(error);
});
@ -443,27 +466,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
return (dmp.status == DmpStatus.Finalized && dmp.isPublic);
}
hasDoi(dmp: DmpOverviewModel) {
return dmp.doi == null ? true : false;
}
getAccessUrl(): string {
const redirectUri = this.configurationService.app + 'oauth2';
const url = this.configurationService.loginProviders.zenodoConfiguration.oauthUrl
+ '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId
+ '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri='
+ redirectUri;
return url;
}
getDoi(dmp: DmpOverviewModel) {
this.userService.hasDOIToken().subscribe(response => {
this.hasDOIToken = true;
this.showConfirmationDOIDialog(dmp);
}, error => {
this.hasDOIToken = false;
this.showErrorConfirmationDOIDialog(error.error.message, dmp);
});
hasDoi(dmp: DmpOverviewModel = null) {
return (this.dmp.dois == null || this.dmp.dois.length == 0);
}
getAllVersions(dmp: DmpOverviewModel) {
@ -474,82 +478,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
});
}
showConfirmationDOIDialog(dmp: DmpOverviewModel) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '600px',
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default' }),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.dmpService.getDoi(dmp.id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.onDOICallbackSuccess();
this.dmp.doi = complete;
},
error => this.onDeleteCallbackError(error)
);
}
});
}
showErrorConfirmationDOIDialog(message: string, dmp: DmpOverviewModel) {
const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, {
maxWidth: '600px',
restoreFocus: false,
data: {
message: message ? this.language.instant(message) : this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'),
titles: [this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN'), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')]
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
switch (result) {
case 0:
// this.authentication.logout();
// this.router.navigate(['/login/external/zenodo']);
this.showOauth2Dialog(this.getAccessUrl(), dmp);
break;
case 1:
this.showConfirmationDOIDialog(dmp);
break;
}
});
}
showOauth2Dialog(url: string, dmp: DmpOverviewModel) {
this.oauth2DialogService.login(url)
.pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (result !== undefined) {
if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) {
this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2')
.pipe(takeUntil(this._destroyed))
.subscribe(() => {
this.hasDOIToken = true;
this.showConfirmationDOIDialog(dmp);
});
this.oauthLock = true;
}
} else {
this.oauthLock = false;
}
});
}
onDOICallbackSuccess(): void {
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success);
}
onDOICallbackError(error) {
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error);
}
showPublishButton(dmp: DmpOverviewModel) {
return this.isFinalizedDmp(dmp) && !dmp.isPublic && this.hasPublishButton;
}
@ -578,43 +506,83 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
});
}
afterDeposit(result: DoiModel[]) {
if (result.length > 0) {
this.dmp.dois = result;
this.selectedModel = this.dmp.dois[this.dmp.dois.length - 1];
this.hasDOIToken = true;
}
}
get inputRepos() {
return this.depositRepos.filter(repo => !this.dmp.dois.find(doi => doi.repositoryId === repo.repositoryId));
}
moreDeposit(){
return (this.dmp.dois.length < this.depositRepos.length);
}
finalize(dmp: DmpOverviewModel) {
const dialogInputModel: DmpFinalizeDialogInput = {
dmpLabel: this.dmp.label,
dmpDescription: this.dmp.description,
datasets: this.dmp.datasets.map(x => {
return { label: x.label, id: x.id, status: x.status }
})
}
const extraProperties = new ExtraPropertiesFormModel();
this.dmpService.getSingle(this.dmp.id).pipe(map(data => data as DmpModel))
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
if (!isNullOrUndefined(data.extraProperties)) {
extraProperties.fromModel(data.extraProperties);
}
const dialogInputModel: DmpFinalizeDialogInput = {
dmpLabel: this.dmp.label,
dmpDescription: this.dmp.description,
datasets: this.dmp.datasets.map(x => {
return { label: x.label, id: x.id, status: x.status }
}),
accessRights: extraProperties.visible
}
const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, {
maxWidth: '500px',
restoreFocus: false,
autoFocus: false,
data: {
dialogInputModel: dialogInputModel,
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'),
confirmButton: this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DmpFinalizeDialogOutput) => {
if (result && !result.cancelled) {
var datasetsToBeFinalized: DatasetsToBeFinalized = {
uuids: result.datasetsToBeFinalized
};
this.dmpService.finalize(datasetsToBeFinalized, this.dmp.id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
if(extraProperties.visible){
//this.publish(this.dmp.id);
this.dmpService.publish(this.dmp.id)
.pipe(takeUntil(this._destroyed))
.subscribe(() => {
//this.hasPublishButton = false;
this.dmp.status = DmpStatus.Finalized;
this.onUpdateCallbackSuccess();
});
}
else{
this.dmp.status = DmpStatus.Finalized;
this.onUpdateCallbackSuccess();
}
},
error => this.onUpdateCallbackError(error)
);
}
});
});
const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, {
maxWidth: '500px',
restoreFocus: false,
autoFocus: false,
data: {
dialogInputModel: dialogInputModel,
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'),
confirmButton: this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DmpFinalizeDialogOutput) => {
if (result && !result.cancelled) {
var datasetsToBeFinalized: DatasetsToBeFinalized = {
uuids: result.datasetsToBeFinalized
};
this.dmpService.finalize(datasetsToBeFinalized, this.dmp.id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.dmp.status = DmpStatus.Finalized;
this.onUpdateCallbackSuccess();
},
error => this.onUpdateCallbackError(error)
);
}
});
}
// newVersion(id: String, label: String) {
@ -677,10 +645,28 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
this.router.navigate(['/datasets', 'new', this.dmp.id]);
}
createDoiLink(doi: string): string {
const doiarr = doi.split('.');
const id = doiarr[doiarr.length - 1];
return this.configurationService.doiLink + id;
selectDoi(doiModel: DoiModel){
this.selectedModel = doiModel;
const foundIdx = this.dmp.dois.findIndex(el => el.id == doiModel.id);
this.dmp.dois.splice(foundIdx, 1);
this.dmp.dois.unshift(doiModel);
}
createDoiLink(doiModel: DoiModel): string {
const recordUrl = this.depositRepos.find(r => r.repositoryId == doiModel.repositoryId).repositoryRecordUrl;
if(typeof recordUrl !== "undefined"){
if(doiModel.repositoryId == "Zenodo"){
const doiarr = doiModel.doi.split('.');
const id = doiarr[doiarr.length - 1];
return this.depositRepos.find(r => r.repositoryId == doiModel.repositoryId).repositoryRecordUrl + id;
}
else{
return this.depositRepos.find(r => r.repositoryId == doiModel.repositoryId).repositoryRecordUrl + doiModel.doi;
}
}
else{
return "";
}
}
reverse() {
@ -750,10 +736,15 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
}
copyDoi(doi) {
let domElement = doi.nativeElement as HTMLInputElement;
domElement.select();
const el = document.createElement('textarea');
el.value = doi;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
domElement.setSelectionRange(0, 0);
document.body.removeChild(el);
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-COPY-TO-CLIPBOARD'), SnackBarNotificationLevel.Success);
}
@ -838,5 +829,99 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
// });
// }
// getAccessUrl(): string {
// const redirectUri = this.configurationService.app + 'oauth2';
// const url = this.configurationService.loginProviders.zenodoConfiguration.oauthUrl
// + '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId
// + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri='
// + redirectUri;
// return url;
// }
// getDoi(dmp: DmpOverviewModel) {
// this.userService.hasDOIToken().subscribe(response => {
// this.hasDOIToken = true;
// this.showConfirmationDOIDialog(dmp);
// }, error => {
// this.hasDOIToken = false;
// this.showErrorConfirmationDOIDialog(error.error.message, dmp);
// });
// }
// showConfirmationDOIDialog(dmp: DmpOverviewModel) {
// const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
// maxWidth: '600px',
// restoreFocus: false,
// data: {
// message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default' }),
// confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
// cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
// }
// });
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// if (result) {
// this.dmpService.getDoi(dmp.id)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// complete => {
// this.onDOICallbackSuccess();
// this.dmp.doi = complete;
// },
// error => this.onDeleteCallbackError(error)
// );
// }
// });
// }
// showErrorConfirmationDOIDialog(message: string, dmp: DmpOverviewModel) {
// const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, {
// maxWidth: '600px',
// restoreFocus: false,
// data: {
// message: message ? this.language.instant(message) : this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'),
// titles: [this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN'), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')]
// }
// });
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// switch (result) {
// case 0:
// // this.authentication.logout();
// // this.router.navigate(['/login/external/zenodo']);
// this.showOauth2Dialog(this.getAccessUrl(), dmp);
// break;
// case 1:
// this.showConfirmationDOIDialog(dmp);
// break;
// }
// });
// }
// showOauth2Dialog(url: string, dmp: DmpOverviewModel) {
// this.oauth2DialogService.login(url)
// .pipe(takeUntil(this._destroyed))
// .subscribe(result => {
// if (result !== undefined) {
// if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) {
// this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2')
// .pipe(takeUntil(this._destroyed))
// .subscribe(() => {
// this.hasDOIToken = true;
// this.showConfirmationDOIDialog(dmp);
// });
// this.oauthLock = true;
// }
// } else {
// this.oauthLock = false;
// }
// });
// }
// onDOICallbackSuccess(): void {
// this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success);
// }
// onDOICallbackError(error) {
// this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error);
// }
}

View File

@ -10,21 +10,24 @@ import { CommonUiModule } from '@common/ui/common-ui.module';
import { RouterModule } from '@angular/router';
import { CloneDialogModule } from '../clone/clone-dialog/clone-dialog.module';
import { NgDialogAnimationService } from 'ng-dialog-animation';
import {DmpModule} from "@app/ui/dmp/dmp.module";
import {DmpDepositDropdown} from "@app/ui/dmp/editor/dmp-deposit-dropdown/dmp-deposit-dropdown.component";
@NgModule({
imports: [
CommonUiModule,
CommonFormsModule,
UrlListingModule,
ConfirmationDialogModule,
CloneDialogModule,
ExportMethodDialogModule,
FormattingModule,
AutoCompleteModule,
RouterModule
],
imports: [
CommonUiModule,
CommonFormsModule,
UrlListingModule,
ConfirmationDialogModule,
CloneDialogModule,
ExportMethodDialogModule,
FormattingModule,
AutoCompleteModule,
RouterModule
],
declarations: [
DmpOverviewComponent
DmpOverviewComponent,
DmpDepositDropdown
],
providers: [
NgDialogAnimationService

View File

@ -0,0 +1,15 @@
<div class="form">
<div class="row d-flex flex-row">
<div class="col-auto ml-auto close-btn" (click)="close()">
<mat-icon>close</mat-icon>
</div>
</div>
<div *ngIf="data.formGroup" mat-dialog-content class="row">
<app-form-composite-field class="align-self-center col" [form]="data.formGroup" [datasetProfileId]="data.datasetProfileId" [altVisibilityRulesService]="visibilityRulesService"
[isChild]="false" [showDelete]="false" [showTitle]="false" [placeholderTitle]="true"></app-form-composite-field>
</div>
<div mat-dialog-actions class="row">
<div class="ml-auto col-auto"><button mat-raised-button type="button" mat-dialog-close (click)="cancel()">{{'DATASET-EDITOR.ACTIONS.CANCEL' | translate}}</button></div>
<div class="col-auto"><button mat-raised-button color="primary" type="button" [disabled]="!data.formGroup.valid" (click)="save()">{{'DATASET-EDITOR.ACTIONS.SAVE' | translate}}</button></div>
</div>
</div>

View File

@ -0,0 +1,31 @@
import {Component, Inject} from "@angular/core";
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
import {VisibilityRulesService} from "@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service";
@Component({
selector: 'app-form-composite-field-dialog',
templateUrl: 'form-composite-field-dialog.component.html'
})
export class FormCompositeFieldDialogComponent {
public visibilityRulesService: VisibilityRulesService;
constructor(
private dialogRef: MatDialogRef<FormCompositeFieldDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
this.visibilityRulesService = data.visibilityRulesService;
}
cancel() {
this.dialogRef.close();
}
save() {
this.dialogRef.close(this.data.formGroup);
}
public close() {
this.dialogRef.close(false);
}
}

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