From 59e26dbb8de840df6a991b270723243d1409fb87 Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Wed, 2 Nov 2022 09:41:40 +0200 Subject: [PATCH] [WIP] EntityDoi table --- .../eudat/data/dao/entities/EntityDoiDao.java | 9 ++ .../data/dao/entities/EntityDoiDaoImpl.java | 51 ++++++++ .../main/java/eu/eudat/data/entities/DMP.java | 11 ++ .../eu/eudat/data/entities/EntityDoi.java | 121 ++++++++++++++++++ .../eudat/controllers/DepositController.java | 9 +- .../managers/DataManagementPlanManager.java | 23 +++- .../eudat/logic/managers/DepositManager.java | 3 +- .../operations/DatabaseRepository.java | 2 + .../operations/DatabaseRepositoryImpl.java | 10 ++ .../models/data/dmp/DataManagementPlan.java | 11 ++ .../java/eu/eudat/models/data/doi/Doi.java | 85 ++++++++++++ .../DataManagementPlanOverviewModel.java | 13 ++ dmp-db-scema/main/dmp-dump.sql | 21 +++ .../updates/00.00.010_Add_EntityDoi_table.sql | 26 ++++ ...Migrate_data_from_dmp_doi_to_entitydoi.sql | 14 ++ .../00.00.012.Delete_doi_from_dmp_table.sql | 11 ++ .../src/app/core/model/dmp/dmp-overview.ts | 2 + dmp-frontend/src/app/core/model/doi/doi.ts | 7 + .../deposit-repositories.service.ts | 5 +- .../dmp-deposit-dialog.component.ts | 18 ++- .../dmp/overview/dmp-overview.component.html | 32 ++++- .../ui/dmp/overview/dmp-overview.component.ts | 57 +++++---- 22 files changed, 498 insertions(+), 43 deletions(-) create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java create mode 100644 dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql create mode 100644 dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql create mode 100644 dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql create mode 100644 dmp-frontend/src/app/core/model/doi/doi.ts diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java new file mode 100644 index 000000000..d6629f598 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java @@ -0,0 +1,9 @@ +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 { +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java new file mode 100644 index 000000000..ead4e2a5c --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java @@ -0,0 +1,51 @@ +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 implements EntityDoiDao { + + @Autowired + public EntityDoiDaoImpl(DatabaseService databaseService){ + super(databaseService); + } + + + @Override + public EntityDoi createOrUpdate(EntityDoi item) { + return this.getDatabaseService().createOrUpdate(item, EntityDoi.class); + } + + @Override + public CompletableFuture 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 find(UUID id, String hint) { + return null; + } + + @Override + public void delete(EntityDoi item) { + this.getDatabaseService().delete(item); + } + + @Override + public QueryableList asQueryable() { + return this.getDatabaseService().getQueryable(EntityDoi.class); + } +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java index b4f212210..14c55dee8 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java @@ -184,6 +184,9 @@ public class DMP implements DataEntity { @Column(name = "\"DOI\"") private String doi; + @OneToMany(mappedBy = "entityId", fetch = FetchType.LAZY) + private Set dois; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "\"Project\"") private Project project; @@ -346,6 +349,13 @@ public class DMP implements DataEntity { this.doi = doi; } + public Set getDois() { + return dois; + } + public void setDois(Set dois) { + this.dois = dois; + } + public Project getProject() { return project; } @@ -381,6 +391,7 @@ public class DMP implements DataEntity { 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(); } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java new file mode 100644 index 000000000..a0b86c6c5 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java @@ -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 { + 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, List 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; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java index c0d603dba..f579394d8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java @@ -6,6 +6,7 @@ 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.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; @@ -49,13 +50,13 @@ public class DepositController extends BaseController { @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"}) public @ResponseBody - ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { try { - String doi = this.depositManager.deposit(depositRequest, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); + Doi doi = this.depositManager.deposit(depositRequest, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); } catch (Exception e) { logger.error(e.getMessage(), e); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); } } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index fff2b168a..a2a8ccc5c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -49,6 +49,7 @@ 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; @@ -2104,7 +2105,7 @@ public class DataManagementPlanManager { return finalDoi; } - public String createDoi(DepositRequest depositRequest, Principal principal) throws Exception { + 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"); @@ -2150,13 +2151,29 @@ public class DataManagementPlanManager { return null; } }).orElse(null); + Doi doiModel = null; if (finalDoi != null) { - dmp.setDoi(finalDoi); + + 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); + } Files.deleteIfExists(file.getFile().toPath()); - return finalDoi; + return doiModel; } /* diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java index 978c27db7..49fceab84 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java @@ -9,6 +9,7 @@ import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper; import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; import eu.eudat.logic.utilities.documents.pdf.PDFUtils; import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.security.Principal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,7 +57,7 @@ public class DepositManager { return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null); } - public String deposit(DepositRequest depositRequest, Principal principal) throws Exception { + public Doi deposit(DepositRequest depositRequest, Principal principal) throws Exception { return this.dataManagementPlanManager.createDoi(depositRequest, principal); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index 67225a76d..99e088a1c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -60,5 +60,7 @@ public interface DatabaseRepository { FileUploadDao getFileUploadDao(); + EntityDoiDao getEntityDoiDao(); + void detachEntity(T entity); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index 7228b5b2f..2e2dd4c63 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -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 void detachEntity(T entity) { this.entityManager.detach(entity); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java index cc2dcd4fb..f0fba6c80 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java @@ -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; @@ -41,6 +42,7 @@ public class DataManagementPlan implements DataModel { private Map properties; private List users; private String doi; + private List dois; private Project project; private Funder funder; private Boolean isPublic; @@ -201,6 +203,13 @@ public class DataManagementPlan implements DataModel { this.doi = doi; } + public List getDois() { + return dois; + } + public void setDois(List dois) { + this.dois = dois; + } + public Project getProject() { return project; } @@ -281,6 +290,7 @@ public class DataManagementPlan implements DataModel { 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(); @@ -377,6 +387,7 @@ public class DataManagementPlan implements DataModel { 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) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java new file mode 100644 index 000000000..9a877dc4d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java @@ -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 { + 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; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java index e90d044c1..9aeac8e0f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java @@ -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; @@ -36,6 +37,7 @@ public class DataManagementPlanOverviewModel implements DataModel dois; public String getId() { @@ -171,6 +173,13 @@ public class DataManagementPlanOverviewModel implements DataModel getDois() { + return dois; + } + public void setDois(List dois) { + this.dois = dois; + } + @Override public DataManagementPlanOverviewModel fromDataModel(DMP entity) { this.id = entity.getId().toString(); @@ -180,6 +189,9 @@ public class DataManagementPlanOverviewModel implements DataModel 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; } @@ -209,6 +221,7 @@ public class DataManagementPlanOverviewModel implements DataModel new Doi().fromDataModel(item)).collect(Collectors.toList()); return this; } diff --git a/dmp-db-scema/main/dmp-dump.sql b/dmp-db-scema/main/dmp-dump.sql index 1a63a0774..470447770 100644 --- a/dmp-db-scema/main/dmp-dump.sql +++ b/dmp-db-scema/main/dmp-dump.sql @@ -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 -- diff --git a/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql b/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql new file mode 100644 index 000000000..d92e9d1d8 --- /dev/null +++ b/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql @@ -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$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql b/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql new file mode 100644 index 000000000..6189fe51a --- /dev/null +++ b/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql @@ -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$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql b/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql new file mode 100644 index 000000000..25219abd0 --- /dev/null +++ b/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql @@ -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$$; \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts b/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts index da5802817..a5171ad61 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts @@ -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[]; } diff --git a/dmp-frontend/src/app/core/model/doi/doi.ts b/dmp-frontend/src/app/core/model/doi/doi.ts new file mode 100644 index 000000000..c72ba0023 --- /dev/null +++ b/dmp-frontend/src/app/core/model/doi/doi.ts @@ -0,0 +1,7 @@ +export interface DoiModel { + id: string; + repositoryId: string; + doi: string; + createdAt: Date; + updatedAt: Date; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts index d4cee9ada..235f766a8 100644 --- a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts +++ b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts @@ -2,6 +2,7 @@ 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'; @@ -27,11 +28,11 @@ export class DepositRepositoriesService { return this.http.post(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers }); } - createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable { + createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable { const depositRequest = new DepositRequest(); depositRequest.repositoryId = repositoryId; depositRequest.dmpId = dmpId; depositRequest.accessToken = accessToken; - return this.http.post(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); + return this.http.post(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts index acd7dec11..0f5133e47 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -3,6 +3,7 @@ import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dial 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 { DmpService } from '@app/core/services/dmp/dmp.service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; @@ -21,7 +22,7 @@ import { takeUntil } from 'rxjs/operators'; export class DmpDepositDialogComponent extends BaseComponent implements OnInit { inputRepos: DepositConfigurationModel[]; - outputRepos: string[]; + outputRepos: DoiModel[]; dmp: DmpOverviewModel; constructor( @@ -37,9 +38,16 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { super(); this.inputRepos = data['depositRepos'][0]; this.dmp = data['depositRepos'][1]; + for(var i = 0; i < this.dmp.dois.length; i++){ + this.inputRepos = this.inputRepos.filter(r => this.hasDoi(r, this.dmp.dois, i)); + } this.outputRepos = []; } + hasDoi(repo, dois, i){ + return repo.repositoryId !== dois[i].repositoryId; + } + ngOnInit(): void { } @@ -76,6 +84,10 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { .subscribe(doi =>{ this.onDOICallbackSuccess(); this.outputRepos.push(doi); + this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; }); + if(this.inputRepos.length == 0){ + this.close(); + } }, error => this.onDeleteCallbackError(error)); break; } @@ -106,6 +118,10 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { .subscribe(doi =>{ this.onDOICallbackSuccess(); this.outputRepos.push(doi); + this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; }); + if(this.inputRepos.length == 0){ + this.close(); + } }, error => this.onDeleteCallbackError(error)); }); // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index 15284e00b..60d21ea68 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -114,21 +114,41 @@

{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}

-

- -

-
+ + + {{x.repositoryId}} + + +
+
@@ -141,7 +161,7 @@
-
+
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index eb89f320d..c01ecf706 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -44,6 +44,7 @@ import { PopupNotificationDialogComponent } from '@app/library/notification/popu import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; import { DmpDepositDialogComponent } from '../editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; +import { DoiModel } from '@app/core/model/doi/doi'; @Component({ selector: 'app-dmp-overview', @@ -71,7 +72,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { @ViewChild('doi') doi: ElementRef; - depositRepos: DepositConfigurationModel[]; + depositRepos: DepositConfigurationModel[] = []; formGroup: FormGroup; @@ -151,6 +152,12 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { }); } }); + this.depositRepositoriesService.getAvailableRepos() + .pipe(takeUntil(this._destroyed)) + .subscribe( + repos => { + this.depositRepos = repos; + }); } onFetchingDeletedCallbackError(redirectRoot: string) { @@ -450,7 +457,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } hasDoi(dmp: DmpOverviewModel) { - return dmp.doi == null ? true : false; + return (this.dmp.dois == null || this.dmp.dois.length == 0) ? true : false; } getAccessUrl(): string { @@ -585,30 +592,28 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } deposit(){ - this.depositRepositoriesService.getAvailableRepos() - .pipe(takeUntil(this._destroyed)) - .subscribe( - repos => { - this.depositRepos = repos; - const dialogRef = this.dialog.open(DmpDepositDialogComponent, { - maxWidth: '600px', - restoreFocus: false, - autoFocus: false, - data: { - depositRepos: [this.depositRepos, this.dmp], - message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), - confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), - cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), - } - }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: string[]) => { - if (result) { - this.dmp.doi = result[0]; - this.hasDOIToken = true; - } - }); - } - ); + const dialogRef = this.dialog.open(DmpDepositDialogComponent, { + maxWidth: '600px', + disableClose: true, + restoreFocus: false, + autoFocus: false, + data: { + depositRepos: [this.depositRepos, this.dmp], + message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), + confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), + cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DoiModel[]) => { + if (result.length > 0) { + this.dmp.dois.push(...result); + this.hasDOIToken = true; + } + }); + } + + moreDeposit(){ + return (this.dmp.dois.length < this.depositRepos.length) ? true : false; } finalize(dmp: DmpOverviewModel) {