diff --git a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java index 2ec15c6f1..7865bbf97 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java +++ b/dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java @@ -80,5 +80,13 @@ public class AuditableAction { public static final EventId Tenant_Persist = new EventId(12002, "Tenant_Persist"); public static final EventId Tenant_Delete = new EventId(12003, "Tenant_Delete"); + public static final EventId Language_Query = new EventId(13000, "Language_Query"); + public static final EventId Language_Lookup = new EventId(13001, "Language_Lookup"); + public static final EventId Language_Persist = new EventId(13002, "Language_Persist"); + public static final EventId Language_Delete = new EventId(13003, "Language_Delete"); + + public static final EventId StorageFile_Download = new EventId(14000, "StorageFile_Download"); + public static final EventId StorageFile_Upload = new EventId(14001, "StorageFile_Upload"); + } diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java index 82d82a3a3..25b24e205 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/Permission.java @@ -28,6 +28,7 @@ public final class Permission { //Language public static String BrowseLanguage = "BrowseLanguage"; public static String EditLanguage = "EditLanguage"; + public static String DeleteLanguage = "DeleteLanguage"; //Language public static String BrowseStatistics = "BrowseStatistics"; @@ -49,6 +50,13 @@ public final class Permission { public static String EditUser = "EditUser"; public static String DeleteUser = "DeleteUser"; public static String ExportUsers = "ExportUsers"; + + + + //StorageFile + public static String BrowseStorageFile = "BrowseStorageFile"; + public static String EditStorageFile = "EditStorageFile"; + public static String DeleteStorageFile = "DeleteStorageFile"; //DescriptionTemplateType public static String BrowseDescriptionTemplateType = "BrowseDescriptionTemplateType"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/enums/StorageFilePermission.java b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/StorageFilePermission.java new file mode 100644 index 000000000..b62afc910 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/StorageFilePermission.java @@ -0,0 +1,30 @@ +package eu.eudat.commons.enums; + +import com.fasterxml.jackson.annotation.JsonValue; +import eu.eudat.data.converters.enums.DatabaseEnum; + +import java.util.Map; + +public enum StorageFilePermission implements DatabaseEnum { + + Read((short) 0), + Write((short) 1); + + private final Short value; + + StorageFilePermission(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(StorageFilePermission.class); + + public static StorageFilePermission of(Short i) { + return map.get(i); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/enums/StorageType.java b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/StorageType.java new file mode 100644 index 000000000..59e0b1bae --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/StorageType.java @@ -0,0 +1,30 @@ +package eu.eudat.commons.enums; + +import com.fasterxml.jackson.annotation.JsonValue; +import eu.eudat.data.converters.enums.DatabaseEnum; + +import java.util.Map; + +public enum StorageType implements DatabaseEnum { + + Temp((short) 0), + Main((short) 1); + + private final Short value; + + StorageType(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(StorageType.class); + + public static StorageType of(Short i) { + return map.get(i); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/fake/FakeRequestAttributes.java b/dmp-backend/core/src/main/java/eu/eudat/commons/fake/FakeRequestAttributes.java new file mode 100644 index 000000000..021c1924b --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/fake/FakeRequestAttributes.java @@ -0,0 +1,126 @@ +package eu.eudat.commons.fake; + +import org.jetbrains.annotations.NotNull; +import org.springframework.util.Assert; +import org.springframework.web.context.request.RequestAttributes; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +public class FakeRequestAttributes implements RequestAttributes { + private final Map requestAttributeMap = new HashMap<>(); + private final Map requestDestructionCallbacks = new LinkedHashMap<>(8); + private volatile boolean requestActive = true; + + @Override + public Object getAttribute(@NotNull String name, int scope) { + if (scope == RequestAttributes.SCOPE_REQUEST) { + if (!isRequestActive()) { + throw new IllegalStateException("Cannot ask for request attribute - request is not active anymore!"); + } + return this.requestAttributeMap.get(name); + } else { + throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName()); + } + } + + @Override + public void setAttribute(@NotNull String name, @NotNull Object value, int scope) { + if (scope == RequestAttributes.SCOPE_REQUEST) { + if (!isRequestActive()) { + throw new IllegalStateException("Cannot set request attribute - request is not active anymore!"); + } + this.requestAttributeMap.put(name, value); + } else { + throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName()); + } + } + + @Override + public void removeAttribute(@NotNull String name, int scope) { + if (scope == RequestAttributes.SCOPE_REQUEST) { + if (isRequestActive()) { + removeRequestDestructionCallback(name); + this.requestAttributeMap.remove(name); + } + } else { + throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName()); + } + } + + @Override + public String @NotNull [] getAttributeNames(int scope) { + if (scope == RequestAttributes.SCOPE_REQUEST) { + if (!isRequestActive()) { + throw new IllegalStateException("Cannot ask for request attributes - request is not active anymore!"); + } + return this.requestAttributeMap.keySet().toArray(new String[0]); + } else { + throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName()); + } + //return new String[0]; + } + + @Override + public void registerDestructionCallback(@NotNull String name, @NotNull Runnable callback, int scope) { + if (scope == SCOPE_REQUEST) { + registerRequestDestructionCallback(name, callback); + } else { + throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName()); + } + } + + protected final void registerRequestDestructionCallback(String name, Runnable callback) { + Assert.notNull(name, "Name must not be null"); + Assert.notNull(callback, "Callback must not be null"); + synchronized (this.requestDestructionCallbacks) { + this.requestDestructionCallbacks.put(name, callback); + } + } + + @Override + public Object resolveReference(@NotNull String key) { + // Not supported + return null; + } + + @Override + public @NotNull String getSessionId() { + return ""; + } + + @Override + public @NotNull Object getSessionMutex() { + return new Object(); + } + + public void requestCompleted() { + executeRequestDestructionCallbacks(); + for (String name : getAttributeNames(RequestAttributes.SCOPE_REQUEST)) { + this.removeAttribute(name, RequestAttributes.SCOPE_REQUEST); + } + this.requestActive = false; + } + + private boolean isRequestActive() { + return this.requestActive; + } + + + private void removeRequestDestructionCallback(String name) { + Assert.notNull(name, "Name must not be null"); + synchronized (this.requestDestructionCallbacks) { + this.requestDestructionCallbacks.remove(name); + } + } + + private void executeRequestDestructionCallbacks() { + synchronized (this.requestDestructionCallbacks) { + for (Runnable runnable : this.requestDestructionCallbacks.values()) { + runnable.run(); + } + this.requestDestructionCallbacks.clear(); + } + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/fake/FakeRequestScope.java b/dmp-backend/core/src/main/java/eu/eudat/commons/fake/FakeRequestScope.java new file mode 100644 index 000000000..3fb372149 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/fake/FakeRequestScope.java @@ -0,0 +1,44 @@ +package eu.eudat.commons.fake; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; + +import java.io.Closeable; + +public class FakeRequestScope implements Closeable { + private RequestAttributes initialRequestAttributes = null; + private FakeRequestAttributes currentRequestAttributes = null; + boolean isInUse = false; + + public FakeRequestScope() { + this.reset(); + } + + public final void reset() { + this.close(); + this.isInUse = true; + + this.initialRequestAttributes = RequestContextHolder.getRequestAttributes(); + this.currentRequestAttributes = new FakeRequestAttributes(); + RequestContextHolder.setRequestAttributes(this.currentRequestAttributes); + } + + @Override + public void close() { + if (!this.isInUse) + return; + this.isInUse = false; + + if (initialRequestAttributes != null) + RequestContextHolder.setRequestAttributes(initialRequestAttributes); + else + RequestContextHolder.resetRequestAttributes(); + + if (currentRequestAttributes != null) + currentRequestAttributes.requestCompleted(); + + this.initialRequestAttributes = null; + this.currentRequestAttributes = null; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java index e8265d54a..2ff4040e4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionEntity.java @@ -3,7 +3,6 @@ package eu.eudat.data; import eu.eudat.commons.enums.DescriptionStatus; import eu.eudat.commons.enums.IsActive; -import eu.eudat.data.converters.DateToUTCConverter; import eu.eudat.data.converters.enums.DescriptionStatusConverter; import eu.eudat.data.converters.enums.IsActiveConverter; import eu.eudat.data.old.helpers.EntityBinder; diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java index f630f2543..918f56622 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionReferenceEntity.java @@ -1,7 +1,6 @@ package eu.eudat.data; import eu.eudat.commons.enums.IsActive; -import eu.eudat.data.converters.DateToUTCConverter; import eu.eudat.data.converters.enums.IsActiveConverter; import jakarta.persistence.*; diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java index fdc88bb78..347add277 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTagEntity.java @@ -1,7 +1,6 @@ package eu.eudat.data; import eu.eudat.commons.enums.IsActive; -import eu.eudat.data.converters.DateToUTCConverter; import eu.eudat.data.converters.enums.IsActiveConverter; import jakarta.persistence.*; @@ -29,13 +28,11 @@ public class DescriptionTagEntity { public static final String _tagId = "tagId"; @Column(name = "created_at") - @Convert(converter = DateToUTCConverter.class) private Instant createdAt; public static final String _createdAt = "createdAt"; @Column(name = "updated_at") - @Convert(converter = DateToUTCConverter.class) private Instant updatedAt; public static final String _updatedAt = "updatedAt"; diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java index 9dae0c4ae..0fd87a705 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DescriptionTemplateEntity.java @@ -1,6 +1,5 @@ package eu.eudat.data; - import eu.eudat.commons.enums.DescriptionTemplateStatus; import eu.eudat.commons.enums.DescriptionTemplateVersionStatus; import eu.eudat.commons.enums.IsActive; @@ -14,7 +13,6 @@ import java.time.Instant; import java.util.List; import java.util.UUID; - @Entity @Table(name = "\"DescriptionTemplate\"") public class DescriptionTemplateEntity implements DataEntity{ diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java index 990147269..ca3f7ad48 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpBlueprintEntity.java @@ -1,6 +1,5 @@ package eu.eudat.data; - import eu.eudat.commons.enums.DmpBlueprintStatus; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.converters.enums.DmpBlueprintStatusConverter; @@ -10,7 +9,6 @@ import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; - @Entity @Table(name = "\"DmpBlueprint\"") public class DmpBlueprintEntity { diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java index 760a5bb78..50c25af0f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpDescriptionTemplateEntity.java @@ -2,11 +2,9 @@ package eu.eudat.data; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.converters.enums.IsActiveConverter; -import eu.eudat.data.old.queryableentity.DataEntity; import jakarta.persistence.*; import java.time.Instant; -import java.util.List; import java.util.UUID; @Entity diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java index 4d86386b6..232470c21 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/DmpUserEntity.java @@ -4,11 +4,9 @@ import eu.eudat.commons.enums.DmpUserRole; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.converters.enums.DmpUserRoleConverter; import eu.eudat.data.converters.enums.IsActiveConverter; -import eu.eudat.data.old.queryableentity.DataEntity; import jakarta.persistence.*; import java.time.Instant; -import java.util.List; import java.util.UUID; @Entity diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java new file mode 100644 index 000000000..d244f670f --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/data/LanguageEntity.java @@ -0,0 +1,87 @@ +package eu.eudat.data; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.data.converters.enums.IsActiveConverter; +import jakarta.persistence.*; + +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "\"Language\"") +public class LanguageEntity { + + @Id + @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) + private UUID id; + public static final String _id = "id"; + + @Column(name = "code", length = 20, nullable = false) + private String code; + public static final String _code = "code"; + + @Column(name = "payload", nullable = false) + private String payload; + public static final String _payload = "payload"; + + @Column(name = "\"created_at\"", nullable = false) + private Instant createdAt; + public static final String _createdAt = "createdAt"; + + @Column(name = "\"updated_at\"", nullable = false) + private Instant updatedAt; + public static final String _updatedAt = "updatedAt"; + + @Column(name = "is_active", nullable = false) + @Convert(converter = IsActiveConverter.class) + private IsActive isActive; + public static final String _isActive = "isActive"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + + public Instant getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Instant updatedAt) { + this.updatedAt = updatedAt; + } + + public IsActive getIsActive() { + return isActive; + } + + public void setIsActive(IsActive isActive) { + this.isActive = isActive; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java new file mode 100644 index 000000000..e42150fef --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/data/StorageFileEntity.java @@ -0,0 +1,141 @@ +package eu.eudat.data; + + +import eu.eudat.commons.enums.StorageType; +import eu.eudat.data.converters.enums.StorageTypeConverter; +import jakarta.persistence.*; + +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "\"StorageFile\"") +public class StorageFileEntity { + + @Id + @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) + private UUID id; + public final static String _id = "id"; + + @Column(name = "file_ref", length = _fileRefLen, nullable = false) + private String fileRef; + public final static String _fileRef = "fileRef"; + public final static int _fileRefLen = 100; + + @Column(name = "name", length = _nameLen, nullable = false) + private String name; + public final static String _name = "name"; + public final static int _nameLen = 250; + + @Column(name = "extension", length = _extensionLen, nullable = false) + private String extension; + public final static String _extension = "extension"; + public final static int _extensionLen = 10; + + @Column(name = "mime_type", length = _mimeTypeLen, nullable = false) + private String mimeType; + public final static String _mimeType = "mimeType"; + public final static int _mimeTypeLen = 200; + + @Column(name = "storage_type", nullable = false) + @Convert(converter = StorageTypeConverter.class) + private StorageType storageType; + public final static String _storageType = "storageType"; + + @Column(name = "created_at", nullable = false) + private Instant createdAt; + public final static String _createdAt = "createdAt"; + + @Column(name = "purge_at", nullable = true) + private Instant purgeAt; + public final static String _purgeAt = "purgeAt"; + + @Column(name = "purged_at", nullable = true) + private Instant purgedAt; + public final static String _purgedAt = "purgedAt"; + + @Column(name = "owner", nullable = true) + private UUID ownerId; + public final static String _ownerId = "ownerId"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getFileRef() { + return fileRef; + } + + public void setFileRef(String fileRef) { + this.fileRef = fileRef; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } + + public String getMimeType() { + return mimeType; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public StorageType getStorageType() { + return storageType; + } + + public void setStorageType(StorageType storageType) { + this.storageType = storageType; + } + + + public Instant getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + + public Instant getPurgeAt() { + return purgeAt; + } + + public void setPurgeAt(Instant purgeAt) { + this.purgeAt = purgeAt; + } + + public Instant getPurgedAt() { + return purgedAt; + } + + public void setPurgedAt(Instant purgedAt) { + this.purgedAt = purgedAt; + } + + public UUID getOwnerId() { + return ownerId; + } + + public void setOwnerId(UUID ownerId) { + this.ownerId = ownerId; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java index ac260f81b..c871bec31 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/TagEntity.java @@ -1,6 +1,5 @@ package eu.eudat.data; - import eu.eudat.commons.enums.IsActive; import eu.eudat.data.converters.enums.IsActiveConverter; import jakarta.persistence.*; @@ -8,7 +7,6 @@ import jakarta.persistence.*; import java.time.Instant; import java.util.UUID; - @Entity @Table(name = "\"Tag\"") public class TagEntity { diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java index b4c0beecf..e347dd35f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserContactInfoEntity.java @@ -1,21 +1,16 @@ package eu.eudat.data; import eu.eudat.commons.enums.ContactInfoType; -import eu.eudat.commons.enums.DescriptionStatus; import eu.eudat.data.converters.enums.ContactInfoTypeConverter; -import eu.eudat.data.converters.enums.DescriptionStatusConverter; -import eu.eudat.data.old.helpers.EntityBinder; -import eu.eudat.data.old.queryableentity.DataEntity; import jakarta.persistence.*; import java.time.Instant; -import java.util.List; import java.util.UUID; - @Entity @Table(name = "\"UserContactInfo\"") public class UserContactInfoEntity { + @Id @Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false) private UUID id; diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java index 8575b8ed8..7ab13682c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserCredentialEntity.java @@ -1,14 +1,13 @@ package eu.eudat.data; -import eu.eudat.data.old.helpers.EntityBinder; -import eu.eudat.data.old.queryableentity.DataEntity; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.time.Instant; -import java.util.List; import java.util.UUID; - @Entity @Table(name = "\"UserCredential\"") public class UserCredentialEntity { diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java index 6846e2336..49a845c2e 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserDescriptionTemplateEntity.java @@ -4,12 +4,9 @@ import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.enums.UserDescriptionTemplateRole; import eu.eudat.data.converters.enums.IsActiveConverter; import eu.eudat.data.converters.enums.UserDescriptionTemplateRoleConverter; -import eu.eudat.data.old.helpers.EntityBinder; -import eu.eudat.data.old.queryableentity.DataEntity; import jakarta.persistence.*; import java.time.Instant; -import java.util.List; import java.util.UUID; @Entity diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserEntity.java index adc57a4c3..8d765e5c4 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserEntity.java @@ -2,14 +2,10 @@ package eu.eudat.data; import eu.eudat.commons.enums.IsActive; import eu.eudat.data.converters.enums.IsActiveConverter; -import eu.eudat.data.old.helpers.EntityBinder; -import eu.eudat.data.old.queryableentity.DataEntity; - import jakarta.persistence.*; import java.time.Instant; -import java.util.*; - +import java.util.UUID; @Entity @Table(name = "\"User\"") diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java index 4e414822b..049e0382b 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserRoleEntity.java @@ -1,15 +1,13 @@ package eu.eudat.data; -import eu.eudat.data.old.helpers.EntityBinder; -import eu.eudat.data.old.queryableentity.DataEntity; - -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.time.Instant; -import java.util.List; import java.util.UUID; - @Entity @Table(name = "\"UserRole\"") public class UserRoleEntity { diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java b/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java index dda975019..4118d413f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/data/UserSettingsEntity.java @@ -1,6 +1,5 @@ package eu.eudat.data; - import eu.eudat.commons.enums.UserSettingsType; import eu.eudat.data.converters.enums.UserSettingsTypeConverter; import jakarta.persistence.*; diff --git a/dmp-backend/core/src/main/java/eu/eudat/data/converters/enums/StorageTypeConverter.java b/dmp-backend/core/src/main/java/eu/eudat/data/converters/enums/StorageTypeConverter.java new file mode 100644 index 000000000..7baa726a0 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/data/converters/enums/StorageTypeConverter.java @@ -0,0 +1,12 @@ +package eu.eudat.data.converters.enums; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.commons.enums.StorageType; +import jakarta.persistence.Converter; + +@Converter +public class StorageTypeConverter extends DatabaseEnumConverter { + public StorageType of(Short i) { + return StorageType.of(i); + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/Dmp.java b/dmp-backend/core/src/main/java/eu/eudat/model/Dmp.java index 317d122a1..907a35d0b 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/Dmp.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/Dmp.java @@ -93,7 +93,7 @@ public class Dmp { private List dmpUsers; - public static final String _dmpUsers = "dmoUsers"; + public static final String _dmpUsers = "dmpUsers"; public UUID getId() { return id; diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/Language.java b/dmp-backend/core/src/main/java/eu/eudat/model/Language.java new file mode 100644 index 000000000..0c99f8b14 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/Language.java @@ -0,0 +1,86 @@ +package eu.eudat.model; + +import eu.eudat.commons.enums.IsActive; + +import java.time.Instant; +import java.util.UUID; + +public class Language { + + private UUID id; + public static final String _id = "id"; + + private String code; + public static final String _code = "code"; + + private String payload; + public static final String _payload = "payload"; + + private Instant createdAt; + public static final String _createdAt = "createdAt"; + + private Instant updatedAt; + public static final String _updatedAt = "updatedAt"; + + private IsActive isActive; + public static final String _isActive = "isActive"; + + private String hash; + public final static String _hash = "hash"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + + public Instant getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Instant updatedAt) { + this.updatedAt = updatedAt; + } + + public IsActive getIsActive() { + return isActive; + } + + public void setIsActive(IsActive isActive) { + this.isActive = isActive; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/StorageFile.java b/dmp-backend/core/src/main/java/eu/eudat/model/StorageFile.java new file mode 100644 index 000000000..763b3a1d5 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/StorageFile.java @@ -0,0 +1,130 @@ +package eu.eudat.model; + +import eu.eudat.commons.enums.StorageType; + +import java.time.Instant; +import java.util.UUID; + +public class StorageFile { + + private UUID id; + public final static String _id = "id"; + + private String fileRef; + public final static String _fileRef = "fileRef"; + + private String name; + public final static String _name = "name"; + + private String fullName; + public final static String _fullName = "fullName"; + + private String extension; + public final static String _extension = "extension"; + + private String mimeType; + public final static String _mimeType = "mimeType"; + + private StorageType storageType; + public final static String _storageType = "storageType"; + + private Instant createdAt; + public final static String _createdAt = "createdAt"; + + private Instant purgeAt; + public final static String _purgeAt = "purgeAt"; + + private Instant purgedAt; + public final static String _purgedAt = "purgedAt"; + + private User owner; + public final static String _owner = "owner"; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getFileRef() { + return fileRef; + } + + public void setFileRef(String fileRef) { + this.fileRef = fileRef; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } + + public String getMimeType() { + return mimeType; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public StorageType getStorageType() { + return storageType; + } + + public void setStorageType(StorageType storageType) { + this.storageType = storageType; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + + public Instant getPurgeAt() { + return purgeAt; + } + + public void setPurgeAt(Instant purgeAt) { + this.purgeAt = purgeAt; + } + + public Instant getPurgedAt() { + return purgedAt; + } + + public void setPurgedAt(Instant purgedAt) { + this.purgedAt = purgedAt; + } + + public User getOwner() { + return owner; + } + + public void setOwner(User owner) { + this.owner = owner; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/LanguageBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/LanguageBuilder.java new file mode 100644 index 000000000..72fffb766 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/LanguageBuilder.java @@ -0,0 +1,61 @@ +package eu.eudat.model.builder; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.commons.XmlHandlingService; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.LanguageEntity; +import eu.eudat.model.Language; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class LanguageBuilder extends BaseBuilder{ + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public LanguageBuilder( + ConventionService conventionService, + BuilderFactory builderFactory, QueryFactory queryFactory, XmlHandlingService xmlHandlingService) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(LanguageBuilder.class))); + } + + public LanguageBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + List models = new ArrayList<>(); + for (LanguageEntity d : data) { + Language m = new Language(); + if (fields.hasField(this.asIndexer(Language._id))) m.setId(d.getId()); + if (fields.hasField(this.asIndexer(Language._code))) m.setCode(d.getCode()); + if (fields.hasField(this.asIndexer(Language._payload))) m.setPayload(d.getPayload()); + if (fields.hasField(this.asIndexer(Language._createdAt))) m.setCreatedAt(d.getCreatedAt()); + if (fields.hasField(this.asIndexer(Language._updatedAt))) m.setUpdatedAt(d.getUpdatedAt()); + if (fields.hasField(this.asIndexer(Language._isActive))) m.setIsActive(d.getIsActive()); + if (fields.hasField(this.asIndexer(Language._hash))) m.setHash(this.hashValue(d.getUpdatedAt())); + models.add(m); + } + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + return models; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/StorageFileBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/StorageFileBuilder.java new file mode 100644 index 000000000..08cb7411e --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/StorageFileBuilder.java @@ -0,0 +1,111 @@ +package eu.eudat.model.builder; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.StorageFileEntity; +import eu.eudat.model.*; +import eu.eudat.query.*; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class StorageFileBuilder extends BaseBuilder { + + private final QueryFactory queryFactory; + + private final BuilderFactory builderFactory; + + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + @Autowired + public StorageFileBuilder( + ConventionService conventionService, + QueryFactory queryFactory, + BuilderFactory builderFactory) { + super(conventionService, new LoggerService(LoggerFactory.getLogger(StorageFileBuilder.class))); + this.queryFactory = queryFactory; + this.builderFactory = builderFactory; + } + + public StorageFileBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + public List build(FieldSet fields, List data) throws MyApplicationException { + this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0)); + this.logger.trace(new DataLogEntry("requested fields", fields)); + if (fields == null || data == null || fields.isEmpty()) + return new ArrayList<>(); + + FieldSet userFields = fields.extractPrefixed(this.asPrefix(StorageFile._owner)); + Map userItemsMap = this.collectUsers(userFields, data); + + List models = new ArrayList<>(); + for (StorageFileEntity d : data) { + StorageFile m = new StorageFile(); + if (fields.hasField(this.asIndexer(StorageFile._id))) m.setId(d.getId()); + if (fields.hasField(this.asIndexer(StorageFile._name))) m.setName(d.getName()); + if (fields.hasField(this.asIndexer(StorageFile._fileRef))) m.setFileRef(d.getFileRef()); + if (fields.hasField(this.asIndexer(StorageFile._extension))) m.setExtension(d.getExtension()); + if (fields.hasField(this.asIndexer(StorageFile._createdAt))) m.setCreatedAt(d.getCreatedAt()); + if (fields.hasField(this.asIndexer(StorageFile._mimeType))) m.setMimeType(d.getMimeType()); + if (fields.hasField(this.asIndexer(StorageFile._storageType))) m.setStorageType(d.getStorageType()); + if (fields.hasField(this.asIndexer(StorageFile._purgeAt))) m.setPurgeAt(d.getPurgeAt()); + if (fields.hasField(this.asIndexer(StorageFile._purgedAt))) m.setPurgedAt(d.getPurgedAt()); + if (fields.hasField(this.asIndexer(StorageFile._fullName))) m.setFullName(d.getName() + (d.getExtension().startsWith(".") ? "" : ".") + d.getExtension()); + if (!userFields.isEmpty() && userItemsMap != null && userItemsMap.containsKey(d.getOwnerId())) m.setOwner(userItemsMap.get(d.getOwnerId())); + models.add(m); + } + + this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0)); + + return models; + } + + private Map collectUsers(FieldSet fields, List data) throws MyApplicationException { + if (fields.isEmpty() || data.isEmpty()) + return null; + this.logger.debug("checking related - {}", User.class.getSimpleName()); + + Map itemMap; + if (!fields.hasOtherField(this.asIndexer(User._id))) { + itemMap = this.asEmpty( + data.stream().map(StorageFileEntity::getOwnerId).distinct().collect(Collectors.toList()), + x -> { + User item = new User(); + item.setId(x); + return item; + }, + User::getId); + } else { + FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(User._id); + UserQuery q = this.queryFactory.query(UserQuery.class).authorize(this.authorize).ids(data.stream().map(StorageFileEntity::getOwnerId).distinct().collect(Collectors.toList())); + itemMap = this.builderFactory.builder(UserBuilder.class).authorize(this.authorize).asForeignKey(q, clone, User::getId); + } + if (!fields.hasField(User._id)) { + itemMap.forEach((id, item) -> { + if (item != null) + item.setId(null); + }); + } + + return itemMap; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/LanguageCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/LanguageCensor.java new file mode 100644 index 000000000..46dd0b47b --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/LanguageCensor.java @@ -0,0 +1,42 @@ +package eu.eudat.model.censorship; + +import eu.eudat.authorization.Permission; +import eu.eudat.convention.ConventionService; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class LanguageCensor extends BaseCensor { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LanguageCensor.class)); + + protected final AuthorizationService authService; + protected final CensorFactory censorFactory; + + public LanguageCensor(ConventionService conventionService, + AuthorizationService authService, + CensorFactory censorFactory) { + super(conventionService); + this.authService = authService; + this.censorFactory = censorFactory; + } + + public void censor(FieldSet fields, UUID userId) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (fields == null || fields.isEmpty()) + return; + + this.authService.authorizeForce(Permission.BrowseLanguage); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/StorageFileCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/StorageFileCensor.java new file mode 100644 index 000000000..e72a54422 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/StorageFileCensor.java @@ -0,0 +1,45 @@ +package eu.eudat.model.censorship; + +import eu.eudat.authorization.Permission; +import eu.eudat.convention.ConventionService; +import eu.eudat.model.StorageFile; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.DataLogEntry; +import gr.cite.tools.logging.LoggerService; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class StorageFileCensor extends BaseCensor { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(StorageFileCensor.class)); + + protected final AuthorizationService authService; + + protected final CensorFactory censorFactory; + + public StorageFileCensor(ConventionService conventionService, AuthorizationService authService, CensorFactory censorFactory) { + super(conventionService); + this.authService = authService; + this.censorFactory = censorFactory; + } + + public void censor(FieldSet fields, UUID userId) { + logger.debug(new DataLogEntry("censoring fields", fields)); + if (fields == null || fields.isEmpty()) + return; + + this.authService.authorizeForce(Permission.BrowseStorageFile); + + FieldSet ownerFields = fields.extractPrefixed(this.asIndexerPrefix(StorageFile._owner)); + this.censorFactory.censor(UserCensor.class).censor(ownerFields, userId); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java new file mode 100644 index 000000000..0e2add77c --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/deleter/LanguageDeleter.java @@ -0,0 +1,78 @@ +package eu.eudat.model.deleter; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.data.LanguageEntity; +import eu.eudat.query.LanguageQuery; +import gr.cite.tools.data.deleter.Deleter; +import gr.cite.tools.data.deleter.DeleterFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import jakarta.persistence.EntityManager; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class LanguageDeleter implements Deleter { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LanguageDeleter.class)); + private final EntityManager entityManager; + + protected final QueryFactory queryFactory; + + protected final DeleterFactory deleterFactory; + + @Autowired + public LanguageDeleter( + EntityManager entityManager, + QueryFactory queryFactory, + DeleterFactory deleterFactory + ) { + this.entityManager = entityManager; + this.queryFactory = queryFactory; + this.deleterFactory = deleterFactory; + } + + public void deleteAndSaveByIds(List ids) throws InvalidApplicationException { + logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids)); + List data = this.queryFactory.query(LanguageQuery.class).ids(ids).collect(); + logger.trace("retrieved {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + this.deleteAndSave(data); + } + + public void deleteAndSave(List data) throws InvalidApplicationException { + logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + this.delete(data); + logger.trace("saving changes"); + this.entityManager.flush(); + logger.trace("changes saved"); + } + + public void delete(List data) throws InvalidApplicationException { + logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0)); + if (data == null || data.isEmpty()) + return; + + Instant now = Instant.now(); + + for (LanguageEntity item : data) { + logger.trace("deleting item {}", item.getId()); + item.setIsActive(IsActive.Inactive); + item.setUpdatedAt(now); + logger.trace("updating item"); + this.entityManager.merge(item); + logger.trace("updated item"); + } + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/mapper/publicapi/DmpToPublicApiDmpListingMapper.java b/dmp-backend/core/src/main/java/eu/eudat/model/mapper/publicapi/DmpToPublicApiDmpListingMapper.java new file mode 100644 index 000000000..3051ef800 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/mapper/publicapi/DmpToPublicApiDmpListingMapper.java @@ -0,0 +1,32 @@ +package eu.eudat.model.mapper.publicapi; + +import eu.eudat.model.Dmp; +import eu.eudat.model.publicapi.listingmodels.DataManagementPlanPublicListingModel; +import eu.eudat.model.publicapi.researcher.ResearcherPublicModel; +import eu.eudat.model.publicapi.user.UserInfoPublicModel; +import org.springframework.stereotype.Component; + +import java.sql.Date; +import java.util.Objects; + +@Component +public class DmpToPublicApiDmpListingMapper { + + public DataManagementPlanPublicListingModel toPublicListingModel(Dmp dmp) { + DataManagementPlanPublicListingModel model = new DataManagementPlanPublicListingModel(); + model.setId(dmp.getId().toString()); + model.setLabel(dmp.getLabel()); + model.setVersion(dmp.getVersion()); + model.setGroupId(dmp.getGroupId()); + + model.setUsers(dmp.getDmpUsers().stream().map(UserInfoPublicModel::fromDmpUser).toList()); + model.setResearchers(dmp.getDmpReferences().stream().map(ResearcherPublicModel::fromDmpReference).filter(Objects::isNull).toList()); + + model.setCreatedAt(Date.from(dmp.getCreatedAt())); + model.setModifiedAt(Date.from(dmp.getUpdatedAt())); + model.setFinalizedAt(Date.from(dmp.getFinalizedAt())); + + return model; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/mapper/publicapi/DmpToPublicApiDmpMapper.java b/dmp-backend/core/src/main/java/eu/eudat/model/mapper/publicapi/DmpToPublicApiDmpMapper.java new file mode 100644 index 000000000..0d802f1c3 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/mapper/publicapi/DmpToPublicApiDmpMapper.java @@ -0,0 +1,33 @@ +package eu.eudat.model.mapper.publicapi; + +import eu.eudat.model.Dmp; +import eu.eudat.model.publicapi.overviewmodels.DataManagementPlanPublicModel; +import eu.eudat.model.publicapi.researcher.ResearcherPublicModel; +import eu.eudat.model.publicapi.user.UserInfoPublicModel; +import org.springframework.stereotype.Component; + +import java.sql.Date; +import java.util.Objects; + +@Component +public class DmpToPublicApiDmpMapper { + + public DataManagementPlanPublicModel toPublicModel(Dmp dmp) { + DataManagementPlanPublicModel model = new DataManagementPlanPublicModel(); + model.setId(dmp.getId().toString()); + model.setLabel(dmp.getLabel()); + model.setDescription(dmp.getDescription()); + model.setVersion(dmp.getVersion()); + model.setGroupId(dmp.getGroupId()); + + model.setUsers(dmp.getDmpUsers().stream().map(UserInfoPublicModel::fromDmpUser).toList()); + model.setResearchers(dmp.getDmpReferences().stream().map(ResearcherPublicModel::fromDmpReference).filter(Objects::isNull).toList()); + + model.setCreatedAt(Date.from(dmp.getCreatedAt())); + model.setModifiedAt(Date.from(dmp.getUpdatedAt())); + model.setFinalizedAt(Date.from(dmp.getFinalizedAt())); + + return model; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/LanguagePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/LanguagePersist.java new file mode 100644 index 000000000..f328a44a1 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/LanguagePersist.java @@ -0,0 +1,56 @@ +package eu.eudat.model.persist; + +import eu.eudat.commons.validation.ValidId; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +import java.util.UUID; + +public class LanguagePersist { + @ValidId(message = "{validation.invalidid}") + private UUID id; + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + @Size(max = 20, message = "{validation.largerthanmax}") + private String code; + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + private String payload; + + private String hash; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public String getHash() { + return hash; + } + + public void setHash(String hash) { + this.hash = hash; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/StorageFilePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/StorageFilePersist.java new file mode 100644 index 000000000..55a8df9d2 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/StorageFilePersist.java @@ -0,0 +1,86 @@ +package eu.eudat.model.persist; + +import eu.eudat.commons.enums.StorageType; +import eu.eudat.commons.validation.ValidEnum; +import eu.eudat.data.StorageFileEntity; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +import java.time.Duration; +import java.util.UUID; + +public class StorageFilePersist { + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + @Size(max = StorageFileEntity._nameLen, message = "{validation.largerthanmax}") + private String name; + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + @Size(max = StorageFileEntity._extensionLen, message = "{validation.largerthanmax}") + private String extension; + + + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + @Size(max = StorageFileEntity._mimeTypeLen, message = "{validation.largerthanmax}") + private String mimeType; + + @NotNull(message = "{validation.empty}") + @ValidEnum(message = "{validation.empty}") + private StorageType storageType; + private Duration lifetime; + + private UUID ownerId; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = extension; + } + + public String getMimeType() { + return mimeType; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public StorageType getStorageType() { + return storageType; + } + + public void setStorageType(StorageType storageType) { + this.storageType = storageType; + } + + public UUID getOwnerId() { + return ownerId; + } + + public void setOwnerId(UUID ownerId) { + this.ownerId = ownerId; + } + + public Duration getLifetime() { + return lifetime; + } + + public void setLifetime(Duration lifetime) { + this.lifetime = lifetime; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/DataModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/DataModel.java new file mode 100644 index 000000000..359fb8852 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/DataModel.java @@ -0,0 +1,12 @@ +package eu.eudat.model.publicapi; + + +import eu.eudat.data.old.queryableentity.DataEntity; + +public interface DataModel, M extends DataModel> { + M fromDataModel(T entity); + + T toDataModel() throws Exception; + + String getHint(); +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/HintedModelFactory.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/HintedModelFactory.java new file mode 100644 index 000000000..5a5ffcf86 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/HintedModelFactory.java @@ -0,0 +1,22 @@ +package eu.eudat.model.publicapi; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationTargetException; + +public class HintedModelFactory { + private static final Logger logger = LoggerFactory.getLogger(HintedModelFactory.class); + + public static > String getHint(Class clazz) { + try { + return clazz.getDeclaredConstructor().newInstance().getHint(); + } catch (InstantiationException | IllegalAccessException e) { + logger.error(e.getMessage(), e); + return null; + } catch (InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/associatedprofile/AssociatedProfilePublicModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/associatedprofile/AssociatedProfilePublicModel.java similarity index 97% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/associatedprofile/AssociatedProfilePublicModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/associatedprofile/AssociatedProfilePublicModel.java index e62d8410a..278640dc4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/associatedprofile/AssociatedProfilePublicModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/associatedprofile/AssociatedProfilePublicModel.java @@ -1,4 +1,4 @@ -package eu.eudat.publicapi.models.associatedprofile; +package eu.eudat.model.publicapi.associatedprofile; import eu.eudat.data.DescriptionTemplateEntity; import eu.eudat.commons.types.xml.XmlSerializable; diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetprofile/DatasetProfilePublicModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetprofile/DatasetProfilePublicModel.java similarity index 72% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetprofile/DatasetProfilePublicModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetprofile/DatasetProfilePublicModel.java index 6936eac5b..03ff3ec3e 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetprofile/DatasetProfilePublicModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetprofile/DatasetProfilePublicModel.java @@ -1,11 +1,10 @@ -package eu.eudat.publicapi.models.datasetprofile; +package eu.eudat.model.publicapi.datasetprofile; import eu.eudat.data.DescriptionTemplateEntity; -import eu.eudat.models.DataModel; import java.util.UUID; -public class DatasetProfilePublicModel implements DataModel { +public class DatasetProfilePublicModel { private UUID id; private String label; @@ -23,14 +22,12 @@ public class DatasetProfilePublicModel implements DataModel, LabelGenerator { +public class DataRepositoryPublicModel { private String id; private String pid; private String name; @@ -124,12 +122,10 @@ public class DataRepositoryPublicModel implements DataModel sections; + private List rules; + private List pages; + private int status; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List
getSections() { + return sections; + } + + public void setSections(List
sections) { + this.sections = sections; + } + + + public List getRules() { + return rules; + } + + public void setRules(List rules) { + this.rules = rules; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public List getPages() { + return pages; + } + + public void setPages(List pages) { + this.pages = pages; + } + + @Override + public void fromJsonObject(Map properties) { + this.sections.forEach(item -> item.fromJsonObject(properties)); + + } + + @Override + public void fromJsonObject(Map properties, String index) { + // TODO Auto-generated method stub + + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/DatasetProfilePage.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/DatasetProfilePage.java new file mode 100644 index 000000000..dbe027089 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/DatasetProfilePage.java @@ -0,0 +1,33 @@ +package eu.eudat.model.publicapi.datasetwizard; + +import java.util.List; + +public class DatasetProfilePage { + private Integer ordinal; + private String title; + private List
sections; + + public Integer getOrdinal() { + return ordinal; + } + + public void setOrdinal(Integer ordinal) { + this.ordinal = ordinal; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List
getSections() { + return sections; + } + + public void setSections(List
sections) { + this.sections = sections; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/ExternalDatasetPublicListingModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/ExternalDatasetPublicListingModel.java similarity index 92% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/ExternalDatasetPublicListingModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/ExternalDatasetPublicListingModel.java index 13e8f2239..5b37a3564 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/ExternalDatasetPublicListingModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/ExternalDatasetPublicListingModel.java @@ -1,13 +1,11 @@ -package eu.eudat.publicapi.models.datasetwizard; +package eu.eudat.model.publicapi.datasetwizard; import eu.eudat.data.old.ExternalDataset; -import eu.eudat.models.DataModel; -import eu.eudat.types.externalsourcetype.ExternalDatasetType; import java.util.Date; import java.util.UUID; -public class ExternalDatasetPublicListingModel implements DataModel { +public class ExternalDatasetPublicListingModel { private UUID id; private String name; private String abbreviation; @@ -105,7 +103,6 @@ public class ExternalDatasetPublicListingModel implements DataModel multiplicityItems; + private List validations; + private VisibilityEntity visible; + private List schematics; + + private Boolean export; + + public List getMultiplicityItems() { + return multiplicityItems; + } + + public void setMultiplicityItems(List multiplicityItems) { + this.multiplicityItems = multiplicityItems; + } + + public void setOrdinal(Integer ordinal) { + this.ordinal = ordinal; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Integer getOrdinal() { + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public FieldDescriptionEntity getViewStyle() { + return viewStyle; + } + + public void setViewStyle(FieldDescriptionEntity viewStyle) { + this.viewStyle = viewStyle; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public DefaultValueEntity getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(DefaultValueEntity defaultValue) { + this.defaultValue = defaultValue; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + public MultiplicityEntity getMultiplicity() { + return multiplicity; + } + + public void setMultiplicity(MultiplicityEntity multiplicity) { + this.multiplicity = multiplicity; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public VisibilityEntity getVisible() { + return visible; + } + + public void setVisible(VisibilityEntity visible) { + this.visible = visible; + } + + public List getValidations() { + if(this.validations == null) { + return null; + } + return this.validations.stream().map(item -> (int) item.getValue()).collect(Collectors.toList()); + } + + public void setValidations(List validations) { + this.validations = validations.stream().map(x-> FieldValidationType.of(x.shortValue())).collect(Collectors.toList()); + } + + public String getNumbering() { + return numbering; + } + + public void setNumbering(String numbering) { + this.numbering = numbering; + } + + public List getSchematics() { + return schematics; + } + + public void setSchematics(List schematics) { + this.schematics = schematics; + } + + public Boolean getExport() { + return export; + } + + public void setExport(Boolean export) { + this.export = export; + } + + Field cloneForMultiplicity(String key, Map properties, int index) { + Field newField = new Field(); + newField.id = key; + newField.ordinal = this.ordinal; + newField.value = properties.containsKey(key)? properties.get(key): null; + newField.viewStyle = this.viewStyle; + newField.datatype = this.datatype; + newField.page = this.page; + newField.defaultValue = this.defaultValue; + newField.data = this.data; + newField.validations = this.validations; + newField.schematics = this.schematics; + newField.numbering = "mult" + index + "_" + this.numbering; + newField.export = this.export; + return newField; + } + + public FieldEntity toDatabaseDefinition(FieldEntity fieldEntity) { + fieldEntity.setId(this.id); + fieldEntity.setOrdinal(this.ordinal); + throw new NotImplementedException(" Use new logic"); + //TODO: Use new logic +// fieldEntity.setData(new FieldDataHelper().toFieldData(data, this.viewStyle.getFieldType())); +// fieldEntity.setDefaultValue(this.defaultValue.getValue()); +// fieldEntity.setVisibilityRules(this.visible.getRules()); +// fieldEntity.setValidations(this.validations); +// fieldEntity.setSchematics(this.schematics); +// fieldEntity.setIncludeInExport(this.export); +// return fieldEntity; + } + + public void fromDatabaseDefinition(FieldEntity item) { + this.id = item.getId(); + this.ordinal = item.getOrdinal(); + FieldDescriptionEntity fieldDescription = new FieldDescriptionEntity(); + fieldDescription.setFieldType(item.getData().getFieldType()); + this.viewStyle = fieldDescription; + this.numbering = item.getNumbering(); + this.data = item.getData(); + + DefaultValueEntity defaultValueEntity = new DefaultValueEntity(); + defaultValueEntity.setValue(item.getDefaultValue()); + this.defaultValue = defaultValueEntity; + VisibilityEntity visibilityEntity = new VisibilityEntity(); + visibilityEntity.setRules(item.getVisibilityRules()); + this.visible = visibilityEntity; + this.validations = item.getValidations(); + this.schematics = item.getSchematics(); + this.export = item.getIncludeInExport(); + } + + @Override + public void fromJsonObject(Map properties) { + try { + ObjectMapper mapper = new ObjectMapper(); + List stringList = mapper.readValue(properties.get(this.id).toString(), LinkedList.class); + this.value = stringList; + } catch (JSONException | NullPointerException | IOException e) { + try { + this.value = (String) properties.get(this.id); + } catch (ClassCastException ce) { + this.value = properties.get(this.id); + } + } + this.multiplicityItems = new LinkedList<>(); + List compositeKeys = properties.keySet().stream().filter(keys -> keys.startsWith("multiple_" + this.getId())).collect(Collectors.toList()); + int index = 1; + for (String key : compositeKeys) { + this.multiplicityItems.add(this.cloneForMultiplicity(key, properties, index)); + } + } + + @Override + public int compareTo(Object o) { + Field comparedField = (Field) o; + if(this.ordinal != null) { + return this.ordinal.compareTo(comparedField.getOrdinal()); + } else if (comparedField.getOrdinal() != null) { + return comparedField.getOrdinal().compareTo(this.ordinal); + } else { + return 0; + } + } + + @Override + public void fromJsonObject(Map properties, String path) { + this.value = (String) properties.get(path); + } + + public void toMap(Map fieldValues) { + if (this.value != null) { + if ((this.viewStyle != null && this.viewStyle.getFieldType().equals("datasetIdentifier") && this.value instanceof Map || this.value instanceof Collection)) { + ObjectMapper mapper = new ObjectMapper(); + String valueString = null; + try { + valueString = mapper.writeValueAsString(this.value); + fieldValues.put(this.id, valueString); + } catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); + } + } /*else if (this.value instanceof Collection) { + Collection valueCollection = (Collection) this.value; + StringBuilder valueBuilder = new StringBuilder(); + valueBuilder.append("["); + for (int i = 0; i < valueCollection.size(); i++) { + valueBuilder.append("\"").append(valueCollection.toArray()[i]).append("\""); + if (i < valueCollection.size() - 1) { + valueBuilder.append(", "); + } + } + valueBuilder.append("]"); + fieldValues.put(this.id, valueBuilder.toString()); + }*/ + else if ((this.viewStyle != null && this.viewStyle.getFieldType().equals("upload"))) { + fieldValues.put(this.id, this.value); + } + else { + fieldValues.put(this.id, this.value.toString()); + } + } else { + fieldValues.put(this.id, ""); + } + } + + public void toMap(Map fieldValues, int index) { + fieldValues.put(this.id, this.value); + } +} \ No newline at end of file diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/FieldSet.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/FieldSet.java new file mode 100644 index 000000000..8dc43d8c1 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/FieldSet.java @@ -0,0 +1,215 @@ +package eu.eudat.model.publicapi.datasetwizard; + +import eu.eudat.commons.types.descriptiontemplate.FieldSetEntity; +import eu.eudat.commons.types.descriptiontemplate.MultiplicityEntity; + +import java.util.*; +import java.util.stream.Collectors; + +public class FieldSet implements Comparable, PropertiesModelBuilder { + private String id; + private Integer ordinal; + private String title; + private String numbering; + private String description; + private String extendedDescription; + private String additionalInformation; + private MultiplicityEntity multiplicity; + private List fields; + private List
multiplicityItems; + private boolean hasCommentField; + private String commentFieldValue; + + public List getFields() { + Collections.sort(this.fields); + return fields; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getExtendedDescription() { + return extendedDescription; + } + + public void setExtendedDescription(String extendedDescription) { + this.extendedDescription = extendedDescription; + } + + public void setFields(List fields) { + this.fields = fields; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getOrdinal() { + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } + + public MultiplicityEntity getMultiplicity() { + return multiplicity; + } + + public void setMultiplicity(MultiplicityEntity multiplicity) { + this.multiplicity = multiplicity; + } + + public List
getMultiplicityItems() { + if (multiplicityItems != null) Collections.sort(multiplicityItems); + return multiplicityItems; + } + + public String getNumbering() { + return numbering; + } + + public void setNumbering(String numbering) { + this.numbering = numbering; + } + + public void setMultiplicityItems(List
multiplicityItems) { + this.multiplicityItems = multiplicityItems; + } + + public void setOrdinal(Integer ordinal) { + this.ordinal = ordinal; + } + + public void setHasCommentField(boolean hasCommentField) { + this.hasCommentField = hasCommentField; + } + + public boolean getHasCommentField() { + return hasCommentField; + } + + public String getCommentFieldValue() { + return commentFieldValue; + } + + public void setCommentFieldValue(String commentFieldValue) { + this.commentFieldValue = commentFieldValue; + } + + public String getAdditionalInformation() { + return additionalInformation; + } + + public void setAdditionalInformation(String additionalInformation) { + this.additionalInformation = additionalInformation; + } + + public FieldSetEntity toDatabaseDefinition(FieldSetEntity item) { +// List viewStylefields = new ModelBuilder().toViewStyleDefinition(this.fields, FieldEntity.class); +// item.setFields(viewStylefields); +// item.setId(this.id); +// item.setOrdinal(this.ordinal); +// item.setHasCommentField(this.hasCommentField); +// item.setMultiplicity(this.multiplicity); +//// item.setCommentFieldValue(this.commentFieldValue); +// return item; + return null; + } + + + public void fromDatabaseDefinition(FieldSetEntity item) { +// this.fields = new ModelBuilder().fromViewStyleDefinition(item.getFields(), Field.class); +// this.id = item.getId(); +// this.ordinal = item.getOrdinal(); +// this.title = item.getTitle(); +// this.description = item.getDescription(); +// this.additionalInformation=item.getAdditionalInformation(); +// this.numbering = item.getNumbering(); +// this.extendedDescription = item.getExtendedDescription(); +// this.hasCommentField = item.getHasCommentField(); +// this.multiplicity = item.getMultiplicity(); +//// this.commentFieldValue = item.getCommentFieldValue(); + } + + @Override + public void fromJsonObject(Map properties) { + this.commentFieldValue = (String) properties.get("commentFieldValue" + this.id); + this.multiplicityItems = new LinkedList
(); + this.fields.forEach(item -> { + item.fromJsonObject(properties); + }); + List compositeKeysFather = properties.keySet().stream().filter(keys -> keys.startsWith("multiple_" + this.getId())).collect(Collectors.toList()); + List Ids=new ArrayList<>(); + int index = 1; + for (String composite : compositeKeysFather) { + String[] split = composite.split("_"); + if (!Ids.contains(split[2])) { + Ids.add(split[2]); + this.multiplicityItems.add(this.CloneForMultiplicity2(properties.keySet().stream().filter(keys -> keys.startsWith("multiple_" + this.getId() + "_" + split[2])).collect(Collectors.toList()), properties,split, index)); + index++; + } + } + } + + private FieldSet CloneForMultiplicity2(List key, Map properties,String[] ids, int index){ + FieldSet newFieldSet = new FieldSet(); + newFieldSet.id = ids[0]+"_"+ids[1]+"_"+ids[2] + (ids.length > 4 ? "_" + ids[3] : ""); + newFieldSet.description = this.description; + newFieldSet.extendedDescription = this.extendedDescription; + newFieldSet.additionalInformation=this.additionalInformation; + newFieldSet.title = this.title; + newFieldSet.ordinal = ids.length > 4 ? Integer.valueOf(ids[3]) : this.ordinal; + newFieldSet.fields = new LinkedList(); + + for (Field field: this.fields) { + newFieldSet.fields.add(field.cloneForMultiplicity(newFieldSet.id + "_" + field.getId(), properties, index)); + } + return newFieldSet; + } + + + + @Override + public int compareTo(Object o) { + return this.ordinal.compareTo(((FieldSet) o).getOrdinal()); + } + + @Override + public void fromJsonObject(Map properties, String path) { + // TODO Auto-generated method stub + + } + + public void toMap(Map fieldValues) { + fieldValues.put("commentFieldValue" + this.id, this.commentFieldValue); + this.fields.forEach(item -> item.toMap(fieldValues)); + Map multiplicity = new HashMap(); + if (this.multiplicityItems != null) { + this.multiplicityItems.forEach(item -> item.toMap(fieldValues, this.multiplicityItems.indexOf(item))); + } + //fieldValues.put(this.id,multiplicity); + } + + public void toMap(Map fieldValues, int index) { + this.fields.forEach(item -> item.toMap(fieldValues, index)); + //this.multiplicityItems.forEach(item->item.toMap(fieldValues,index)); + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/Page.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/Page.java new file mode 100644 index 000000000..a22dde89d --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/Page.java @@ -0,0 +1,51 @@ +package eu.eudat.model.publicapi.datasetwizard; + +import eu.eudat.commons.types.descriptiontemplate.PageEntity; + +public class Page implements Comparable { + private String id; + private Integer ordinal; + private String title; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getOrdinal() { + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public PageEntity toDatabaseDefinition(PageEntity item) { + item.setId(this.id); + item.setOrdinal(this.ordinal); + item.setTitle(this.title); + return item; + } + + public void fromDatabaseDefinition(PageEntity item) { + this.title = item.getTitle(); + this.ordinal = item.getOrdinal(); + this.id = item.getId(); + } + + @Override + public int compareTo(Object o) { + return this.ordinal.compareTo((Integer) o); + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/PagedDatasetProfile.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/PagedDatasetProfile.java new file mode 100644 index 000000000..7a6677514 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/PagedDatasetProfile.java @@ -0,0 +1,60 @@ +package eu.eudat.model.publicapi.datasetwizard; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class PagedDatasetProfile { + private List pages; + private List rules; + private int status; + + public List getPages() { + return pages; + } + + public void setPages(List pages) { + this.pages = pages; + } + + public List getRules() { + return rules; + } + + public void setRules(List rules) { + this.rules = rules; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public PagedDatasetProfile buildPagedDatasetProfile(DatasetProfile profile) { + this.status = profile.getStatus(); + this.rules = profile.getRules(); + this.pages = new LinkedList<>(); + List pages = profile.getPages(); + for (Page page : pages) { + DatasetProfilePage datasetProfilePage = new DatasetProfilePage(); + datasetProfilePage.setOrdinal(page.getOrdinal()); + datasetProfilePage.setTitle(page.getTitle()); + datasetProfilePage.setSections(profile.getSections().stream().filter(item -> item.getPage().equals(page.getId())).collect(Collectors.toList())); + this.pages.add(datasetProfilePage); + } + + return this; + } + + public void toMap(Map fieldValues) { + this.pages.forEach(item -> item.getSections().forEach(sectionItem -> sectionItem.toMap(fieldValues))); + } + + public void toMap(Map fieldValues, int index) { + + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/PropertiesModelBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/PropertiesModelBuilder.java new file mode 100644 index 000000000..08f55ed9c --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/PropertiesModelBuilder.java @@ -0,0 +1,9 @@ +package eu.eudat.model.publicapi.datasetwizard; + +import java.util.Map; + +public interface PropertiesModelBuilder { + void fromJsonObject(Map properties); + + void fromJsonObject(Map properties, String pathKey); +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/RegistryPublicModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/RegistryPublicModel.java similarity index 91% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/RegistryPublicModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/RegistryPublicModel.java index 9e6a5a34f..168976d46 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/RegistryPublicModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/RegistryPublicModel.java @@ -1,13 +1,11 @@ -package eu.eudat.publicapi.models.datasetwizard; +package eu.eudat.model.publicapi.datasetwizard; import eu.eudat.data.old.Registry; -import eu.eudat.logic.utilities.helpers.LabelGenerator; -import eu.eudat.models.DataModel; import java.util.Date; import java.util.UUID; -public class RegistryPublicModel implements DataModel, LabelGenerator { +public class RegistryPublicModel { private UUID id; private String label; private String abbreviation; @@ -33,7 +31,7 @@ public class RegistryPublicModel implements DataModel, PropertiesModelBuilder { + private List
sections; + private List
compositeFields; + private Boolean defaultVisibility; + private String numbering; + private String page; + private Integer ordinal; + private String id; + private String title; + private String description; + private Boolean multiplicity; + + public List
getSections() { + Collections.sort(sections); + return sections; + } + + public void setSections(List
sections) { + this.sections = sections; + } + + public List
getCompositeFields() { + Collections.sort(compositeFields); + return compositeFields; + } + + public void setCompositeFields(List
compositeFields) { + this.compositeFields = compositeFields; + } + + public Boolean getDefaultVisibility() { + return defaultVisibility; + } + + public void setDefaultVisibility(Boolean defaultVisibility) { + this.defaultVisibility = defaultVisibility; + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getOrdinal() { + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } + + public String getNumbering() { + return numbering; + } + + public void setNumbering(String numbering) { + this.numbering = numbering; + } + + public Boolean getMultiplicity() { + return multiplicity; + } + + public void setMultiplicity(Boolean multiplicity) { + this.multiplicity = multiplicity; + } + + public SectionEntity toDatabaseDefinition(SectionEntity item) { +// item.setDefaultVisibility(this.defaultVisibility); +// item.setDescription(this.description); +// if (this.compositeFields != null) +// item.setFieldSets(new ModelBuilder().toViewStyleDefinition(this.compositeFields, FieldSetEntity.class)); +// item.setId(this.id); +// item.setOrdinal(this.ordinal); +// item.setPage(this.page); +// if (this.sections != null) +// item.setSections(new ModelBuilder().toViewStyleDefinition(this.sections, SectionEntity.class)); +// item.setTitle(this.title); +// item.setMultiplicity(this.multiplicity); +// return item; + return null; + } + + public void fromDatabaseDefinition(SectionEntity item) { +// this.defaultVisibility = item.isDefaultVisibility(); +// this.description = item.getDescription(); +// this.compositeFields = new ModelBuilder().fromViewStyleDefinition(item.getFieldSets(), FieldSet.class); +// this.id = item.getId(); +// this.ordinal = item.getOrdinal(); +// this.numbering = item.getNumbering(); +// this.page = item.getPage(); +// this.sections = new ModelBuilder().fromViewStyleDefinition(item.getSections(), Section.class); +// this.title = item.getTitle(); +// this.multiplicity = item.getMultiplicity(); + } + + @Override + public void fromJsonObject(Map properties) { + this.sections.forEach(item -> item.fromJsonObject(properties)); + this.compositeFields.forEach(item -> item.fromJsonObject(properties)); + } + + @Override + public int compareTo(Object o) { + return this.ordinal.compareTo(((Section) o).getOrdinal()); + } + + @Override + public void fromJsonObject(Map properties, String index) { + // TODO Auto-generated method stub + + } + + public void toMap(Map fieldValues) { + this.sections.forEach(item -> item.toMap(fieldValues)); + this.compositeFields.forEach(item -> item.toMap(fieldValues)); + } + + public void toMap(Map fieldValues, int index) { + + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/ServicePublicModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/ServicePublicModel.java similarity index 91% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/ServicePublicModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/ServicePublicModel.java index 6e9359da5..83a8edea6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/datasetwizard/ServicePublicModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/datasetwizard/ServicePublicModel.java @@ -1,13 +1,11 @@ -package eu.eudat.publicapi.models.datasetwizard; +package eu.eudat.model.publicapi.datasetwizard; import eu.eudat.data.old.Service; -import eu.eudat.logic.utilities.helpers.LabelGenerator; -import eu.eudat.models.DataModel; import java.util.Date; import java.util.UUID; -public class ServicePublicModel implements DataModel, LabelGenerator { +public class ServicePublicModel { private UUID id; private String label; private String abbreviation; @@ -101,12 +99,10 @@ public class ServicePublicModel implements DataModel { +public class FunderPublicOverviewModel { private UUID id; private String label; @@ -23,19 +22,16 @@ public class FunderPublicOverviewModel implements DataModel { +public class GrantPublicOverviewModel { private UUID id; private String label; private String abbreviation; @@ -73,7 +72,6 @@ public class GrantPublicOverviewModel implements DataModel { +public class DataManagementPlanPublicListingModel { private String id; private String label; private String grant; @@ -17,7 +14,7 @@ public class DataManagementPlanPublicListingModel implements DataModel users; + private List users; private List researchers; private Date finalizedAt; private Date publishedAt; @@ -71,10 +68,10 @@ public class DataManagementPlanPublicListingModel implements DataModel getUsers() { + public List getUsers() { return users; } - public void setUsers(List users) { + public void setUsers(List users) { this.users = users; } @@ -99,7 +96,6 @@ public class DataManagementPlanPublicListingModel implements DataModel new UserInfoPublicModel().fromDataModel(x)).collect(Collectors.toList()) : new ArrayList<>(); -// this.researchers = entity.getResearchers() != null ? entity.getResearchers().stream().map(x -> new ResearcherPublicModel().fromDataModel(x)).collect(Collectors.toList()) : new ArrayList<>(); -// } -// catch(Exception ex){ -// this.users = new ArrayList<>(); -// this.researchers = new ArrayList<>(); -// } -// this.finalizedAt = entity.getFinalizedAt(); -// this.publishedAt = entity.getPublishedAt(); - return this; } - @Override public DmpEntity toDataModel() { DmpEntity entity = new DmpEntity(); entity.setId(UUID.fromString(this.getId())); entity.setLabel(this.getLabel()); entity.setGroupId(this.getGroupId()); -// entity.setCreated(this.getCreatedAt()); //TODO -// entity.setFinalizedAt(this.getFinalizedAt()); -// entity.setModified(this.getModifiedAt()); -// entity.setPublishedAt(this.getPublishedAt()); -// entity.setVersion(this.getVersion()); -// -// if (this.getGrant() != null) { -// Grant grant = new Grant(); -// grant.setLabel(this.getGrant()); -// entity.setGrant(grant); -// } -// entity.setUsers(this.getUsers().stream().map(UserInfoPublicModel::toDataModel).collect(Collectors.toSet())); -// entity.setResearchers(this.getResearchers().stream().map(ResearcherPublicModel::toDataModel).collect(Collectors.toSet())); return entity; } - @Override - public String getHint() { + public static String getHint() { return "fullyDetailed"; } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/listingmodels/DatasetPublicListingModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/listingmodels/DatasetPublicListingModel.java new file mode 100644 index 000000000..09fab7fa8 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/listingmodels/DatasetPublicListingModel.java @@ -0,0 +1,129 @@ +package eu.eudat.model.publicapi.listingmodels; + +import eu.eudat.data.DescriptionEntity; +import eu.eudat.model.publicapi.datasetprofile.DatasetProfilePublicModel; +import eu.eudat.model.publicapi.user.UserInfoPublicModel; + +import java.util.Date; +import java.util.List; + +public class DatasetPublicListingModel { + private String id; + private String label; + private String grant; + private String dmp; + private String dmpId; + private DatasetProfilePublicModel profile; + private Date createdAt; + private Date modifiedAt; + private String description; + private Date finalizedAt; + private Date dmpPublishedAt; + private int version; + private List users; + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public String getGrant() { + return grant; + } + public void setGrant(String grant) { + this.grant = grant; + } + + public String getDmp() { + return dmp; + } + public void setDmp(String dmp) { + this.dmp = dmp; + } + + public String getDmpId() { + return dmpId; + } + public void setDmpId(String dmpId) { + this.dmpId = dmpId; + } + + public DatasetProfilePublicModel getProfile() { + return profile; + } + public void setProfile(DatasetProfilePublicModel profile) { + this.profile = profile; + } + + public Date getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getModifiedAt() { + return modifiedAt; + } + public void setModifiedAt(Date modifiedAt) { + this.modifiedAt = modifiedAt; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public Date getFinalizedAt() { + return finalizedAt; + } + public void setFinalizedAt(Date finalizedAt) { + this.finalizedAt = finalizedAt; + } + + public Date getDmpPublishedAt() { + return dmpPublishedAt; + } + public void setDmpPublishedAt(Date dmpPublishedAt) { + this.dmpPublishedAt = dmpPublishedAt; + } + + public int getVersion() { + return version; + } + public void setVersion(int version) { + this.version = version; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + + public DatasetPublicListingModel fromDataModel(DescriptionEntity entity) { + return this; + } + + public DescriptionEntity toDataModel() { + DescriptionEntity entity = new DescriptionEntity(); + return entity; + } + + public static String getHint() { + return "datasetListingModel"; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/organisation/OrganizationPublicModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/organisation/OrganizationPublicModel.java similarity index 91% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/organisation/OrganizationPublicModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/organisation/OrganizationPublicModel.java index 05157ceba..4c802a24c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/organisation/OrganizationPublicModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/organisation/OrganizationPublicModel.java @@ -1,14 +1,12 @@ -package eu.eudat.publicapi.models.organisation; +package eu.eudat.model.publicapi.organisation; import eu.eudat.data.old.Organisation; -import eu.eudat.logic.utilities.helpers.LabelGenerator; -import eu.eudat.models.DataModel; import java.util.Date; import java.util.HashMap; import java.util.UUID; -public class OrganizationPublicModel implements DataModel, LabelGenerator { +public class OrganizationPublicModel { private String label; private String name; private String id; @@ -66,7 +64,6 @@ public class OrganizationPublicModel implements DataModel organisations; + private int version; + private UUID groupId; + private List datasets; + private List associatedProfiles; + private List researchers; + private List users; + private String description; + private Date publishedAt; + private List dois; + + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public String getProfile() { + return profile; + } + public void setProfile(String profile) { + this.profile = profile; + } + + public GrantPublicOverviewModel getGrant() { + return grant; + } + public void setGrant(GrantPublicOverviewModel grant) { + this.grant = grant; + } + + public Date getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getModifiedAt() { + return modifiedAt; + } + public void setModifiedAt(Date modifiedAt) { + this.modifiedAt = modifiedAt; + } + + public Date getFinalizedAt() { + return finalizedAt; + } + public void setFinalizedAt(Date finalizedAt) { + this.finalizedAt = finalizedAt; + } + + public List getOrganisations() { + return organisations; + } + public void setOrganisations(List organizations) { + this.organisations = organizations; + } + + public int getVersion() { + return version; + } + public void setVersion(int version) { + this.version = version; + } + + public UUID getGroupId() { + return groupId; + } + public void setGroupId(UUID groupId) { + this.groupId = groupId; + } + + public List getDatasets() { + return datasets; + } + public void setDatasets(List datasets) { + this.datasets = datasets; + } + + public List getAssociatedProfiles() { + return associatedProfiles; + } + public void setAssociatedProfiles(List associatedProfiles) { + this.associatedProfiles = associatedProfiles; + } + + public List getUsers() { + return users; + } + public void setUsers(List users) { + this.users = users; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public List getResearchers() { + return researchers; + } + public void setResearchers(List researchers) { + this.researchers = researchers; + } + + public Date getPublishedAt() { + return publishedAt; + } + public void setPublishedAt(Date publishedAt) { + this.publishedAt = publishedAt; + } + + public List getDois() { + return dois; + } + public void setDois(List dois) { + this.dois = dois; + } + + public DmpEntity toDataModel() { + return null; + } + + public String getHint() { + return "dataManagementPlanOverviewModel"; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DatasetPublicModel.java b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/overviewmodels/DatasetPublicModel.java similarity index 94% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DatasetPublicModel.java rename to dmp-backend/core/src/main/java/eu/eudat/model/publicapi/overviewmodels/DatasetPublicModel.java index 9f20b8fbe..d5501211d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DatasetPublicModel.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/publicapi/overviewmodels/DatasetPublicModel.java @@ -1,19 +1,14 @@ -package eu.eudat.publicapi.models.overviewmodels; +package eu.eudat.model.publicapi.overviewmodels; import eu.eudat.commons.enums.DescriptionStatus; +import eu.eudat.model.publicapi.datasetprofile.DatasetProfilePublicModel; +import eu.eudat.model.publicapi.datasetwizard.*; +import eu.eudat.model.publicapi.listingmodels.DataManagementPlanPublicListingModel; import eu.eudat.data.DescriptionEntity; -import eu.eudat.models.DataModel; -import eu.eudat.models.data.user.composite.PagedDatasetProfile; -import eu.eudat.publicapi.models.datasetprofile.DatasetProfilePublicModel; -import eu.eudat.publicapi.models.datasetwizard.DataRepositoryPublicModel; -import eu.eudat.publicapi.models.datasetwizard.ExternalDatasetPublicListingModel; -import eu.eudat.publicapi.models.datasetwizard.RegistryPublicModel; -import eu.eudat.publicapi.models.datasetwizard.ServicePublicModel; -import eu.eudat.publicapi.models.listingmodels.DataManagementPlanPublicListingModel; import java.util.*; -public class DatasetPublicModel implements DataModel { +public class DatasetPublicModel { private UUID id; private String label; private String reference; @@ -143,7 +138,6 @@ public class DatasetPublicModel implements DataModel { + + private String like; + + private Collection ids; + + private Collection isActives; + + private Collection codes; + + private Collection excludedIds; + + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + public LanguageQuery like(String value) { + this.like = value; + return this; + } + + public LanguageQuery ids(UUID value) { + this.ids = List.of(value); + return this; + } + + public LanguageQuery ids(UUID... value) { + this.ids = Arrays.asList(value); + return this; + } + + public LanguageQuery ids(Collection values) { + this.ids = values; + return this; + } + + public LanguageQuery isActive(IsActive value) { + this.isActives = List.of(value); + return this; + } + + public LanguageQuery isActive(IsActive... value) { + this.isActives = Arrays.asList(value); + return this; + } + + public LanguageQuery isActive(Collection values) { + this.isActives = values; + return this; + } + + public LanguageQuery codes(String value) { + this.codes = List.of(value); + return this; + } + + public LanguageQuery codes(String... value) { + this.codes = Arrays.asList(value); + return this; + } + + public LanguageQuery codes(Collection values) { + this.codes = values; + return this; + } + + public LanguageQuery excludedIds(Collection values) { + this.excludedIds = values; + return this; + } + + public LanguageQuery excludedIds(UUID value) { + this.excludedIds = List.of(value); + return this; + } + + public LanguageQuery excludedIds(UUID... value) { + this.excludedIds = Arrays.asList(value); + return this; + } + + public LanguageQuery authorize(EnumSet values) { + this.authorize = values; + return this; + } + + public LanguageQuery( + ) { + } + + @Override + protected Class entityClass() { + return LanguageEntity.class; + } + + @Override + protected Boolean isFalseQuery() { + return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.excludedIds) || this.isEmpty(this.codes); + } + + @Override + protected Predicate applyFilters(QueryContext queryContext) { + List predicates = new ArrayList<>(); + if (this.ids != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._id)); + for (UUID item : this.ids) + inClause.value(item); + predicates.add(inClause); + } + if (this.like != null && !this.like.isEmpty()) { + predicates.add(queryContext.CriteriaBuilder.like(queryContext.Root.get(LanguageEntity._code), this.like)); + } + if (this.isActives != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._isActive)); + for (IsActive item : this.isActives) + inClause.value(item); + predicates.add(inClause); + } + if (this.codes != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._code)); + for (String item : this.codes) + inClause.value(item); + predicates.add(inClause); + } + if (this.excludedIds != null) { + CriteriaBuilder.In notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(LanguageEntity._id)); + for (UUID item : this.excludedIds) + notInClause.value(item); + predicates.add(notInClause.not()); + } + if (!predicates.isEmpty()) { + Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); + return queryContext.CriteriaBuilder.and(predicatesArray); + } else { + return null; + } + } + + @Override + protected LanguageEntity convert(Tuple tuple, Set columns) { + LanguageEntity item = new LanguageEntity(); + item.setId(QueryBase.convertSafe(tuple, columns, LanguageEntity._id, UUID.class)); + item.setCode(QueryBase.convertSafe(tuple, columns, LanguageEntity._code, String.class)); + item.setPayload(QueryBase.convertSafe(tuple, columns, LanguageEntity._payload, String.class)); + item.setCreatedAt(QueryBase.convertSafe(tuple, columns, LanguageEntity._createdAt, Instant.class)); + item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, LanguageEntity._updatedAt, Instant.class)); + item.setIsActive(QueryBase.convertSafe(tuple, columns, LanguageEntity._isActive, IsActive.class)); + return item; + } + + @Override + protected String fieldNameOf(FieldResolver item) { + if (item.match(Language._id)) return LanguageEntity._id; + else if (item.match(Language._code)) return LanguageEntity._code; + else if (item.match(Language._payload)) return LanguageEntity._payload; + else if (item.match(Language._createdAt)) return LanguageEntity._createdAt; + else if (item.match(Language._updatedAt)) return LanguageEntity._updatedAt; + else if (item.match(Language._hash)) return LanguageEntity._updatedAt; + else if (item.match(Language._isActive)) return LanguageEntity._isActive; + else return null; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/StorageFileQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/StorageFileQuery.java new file mode 100644 index 000000000..2aef9ced3 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/query/StorageFileQuery.java @@ -0,0 +1,206 @@ +package eu.eudat.query; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.authorization.Permission; +import eu.eudat.commons.enums.StorageType; +import eu.eudat.commons.scope.user.UserScope; +import eu.eudat.data.StorageFileEntity; +import eu.eudat.model.StorageFile; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.data.query.FieldResolver; +import gr.cite.tools.data.query.QueryBase; +import gr.cite.tools.data.query.QueryContext; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.Predicate; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.*; + +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class StorageFileQuery extends QueryBase { + private String like; + private Collection ids; + private Boolean canPurge; + private Boolean isPurged; + private Instant createdAfter; + private Collection excludedIds; + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + + private final UserScope userScope; + private final AuthorizationService authService; + public StorageFileQuery(UserScope userScope, AuthorizationService authService) { + this.userScope = userScope; + this.authService = authService; + } + + public StorageFileQuery like(String value) { + this.like = value; + return this; + } + + public StorageFileQuery ids(UUID value) { + this.ids = List.of(value); + return this; + } + + public StorageFileQuery ids(UUID... value) { + this.ids = Arrays.asList(value); + return this; + } + + public StorageFileQuery ids(Collection values) { + this.ids = values; + return this; + } + + public StorageFileQuery createdAfter(Instant value) { + this.createdAfter = value; + return this; + } + + public StorageFileQuery canPurge(Boolean value) { + this.canPurge = value; + return this; + } + + public StorageFileQuery isPurged(Boolean value) { + this.isPurged = value; + return this; + } + + public StorageFileQuery excludedIds(Collection values) { + this.excludedIds = values; + return this; + } + + public StorageFileQuery excludedIds(UUID value) { + this.excludedIds = List.of(value); + return this; + } + + public StorageFileQuery excludedIds(UUID... value) { + this.excludedIds = Arrays.asList(value); + return this; + } + + public StorageFileQuery authorize(EnumSet values) { + this.authorize = values; + return this; + } + + @Override + protected Boolean isFalseQuery() { + return + this.isEmpty(this.ids) || + this.isEmpty(this.excludedIds) ; + } + + @Override + protected Class entityClass() { + return StorageFileEntity.class; + } + + @Override + protected Predicate applyAuthZ(QueryContext queryContext) { + if (this.authorize.contains(AuthorizationFlags.None)) return null; + if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseStorageFile)) return null; + UUID userId; + if (this.authorize.contains(AuthorizationFlags.Owner)) userId = this.userScope.getUserIdSafe(); + else userId = null; + + List predicates = new ArrayList<>(); + if (userId != null) { + predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(StorageFileEntity._ownerId)).value(userId)); + } + if (!predicates.isEmpty()) { + Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); + return queryContext.CriteriaBuilder.and(predicatesArray); + } else { + return queryContext.CriteriaBuilder.or(); //Creates a false query + } + } + + @Override + protected Predicate applyFilters(QueryContext queryContext) { + List predicates = new ArrayList<>(); + if (this.like != null && !this.like.isEmpty()) { + predicates.add( queryContext.CriteriaBuilder.like(queryContext.Root.get(StorageFileEntity._name), this.like)); + } + if (this.ids != null) { + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(StorageFileEntity._id)); + for (UUID item : this.ids) + inClause.value(item); + predicates.add(inClause); + } + if (this.createdAfter != null) { + predicates.add(queryContext.CriteriaBuilder.greaterThan(queryContext.Root.get(StorageFileEntity._createdAt), this.createdAfter)); + } + if (this.canPurge != null) { + predicates.add( + queryContext.CriteriaBuilder.and( + queryContext.CriteriaBuilder.isNull(queryContext.Root.get(StorageFileEntity._purgeAt)).not(), + queryContext.CriteriaBuilder.lessThan(queryContext.Root.get(StorageFileEntity._purgeAt), Instant.now()) + ) + ); + } + if (this.isPurged != null) { + if (!this.isPurged){ + predicates.add(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(StorageFileEntity._purgedAt)).not()); + } else { + predicates.add(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(StorageFileEntity._purgedAt))); + } + } + if (this.excludedIds != null) { + CriteriaBuilder.In notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(StorageFileEntity._id)); + for (UUID item : this.excludedIds) + notInClause.value(item); + predicates.add(notInClause.not()); + } + + if (!predicates.isEmpty()) { + Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); + return queryContext.CriteriaBuilder.and(predicatesArray); + } else { + return null; + } + } + + @Override + protected String fieldNameOf(FieldResolver item) { + if (item.match(StorageFile._id)) return StorageFileEntity._id; + else if (item.match(StorageFile._name)) return StorageFileEntity._name; + else if (item.match(StorageFile._fileRef)) return StorageFileEntity._fileRef; + else if (item.match(StorageFile._fullName)) return StorageFileEntity._name; + else if (item.match(StorageFile._extension)) return StorageFileEntity._extension; + else if (item.match(StorageFile._mimeType)) return StorageFileEntity._mimeType; + else if (item.match(StorageFile._storageType)) return StorageFileEntity._storageType; + else if (item.match(StorageFile._createdAt)) return StorageFileEntity._createdAt; + else if (item.match(StorageFile._purgeAt)) return StorageFileEntity._purgeAt; + else if (item.match(StorageFile._purgedAt)) return StorageFileEntity._purgedAt; + else if (item.match(StorageFile._owner)) return StorageFileEntity._ownerId; + else if (item.prefix(StorageFile._owner)) return StorageFileEntity._ownerId; + else return null; + } + + @Override + protected StorageFileEntity convert(Tuple tuple, Set columns) { + StorageFileEntity item = new StorageFileEntity(); + item.setId(QueryBase.convertSafe(tuple, columns, StorageFileEntity._id, UUID.class)); + item.setName(QueryBase.convertSafe(tuple, columns, StorageFileEntity._name, String.class)); + item.setFileRef(QueryBase.convertSafe(tuple, columns, StorageFileEntity._fileRef, String.class)); + item.setExtension(QueryBase.convertSafe(tuple, columns, StorageFileEntity._extension, String.class)); + item.setMimeType(QueryBase.convertSafe(tuple, columns, StorageFileEntity._mimeType, String.class)); + item.setStorageType(QueryBase.convertSafe(tuple, columns, StorageFileEntity._storageType, StorageType.class)); + item.setCreatedAt(QueryBase.convertSafe(tuple, columns, StorageFileEntity._createdAt, Instant.class)); + item.setPurgeAt(QueryBase.convertSafe(tuple, columns, StorageFileEntity._purgeAt, Instant.class)); + item.setPurgedAt(QueryBase.convertSafe(tuple, columns, StorageFileEntity._purgedAt, Instant.class)); + item.setOwnerId(QueryBase.convertSafe(tuple, columns, StorageFileEntity._ownerId, UUID.class)); + return item; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/lookup/LanguageLookup.java b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/LanguageLookup.java new file mode 100644 index 000000000..57b7bc4aa --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/query/lookup/LanguageLookup.java @@ -0,0 +1,76 @@ +package eu.eudat.query.lookup; + +import eu.eudat.commons.enums.IsActive; +import eu.eudat.query.LanguageQuery; +import gr.cite.tools.data.query.Lookup; +import gr.cite.tools.data.query.QueryFactory; + +import java.util.List; +import java.util.UUID; + +public class LanguageLookup extends Lookup { + + private String like; + + private List isActive; + + private List codes; + + private List ids; + + private List excludedIds; + + public String getLike() { + return like; + } + + public void setLike(String like) { + this.like = like; + } + + public List getIsActive() { + return isActive; + } + + public void setIsActive(List isActive) { + this.isActive = isActive; + } + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + public List getExcludedIds() { + return excludedIds; + } + + public void setExcludedIds(List excludeIds) { + this.excludedIds = excludeIds; + } + + public List getCodes() { + return codes; + } + + public void setCodes(List codes) { + this.codes = codes; + } + + public LanguageQuery enrich(QueryFactory queryFactory) { + LanguageQuery query = queryFactory.query(LanguageQuery.class); + if (this.like != null) query.like(this.like); + if (this.isActive != null) query.isActive(this.isActive); + if (this.codes != null) query.codes(this.codes); + if (this.ids != null) query.ids(this.ids); + if (this.excludedIds != null) query.excludedIds(this.excludedIds); + + this.enrichCommon(query); + + return query; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageService.java b/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageService.java new file mode 100644 index 000000000..f072b0b38 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageService.java @@ -0,0 +1,19 @@ +package eu.eudat.service.language; + +import eu.eudat.model.Language; +import eu.eudat.model.persist.LanguagePersist; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.exception.MyValidationException; +import gr.cite.tools.fieldset.FieldSet; + +import javax.management.InvalidApplicationException; +import java.util.UUID; + +public interface LanguageService { + + Language persist(LanguagePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException; + + void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException; +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java new file mode 100644 index 000000000..0cac30f44 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/language/LanguageServiceImpl.java @@ -0,0 +1,102 @@ +package eu.eudat.service.language; + +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.authorization.Permission; +import eu.eudat.commons.enums.IsActive; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.LanguageEntity; +import eu.eudat.errorcode.ErrorThesaurusProperties; +import eu.eudat.model.Language; +import eu.eudat.model.builder.LanguageBuilder; +import eu.eudat.model.deleter.LanguageDeleter; +import eu.eudat.model.persist.LanguagePersist; +import eu.eudat.service.dmpblueprint.DmpBlueprintServiceImpl; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.deleter.DeleterFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.exception.MyValidationException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import jakarta.persistence.EntityManager; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Service; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.List; +import java.util.UUID; + +@Service +public class LanguageServiceImpl implements LanguageService { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DmpBlueprintServiceImpl.class)); + private final EntityManager entityManager; + private final AuthorizationService authorizationService; + private final DeleterFactory deleterFactory; + private final BuilderFactory builderFactory; + private final ConventionService conventionService; + private final MessageSource messageSource; + private final ErrorThesaurusProperties errors; + + + public LanguageServiceImpl( + EntityManager entityManager, AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, + ConventionService conventionService, MessageSource messageSource, ErrorThesaurusProperties errors){ + this.entityManager = entityManager; + this.authorizationService = authorizationService; + this.deleterFactory = deleterFactory; + this.builderFactory = builderFactory; + this.conventionService = conventionService; + this.messageSource = messageSource; + this.errors = errors; + } + + + public Language persist(LanguagePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException{ + logger.debug(new MapLogEntry("persisting data").And("model", model).And("fields", fields)); + + this.authorizationService.authorizeForce(Permission.EditLanguage); + + Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); + + LanguageEntity data; + if (isUpdate) { + data = this.entityManager.find(LanguageEntity.class, model.getId()); + if (data == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Language.class.getSimpleName()}, LocaleContextHolder.getLocale())); + if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage()); + } else { + + data = new LanguageEntity(); + data.setId(UUID.randomUUID()); + data.setIsActive(IsActive.Active); + data.setCreatedAt(Instant.now()); + } + + data.setCode(model.getCode()); + data.setPayload(model.getPayload()); + data.setUpdatedAt(Instant.now()); + + if (isUpdate) this.entityManager.merge(data); + else this.entityManager.persist(data); + + this.entityManager.flush(); + + return this.builderFactory.builder(LanguageBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Language._id), data); + } + + public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug("deleting : {}", id); + + this.authorizationService.authorizeForce(Permission.DeleteLanguage); + + this.deleterFactory.deleter(LanguageDeleter.class).deleteAndSaveByIds(List.of(id)); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicApiStaticHelpers.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicApiStaticHelpers.java new file mode 100644 index 000000000..9d16a55b3 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicApiStaticHelpers.java @@ -0,0 +1,424 @@ +package eu.eudat.controllers.publicapi; + +public final class PublicApiStaticHelpers { + + public static final class Dmp { + + public static final String getPagedNotes = "The json response is of type **ResponseItem>** containing the following properties:\n" + + "
    " + + "
  1. message: string, message indicating error, null if everything went well
  2. " + + "
  3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
  4. " + + "
  5. responseType: integer, 0 for json, 1 for file
  6. " + + "
  7. payload: DataTableData, containing the number of values of actual data returned and the data of type DataManagementPlanPublicListingModel
  8. " + + "
      " + + "
    1. id: string, id of dmp returned
    2. " + + "
    3. label: string, label of dmp
    4. " + + "
    5. grant: string, grant of dmp
    6. " + + "
    7. createdAt: date, creation time of dmp
    8. " + + "
    9. modifiedAt: date, modification time of dmp
    10. " + + "
    11. version: integer, version of dmp
    12. " + + "
    13. groupId: uuid, group id in which dmp belongs
    14. " + + "
    15. users: list of UserInfoPublicModel, user who collaborated on the dmp
    16. " + + "
    17. researchers: list of ResearcherPublicModel, researchers involved in the dmp
    18. " + + "
    19. finalizedAt: date, finalization date
    20. " + + "
    21. publishedAt: date, publication date
    22. " + + "
    " + + "
"; + + public static final String getPagedResponseExample = "{\n" + + " \"statusCode\": 0,\n" + + " \"responseType\": 0,\n" + + " \"message\": null,\n" + + " \"payload\": {\n" + + " \"totalCount\": 2,\n" + + " \"data\": [\n" + + " {\n" + + " \"id\": \"e9a73d77-adfa-4546-974f-4a4a623b53a8\",\n" + + " \"label\": \"Giorgos's DMP\",\n" + + " \"grant\": \"Novel EOSC services for Emerging Atmosphere, Underwater and Space Challenges\",\n" + + " \"createdAt\": 1579077317000,\n" + + " \"modifiedAt\": 1586444334000,\n" + + " \"version\": 0,\n" + + " \"groupId\": \"d949592d-f862-4b31-a43a-f5f70596df5e\",\n" + + " \"users\": [],\n" + + " \"finalizedAt\": 1586444334000,\n" + + " \"publishedAt\": 1586444334000,\n" + + " \"hint\": \"dataManagementPlanListingModel\"\n" + + " },\n" + + " {\n" + + " \"id\": \"e27789f1-de35-4b4a-9587-a46d131c366e\",\n" + + " \"label\": \"TestH2020Clone3\",\n" + + " \"grant\": \"Evaluation of the Benefits of innovative Concepts of laminar nacelle and HTP installed on a business jet configuration\",\n" + + " \"createdAt\": 1600774437000,\n" + + " \"modifiedAt\": 1600879107000,\n" + + " \"version\": 0,\n" + + " \"groupId\": \"7b793c17-cb69-41d2-a97d-e8d1b03ddbed\",\n" + + " \"users\": [],\n" + + " \"finalizedAt\": 1600879107000,\n" + + " \"publishedAt\": 1600879107000,\n" + + " \"hint\": \"dataManagementPlanListingModel\"\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + public static final String getPagedRequestBodyDescription = "The dmpTableRequest is a DataManagementPlanPublicTableRequest object with the following fields:\n" + + "
    " + + "
  • length: how many dmps should be fetched (required)
  • " + + "
  • offset: offset of the returned dmps, first time should be 0, then offset += length
  • " + + "
  • orderings: array of strings specifying the order, format:= +string or -string or asc or desc.
  • " + + "+ means ascending order. - means descending order.
        Available strings are: 1) status, 2) label, 3) publishedAt, 4) created.
    " + + "    asc equivalent to +label.
        desc equivalent to -label.
    " + + "
  • criteria: this is DataManagementPlanPublicCriteria object which applies filters for the dmp returned. More specifically:
  • " + + "
      " + + "
    1. periodStart: date, dmps created date greater than periodStart
    2. " + + "
    3. periodEnd: date, dmps created date less than periodEnd
    4. " + + "
    5. grants: list of uuids, dmps with the corresponding grants
    6. " + + "
    7. grantsLike: list of strings, dmps fetched having their grant matching any of the strings provided
    8. " + + "
    9. funders: list of uuids, dmps with the corresponding funders
    10. " + + "
    11. fundersLike: list of strings, dmps fetched having their funders matching any of the strings provided
    12. " + + "
    13. datasetTemplates: list of uuids, dataset templates which are described in the dmps
    14. " + + "
    15. dmpOrganisations: list of strings, dmps belonging to these organisations
    16. " + + "
    17. collaborators: list of uuids, user who collaborated on the creation/modification of dmps
    18. " + + "
    19. collaboratorsLike: list of strings, dmps fetched having their collaborators matching any of the strings provided
    20. " + + "
    21. allVersions: boolean, if dmps should be fetched with all their versions
    22. " + + "
    23. groupIds: list of uuids, in which groups the dmps are
    24. " + + "
    25. like: string, dmps fetched have this string matched in their label or description
    26. " + + "
    " + + "
      "; + + public static final String getPagedRequestParamDescription = "The fieldsGroup is a string which indicates if the returned objects would have all their properties\n" + + "There are two available values: 1) listing and 2) autocomplete\n" + + "
        " + + "
      • listing: returns objects with all their properties completed
      • " + + "
      • autocomplete: returns objects with only id, label, groupId and creationTime assigned
      • " + + "
          "; + + public static final String getOverviewSinglePublicNotes = "The json response is of type **ResponseItem< DataManagementPlanPublicModel >** containing the following properties:\n" + + "
            " + + "
          1. message: string, message indicating error, null if everything went well
          2. " + + "
          3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
          4. " + + "
          5. responseType: integer, 0 for json, 1 for file
          6. " + + "
          7. payload: DataManagementPlanPublicModel, dmp returned
          8. " + + "
              " + + "
            1. id: string, id of dmp returned
            2. " + + "
            3. label: string, label of dmp
            4. " + + "
            5. profile: string, profile of dmp
            6. " + + "
            7. grant: GrantPublicOverviewModel, grant of dmp
            8. " + + "
            9. createdAt: date, creation time of dmp
            10. " + + "
            11. modifiedAt: date, modification time of dmp
            12. " + + "
            13. finalizedAt: date, finalization date of dmp
            14. " + + "
            15. organisations: list of OrganizationPublicModel, organizations in which dmp belongs
            16. " + + "
            17. version: integer, version of dmp
            18. " + + "
            19. groupId: uuid, group id in which dmp belongs
            20. " + + "
            21. datasets: list of DatasetPublicModel, contained datasets
            22. " + + "
            23. associatedProfiles: list of AssociatedProfilePublicModel, associated profiles of dmp
            24. " + + "
            25. researchers: list of ResearcherPublicModel, researchers involved in dmp
            26. " + + "
            27. users: list of UserInfoPublicModel, user who collaborated on the dmp
            28. " + + "
            29. description: string, description of dmp
            30. " + + "
            31. publishedAt: date, publication date
            32. " + + "
            33. doi: string, if dmp has been published to zenodo so it has doi
            34. " + + "
            " + + "
          "; + + public static final String getOverviewSinglePublicResponseExample = "{\n" + + " \"statusCode\": 0,\n" + + " \"responseType\": 0,\n" + + " \"message\": null,\n" + + " \"payload\": {\n" + + " \"id\": \"e9a73d77-adfa-4546-974f-4a4a623b53a8\",\n" + + " \"label\": \"Giorgos's DMP\",\n" + + " \"profile\": null,\n" + + " \"grant\": {\n" + + " \"id\": \"c8309ae5-4e56-43eb-aa5a-9950c24051fe\",\n" + + " \"label\": \"Novel EOSC services for Emerging Atmosphere, Underwater and Space Challenges\",\n" + + " \"abbreviation\": null,\n" + + " \"description\": null,\n" + + " \"startDate\": null,\n" + + " \"endDate\": null,\n" + + " \"uri\": null,\n" + + " \"funder\": {\n" + + " \"id\": \"25e76828-3539-4c66-9870-0ecea7a4d16e\",\n" + + " \"label\": \"European Commission||EC\",\n" + + " \"hint\": null\n" + + " },\n" + + " \"hint\": null\n" + + " },\n" + + " \"createdAt\": 1579077317000,\n" + + " \"modifiedAt\": 1586444334000,\n" + + " \"finalizedAt\": 1586444334000,\n" + + " \"organisations\": [],\n" + + " \"version\": 0,\n" + + " \"groupId\": \"d949592d-f862-4b31-a43a-f5f70596df5e\",\n" + + " \"datasets\": [\n" + + " {\n" + + " \"id\": \"853a24c3-def4-4978-985f-92e7fa57ef22\",\n" + + " \"label\": \"Giorgos's Dataset Desc\",\n" + + " \"reference\": null,\n" + + " \"uri\": null,\n" + + " \"description\": null,\n" + + " \"status\": 1,\n" + + " \"createdAt\": 1579077532000,\n" + + " \"dmp\": {\n" + + " \"id\": \"e9a73d77-adfa-4546-974f-4a4a623b53a8\",\n" + + " \"label\": \"Giorgos's DMP\",\n" + + " \"grant\": \"Novel EOSC services for Emerging Atmosphere, Underwater and Space Challenges\",\n" + + " \"createdAt\": 1579077317000,\n" + + " \"modifiedAt\": 1586444334000,\n" + + " \"version\": 0,\n" + + " \"groupId\": \"d949592d-f862-4b31-a43a-f5f70596df5e\",\n" + + " \"users\": [\n" + + " {\n" + + " \"id\": \"00476b4d-0491-44ca-b2fd-92e695062a48\",\n" + + " \"name\": \"OpenDMP OpenDMP\",\n" + + " \"role\": 0,\n" + + " \"email\": \"opendmpeu@gmail.com\",\n" + + " \"hint\": \"UserInfoListingModel\"\n" + + " }\n" + + " ],\n" + + " \"finalizedAt\": 1586444334000,\n" + + " \"publishedAt\": 1586444334000,\n" + + " \"hint\": \"dataManagementPlanListingModel\"\n" + + " },\n" + + " \"datasetProfileDefinition\": {\n" + + " \"pages\": [...],\n" + + " \"rules\": [...],\n" + + " \"status\": 0\n" + + " },\n" + + " \"registries\": [],\n" + + " \"services\": [],\n" + + " \"dataRepositories\": [],\n" + + " \"tags\": null,\n" + + " \"externalDatasets\": [],\n" + + " \"profile\": {\n" + + " \"id\": \"2a6e0835-349e-412c-9fcc-8e1298ce8a5a\",\n" + + " \"label\": \"Horizon 2020\",\n" + + " \"hint\": null\n" + + " },\n" + + " \"modifiedAt\": 1579077898000,\n" + + " \"hint\": \"datasetOverviewModel\"\n" + + " }\n" + + " ],\n" + + " \"associatedProfiles\": [\n" + + " {\n" + + " \"id\": \"f41bd794-761d-4fe8-ab67-3a989d982c53\",\n" + + " \"label\": \"Swedish Research Council\"\n" + + " },\n" + + " {\n" + + " \"id\": \"2a6e0835-349e-412c-9fcc-8e1298ce8a5a\",\n" + + " \"label\": \"Horizon 2020\"\n" + + " }\n" + + " ],\n" + + " \"researchers\": [],\n" + + " \"users\": [\n" + + " {\n" + + " \"id\": \"00476b4d-0491-44ca-b2fd-92e695062a48\",\n" + + " \"name\": \"OpenDMP OpenDMP\",\n" + + " \"role\": 0,\n" + + " \"email\": \"opendmpeu@gmail.com\",\n" + + " \"hint\": \"UserInfoListingModel\"\n" + + " }\n" + + " ],\n" + + " \"description\": null,\n" + + " \"publishedAt\": 1586444334000,\n" + + " \"doi\": \"10.5072/zenodo.522151\",\n" + + " \"hint\": \"dataManagementPlanOverviewModel\"\n" + + " }\n" + + "}"; + + } + + public static final class Description { + + public static final String getPagedNotes = "The json response is of type **ResponseItem>** containing the following properties:\n" + + "
            " + + "
          1. message: string, message indicating error, null if everything went well
          2. " + + "
          3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
          4. " + + "
          5. responseType: integer, 0 for json, 1 for file
          6. " + + "
          7. payload: DataTableData, containing the number of values of actual data returned and the data of type DatasetPublicListingModel
          8. " + + "
              " + + "
            1. id: string, id of dataset returned
            2. " + + "
            3. label: string, label of dataset
            4. " + + "
            5. grant: string, grant of dataset
            6. " + + "
            7. dmp: string, dmp description
            8. " + + "
            9. dmpId: string, dmp's id
            10. " + + "
            11. profile: DatasetProfilePublicModel, dataset's profile
            12. " + + "
            13. createdAt: date, creation date
            14. " + + "
            15. modifiedAt: date, modification date
            16. " + + "
            17. description: string, dataset's description
            18. " + + "
            19. finalizedAt: date, finalization date
            20. " + + "
            21. dmpPublishedAt: date, dmp's publication date
            22. " + + "
            23. version: integer, dataset's version
            24. " + + "
            25. users: list of UserInfoPublicModel, user who collaborated on the dataset
            26. " + + "
            " + + "
          "; + public static final String getPagedResponseExample = "{\n" + + " \"statusCode\": 0,\n" + + " \"responseType\": 0,\n" + + " \"message\": null,\n" + + " \"payload\": {\n" + + " \"totalCount\": 2,\n" + + " \"data\": [\n" + + " {\n" + + " \"id\": \"ef7dfbdc-c5c1-46a7-a37b-c8d8692f1c0e\",\n" + + " \"label\": \"BARKAMOL RIVOJLANGAN SHAXSNI TARBIYALASHDA HARAKATLI O`YINLARNING O`RNI\",\n" + + " \"grant\": \"A next generation nano media tailored to capture and recycle hazardous micropollutants in contaminated industrial wastewater.\",\n" + + " \"dmp\": \"test for demo\",\n" + + " \"dmpId\": \"9dee6e72-7a4c-4fbd-b8a4-1f8cda38eb5e\",\n" + + " \"profile\": {\n" + + " \"id\": \"771283d7-a5be-4a93-bd3c-8b1883fe837c\",\n" + + " \"label\": \"Horizon Europe\",\n" + + " \"hint\": null\n" + + " },\n" + + " \"createdAt\": 1662711279000,\n" + + " \"modifiedAt\": 1662712928000,\n" + + " \"description\": \"

               Annotatsiya  Maqolada  bolalarni  o`yin  mavjud  bo`lgan  shakllarda  mavjud 
          \\nhayot  bilan  kengroq  tanishtirishga  imkon  beradi.  O`yin  bolalarning  turli  xil 
          \\nfaoliyati,o`yin  ko`nikmalarini  shakllantirishga  yordam  beradi.Ularni  fikrlash,  his-
          \\ntuyg`ular, tajribalar, o`yin muammosini hal qilishning faol usullarini izlash, ularning 
          \\no`yin sharoitlari va sharoitlariga bo`ysunishi, o`yindagi bolalarning munosabatlari, 
          \\no`yin orqali bola organik rivojlanadi,  inson madaniyatining muhim qatlami kattalar 
          \\no`rtasidagi  munosabatlar  -  oilada,  ularning  kasbiy  faoliyati  va  boshqalar.  O`yin 
          \\no`qituvchilar barcha ta’lim vazifalarini, shu jumladan o`rganishni hal qiladigan eng 
          \\nmuhim faoliyat sifatida foydalaniladi. 

          \",\n" + + " \"finalizedAt\": 1662712928000,\n" + + " \"dmpPublishedAt\": 1662713226000,\n" + + " \"version\": 0,\n" + + " \"users\": [\n" + + " {\n" + + " \"id\": \"33024e48-d528-45a5-8035-ea48641bd2f2\",\n" + + " \"name\": \"DMP author\",\n" + + " \"role\": 0,\n" + + " \"email\": \"kanavou.p@gmail.com\",\n" + + " \"hint\": \"UserInfoListingModel\"\n" + + " }\n" + + " ],\n" + + " \"hint\": \"datasetListingModel\"\n" + + " },\n" + + " {\n" + + " \"id\": \"0f253ab2-18cb-4798-adc1-135b81cfad0c\",\n" + + " \"label\": \"A \\\"zoom-elit\\\" és a kamionosok küzdelme, avagy a meritokrácia és a populizmus összecsapása\",\n" + + " \"grant\": \"Discovery Projects - Grant ID: DP140100157\",\n" + + " \"dmp\": \"TEST UPDATE 2.8.2022\",\n" + + " \"dmpId\": \"1f4daa8f-4e2f-4dc9-a60b-f6b75d313400\",\n" + + " \"profile\": {\n" + + " \"id\": \"3d43ba45-25fa-4815-81b4-9bf22ecd8316\",\n" + + " \"label\": \"HE_Final\",\n" + + " \"hint\": null\n" + + " },\n" + + " \"createdAt\": 1659392761000,\n" + + " \"modifiedAt\": 1659393655000,\n" + + " \"description\": \"

          A kanadai kamionosok „szabadságmenete” kapcsán a New York Times hasábjain Ross Donthat publicista egy régi könyvre hívja fel a figyelmet, amely sok évtizeddel ezelÅ‘tt megjósolta az elit elleni hasonló lázadásokat.

          \",\n" + + " \"finalizedAt\": 1659393654000,\n" + + " \"dmpPublishedAt\": 1659393698000,\n" + + " \"version\": 0,\n" + + " \"users\": [\n" + + " {\n" + + " \"id\": \"33024e48-d528-45a5-8035-ea48641bd2f2\",\n" + + " \"name\": \"DMP author\",\n" + + " \"role\": 0,\n" + + " \"email\": \"kanavou.p@gmail.com\",\n" + + " \"hint\": \"UserInfoListingModel\"\n" + + " }\n" + + " ],\n" + + " \"hint\": \"datasetListingModel\"\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + public static final String getPagedRequestBodyDescription = "The datasetTableRequest is a DatasetPublicTableRequest object with the following fields:\n" + + "
            " + + "
          • length: how many datasets should be fetched (required)
          • " + + "
          • offset: offset of the returned datasets, first time should be 0, then offset += length
          • " + + "
          • orderings: array of strings specifying the order, format:= +string or -string or asc or desc.
          • " + + "+ means ascending order. - means descending order.
                Available strings are: 1) status, 2) label, 3) created.
            " + + "    asc equivalent to +label.
                desc equivalent to -label.
            " + + "
          • criteria: this is DatasetPublicCriteria object which applies filters for the datasets returned. More specifically:
          • " + + "
              " + + "
            1. periodStart: date, datasets created date greater than periodStart
            2. " + + "
            3. periodEnd: date, datasets created date less than periodEnd
            4. " + + "
            5. grants: list of uuids, dmps(datasets) with the corresponding grants
            6. " + + "
            7. collaborators: list of uuids, user who collaborated on the creation/modification of datasets
            8. " + + "
            9. datasetTemplates: list of uuids, dataset templates uuids to be included
            10. " + + "
            11. dmpOrganisations: list of strings, datasets involved in dmps which belong to these organisations
            12. " + + "
            13. tags: list of Tag objects, tags involved in datasets
            14. " + + "
            15. dmpIds: list of uuids, dmps with the specific ids
            16. " + + "
            17. groupIds: list of uuids, in which groups the datasets are
            18. " + + "
            19. allVersions: boolean, if datasets should be fetched with all their versions
            20. " + + "
            21. like: string, datasets fetched have this string matched in their label or description
            22. " + + "
            " + + "
          "; + + public static final String getOverviewSinglePublicNotes = "The json response is of type **ResponseItem< DatasetPublicModel >** containing the following properties:\n" + + "
            " + + "
          1. message: string, message indicating error, null if everything went well
          2. " + + "
          3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
          4. " + + "
          5. responseType: integer, 0 for json, 1 for file
          6. " + + "
          7. payload: DatasetPublicModel, dmp returned
          8. " + + "
              " + + "
            1. id: uuid, id of dataset returned
            2. " + + "
            3. label: string, label of dataset
            4. " + + "
            5. reference: string, reference of dataset
            6. " + + "
            7. uri: string, uri of dataset
            8. " + + "
            9. description: string, dataset's description
            10. " + + "
            11. status: string, dataset's status
            12. " + + "
            13. createdAt: date, creation time of dataset
            14. " + + "
            15. dmp: DataManagementPlanPublicListingModel, dmp to which dataset belongs
            16. " + + "
            17. datasetProfileDefinition: PagedDatasetProfile, dataset's paged description
            18. " + + "
            19. registries: list of RegistryPublicModel, dataset's registries
            20. " + + "
            21. services: list of ServicePublicModel, dataset's services
            22. " + + "
            23. dataRepositories: list of DataRepositoryPublicModel, dataset's data repositories
            24. " + + "
            25. tags: list of Tag, dataset's tags
            26. " + + "
            27. externalDatasets: list of ExternalDatasetPublicListingModel, dataset's external datasets
            28. " + + "
            29. profile: DatasetProfilePublicModel, dataset's profile
            30. " + + "
            31. modifiedAt: date, modification time of dataset
            32. " + + "
            " + + "
          "; + public static final String getOverviewSinglePublicResponseExample = "{\n" + + " \"statusCode\": 0,\n" + + " \"responseType\": 0,\n" + + " \"message\": null,\n" + + " \"payload\": {\n" + + " \"id\": \"ef7dfbdc-c5c1-46a7-a37b-c8d8692f1c0e\",\n" + + " \"label\": \"BARKAMOL RIVOJLANGAN SHAXSNI TARBIYALASHDA HARAKATLI O`YINLARNING O`RNI\",\n" + + " \"reference\": null,\n" + + " \"uri\": null,\n" + + " \"description\": \"

               Annotatsiya  Maqolada  bolalarni  o`yin  mavjud  bo`lgan  shakllarda  mavjud 
          \\nhayot  bilan  kengroq  tanishtirishga  imkon  beradi.  O`yin  bolalarning  turli  xil 
          \\nfaoliyati,o`yin  ko`nikmalarini  shakllantirishga  yordam  beradi.Ularni  fikrlash,  his-
          \\ntuyg`ular, tajribalar, o`yin muammosini hal qilishning faol usullarini izlash, ularning 
          \\no`yin sharoitlari va sharoitlariga bo`ysunishi, o`yindagi bolalarning munosabatlari, 
          \\no`yin orqali bola organik rivojlanadi,  inson madaniyatining muhim qatlami kattalar 
          \\no`rtasidagi  munosabatlar  -  oilada,  ularning  kasbiy  faoliyati  va  boshqalar.  O`yin 
          \\no`qituvchilar barcha ta’lim vazifalarini, shu jumladan o`rganishni hal qiladigan eng 
          \\nmuhim faoliyat sifatida foydalaniladi. 

          \",\n" + + " \"status\": 1,\n" + + " \"createdAt\": 1662711279000,\n" + + " \"dmp\": {\n" + + " \"id\": \"9dee6e72-7a4c-4fbd-b8a4-1f8cda38eb5e\",\n" + + " \"label\": \"test for demo\",\n" + + " \"grant\": \"A next generation nano media tailored to capture and recycle hazardous micropollutants in contaminated industrial wastewater.\",\n" + + " \"createdAt\": 1662710691000,\n" + + " \"modifiedAt\": 1662713226000,\n" + + " \"version\": 0,\n" + + " \"groupId\": \"adaa4e17-7375-45b8-b052-09edaeb6da86\",\n" + + " \"users\": [\n" + + " {\n" + + " \"id\": \"33024e48-d528-45a5-8035-ea48641bd2f2\",\n" + + " \"name\": \"DMP author\",\n" + + " \"role\": 0,\n" + + " \"email\": \"kanavou.p@gmail.com\",\n" + + " \"hint\": \"UserInfoListingModel\"\n" + + " }\n" + + " ],\n" + + " \"finalizedAt\": 1662713226000,\n" + + " \"publishedAt\": 1662713226000,\n" + + " \"hint\": \"dataManagementPlanListingModel\"\n" + + " },\n" + + " \"datasetProfileDefinition\": {\n" + + " \"pages\": [...],\n" + + " \"rules\": [...],\n" + + " \"status\": 0\n" + + " },\n" + + " \"registries\": [],\n" + + " \"services\": [],\n" + + " \"dataRepositories\": [],\n" + + " \"tags\": null,\n" + + " \"externalDatasets\": [],\n" + + " \"profile\": {\n" + + " \"id\": \"771283d7-a5be-4a93-bd3c-8b1883fe837c\",\n" + + " \"label\": \"Horizon Europe\",\n" + + " \"hint\": null\n" + + " },\n" + + " \"modifiedAt\": 1662712928000,\n" + + " \"hint\": \"datasetOverviewModel\"\n" + + " }\n" + + "}"; + + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicDatasetsDescriptionDocumentation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicDatasetsDescriptionDocumentation.java new file mode 100644 index 000000000..a666ed364 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicDatasetsDescriptionDocumentation.java @@ -0,0 +1,71 @@ +package eu.eudat.controllers.publicapi; + +import eu.eudat.controllers.BaseController; +import eu.eudat.model.publicapi.listingmodels.DatasetPublicListingModel; +import eu.eudat.controllers.publicapi.response.DataTableData; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.model.publicapi.overviewmodels.DatasetPublicModel; +import eu.eudat.controllers.publicapi.request.dataset.DatasetPublicTableRequest; +import eu.eudat.types.ApiMessageCode; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +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 static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@Tag(name = "Datasets Description", description = "Provides Dataset description public API's.") +@RestController +@CrossOrigin +@RequestMapping(value = {"/api/public/datasets/"}) +public class PublicDatasetsDescriptionDocumentation extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(PublicDatasetsDescriptionDocumentation.class); + + @Autowired + public PublicDatasetsDescriptionDocumentation(ApiContext apiContext) { + super(apiContext); + } + + @Operation(summary = "This method is used to get a listing of public datasets.", description = PublicApiStaticHelpers.Description.getPagedNotes) + @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@io.swagger.v3.oas.annotations.responses.ApiResponse( + responseCode = "200", + description = "The following example is generated using body: *{\"criteria\": {},\"length\": 2,\"offset\": 0,\"orderings\": {\"fields\": []} }*", + content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( + value = PublicApiStaticHelpers.Description.getPagedResponseExample + )}) + )}) + @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") + public @ResponseBody ResponseEntity>> getPaged( + @Valid @RequestBody @io.swagger.v3.oas.annotations.parameters.RequestBody(description = PublicApiStaticHelpers.Description.getPagedRequestBodyDescription) DatasetPublicTableRequest datasetTableRequest + ) throws Exception { +// DataTableData dataTable = this.datasetManager.getPublicPaged(datasetTableRequest); TODO + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(null)); + } + + @Operation(summary = "This method is used to get the overview of a public dataset.", description = PublicApiStaticHelpers.Description.getOverviewSinglePublicNotes) + @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@ApiResponse( + responseCode = "200", + description = "The following example is generated using id: *ef7dfbdc-c5c1-46a7-a37b-c8d8692f1c0e*", + content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( + value = PublicApiStaticHelpers.Description.getOverviewSinglePublicResponseExample + )}) + )}) + @RequestMapping(method = RequestMethod.GET, value = {"/{id}"}, produces = "application/json") + public @ResponseBody ResponseEntity> getOverviewSinglePublic( + @PathVariable @Parameter(description = "fetch the dataset with the given id", example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") String id + ) { +// DatasetPublicModel dataset = this.datasetManager.getOverviewSinglePublic(id); TODO + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(null)); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicDmpsDocumentation.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicDmpsDocumentation.java new file mode 100644 index 000000000..8a8b6d6f1 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/PublicDmpsDocumentation.java @@ -0,0 +1,177 @@ +package eu.eudat.controllers.publicapi; + +import eu.eudat.commons.enums.DmpAccessType; +import eu.eudat.commons.enums.IsActive; +import eu.eudat.controllers.BaseController; +import eu.eudat.controllers.publicapi.request.dmp.DataManagmentPlanPublicTableRequest; +import eu.eudat.controllers.publicapi.response.DataTableData; +import eu.eudat.data.DmpEntity; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.model.*; +import eu.eudat.model.builder.DmpBuilder; +import eu.eudat.model.mapper.publicapi.DmpToPublicApiDmpListingMapper; +import eu.eudat.model.mapper.publicapi.DmpToPublicApiDmpMapper; +import eu.eudat.model.publicapi.listingmodels.DataManagementPlanPublicListingModel; +import eu.eudat.model.publicapi.overviewmodels.DataManagementPlanPublicModel; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.query.DmpQuery; +import eu.eudat.query.lookup.DmpLookup; +import eu.eudat.types.ApiMessageCode; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.fieldset.BaseFieldSet; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +@Tag(name = "DMPs", description = "Provides DMP public API's.") +@RestController +@CrossOrigin +@RequestMapping(value = {"/api/public/dmps"}) +public class PublicDmpsDocumentation extends BaseController { + + private static final Logger logger = LoggerFactory.getLogger(PublicDmpsDocumentation.class); + + private final QueryFactory queryFactory; + + private final BuilderFactory builderFactory; + + private final MessageSource messageSource; + + private final DmpToPublicApiDmpMapper dmpToPublicApiDmpMapper; + + private final DmpToPublicApiDmpListingMapper dmpToPublicApiDmpListingMapper; + + @Autowired + public PublicDmpsDocumentation(ApiContext apiContext, QueryFactory queryFactory, BuilderFactory builderFactory, MessageSource messageSource, DmpToPublicApiDmpMapper dmpToPublicApiDmpMapper, DmpToPublicApiDmpListingMapper dmpToPublicApiDmpListingMapper) { + super(apiContext); + this.queryFactory = queryFactory; + this.builderFactory = builderFactory; + this.messageSource = messageSource; + this.dmpToPublicApiDmpMapper = dmpToPublicApiDmpMapper; + this.dmpToPublicApiDmpListingMapper = dmpToPublicApiDmpListingMapper; + } + + @Operation(summary = "This method is used to get a listing of public dmps.", description = PublicApiStaticHelpers.Dmp.getPagedNotes) + @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@ApiResponse( + responseCode = "200", + description = """ + The following example is generated using: + a) body: *{"criteria": {},"length": 2,"offset": 0,"orderings": {"fields": []} }* + b) fieldsGroup: listing""", + content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( + value = PublicApiStaticHelpers.Dmp.getPagedResponseExample + )}) + )}) + @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") + public @ResponseBody ResponseEntity>> getPaged( + @Valid @RequestBody @io.swagger.v3.oas.annotations.parameters.RequestBody(description = PublicApiStaticHelpers.Dmp.getPagedRequestBodyDescription) DataManagmentPlanPublicTableRequest dmpTableRequest, + @RequestParam @Parameter(description = PublicApiStaticHelpers.Dmp.getPagedRequestParamDescription, example = "listing") String fieldsGroup + ) throws Exception { + DmpLookup lookup = getDmpLookup(fieldsGroup, dmpTableRequest); + DmpQuery query = lookup.enrich(this.queryFactory).accessTypes(DmpAccessType.Public).isActive(IsActive.Active); + long count = this.queryFactory.query(DmpQuery.class).accessTypes(DmpAccessType.Public).isActive(IsActive.Active).count(); + + List data = query.collectAs(lookup.getProject()); + List models = this.builderFactory.builder(DmpBuilder.class).build(lookup.getProject(), data); + DataTableData dataTableData = new DataTableData<>(); + dataTableData.setData(models.stream().map(this.dmpToPublicApiDmpListingMapper::toPublicListingModel).toList()); + dataTableData.setTotalCount(count); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataTableData)); + } + + @NotNull + private static DmpLookup getDmpLookup(String fieldsGroup, DataManagmentPlanPublicTableRequest request) { + BaseFieldSet fieldSet = new BaseFieldSet(); + Set fields; + if (fieldsGroup.equals("listing")) { + fields = Set.of( + Dmp._id, + Dmp._label, + Dmp._description, + Dmp._version, + Dmp._groupId, + String.join(".", Dmp._dmpUsers, String.join(".", DmpUser._user, User._id)), + String.join(".", Dmp._dmpUsers, String.join(".", DmpUser._user, User._name)), + String.join(".", Dmp._dmpUsers, DmpUser._role), + String.join(".", Dmp._dmpReferences, String.join(".", DmpReference._reference, Reference._id)), + String.join(".", Dmp._dmpReferences, String.join(".", DmpReference._reference, Reference._reference)), + String.join(".", Dmp._dmpReferences, String.join(".", DmpReference._reference, Reference._label)), + Dmp._dmpReferences, + Dmp._createdAt, + Dmp._updatedAt, + Dmp._finalizedAt + ); + } else { + fields = Set.of( + Dmp._id, + Dmp._label, + Dmp._groupId, + Dmp._createdAt + ); + } + fieldSet.setFields(fields); + DmpLookup lookup = new DmpLookup(); + lookup.setProject(fieldSet); + return lookup; + } + + @Operation(summary = "This method is used to get the overview of a public dmp.", description = PublicApiStaticHelpers.Dmp.getOverviewSinglePublicNotes) + @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@ApiResponse( + responseCode = "200", + description = "The following example is generated using id: *e9a73d77-adfa-4546-974f-4a4a623b53a8*", + content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( + value = PublicApiStaticHelpers.Dmp.getOverviewSinglePublicResponseExample + )}) + )}) + @RequestMapping(method = RequestMethod.GET, value = {"/{id}"}, produces = "application/json") + public @ResponseBody ResponseEntity> getOverviewSinglePublic( + @PathVariable @Parameter(description = "fetch the dmp with the given id", example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") String id + ) { + BaseFieldSet fieldSet = new BaseFieldSet(); + Set fields = Set.of( + Dmp._id, + Dmp._label, + Dmp._description, + Dmp._version, + Dmp._groupId, + String.join(".", Dmp._dmpUsers, String.join(".", DmpUser._user, User._id)), + String.join(".", Dmp._dmpUsers, String.join(".", DmpUser._user, User._name)), + String.join(".", Dmp._dmpUsers, DmpUser._role), + String.join(".", Dmp._dmpReferences, String.join(".", DmpReference._reference, Reference._id)), + String.join(".", Dmp._dmpReferences, String.join(".", DmpReference._reference, Reference._reference)), + String.join(".", Dmp._dmpReferences, String.join(".", DmpReference._reference, Reference._label)), + Dmp._createdAt, + Dmp._updatedAt, + Dmp._finalizedAt + ); + fieldSet.setFields(fields); + DmpQuery query = this.queryFactory.query(DmpQuery.class).ids(UUID.fromString(id)).accessTypes(DmpAccessType.Public).isActive(IsActive.Active); + Dmp model = this.builderFactory.builder(DmpBuilder.class).build(fieldSet, query.firstAs(fieldSet)); + if (model == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale())); + DataManagementPlanPublicModel dataManagementPlan = this.dmpToPublicApiDmpMapper.toPublicModel(model); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/criteria/dataset/DatasetPublicCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/criteria/dataset/DatasetPublicCriteria.java similarity index 98% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/criteria/dataset/DatasetPublicCriteria.java rename to dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/criteria/dataset/DatasetPublicCriteria.java index abe7a1f42..76e58a9ec 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/criteria/dataset/DatasetPublicCriteria.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/criteria/dataset/DatasetPublicCriteria.java @@ -1,4 +1,4 @@ -package eu.eudat.publicapi.criteria.dataset; +package eu.eudat.controllers.publicapi.criteria.dataset; import eu.eudat.data.dao.criteria.Criteria; import eu.eudat.data.DescriptionEntity; diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/criteria/dmp/DataManagementPlanPublicCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/criteria/dmp/DataManagementPlanPublicCriteria.java similarity index 98% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/criteria/dmp/DataManagementPlanPublicCriteria.java rename to dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/criteria/dmp/DataManagementPlanPublicCriteria.java index c9a4e3a26..0f9c27c7a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/criteria/dmp/DataManagementPlanPublicCriteria.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/criteria/dmp/DataManagementPlanPublicCriteria.java @@ -1,4 +1,4 @@ -package eu.eudat.publicapi.criteria.dmp; +package eu.eudat.controllers.publicapi.criteria.dmp; import eu.eudat.data.DmpEntity; import eu.eudat.data.dao.criteria.Criteria; diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/request/dataset/DatasetPublicTableRequest.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/request/dataset/DatasetPublicTableRequest.java similarity index 97% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/request/dataset/DatasetPublicTableRequest.java rename to dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/request/dataset/DatasetPublicTableRequest.java index 3c5284306..c11b12cf0 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/request/dataset/DatasetPublicTableRequest.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/request/dataset/DatasetPublicTableRequest.java @@ -1,10 +1,10 @@ -package eu.eudat.publicapi.request.dataset; +package eu.eudat.controllers.publicapi.request.dataset; import eu.eudat.commons.enums.DescriptionStatus; import eu.eudat.commons.enums.IsActive; +import eu.eudat.controllers.publicapi.criteria.dataset.DatasetPublicCriteria; import eu.eudat.data.DescriptionEntity; import eu.eudat.data.query.definition.TableQuery; -import eu.eudat.publicapi.criteria.dataset.DatasetPublicCriteria; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.types.FieldSelectionType; import eu.eudat.queryable.types.SelectionField; diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/request/dmp/DataManagmentPlanPublicTableRequest.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/request/dmp/DataManagmentPlanPublicTableRequest.java similarity index 98% rename from dmp-backend/web/src/main/java/eu/eudat/publicapi/request/dmp/DataManagmentPlanPublicTableRequest.java rename to dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/request/dmp/DataManagmentPlanPublicTableRequest.java index 36ab1ca7d..c37848f2d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/request/dmp/DataManagmentPlanPublicTableRequest.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/request/dmp/DataManagmentPlanPublicTableRequest.java @@ -1,10 +1,10 @@ -package eu.eudat.publicapi.request.dmp; +package eu.eudat.controllers.publicapi.request.dmp; import eu.eudat.commons.enums.IsActive; +import eu.eudat.controllers.publicapi.criteria.dmp.DataManagementPlanPublicCriteria; import eu.eudat.data.DmpEntity; import eu.eudat.data.query.PaginationService; import eu.eudat.data.query.definition.TableQuery; -import eu.eudat.publicapi.criteria.dmp.DataManagementPlanPublicCriteria; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.types.FieldSelectionType; import eu.eudat.queryable.types.SelectionField; diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/response/DataTableData.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/response/DataTableData.java new file mode 100644 index 000000000..26092a088 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/publicapi/response/DataTableData.java @@ -0,0 +1,24 @@ +package eu.eudat.controllers.publicapi.response; + +import java.util.List; + +public class DataTableData { + private Long totalCount; + private List data; + + public Long getTotalCount() { + return totalCount; + } + + public void setTotalCount(Long totalCount) { + this.totalCount = totalCount; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageV2Controller.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageV2Controller.java new file mode 100644 index 000000000..9af208ed5 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/LanguageV2Controller.java @@ -0,0 +1,151 @@ +package eu.eudat.controllers.v2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.eudat.audit.AuditableAction; +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.data.LanguageEntity; +import eu.eudat.model.Language; +import eu.eudat.model.builder.LanguageBuilder; +import eu.eudat.model.censorship.LanguageCensor; +import eu.eudat.model.persist.LanguagePersist; +import eu.eudat.model.result.QueryResult; +import eu.eudat.query.LanguageQuery; +import eu.eudat.query.lookup.LanguageLookup; +import eu.eudat.service.language.LanguageService; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import gr.cite.tools.validation.MyValidate; +import jakarta.transaction.Transactional; +import jakarta.xml.bind.JAXBException; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.web.bind.annotation.*; + +import javax.management.InvalidApplicationException; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@RestController +@RequestMapping(path = {"api/v2/language"}) +public class LanguageV2Controller { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(LanguageV2Controller.class)); + private final BuilderFactory builderFactory; + private final AuditService auditService; + private final CensorFactory censorFactory; + private final QueryFactory queryFactory; + private final MessageSource messageSource; + private final AuthorizationService authorizationService; + private final LanguageService languageService; + + @Autowired + public LanguageV2Controller( + BuilderFactory builderFactory, + AuditService auditService, + CensorFactory censorFactory, + QueryFactory queryFactory, + MessageSource messageSource, AuthorizationService authorizationService, + LanguageService languageService) { + this.builderFactory = builderFactory; + this.auditService = auditService; + this.censorFactory = censorFactory; + this.queryFactory = queryFactory; + this.messageSource = messageSource; + this.authorizationService = authorizationService; + this.languageService = languageService; + } + + @PostMapping("query") + public QueryResult query(@RequestBody LanguageLookup lookup) throws MyApplicationException, MyForbiddenException { + logger.debug("querying {}", Language.class.getSimpleName()); + + this.censorFactory.censor(LanguageCensor.class).censor(lookup.getProject(), null); + + LanguageQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic); + List data = query.collectAs(lookup.getProject()); + List models = this.builderFactory.builder(LanguageBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(lookup.getProject(), data); + long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); + + this.auditService.track(AuditableAction.Language_Query, "lookup", lookup); + + return new QueryResult(models, count); + } + + @GetMapping("{id}") + public Language get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("retrieving" + Language.class.getSimpleName()).And("id", id).And("fields", fieldSet)); + + this.censorFactory.censor(LanguageCensor.class).censor(fieldSet, null); + + LanguageQuery query = this.queryFactory.query(LanguageQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).ids(id); + Language model = this.builderFactory.builder(LanguageBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(fieldSet, query.firstAs(fieldSet)); + if (model == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Language.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.Language_Lookup, Map.ofEntries( + new AbstractMap.SimpleEntry("id", id), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return model; + } + + @GetMapping("code/{code}") + public Language get(@PathVariable("code") String code, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("retrieving" + Language.class.getSimpleName()).And("code", code).And("fields", fieldSet)); + + this.censorFactory.censor(LanguageCensor.class).censor(fieldSet, null); + + LanguageQuery query = this.queryFactory.query(LanguageQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).codes(code); + Language model = this.builderFactory.builder(LanguageBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(fieldSet, query.firstAs(fieldSet)); + if (model == null) + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{code, Language.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.Language_Lookup, Map.ofEntries( + new AbstractMap.SimpleEntry("code", code), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return model; + } + + @PostMapping("persist") + @Transactional + public Language persist(@MyValidate @RequestBody LanguagePersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, JsonProcessingException, InvalidApplicationException { + logger.debug(new MapLogEntry("persisting" + Language.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet)); + this.censorFactory.censor(LanguageCensor.class).censor(fieldSet, null); + + Language persisted = this.languageService.persist(model, fieldSet); + + this.auditService.track(AuditableAction.Language_Persist, Map.ofEntries( + new AbstractMap.SimpleEntry("model", model), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return persisted; + } + + @DeleteMapping("{id}") + @Transactional + public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException { + logger.debug(new MapLogEntry("retrieving" + Language.class.getSimpleName()).And("id", id)); + + this.languageService.deleteAndSave(id); + + this.auditService.track(AuditableAction.Language_Delete, "id", id); + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java new file mode 100644 index 000000000..6b228dfb1 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/StorageFileController.java @@ -0,0 +1,142 @@ +package eu.eudat.controllers.v2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.eudat.audit.AuditableAction; +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.authorization.Permission; +import eu.eudat.commons.enums.*; +import eu.eudat.commons.scope.user.UserScope; +import eu.eudat.convention.ConventionService; +import eu.eudat.data.StorageFileEntity; +import eu.eudat.model.*; +import eu.eudat.model.builder.DescriptionBuilder; +import eu.eudat.model.censorship.DescriptionCensor; +import eu.eudat.model.censorship.PublicDescriptionCensor; +import eu.eudat.model.persist.DescriptionPersist; +import eu.eudat.model.persist.StorageFilePersist; +import eu.eudat.model.result.QueryResult; +import eu.eudat.query.DescriptionQuery; +import eu.eudat.query.DmpQuery; +import eu.eudat.query.StorageFileQuery; +import eu.eudat.query.lookup.DescriptionLookup; +import eu.eudat.service.description.DescriptionService; +import eu.eudat.service.elastic.ElasticQueryHelperService; +import eu.eudat.service.storage.StorageFileProperties; +import eu.eudat.service.storage.StorageFileService; +import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.exception.MyApplicationException; +import gr.cite.tools.exception.MyForbiddenException; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.fieldset.BaseFieldSet; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; +import gr.cite.tools.validation.MyValidate; +import org.apache.commons.io.FilenameUtils; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.management.InvalidApplicationException; +import java.io.IOException; +import java.net.URLConnection; +import java.time.Duration; +import java.util.*; + +import static eu.eudat.authorization.AuthorizationFlags.Public; + +@RestController +@RequestMapping(path = "api/storage-file") +public class StorageFileController { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(StorageFileController.class)); + private final AuditService auditService; + private final QueryFactory queryFactory; + private final MessageSource messageSource; + private final StorageFileService storageFileService; + private final StorageFileProperties config; + private final UserScope userScope; + private final AuthorizationService authorizationService; + private final ConventionService conventionService; + public StorageFileController( + AuditService auditService, + QueryFactory queryFactory, + MessageSource messageSource, + StorageFileService storageFileService, + StorageFileProperties config, + UserScope userScope, + AuthorizationService authorizationService, ConventionService conventionService) { + this.auditService = auditService; + this.queryFactory = queryFactory; + this.messageSource = messageSource; + this.storageFileService = storageFileService; + this.config = config; + this.userScope = userScope; + this.authorizationService = authorizationService; + this.conventionService = conventionService; + } + + + @PostMapping("upload-temp-files") + @Transactional + public List uploadTempFiles(@RequestParam("files") MultipartFile[] files) throws IOException { + logger.debug("upload temp files"); + + this.authorizationService.authorizeForce(Permission.EditStorageFile); + + List addedFiles = new ArrayList<>(); + for (MultipartFile file : files) { + StorageFilePersist storageFilePersist = new StorageFilePersist(); + storageFilePersist.setName(FilenameUtils.removeExtension(file.getName())); + storageFilePersist.setExtension(FilenameUtils.getExtension(file.getName())); + storageFilePersist.setMimeType(URLConnection.guessContentTypeFromName(file.getName())); + storageFilePersist.setOwnerId(this.userScope.getUserIdSafe()); + storageFilePersist.setStorageType(StorageType.Temp); + storageFilePersist.setLifetime(Duration.ofSeconds(this.config.getTempStoreLifetimeSeconds())); + StorageFile persisted = this.storageFileService.persistBytes(storageFilePersist, file.getBytes(), new BaseFieldSet(StorageFile._id, StorageFile._name)); + + addedFiles.add(persisted); + } + this.auditService.track(AuditableAction.StorageFile_Upload, "models", addedFiles); + + return addedFiles; + } + + @GetMapping("{id}") + public ResponseEntity get(@PathVariable("id") UUID id) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + logger.debug(new MapLogEntry("download" ).And("id", id)); + + this.authorizationService.authorizeForce(Permission.BrowseStorageFile); + + StorageFileEntity storageFile = this.queryFactory.query(StorageFileQuery.class).ids(id).firstAs(new BaseFieldSet().ensure(StorageFile._createdAt, StorageFile._fullName, StorageFile._mimeType)); + if (storageFile == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + byte[] file = this.storageFileService.readAsBytesSafe(id); + if (file == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.StorageFile_Download, Map.ofEntries( + new AbstractMap.SimpleEntry("id", id) + )); + + String contentType = storageFile.getMimeType(); + if (this.conventionService.isNullOrEmpty(contentType)) contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE; + + return ResponseEntity.ok() + .contentType(MediaType.valueOf(contentType)) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + storageFile.getName() + (storageFile.getExtension().startsWith(".") ? "" : ".") + storageFile.getExtension() + "\"") + .body(new ByteArrayResource(file)); + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/references/ReferenceService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/references/ReferenceService.java index 1aa4ea04a..f1f0eabd8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/references/ReferenceService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/references/ReferenceService.java @@ -407,10 +407,8 @@ public class ReferenceService { if (urlPath.contains("openaire") || urlPath.contains("orcid") ){ if (lookup.getLike() != null) { - completedPath = completedPath.replace("{query}", lookup.getLike()); completedPath = completedPath.replace("{like}", lookup.getLike()); } else { - completedPath = completedPath.replace("{query}", "*"); completedPath = completedPath.replace("{like}", "*"); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java index bc5692c39..5e7619387 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/externaldataset/ExternalDatasetListingModel.java @@ -2,7 +2,7 @@ package eu.eudat.models.data.externaldataset; import eu.eudat.data.old.ExternalDataset; import eu.eudat.models.DataModel; -import eu.eudat.types.externalsourcetype.ExternalDatasetType; +import eu.eudat.model.publicapi.datasetwizard.ExternalDatasetType; import java.util.Date; import java.util.UUID; diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java deleted file mode 100644 index 232794013..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java +++ /dev/null @@ -1,32 +0,0 @@ -package eu.eudat.publicapi.configurations; - -//import io.swagger.v3.oas.models.OpenAPI; -//import io.swagger.v3.oas.models.info.Contact; -//import io.swagger.v3.oas.models.info.Info; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.core.env.Environment; -// -//@Configuration -//public class SwaggerConfiguration { -// -// // private static final TypeResolver resolver = new TypeResolver(); -// -// @Autowired -// private Environment environment; -// -// @Bean -// public OpenAPI ArgosOpenApi() { -// return new OpenAPI().info(apiInfo()); -// } -// -// private Info apiInfo() { -// return new Info() -// .title("OpenDMP public API") -// .description("Argos public API.") -// .version("1.0") -// .termsOfService("https://argos.openaire.eu/terms-and-conditions") -// .contact(new Contact().name("Argos").url("https://argos.openaire.eu/").email("argos@openaire.eu ")); -// } -//} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/controllers/PublicDatasetsDescriptionDocumentation.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/controllers/PublicDatasetsDescriptionDocumentation.java deleted file mode 100644 index db8675a58..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/controllers/PublicDatasetsDescriptionDocumentation.java +++ /dev/null @@ -1,266 +0,0 @@ -package eu.eudat.publicapi.controllers; - -import eu.eudat.controllers.BaseController; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.models.data.helpers.common.DataTableData; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.publicapi.managers.DatasetPublicManager; -import eu.eudat.publicapi.models.listingmodels.DatasetPublicListingModel; -import eu.eudat.publicapi.models.overviewmodels.DatasetPublicModel; -import eu.eudat.publicapi.request.dataset.DatasetPublicTableRequest; -import eu.eudat.types.ApiMessageCode; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -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 static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; - -@Tag(name = "Datasets Description", description = "Provides Dataset description public API's.") -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/public/datasets/"}) -public class PublicDatasetsDescriptionDocumentation extends BaseController { - - private static final Logger logger = LoggerFactory.getLogger(PublicDatasetsDescriptionDocumentation.class); - - private DatasetPublicManager datasetManager; - - public static final String getPagedNotes = "The json response is of type **ResponseItem>** containing the following properties:\n" + - "
            " + - "
          1. message: string, message indicating error, null if everything went well
          2. " + - "
          3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
          4. " + - "
          5. responseType: integer, 0 for json, 1 for file
          6. " + - "
          7. payload: DataTableData, containing the number of values of actual data returned and the data of type DatasetPublicListingModel
          8. " + - "
              " + - "
            1. id: string, id of dataset returned
            2. " + - "
            3. label: string, label of dataset
            4. " + - "
            5. grant: string, grant of dataset
            6. " + - "
            7. dmp: string, dmp description
            8. " + - "
            9. dmpId: string, dmp's id
            10. " + - "
            11. profile: DatasetProfilePublicModel, dataset's profile
            12. " + - "
            13. createdAt: date, creation date
            14. " + - "
            15. modifiedAt: date, modification date
            16. " + - "
            17. description: string, dataset's description
            18. " + - "
            19. finalizedAt: date, finalization date
            20. " + - "
            21. dmpPublishedAt: date, dmp's publication date
            22. " + - "
            23. version: integer, dataset's version
            24. " + - "
            25. users: list of UserInfoPublicModel, user who collaborated on the dataset
            26. " + - "
            " + - "
          "; - public static final String getPagedResponseExample = "{\n" + - " \"statusCode\": 0,\n" + - " \"responseType\": 0,\n" + - " \"message\": null,\n" + - " \"payload\": {\n" + - " \"totalCount\": 2,\n" + - " \"data\": [\n" + - " {\n" + - " \"id\": \"ef7dfbdc-c5c1-46a7-a37b-c8d8692f1c0e\",\n" + - " \"label\": \"BARKAMOL RIVOJLANGAN SHAXSNI TARBIYALASHDA HARAKATLI O`YINLARNING O`RNI\",\n" + - " \"grant\": \"A next generation nano media tailored to capture and recycle hazardous micropollutants in contaminated industrial wastewater.\",\n" + - " \"dmp\": \"test for demo\",\n" + - " \"dmpId\": \"9dee6e72-7a4c-4fbd-b8a4-1f8cda38eb5e\",\n" + - " \"profile\": {\n" + - " \"id\": \"771283d7-a5be-4a93-bd3c-8b1883fe837c\",\n" + - " \"label\": \"Horizon Europe\",\n" + - " \"hint\": null\n" + - " },\n" + - " \"createdAt\": 1662711279000,\n" + - " \"modifiedAt\": 1662712928000,\n" + - " \"description\": \"

               Annotatsiya  Maqolada  bolalarni  o`yin  mavjud  bo`lgan  shakllarda  mavjud 
          \\nhayot  bilan  kengroq  tanishtirishga  imkon  beradi.  O`yin  bolalarning  turli  xil 
          \\nfaoliyati,o`yin  ko`nikmalarini  shakllantirishga  yordam  beradi.Ularni  fikrlash,  his-
          \\ntuyg`ular, tajribalar, o`yin muammosini hal qilishning faol usullarini izlash, ularning 
          \\no`yin sharoitlari va sharoitlariga bo`ysunishi, o`yindagi bolalarning munosabatlari, 
          \\no`yin orqali bola organik rivojlanadi,  inson madaniyatining muhim qatlami kattalar 
          \\no`rtasidagi  munosabatlar  -  oilada,  ularning  kasbiy  faoliyati  va  boshqalar.  O`yin 
          \\no`qituvchilar barcha ta’lim vazifalarini, shu jumladan o`rganishni hal qiladigan eng 
          \\nmuhim faoliyat sifatida foydalaniladi. 

          \",\n" + - " \"finalizedAt\": 1662712928000,\n" + - " \"dmpPublishedAt\": 1662713226000,\n" + - " \"version\": 0,\n" + - " \"users\": [\n" + - " {\n" + - " \"id\": \"33024e48-d528-45a5-8035-ea48641bd2f2\",\n" + - " \"name\": \"DMP author\",\n" + - " \"role\": 0,\n" + - " \"email\": \"kanavou.p@gmail.com\",\n" + - " \"hint\": \"UserInfoListingModel\"\n" + - " }\n" + - " ],\n" + - " \"hint\": \"datasetListingModel\"\n" + - " },\n" + - " {\n" + - " \"id\": \"0f253ab2-18cb-4798-adc1-135b81cfad0c\",\n" + - " \"label\": \"A \\\"zoom-elit\\\" és a kamionosok küzdelme, avagy a meritokrácia és a populizmus összecsapása\",\n" + - " \"grant\": \"Discovery Projects - Grant ID: DP140100157\",\n" + - " \"dmp\": \"TEST UPDATE 2.8.2022\",\n" + - " \"dmpId\": \"1f4daa8f-4e2f-4dc9-a60b-f6b75d313400\",\n" + - " \"profile\": {\n" + - " \"id\": \"3d43ba45-25fa-4815-81b4-9bf22ecd8316\",\n" + - " \"label\": \"HE_Final\",\n" + - " \"hint\": null\n" + - " },\n" + - " \"createdAt\": 1659392761000,\n" + - " \"modifiedAt\": 1659393655000,\n" + - " \"description\": \"

          A kanadai kamionosok „szabadságmenete” kapcsán a New York Times hasábjain Ross Donthat publicista egy régi könyvre hívja fel a figyelmet, amely sok évtizeddel ezelÅ‘tt megjósolta az elit elleni hasonló lázadásokat.

          \",\n" + - " \"finalizedAt\": 1659393654000,\n" + - " \"dmpPublishedAt\": 1659393698000,\n" + - " \"version\": 0,\n" + - " \"users\": [\n" + - " {\n" + - " \"id\": \"33024e48-d528-45a5-8035-ea48641bd2f2\",\n" + - " \"name\": \"DMP author\",\n" + - " \"role\": 0,\n" + - " \"email\": \"kanavou.p@gmail.com\",\n" + - " \"hint\": \"UserInfoListingModel\"\n" + - " }\n" + - " ],\n" + - " \"hint\": \"datasetListingModel\"\n" + - " }\n" + - " ]\n" + - " }\n" + - "}"; - public static final String getPagedRequestBodyDescription = "The datasetTableRequest is a DatasetPublicTableRequest object with the following fields:\n" + - "
            " + - "
          • length: how many datasets should be fetched (required)
          • " + - "
          • offset: offset of the returned datasets, first time should be 0, then offset += length
          • " + - "
          • orderings: array of strings specifying the order, format:= +string or -string or asc or desc.
          • " + - "+ means ascending order. - means descending order.
                Available strings are: 1) status, 2) label, 3) created.
            " + - "    asc equivalent to +label.
                desc equivalent to -label.
            " + - "
          • criteria: this is DatasetPublicCriteria object which applies filters for the datasets returned. More specifically:
          • " + - "
              " + - "
            1. periodStart: date, datasets created date greater than periodStart
            2. " + - "
            3. periodEnd: date, datasets created date less than periodEnd
            4. " + - "
            5. grants: list of uuids, dmps(datasets) with the corresponding grants
            6. " + - "
            7. collaborators: list of uuids, user who collaborated on the creation/modification of datasets
            8. " + - "
            9. datasetTemplates: list of uuids, dataset templates uuids to be included
            10. " + - "
            11. dmpOrganisations: list of strings, datasets involved in dmps which belong to these organisations
            12. " + - "
            13. tags: list of Tag objects, tags involved in datasets
            14. " + - "
            15. dmpIds: list of uuids, dmps with the specific ids
            16. " + - "
            17. groupIds: list of uuids, in which groups the datasets are
            18. " + - "
            19. allVersions: boolean, if datasets should be fetched with all their versions
            20. " + - "
            21. like: string, datasets fetched have this string matched in their label or description
            22. " + - "
            " + - "
          "; - - public static final String getOverviewSinglePublicNotes = "The json response is of type **ResponseItem< DatasetPublicModel >** containing the following properties:\n" + - "
            " + - "
          1. message: string, message indicating error, null if everything went well
          2. " + - "
          3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
          4. " + - "
          5. responseType: integer, 0 for json, 1 for file
          6. " + - "
          7. payload: DatasetPublicModel, dmp returned
          8. " + - "
              " + - "
            1. id: uuid, id of dataset returned
            2. " + - "
            3. label: string, label of dataset
            4. " + - "
            5. reference: string, reference of dataset
            6. " + - "
            7. uri: string, uri of dataset
            8. " + - "
            9. description: string, dataset's description
            10. " + - "
            11. status: string, dataset's status
            12. " + - "
            13. createdAt: date, creation time of dataset
            14. " + - "
            15. dmp: DataManagementPlanPublicListingModel, dmp to which dataset belongs
            16. " + - "
            17. datasetProfileDefinition: PagedDatasetProfile, dataset's paged description
            18. " + - "
            19. registries: list of RegistryPublicModel, dataset's registries
            20. " + - "
            21. services: list of ServicePublicModel, dataset's services
            22. " + - "
            23. dataRepositories: list of DataRepositoryPublicModel, dataset's data repositories
            24. " + - "
            25. tags: list of Tag, dataset's tags
            26. " + - "
            27. externalDatasets: list of ExternalDatasetPublicListingModel, dataset's external datasets
            28. " + - "
            29. profile: DatasetProfilePublicModel, dataset's profile
            30. " + - "
            31. modifiedAt: date, modification time of dataset
            32. " + - "
            " + - "
          "; - public static final String getOverviewSinglePublicResponseExample = "{\n" + - " \"statusCode\": 0,\n" + - " \"responseType\": 0,\n" + - " \"message\": null,\n" + - " \"payload\": {\n" + - " \"id\": \"ef7dfbdc-c5c1-46a7-a37b-c8d8692f1c0e\",\n" + - " \"label\": \"BARKAMOL RIVOJLANGAN SHAXSNI TARBIYALASHDA HARAKATLI O`YINLARNING O`RNI\",\n" + - " \"reference\": null,\n" + - " \"uri\": null,\n" + - " \"description\": \"

               Annotatsiya  Maqolada  bolalarni  o`yin  mavjud  bo`lgan  shakllarda  mavjud 
          \\nhayot  bilan  kengroq  tanishtirishga  imkon  beradi.  O`yin  bolalarning  turli  xil 
          \\nfaoliyati,o`yin  ko`nikmalarini  shakllantirishga  yordam  beradi.Ularni  fikrlash,  his-
          \\ntuyg`ular, tajribalar, o`yin muammosini hal qilishning faol usullarini izlash, ularning 
          \\no`yin sharoitlari va sharoitlariga bo`ysunishi, o`yindagi bolalarning munosabatlari, 
          \\no`yin orqali bola organik rivojlanadi,  inson madaniyatining muhim qatlami kattalar 
          \\no`rtasidagi  munosabatlar  -  oilada,  ularning  kasbiy  faoliyati  va  boshqalar.  O`yin 
          \\no`qituvchilar barcha ta’lim vazifalarini, shu jumladan o`rganishni hal qiladigan eng 
          \\nmuhim faoliyat sifatida foydalaniladi. 

          \",\n" + - " \"status\": 1,\n" + - " \"createdAt\": 1662711279000,\n" + - " \"dmp\": {\n" + - " \"id\": \"9dee6e72-7a4c-4fbd-b8a4-1f8cda38eb5e\",\n" + - " \"label\": \"test for demo\",\n" + - " \"grant\": \"A next generation nano media tailored to capture and recycle hazardous micropollutants in contaminated industrial wastewater.\",\n" + - " \"createdAt\": 1662710691000,\n" + - " \"modifiedAt\": 1662713226000,\n" + - " \"version\": 0,\n" + - " \"groupId\": \"adaa4e17-7375-45b8-b052-09edaeb6da86\",\n" + - " \"users\": [\n" + - " {\n" + - " \"id\": \"33024e48-d528-45a5-8035-ea48641bd2f2\",\n" + - " \"name\": \"DMP author\",\n" + - " \"role\": 0,\n" + - " \"email\": \"kanavou.p@gmail.com\",\n" + - " \"hint\": \"UserInfoListingModel\"\n" + - " }\n" + - " ],\n" + - " \"finalizedAt\": 1662713226000,\n" + - " \"publishedAt\": 1662713226000,\n" + - " \"hint\": \"dataManagementPlanListingModel\"\n" + - " },\n" + - " \"datasetProfileDefinition\": {\n" + - " \"pages\": [...],\n" + - " \"rules\": [...],\n" + - " \"status\": 0\n" + - " },\n" + - " \"registries\": [],\n" + - " \"services\": [],\n" + - " \"dataRepositories\": [],\n" + - " \"tags\": null,\n" + - " \"externalDatasets\": [],\n" + - " \"profile\": {\n" + - " \"id\": \"771283d7-a5be-4a93-bd3c-8b1883fe837c\",\n" + - " \"label\": \"Horizon Europe\",\n" + - " \"hint\": null\n" + - " },\n" + - " \"modifiedAt\": 1662712928000,\n" + - " \"hint\": \"datasetOverviewModel\"\n" + - " }\n" + - "}"; - - @Autowired - public PublicDatasetsDescriptionDocumentation(ApiContext apiContext, DatasetPublicManager datasetManager) { - super(apiContext); - this.datasetManager = datasetManager; - } - - @Operation(summary = "This method is used to get a listing of public datasets.", description = getPagedNotes) - @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@io.swagger.v3.oas.annotations.responses.ApiResponse( - responseCode = "200", - description = "The following example is generated using body: *{\"criteria\": {},\"length\": 2,\"offset\": 0,\"orderings\": {\"fields\": []} }*", - content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( - value = getPagedResponseExample - )}) - )}) - @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity>> getPaged(@Valid @RequestBody @io.swagger.v3.oas.annotations.parameters.RequestBody(description = getPagedRequestBodyDescription) DatasetPublicTableRequest datasetTableRequest) throws Exception { - DataTableData dataTable = this.datasetManager.getPublicPaged(datasetTableRequest); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); - } - - @Operation(summary = "This method is used to get the overview of a public dataset.", description = getOverviewSinglePublicNotes) - @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@ApiResponse( - responseCode = "200", - description = "The following example is generated using id: *ef7dfbdc-c5c1-46a7-a37b-c8d8692f1c0e*", - content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( - value = getOverviewSinglePublicResponseExample - )}) - )}) - @RequestMapping(method = RequestMethod.GET, value = {"/{id}"}, produces = "application/json") - public @ResponseBody - ResponseEntity> getOverviewSinglePublic(@PathVariable @Parameter(description = "fetch the dataset with the given id", example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") String id) throws Exception { -// try { - DatasetPublicModel dataset = this.datasetManager.getOverviewSinglePublic(id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); -// } catch (Exception ex) { -// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); -// } - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/controllers/PublicDmpsDocumentation.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/controllers/PublicDmpsDocumentation.java deleted file mode 100644 index 2808eecbe..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/controllers/PublicDmpsDocumentation.java +++ /dev/null @@ -1,300 +0,0 @@ -package eu.eudat.publicapi.controllers; - -import eu.eudat.controllers.BaseController; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.models.data.helpers.common.DataTableData; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.publicapi.managers.DataManagementPlanPublicManager; -import eu.eudat.publicapi.models.listingmodels.DataManagementPlanPublicListingModel; -import eu.eudat.publicapi.models.overviewmodels.DataManagementPlanPublicModel; -import eu.eudat.publicapi.request.dmp.DataManagmentPlanPublicTableRequest; -import eu.eudat.types.ApiMessageCode; -import io.swagger.annotations.*; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -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 static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; - -@Tag(name = "DMPs", description = "Provides DMP public API's.") -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/public/dmps"}) -public class PublicDmpsDocumentation extends BaseController { - - private static final Logger logger = LoggerFactory.getLogger(PublicDmpsDocumentation.class); - - private DataManagementPlanPublicManager dataManagementPlanManager; - - private static final String getPagedNotes = "The json response is of type **ResponseItem>** containing the following properties:\n" + - "
            " + - "
          1. message: string, message indicating error, null if everything went well
          2. " + - "
          3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
          4. " + - "
          5. responseType: integer, 0 for json, 1 for file
          6. " + - "
          7. payload: DataTableData, containing the number of values of actual data returned and the data of type DataManagementPlanPublicListingModel
          8. " + - "
              " + - "
            1. id: string, id of dmp returned
            2. " + - "
            3. label: string, label of dmp
            4. " + - "
            5. grant: string, grant of dmp
            6. " + - "
            7. createdAt: date, creation time of dmp
            8. " + - "
            9. modifiedAt: date, modification time of dmp
            10. " + - "
            11. version: integer, version of dmp
            12. " + - "
            13. groupId: uuid, group id in which dmp belongs
            14. " + - "
            15. users: list of UserInfoPublicModel, user who collaborated on the dmp
            16. " + - "
            17. researchers: list of ResearcherPublicModel, researchers involved in the dmp
            18. " + - "
            19. finalizedAt: date, finalization date
            20. " + - "
            21. publishedAt: date, publication date
            22. " + - "
            " + - "
          "; - private static final String getPagedResponseExample = "{\n" + - " \"statusCode\": 0,\n" + - " \"responseType\": 0,\n" + - " \"message\": null,\n" + - " \"payload\": {\n" + - " \"totalCount\": 2,\n" + - " \"data\": [\n" + - " {\n" + - " \"id\": \"e9a73d77-adfa-4546-974f-4a4a623b53a8\",\n" + - " \"label\": \"Giorgos's DMP\",\n" + - " \"grant\": \"Novel EOSC services for Emerging Atmosphere, Underwater and Space Challenges\",\n" + - " \"createdAt\": 1579077317000,\n" + - " \"modifiedAt\": 1586444334000,\n" + - " \"version\": 0,\n" + - " \"groupId\": \"d949592d-f862-4b31-a43a-f5f70596df5e\",\n" + - " \"users\": [],\n" + - " \"finalizedAt\": 1586444334000,\n" + - " \"publishedAt\": 1586444334000,\n" + - " \"hint\": \"dataManagementPlanListingModel\"\n" + - " },\n" + - " {\n" + - " \"id\": \"e27789f1-de35-4b4a-9587-a46d131c366e\",\n" + - " \"label\": \"TestH2020Clone3\",\n" + - " \"grant\": \"Evaluation of the Benefits of innovative Concepts of laminar nacelle and HTP installed on a business jet configuration\",\n" + - " \"createdAt\": 1600774437000,\n" + - " \"modifiedAt\": 1600879107000,\n" + - " \"version\": 0,\n" + - " \"groupId\": \"7b793c17-cb69-41d2-a97d-e8d1b03ddbed\",\n" + - " \"users\": [],\n" + - " \"finalizedAt\": 1600879107000,\n" + - " \"publishedAt\": 1600879107000,\n" + - " \"hint\": \"dataManagementPlanListingModel\"\n" + - " }\n" + - " ]\n" + - " }\n" + - "}"; - private static final String getPagedRequestBodyDescription = "The dmpTableRequest is a DataManagementPlanPublicTableRequest object with the following fields:\n" + - "
            " + - "
          • length: how many dmps should be fetched (required)
          • " + - "
          • offset: offset of the returned dmps, first time should be 0, then offset += length
          • " + - "
          • orderings: array of strings specifying the order, format:= +string or -string or asc or desc.
          • " + - "+ means ascending order. - means descending order.
                Available strings are: 1) status, 2) label, 3) publishedAt, 4) created.
            " + - "    asc equivalent to +label.
                desc equivalent to -label.
            " + - "
          • criteria: this is DataManagementPlanPublicCriteria object which applies filters for the dmp returned. More specifically:
          • " + - "
              " + - "
            1. periodStart: date, dmps created date greater than periodStart
            2. " + - "
            3. periodEnd: date, dmps created date less than periodEnd
            4. " + - "
            5. grants: list of uuids, dmps with the corresponding grants
            6. " + - "
            7. grantsLike: list of strings, dmps fetched having their grant matching any of the strings provided
            8. " + - "
            9. funders: list of uuids, dmps with the corresponding funders
            10. " + - "
            11. fundersLike: list of strings, dmps fetched having their funders matching any of the strings provided
            12. " + - "
            13. datasetTemplates: list of uuids, dataset templates which are described in the dmps
            14. " + - "
            15. dmpOrganisations: list of strings, dmps belonging to these organisations
            16. " + - "
            17. collaborators: list of uuids, user who collaborated on the creation/modification of dmps
            18. " + - "
            19. collaboratorsLike: list of strings, dmps fetched having their collaborators matching any of the strings provided
            20. " + - "
            21. allVersions: boolean, if dmps should be fetched with all their versions
            22. " + - "
            23. groupIds: list of uuids, in which groups the dmps are
            24. " + - "
            25. like: string, dmps fetched have this string matched in their label or description
            26. " + - "
            " + - "
              "; - private static final String getPagedRequestParamDescription = "The fieldsGroup is a string which indicates if the returned objects would have all their properties\n" + - "There are two available values: 1) listing and 2) autocomplete\n" + - "
                " + - "
              • listing: returns objects with all their properties completed
              • " + - "
              • autocomplete: returns objects with only id, label, groupId and creationTime assigned
              • " + - "
                  "; - - private static final String getOverviewSinglePublicNotes = "The json response is of type **ResponseItem< DataManagementPlanPublicModel >** containing the following properties:\n" + - "
                    " + - "
                  1. message: string, message indicating error, null if everything went well
                  2. " + - "
                  3. statusCode: integer, status code indicating if something unexpected happened, otherwise 0
                  4. " + - "
                  5. responseType: integer, 0 for json, 1 for file
                  6. " + - "
                  7. payload: DataManagementPlanPublicModel, dmp returned
                  8. " + - "
                      " + - "
                    1. id: string, id of dmp returned
                    2. " + - "
                    3. label: string, label of dmp
                    4. " + - "
                    5. profile: string, profile of dmp
                    6. " + - "
                    7. grant: GrantPublicOverviewModel, grant of dmp
                    8. " + - "
                    9. createdAt: date, creation time of dmp
                    10. " + - "
                    11. modifiedAt: date, modification time of dmp
                    12. " + - "
                    13. finalizedAt: date, finalization date of dmp
                    14. " + - "
                    15. organisations: list of OrganizationPublicModel, organizations in which dmp belongs
                    16. " + - "
                    17. version: integer, version of dmp
                    18. " + - "
                    19. groupId: uuid, group id in which dmp belongs
                    20. " + - "
                    21. datasets: list of DatasetPublicModel, contained datasets
                    22. " + - "
                    23. associatedProfiles: list of AssociatedProfilePublicModel, associated profiles of dmp
                    24. " + - "
                    25. researchers: list of ResearcherPublicModel, researchers involved in dmp
                    26. " + - "
                    27. users: list of UserInfoPublicModel, user who collaborated on the dmp
                    28. " + - "
                    29. description: string, description of dmp
                    30. " + - "
                    31. publishedAt: date, publication date
                    32. " + - "
                    33. doi: string, if dmp has been published to zenodo so it has doi
                    34. " + - "
                    " + - "
                  "; - private static final String getOverviewSinglePublicResponseExample = "{\n" + - " \"statusCode\": 0,\n" + - " \"responseType\": 0,\n" + - " \"message\": null,\n" + - " \"payload\": {\n" + - " \"id\": \"e9a73d77-adfa-4546-974f-4a4a623b53a8\",\n" + - " \"label\": \"Giorgos's DMP\",\n" + - " \"profile\": null,\n" + - " \"grant\": {\n" + - " \"id\": \"c8309ae5-4e56-43eb-aa5a-9950c24051fe\",\n" + - " \"label\": \"Novel EOSC services for Emerging Atmosphere, Underwater and Space Challenges\",\n" + - " \"abbreviation\": null,\n" + - " \"description\": null,\n" + - " \"startDate\": null,\n" + - " \"endDate\": null,\n" + - " \"uri\": null,\n" + - " \"funder\": {\n" + - " \"id\": \"25e76828-3539-4c66-9870-0ecea7a4d16e\",\n" + - " \"label\": \"European Commission||EC\",\n" + - " \"hint\": null\n" + - " },\n" + - " \"hint\": null\n" + - " },\n" + - " \"createdAt\": 1579077317000,\n" + - " \"modifiedAt\": 1586444334000,\n" + - " \"finalizedAt\": 1586444334000,\n" + - " \"organisations\": [],\n" + - " \"version\": 0,\n" + - " \"groupId\": \"d949592d-f862-4b31-a43a-f5f70596df5e\",\n" + - " \"datasets\": [\n" + - " {\n" + - " \"id\": \"853a24c3-def4-4978-985f-92e7fa57ef22\",\n" + - " \"label\": \"Giorgos's Dataset Desc\",\n" + - " \"reference\": null,\n" + - " \"uri\": null,\n" + - " \"description\": null,\n" + - " \"status\": 1,\n" + - " \"createdAt\": 1579077532000,\n" + - " \"dmp\": {\n" + - " \"id\": \"e9a73d77-adfa-4546-974f-4a4a623b53a8\",\n" + - " \"label\": \"Giorgos's DMP\",\n" + - " \"grant\": \"Novel EOSC services for Emerging Atmosphere, Underwater and Space Challenges\",\n" + - " \"createdAt\": 1579077317000,\n" + - " \"modifiedAt\": 1586444334000,\n" + - " \"version\": 0,\n" + - " \"groupId\": \"d949592d-f862-4b31-a43a-f5f70596df5e\",\n" + - " \"users\": [\n" + - " {\n" + - " \"id\": \"00476b4d-0491-44ca-b2fd-92e695062a48\",\n" + - " \"name\": \"OpenDMP OpenDMP\",\n" + - " \"role\": 0,\n" + - " \"email\": \"opendmpeu@gmail.com\",\n" + - " \"hint\": \"UserInfoListingModel\"\n" + - " }\n" + - " ],\n" + - " \"finalizedAt\": 1586444334000,\n" + - " \"publishedAt\": 1586444334000,\n" + - " \"hint\": \"dataManagementPlanListingModel\"\n" + - " },\n" + - " \"datasetProfileDefinition\": {\n" + - " \"pages\": [...],\n" + - " \"rules\": [...],\n" + - " \"status\": 0\n" + - " },\n" + - " \"registries\": [],\n" + - " \"services\": [],\n" + - " \"dataRepositories\": [],\n" + - " \"tags\": null,\n" + - " \"externalDatasets\": [],\n" + - " \"profile\": {\n" + - " \"id\": \"2a6e0835-349e-412c-9fcc-8e1298ce8a5a\",\n" + - " \"label\": \"Horizon 2020\",\n" + - " \"hint\": null\n" + - " },\n" + - " \"modifiedAt\": 1579077898000,\n" + - " \"hint\": \"datasetOverviewModel\"\n" + - " }\n" + - " ],\n" + - " \"associatedProfiles\": [\n" + - " {\n" + - " \"id\": \"f41bd794-761d-4fe8-ab67-3a989d982c53\",\n" + - " \"label\": \"Swedish Research Council\"\n" + - " },\n" + - " {\n" + - " \"id\": \"2a6e0835-349e-412c-9fcc-8e1298ce8a5a\",\n" + - " \"label\": \"Horizon 2020\"\n" + - " }\n" + - " ],\n" + - " \"researchers\": [],\n" + - " \"users\": [\n" + - " {\n" + - " \"id\": \"00476b4d-0491-44ca-b2fd-92e695062a48\",\n" + - " \"name\": \"OpenDMP OpenDMP\",\n" + - " \"role\": 0,\n" + - " \"email\": \"opendmpeu@gmail.com\",\n" + - " \"hint\": \"UserInfoListingModel\"\n" + - " }\n" + - " ],\n" + - " \"description\": null,\n" + - " \"publishedAt\": 1586444334000,\n" + - " \"doi\": \"10.5072/zenodo.522151\",\n" + - " \"hint\": \"dataManagementPlanOverviewModel\"\n" + - " }\n" + - "}"; - - @Autowired - public PublicDmpsDocumentation(ApiContext apiContext, DataManagementPlanPublicManager dataManagementPlanManager) { - super(apiContext); - this.dataManagementPlanManager = dataManagementPlanManager; - } - - @Operation(summary = "This method is used to get a listing of public dmps.", description = getPagedNotes) - @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@ApiResponse( - responseCode = "200", - description = "The following example is generated using:\n" + - "a) body: *{\"criteria\": {},\"length\": 2,\"offset\": 0,\"orderings\": {\"fields\": []} }*\n" + - "b) fieldsGroup: listing", - content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( - value = getPagedResponseExample - )}) - )}) - @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity>> getPaged(@Valid @RequestBody @io.swagger.v3.oas.annotations.parameters.RequestBody(description = getPagedRequestBodyDescription) DataManagmentPlanPublicTableRequest dmpTableRequest, - @RequestParam @Parameter(description = getPagedRequestParamDescription, example = "listing") String fieldsGroup) throws Exception { - DataTableData dataTable = this.dataManagementPlanManager.getPublicPaged(dmpTableRequest, fieldsGroup); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); - } - - @Operation(summary = "This method is used to get the overview of a public dmp.", description = getOverviewSinglePublicNotes) - @io.swagger.v3.oas.annotations.responses.ApiResponses(value = {@ApiResponse( - responseCode = "200", - description = "The following example is generated using id: *e9a73d77-adfa-4546-974f-4a4a623b53a8*", - content = @Content(mediaType = APPLICATION_JSON_VALUE, examples = {@ExampleObject( - value = getOverviewSinglePublicResponseExample - )}) - )}) - @RequestMapping(method = RequestMethod.GET, value = {"/{id}"}, produces = "application/json") - public @ResponseBody - ResponseEntity> getOverviewSinglePublic(@PathVariable @Parameter(description = "fetch the dmp with the given id", example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") String id) throws Exception { -// try { - DataManagementPlanPublicModel dataManagementPlan = this.dataManagementPlanManager.getOverviewSinglePublic(id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlan)); -// } catch (Exception ex) { -// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); -// } - } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/managers/DataManagementPlanPublicManager.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/managers/DataManagementPlanPublicManager.java deleted file mode 100644 index bee4a9bbc..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/managers/DataManagementPlanPublicManager.java +++ /dev/null @@ -1,80 +0,0 @@ -package eu.eudat.publicapi.managers; - -import eu.eudat.commons.enums.DmpAccessType; -import eu.eudat.commons.enums.IsActive; -import eu.eudat.data.DmpEntity; -import eu.eudat.exceptions.security.ForbiddenException; -import eu.eudat.logic.managers.PaginationManager; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.logic.services.operations.DatabaseRepository; -import eu.eudat.models.HintedModelFactory; -import eu.eudat.models.data.helpers.common.DataTableData; -import eu.eudat.publicapi.models.listingmodels.DataManagementPlanPublicListingModel; -import eu.eudat.publicapi.models.overviewmodels.DataManagementPlanPublicModel; -import eu.eudat.publicapi.request.dmp.DataManagmentPlanPublicTableRequest; -import eu.eudat.queryable.QueryableList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -@Component -public class DataManagementPlanPublicManager { - private static final Logger logger = LoggerFactory.getLogger(DataManagementPlanPublicManager.class); - - private DatabaseRepository databaseRepository; - - @Autowired - public DataManagementPlanPublicManager(ApiContext apiContext) { - this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); - } - - public DataTableData getPublicPaged(DataManagmentPlanPublicTableRequest dmpTableRequest, String fieldsGroup) throws Exception { - dmpTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable().withHint(HintedModelFactory.getHint(DataManagementPlanPublicListingModel.class))); - QueryableList items = dmpTableRequest.applyCriteria(); - QueryableList pagedItems = PaginationManager.applyPaging(items, dmpTableRequest); - - DataTableData dataTable = new DataTableData<>(); - - CompletableFuture itemsFuture; - if (fieldsGroup.equals("listing")) { - itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanPublicListingModel.class)) - .selectAsync(item -> { -// item.setDataset( -// item.getDataset().stream() -// .filter(dataset -> dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())).collect(Collectors.toSet())); - return new DataManagementPlanPublicListingModel().fromDataModelNoDatasets(item); - }) - .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); - } else { - itemsFuture = pagedItems - .selectAsync(item -> new DataManagementPlanPublicListingModel().fromDataModel(item)) - .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); - } - - CompletableFuture countFuture = pagedItems.countAsync().whenComplete((count, throwable) -> { - dataTable.setTotalCount(count); - }); - CompletableFuture.allOf(itemsFuture, countFuture).join(); - - return dataTable; - } - - public DataManagementPlanPublicModel getOverviewSinglePublic(String id) throws Exception { - DmpEntity dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); - if (dataManagementPlanEntity.getIsActive().equals(IsActive.Inactive)) { - throw new Exception("DMP is deleted."); - } - if (!dataManagementPlanEntity.getAccessType().equals(DmpAccessType.Public)) { - throw new ForbiddenException("Selected DMP is not public"); - } - DataManagementPlanPublicModel datamanagementPlan = new DataManagementPlanPublicModel(); - datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity); - datamanagementPlan.setDatasets(datamanagementPlan.getDatasets()); - - return datamanagementPlan; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/managers/DatasetPublicManager.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/managers/DatasetPublicManager.java deleted file mode 100644 index 5c97c0ef1..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/managers/DatasetPublicManager.java +++ /dev/null @@ -1,176 +0,0 @@ -package eu.eudat.publicapi.managers; - -import eu.eudat.commons.enums.DescriptionStatus; -import eu.eudat.commons.enums.IsActive; -import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; -import eu.eudat.data.DescriptionEntity; -import eu.eudat.data.DescriptionTemplateEntity; -import eu.eudat.data.query.definition.helpers.ColumnOrderings; -import eu.eudat.logic.managers.PaginationManager; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.logic.services.operations.DatabaseRepository; -import eu.eudat.commons.types.xml.XmlBuilder; -import eu.eudat.models.HintedModelFactory; -import eu.eudat.models.data.helpers.common.DataTableData; -import eu.eudat.models.data.user.composite.PagedDatasetProfile; -import eu.eudat.publicapi.models.listingmodels.DatasetPublicListingModel; -import eu.eudat.publicapi.models.overviewmodels.DatasetPublicModel; -import eu.eudat.queryable.QueryableList; -import eu.eudat.types.grant.GrantStateType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import jakarta.transaction.Transactional; -import java.util.*; -import java.util.stream.Collectors; - -@Component -public class DatasetPublicManager { - private static final Logger logger = LoggerFactory.getLogger(DatasetPublicManager.class); - - private DatabaseRepository databaseRepository; -// private DatasetRepository datasetRepository; - - @Autowired - public DatasetPublicManager(ApiContext apiContext){ - this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); -// this.datasetRepository = apiContext.getOperationsContext().getElasticRepository().getDatasetRepository(); - } - - public DataTableData getPublicPaged(eu.eudat.publicapi.request.dataset.DatasetPublicTableRequest datasetTableRequest) throws Exception { - Long count = 0L; -// DatasetCriteria datasetCriteria = new DatasetCriteria(); -// datasetCriteria.setPublic(true); -// datasetCriteria.setLike(datasetTableRequest.getCriteria().getLike()); -// datasetCriteria.setDatasetTemplates(datasetTableRequest.getCriteria().getDatasetTemplates()); -// datasetCriteria.setDmps(datasetTableRequest.getCriteria().getDmpIds()); -// datasetCriteria.setGrants(datasetTableRequest.getCriteria().getGrants()); -// datasetCriteria.setCollaborators(datasetTableRequest.getCriteria().getCollaborators()); -// datasetCriteria.setAllowAllVersions(datasetTableRequest.getCriteria().getAllVersions()); -// datasetCriteria.setOrganiztions(datasetTableRequest.getCriteria().getDmpOrganisations()); -// if(datasetTableRequest.getCriteria().getTags() != null && !datasetTableRequest.getCriteria().getTags().isEmpty()){ -// datasetCriteria.setHasTags(true); -// datasetCriteria.setTags(datasetTableRequest.getCriteria().getTags()); -// } -// datasetCriteria.setGroupIds(datasetTableRequest.getCriteria().getGroupIds()); -// datasetCriteria.setGrantStatus(GrantStateType.ONGOING.getValue().shortValue()); // grant status ongoing -// datasetCriteria.setStatus(DescriptionStatus.Finalized.getValue()); // dataset status finalized -// if (datasetTableRequest.getOrderings() != null) { -// datasetCriteria.setSortCriteria(DmpPublicCriteriaMapper.toElasticSorting(datasetTableRequest.getOrderings())); -// } -// datasetCriteria.setOffset(datasetTableRequest.getOffset()); -// datasetCriteria.setSize(datasetTableRequest.getLength()); -// List datasets; -// try { -//// datasets = datasetRepository.exists() ? -//// datasetRepository.queryIds(datasetCriteria) : new LinkedList<>(); -// if(datasetTableRequest.getCriteria().getPeriodStart() != null) -// datasets = datasets.stream().filter(dataset -> dataset.getCreated().after(datasetTableRequest.getCriteria().getPeriodStart())).collect(Collectors.toList()); -// if(datasetTableRequest.getCriteria().getPeriodEnd() != null) -// datasets = datasets.stream().filter(dataset -> dataset.getCreated().before(datasetTableRequest.getCriteria().getPeriodEnd())).collect(Collectors.toList()); -// count = (long) datasets.size(); -// } catch (Exception ex) { -// logger.warn(ex.getMessage()); -// datasets = null; -// } - /*datasetTableRequest.setQuery(databaseRepository.getDatasetDao().asQueryable().withHint(HintedModelFactory.getHint(DatasetPublicListingModel.class))); - QueryableList items = datasetTableRequest.applyCriteria();*/ - datasetTableRequest.setQuery(databaseRepository.getDatasetDao().asQueryable().withHint(HintedModelFactory.getHint(DatasetPublicListingModel.class))); - QueryableList items; -// if (datasets != null) { -// if (!datasets.isEmpty()) { -// items = databaseRepository.getDatasetDao().asQueryable().withHint(HintedModelFactory.getHint(DatasetPublicListingModel.class)); -// List finalDatasets = datasets; -// items.where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))); -// } else -// items = datasetTableRequest.applyCriteria(); -// //items.where((builder, root) -> root.get("id").in(new UUID[]{UUID.randomUUID()})); -// } else { - items = datasetTableRequest.applyCriteria(); -// } - - List strings = new ArrayList<>(); - strings.add("-dmp:publishedAt|join|"); - if(datasetTableRequest.getOrderings() != null) { - datasetTableRequest.getOrderings().setFields(strings); - } - else{ - datasetTableRequest.setOrderings(new ColumnOrderings()); - datasetTableRequest.getOrderings().setFields(strings); - } - if (count == 0L) { - count = items.count(); - } - QueryableList pagedItems = PaginationManager.applyPaging(items, datasetTableRequest); - DataTableData dataTable = new DataTableData<>(); - - List datasetLists = pagedItems. - select(this::mapPublicModel); - - dataTable.setData(datasetLists.stream().filter(Objects::nonNull).collect(Collectors.toList())); - dataTable.setTotalCount(count); - return dataTable; - } - - public DatasetPublicModel getOverviewSinglePublic(String id) throws Exception { - DescriptionEntity descriptionEntityEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id)); - if (descriptionEntityEntity.getIsActive() == IsActive.Inactive) { - throw new Exception("Dataset is deleted."); - } - //TODO -// if (!descriptionEntityEntity.getDmp().isPublic()) { -// throw new ForbiddenException("Selected Dataset is not public"); -// } - DatasetPublicModel dataset = new DatasetPublicModel(); - dataset.setDatasetProfileDefinition(this.getPagedProfile(dataset.getStatus(), descriptionEntityEntity)); - dataset.fromDataModel(descriptionEntityEntity); - - return dataset; - } - - @Transactional - private DatasetPublicListingModel mapPublicModel(DescriptionEntity item) { - /*if (item.getProfile() == null) - return null;*/ - DatasetPublicListingModel listingPublicModel = new DatasetPublicListingModel().fromDataModel(item); - /*DatasetProfileCriteria criteria = new DatasetProfileCriteria(); - criteria.setGroupIds(Collections.singletonList(item.getProfile().getGroupId())); - List profiles = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).toList(); - boolean islast = false; - if (!profiles.isEmpty()) { - profiles = profiles.stream().sorted(Comparator.comparing(DescriptionTemplate::getVersion)).collect(Collectors.toList()); - islast = profiles.get(0).getId().equals(item.getProfile().getId()); - } - listingModel.setProfileLatestVersion(islast);*/ - return listingPublicModel; - } - - private PagedDatasetProfile getPagedProfile(DescriptionStatus status, DescriptionEntity descriptionEntityEntity){ - //TODO -// eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = this.generateDatasetProfileModel(descriptionEntityEntity.getProfile()); -// datasetprofile.setStatus(status.getValue()); -// if (descriptionEntityEntity.getProperties() != null) { -// JSONObject jObject = new JSONObject(descriptionEntityEntity.getProperties()); -// Map properties = jObject.toMap(); -// datasetprofile.fromJsonObject(properties); -// } - PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); -// pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); - return pagedDatasetProfile; - } - - private eu.eudat.models.data.user.composite.DatasetProfile generateDatasetProfileModel(DescriptionTemplateEntity profile) { - Document viewStyleDoc = XmlBuilder.fromXml(profile.getDefinition()); - Element root = (Element) viewStyleDoc.getDocumentElement(); - DefinitionEntity viewstyle = new DefinitionEntity().fromXml(root); - - eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = new eu.eudat.models.data.user.composite.DatasetProfile(); - datasetprofile.buildProfile(viewstyle); - - return datasetprofile; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/listingmodels/DatasetPublicListingModel.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/listingmodels/DatasetPublicListingModel.java deleted file mode 100644 index 98ef1b213..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/listingmodels/DatasetPublicListingModel.java +++ /dev/null @@ -1,175 +0,0 @@ -package eu.eudat.publicapi.models.listingmodels; - -import eu.eudat.data.DescriptionEntity; -import eu.eudat.model.DmpUser; -import eu.eudat.models.DataModel; -import eu.eudat.publicapi.models.datasetprofile.DatasetProfilePublicModel; - -import java.util.Date; -import java.util.List; - -public class DatasetPublicListingModel implements DataModel { - private String id; - private String label; - private String grant; - private String dmp; - private String dmpId; - private DatasetProfilePublicModel profile; - private Date createdAt; - private Date modifiedAt; - private String description; - private Date finalizedAt; - private Date dmpPublishedAt; - private int version; - private List users; - - public String getId() { - return id; - } - public void setId(String id) { - this.id = id; - } - - public String getLabel() { - return label; - } - public void setLabel(String label) { - this.label = label; - } - - public String getGrant() { - return grant; - } - public void setGrant(String grant) { - this.grant = grant; - } - - public String getDmp() { - return dmp; - } - public void setDmp(String dmp) { - this.dmp = dmp; - } - - public String getDmpId() { - return dmpId; - } - public void setDmpId(String dmpId) { - this.dmpId = dmpId; - } - - public DatasetProfilePublicModel getProfile() { - return profile; - } - public void setProfile(DatasetProfilePublicModel profile) { - this.profile = profile; - } - - public Date getCreatedAt() { - return createdAt; - } - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getModifiedAt() { - return modifiedAt; - } - public void setModifiedAt(Date modifiedAt) { - this.modifiedAt = modifiedAt; - } - - public String getDescription() { - return description; - } - public void setDescription(String description) { - this.description = description; - } - - public Date getFinalizedAt() { - return finalizedAt; - } - public void setFinalizedAt(Date finalizedAt) { - this.finalizedAt = finalizedAt; - } - - public Date getDmpPublishedAt() { - return dmpPublishedAt; - } - public void setDmpPublishedAt(Date dmpPublishedAt) { - this.dmpPublishedAt = dmpPublishedAt; - } - - public int getVersion() { - return version; - } - public void setVersion(int version) { - this.version = version; - } - - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } - - @Override - public DatasetPublicListingModel fromDataModel(DescriptionEntity entity) { - //TODO -// this.id = entity.getId() != null ? entity.getId().toString() : ""; -// this.label = entity.getLabel(); -// this.createdAt = entity.getCreated(); -// this.modifiedAt = entity.getModified(); -// if(entity.getDmp() != null && entity.getDmp().getGrant() != null) { -// this.grant = entity.getDmp().getGrant().getLabel(); -// } -// this.dmp = entity.getDmp() != null ? entity.getDmp().getLabel() : ""; -// this.dmpId = entity.getDmp() != null ? entity.getDmp().getId().toString() : ""; -// this.profile = entity.getProfile() != null ? new DatasetProfilePublicModel().fromDataModel(entity.getProfile()) : null; -// this.description = entity.getDescription(); -// if (entity.getFinalizedAt() == null && entity.getStatus() == DescriptionEntity.Status.FINALISED.getValue()) { -// this.finalizedAt = entity.getDmp().getFinalizedAt(); -// } else { -// this.finalizedAt = entity.getFinalizedAt(); -// } -// this.dmpPublishedAt = entity.getDmp().getPublishedAt(); -// this.version = entity.getDmp().getVersion(); -// this.users = entity.getDmp() != null ? entity.getDmp().getUsers().stream().map(x -> new UserInfoPublicModel().fromDataModel(x)).collect(Collectors.toList()) : new ArrayList<>(); - return this; - } - - @Override - public DescriptionEntity toDataModel() { - //TODO - DescriptionEntity entity = new DescriptionEntity(); -// entity.setId(UUID.fromString(this.getId())); -// entity.setLabel(this.getLabel()); -// entity.setCreated(this.getCreatedAt()); -// entity.setModified(this.getModifiedAt()); -// entity.setDescription(this.getDescription()); -// entity.setFinalizedAt(this.getFinalizedAt()); -// entity.setStatus(DescriptionEntity.Status.FINALISED.getValue()); -// DMP dmp = new DMP(); -// if (this.getGrant() != null && !this.getGrant().isEmpty()) { -// Grant grant = new Grant(); -// grant.setLabel(this.getGrant()); -// dmp.setGrant(grant); -// } -// dmp.setLabel(this.getDmp()); -// dmp.setId(UUID.fromString(this.getDmpId())); -// dmp.setPublishedAt(this.getDmpPublishedAt()); -// dmp.setVersion(this.getVersion()); -// dmp.setUsers(this.getUsers().stream().map(UserInfoPublicModel::toDataModel).collect(Collectors.toSet())); -// dmp.setFinalizedAt(this.getFinalizedAt()); -// entity.setDmp(dmp); -// entity.setProfile(this.getProfile() != null ? this.getProfile().toDataModel() : null); - return entity; - } - - @Override - public String getHint() { - return "datasetListingModel"; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java deleted file mode 100644 index 64cddf2d3..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/overviewmodels/DataManagementPlanPublicModel.java +++ /dev/null @@ -1,254 +0,0 @@ -package eu.eudat.publicapi.models.overviewmodels; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import eu.eudat.commons.enums.DescriptionStatus; -import eu.eudat.commons.enums.IsActive; -import eu.eudat.commons.types.descriptiontemplate.DefinitionEntity; -import eu.eudat.data.DescriptionEntity; -import eu.eudat.data.DescriptionTemplateEntity; -import eu.eudat.commons.types.xml.XmlBuilder; -import eu.eudat.data.DmpEntity; -import eu.eudat.model.DmpUser; -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; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.*; -import java.util.stream.Collectors; - -public class DataManagementPlanPublicModel implements DataModel { - private String id; - private String label; - private String profile; - private GrantPublicOverviewModel grant; - private Date createdAt; - private Date modifiedAt; - private Date finalizedAt; - private List organisations; - private int version; - private UUID groupId; - private List datasets; - private List associatedProfiles; - private List researchers; - private List users; - private String description; - private Date publishedAt; - private List dois; - - - public String getId() { - return id; - } - public void setId(String id) { - this.id = id; - } - - public String getLabel() { - return label; - } - public void setLabel(String label) { - this.label = label; - } - - public String getProfile() { - return profile; - } - public void setProfile(String profile) { - this.profile = profile; - } - - public GrantPublicOverviewModel getGrant() { - return grant; - } - public void setGrant(GrantPublicOverviewModel grant) { - this.grant = grant; - } - - public Date getCreatedAt() { - return createdAt; - } - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getModifiedAt() { - return modifiedAt; - } - public void setModifiedAt(Date modifiedAt) { - this.modifiedAt = modifiedAt; - } - - public Date getFinalizedAt() { - return finalizedAt; - } - public void setFinalizedAt(Date finalizedAt) { - this.finalizedAt = finalizedAt; - } - - public List getOrganisations() { - return organisations; - } - public void setOrganisations(List organizations) { - this.organisations = organizations; - } - - public int getVersion() { - return version; - } - public void setVersion(int version) { - this.version = version; - } - - public UUID getGroupId() { - return groupId; - } - public void setGroupId(UUID groupId) { - this.groupId = groupId; - } - - public List getDatasets() { - return datasets; - } - public void setDatasets(List datasets) { - this.datasets = datasets; - } - - public List getAssociatedProfiles() { - return associatedProfiles; - } - public void setAssociatedProfiles(List associatedProfiles) { - this.associatedProfiles = associatedProfiles; - } - - public List getUsers() { - return users; - } - public void setUsers(List users) { - this.users = users; - } - - public String getDescription() { - return description; - } - public void setDescription(String description) { - this.description = description; - } - - public List getResearchers() { - return researchers; - } - public void setResearchers(List researchers) { - this.researchers = researchers; - } - - public Date getPublishedAt() { - return publishedAt; - } - public void setPublishedAt(Date publishedAt) { - this.publishedAt = publishedAt; - } - - public List getDois() { - return dois; - } - public void setDois(List dois) { - this.dois = dois; - } - - @Override - public DataManagementPlanPublicModel fromDataModel(DmpEntity entity) { - this.id = entity.getId().toString(); - this.label = entity.getLabel(); - this.groupId = entity.getGroupId(); -// if (entity.getResearchers() != null) { //TODO -// this.researchers = entity.getResearchers().stream().map(item -> new ResearcherPublicModel().fromDataModel(item)).collect(Collectors.toList()); -// } - return this; - } - - public DataManagementPlanPublicModel fromDataModelDatasets(DmpEntity entity) { - this.fromDataModel(entity); - this.version = entity.getVersion();//TODO -// if (entity.getGrant() != null) { -// this.grant = new GrantPublicOverviewModel().fromDataModel(entity.getGrant()); -// } -// if (entity.getProfile() != null) this.profile = entity.getProfile().getLabel(); -// this.createdAt = entity.getCreated(); -// this.modifiedAt = entity.getModified(); -// this.finalizedAt = entity.getFinalizedAt(); -// this.organisations = entity.getOrganisations().stream().map(item -> new OrganizationPublicModel().fromDataModel(item)).collect(Collectors.toList()); -// this.datasets = entity.getDataset().stream().filter(dataset -> !dataset.getIsActive().equals(IsActive.Inactive) && !dataset.getStatus().equals(DescriptionStatus.Canceled)) -// .map(datasetEntity-> { -// DatasetPublicModel dataset = new DatasetPublicModel(); -// dataset.setDatasetProfileDefinition(this.getPagedProfile(dataset.getStatus().getValue(), datasetEntity)); -// dataset.fromDataModel(datasetEntity); -// return dataset; -// }).collect(Collectors.toList()); -// this.users = entity.getUsers().stream().map(x -> new UserInfoPublicModel().fromDataModel(x)).collect(Collectors.toList()); -// this.description = entity.getDescription(); -// if (entity.getResearchers() != null) { -// this.researchers = entity.getResearchers().stream().map(item -> new ResearcherPublicModel().fromDataModel(item)).collect(Collectors.toList()); -// } -// -// if (entity.getAssociatedDmps() != null && !entity.getAssociatedDmps().isEmpty()) { -// this.associatedProfiles = new LinkedList<>(); -// for (DMPDatasetProfile dmpDescriptionProfile : entity.getAssociatedDmps()) { -// AssociatedProfilePublicModel associatedProfile = new AssociatedProfilePublicModel().fromData(dmpDescriptionProfile.getDatasetprofile()); -// associatedProfile.setId(dmpDescriptionProfile.getId()); -// try { -// associatedProfile.setData(new ObjectMapper().readValue(dmpDescriptionProfile.getData(), new TypeReference>() {})); -// } -// catch (Exception e) { -// associatedProfile.setData(null); -// } -// this.associatedProfiles.add(associatedProfile); -// } -// } -// this.publishedAt = entity.getPublishedAt(); -// this.dois = entity.getDois().stream().map(item -> new DoiPublicModel().fromDataModel(item)).collect(Collectors.toList()); - - return this; - } - - private PagedDatasetProfile getPagedProfile(int status, DescriptionEntity descriptionEntityEntity){ - //TODO -// eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = this.generateDatasetProfileModel(descriptionEntityEntity.getProfile()); -// datasetprofile.setStatus(status); -// if (descriptionEntityEntity.getProperties() != null) { -// JSONObject jObject = new JSONObject(descriptionEntityEntity.getProperties()); -// Map properties = jObject.toMap(); -// datasetprofile.fromJsonObject(properties); -// } - PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); - //pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); - return pagedDatasetProfile; - } - - private eu.eudat.models.data.user.composite.DatasetProfile generateDatasetProfileModel(DescriptionTemplateEntity profile) { - Document viewStyleDoc = XmlBuilder.fromXml(profile.getDefinition()); - Element root = (Element) viewStyleDoc.getDocumentElement(); - DefinitionEntity viewstyle = new DefinitionEntity().fromXml(root); - - eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = new eu.eudat.models.data.user.composite.DatasetProfile(); - datasetprofile.buildProfile(viewstyle); - - return datasetprofile; - } - - @Override - public DmpEntity toDataModel() { - return null; - } - - @Override - public String getHint() { - return "dataManagementPlanOverviewModel"; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/researcher/ResearcherPublicModel.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/researcher/ResearcherPublicModel.java deleted file mode 100644 index bf57f8423..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/models/researcher/ResearcherPublicModel.java +++ /dev/null @@ -1,151 +0,0 @@ -package eu.eudat.publicapi.models.researcher; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import eu.eudat.data.old.Researcher; -import eu.eudat.logic.utilities.helpers.LabelGenerator; -import eu.eudat.models.DataModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Date; -import java.util.UUID; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ResearcherPublicModel implements DataModel, LabelGenerator { - private static final Logger logger = LoggerFactory.getLogger(eu.eudat.models.data.dmp.Researcher.class); - private String label; - private String name; - private String id; - private String reference; - private int status; - private String tag; - private String key; - - public String getLabel() { - return label; - } - public void setLabel(String label) { - this.label = label; - } - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - - public String getId() { - return id; - } - public void setId(String id) { - this.id = id; - } - - public String getReference() { - return reference; - } - public void setReference(String reference) { - this.reference = reference; - } - - public int getStatus() { - return status; - } - public void setStatus(int status) { - this.status = status; - } - - public String getTag() { - return tag; - } - public void setTag(String tag) { - this.tag = tag; - } - - public String getKey() { - return key; - } - public void setKey(String key) { - this.key = key; - } - - @Override - public ResearcherPublicModel fromDataModel(Researcher entity) { - this.id = entity.getId().toString(); - this.label = entity.getUri(); - this.name = entity.getLabel(); - this.status = entity.getStatus(); - this.reference = entity.getReference(); - String refParts[] = entity.getReference().split(":"); - String source = refParts[0]; - if (source.equals("dmp")) - this.key = "Internal"; - else - this.key = source; - return this; - } - - @Override - public Researcher toDataModel() { - Researcher researcher = new Researcher(); - if (this.id == null) { - this.id = UUID.randomUUID().toString(); - } - researcher.setId(UUID.fromString(this.id)); - if (this.key != null) { - if (this.key.toLowerCase().equals("internal")) { - if (this.reference != null && !this.reference.startsWith("dmp:")) { - researcher.setReference("dmp:" + this.reference); - } else if (this.reference == null) { - researcher.setReference("dmp:" + this.id); - } else { - researcher.setReference(this.reference); - } - } else { - if ((this.key + ":").equals(this.reference.substring(0, this.key.length() + 1))) { - researcher.setReference(this.reference); - } else { - researcher.setReference(this.key + ":" + this.reference); - } - } - } else { - try { - throw new Exception("Researcher has no key value"); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - - researcher.setLabel(this.name); - researcher.setUri(this.label); - researcher.setCreated(new Date()); - researcher.setStatus((short) this.status); - return researcher; - } - - @Override - public String generateLabel() { - return this.getName(); - } - - @Override - public String getHint() { - return null; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ResearcherPublicModel that = (ResearcherPublicModel) o; - - return id.equals(that.id); - } - - @Override - public int hashCode() { - return reference.hashCode(); - } -} diff --git a/dmp-backend/web/src/main/resources/config/application.yml b/dmp-backend/web/src/main/resources/config/application.yml index 6f847d3b8..0fce2f3d3 100644 --- a/dmp-backend/web/src/main/resources/config/application.yml +++ b/dmp-backend/web/src/main/resources/config/application.yml @@ -19,6 +19,7 @@ spring: optional:classpath:config/swagger.yml[.yml], optional:classpath:config/swagger-${spring.profiles.active}.yml[.yml], optional:file:../config/swagger-${spring.profiles.active}.yml[.yml], optional:classpath:config/deposit.yml[.yml], optional:classpath:config/deposit-${spring.profiles.active}.yml[.yml], optional:file:../config/deposit-${spring.profiles.active}.yml[.yml], optional:classpath:config/errors.yml[.yml], optional:classpath:config/errors-${spring.profiles.active}.yml[.yml], optional:file:../config/errors-${spring.profiles.active}.yml[.yml], + optional:classpath:config/storage.yml[.yml], optional:classpath:config/storage-${spring.profiles.active}.yml[.yml], optional:file:../config/storage-${spring.profiles.active}.yml[.yml], optional:classpath:config/reference-type.yml[.yml], optional:classpath:config/reference-type-${spring.profiles.active}.yml[.yml], optional:file:../config/reference-type-${spring.profiles.active}.yml[.yml], optional:classpath:config/tenant.yml[.yml], optional:classpath:config/tenant-${spring.profiles.active}.yml[.yml], optional:file:../config/tenant-${spring.profiles.active}.yml[.yml] diff --git a/dmp-backend/web/src/main/resources/config/permissions.yml b/dmp-backend/web/src/main/resources/config/permissions.yml index 442863af6..b3877914b 100644 --- a/dmp-backend/web/src/main/resources/config/permissions.yml +++ b/dmp-backend/web/src/main/resources/config/permissions.yml @@ -101,6 +101,13 @@ permissions: clients: [ ] allowAnonymous: false allowAuthenticated: false + DeleteLanguage: + roles: + - Admin + claims: [ ] + clients: [ ] + allowAnonymous: false + allowAuthenticated: false # Statistics BrowseStatistics: roles: [ ] @@ -207,6 +214,27 @@ permissions: clients: [ ] allowAnonymous: false allowAuthenticated: false + # StorageFile + BrowseStorageFile: + roles: [ ] + claims: [ ] + clients: [ ] + allowAnonymous: false + allowAuthenticated: true + EditStorageFile: + roles: + - Admin + claims: [ ] + clients: [ ] + allowAnonymous: false + allowAuthenticated: false + DeleteStorageFile: + roles: + - Admin + claims: [ ] + clients: [ ] + allowAnonymous: false + allowAuthenticated: false # DescriptionTemplate BrowseDescriptionTemplate: roles: diff --git a/dmp-backend/web/src/main/resources/config/storage-devel.yml b/dmp-backend/web/src/main/resources/config/storage-devel.yml new file mode 100644 index 000000000..4c9edee77 --- /dev/null +++ b/dmp-backend/web/src/main/resources/config/storage-devel.yml @@ -0,0 +1,7 @@ +storage: + service: + storages: + - type: Temp + basePath: ./storage/temp + - type: Main + basePath: ./storage/main diff --git a/dmp-backend/web/src/main/resources/config/storage.yml b/dmp-backend/web/src/main/resources/config/storage.yml new file mode 100644 index 000000000..649c39240 --- /dev/null +++ b/dmp-backend/web/src/main/resources/config/storage.yml @@ -0,0 +1,6 @@ +storage: + task: + enable: true + intervalSeconds: 600 + service: + tempStoreLifetimeSeconds: 7200 diff --git a/dmp-backend/web/src/main/resources/config/tenant.yml b/dmp-backend/web/src/main/resources/config/tenant.yml index 2b442bb71..ce3c2cdcd 100644 --- a/dmp-backend/web/src/main/resources/config/tenant.yml +++ b/dmp-backend/web/src/main/resources/config/tenant.yml @@ -1,3 +1,3 @@ tenant: - configEncryptionAesKey: 42J7rLaej8X+kUGR - configEncryptionAesIv: oL859DQRZP+AhfQ+ \ No newline at end of file + configEncryptionAesKey: rmpTvZnRWzyisUtFADBcZCn0q7Z75Xdz + configEncryptionAesIv: ec05d521a23f80ad \ No newline at end of file diff --git a/dmp-db-scema/updates/00.01.024_addLanguage.sql b/dmp-db-scema/updates/00.01.024_addLanguage.sql new file mode 100644 index 000000000..c94160411 --- /dev/null +++ b/dmp-db-scema/updates/00.01.024_addLanguage.sql @@ -0,0 +1,23 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.01.024'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + + CREATE TABLE public."Language" + ( + id uuid NOT NULL, + code character varying(20) NOT NULL, + payload text NOT NULL, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL, + is_active smallint NOT NULL, + CONSTRAINT "Language_pkey" PRIMARY KEY (id) + ) + WITH ( + OIDS = FALSE + ); + + INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.01.024', '2023-11-27 12:00:00.000000+02', now(), 'Add table Language.'); + +END$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.01.024_addStorageFile.sql b/dmp-db-scema/updates/00.01.024_addStorageFile.sql new file mode 100644 index 000000000..e4776a4da --- /dev/null +++ b/dmp-db-scema/updates/00.01.024_addStorageFile.sql @@ -0,0 +1,32 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.01.024'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + + CREATE TABLE public."StorageFile" + ( + id uuid NOT NULL, + file_ref character varying(100) NOT NULL, + name character varying(250) NOT NULL, + extension character varying(10) NOT NULL, + mime_type character varying(200) NOT NULL, + storage_type smallint NOT NULL, + created_at timestamp without time zone NOT NULL, + purge_at timestamp without time zone, + purged_at timestamp without time zone, + owner uuid, + PRIMARY KEY (id), + FOREIGN KEY (owner) + REFERENCES public."User" (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION + NOT VALID + ) + WITH ( + OIDS = FALSE + ); + + INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.01.024', '2023-11-20 12:00:00.000000+02', now(), 'Add table StorageFile.'); + +END$$; \ No newline at end of file diff --git a/dmp-frontend/src/app/app-routing.module.ts b/dmp-frontend/src/app/app-routing.module.ts index c3d14b776..21f984bb8 100644 --- a/dmp-frontend/src/app/app-routing.module.ts +++ b/dmp-frontend/src/app/app-routing.module.ts @@ -232,35 +232,63 @@ const appRoutes: Routes = [ }, }, { - path: 'language-editor', - loadChildren: () => import('./ui/language-editor/language-editor.module').then(m => m.LanguageEditorModule), + path: 'languages', + loadChildren: () => import('./ui/admin/language/language.module').then(m => m.LanguageModule), data: { - breadcrumb: true, - title: 'GENERAL.TITLES.LANGUAGE-EDITOR' + authContext: { + permissions: [AppPermission.ViewLanguagePage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.LANGUAGES' + }) }, }, { path: 'supportive-material', loadChildren: () => import('./ui/supportive-material-editor/supportive-material-editor.module').then(m => m.SupportiveMaterialEditorModule), data: { - breadcrumb: true, - title: 'GENERAL.TITLES.SUPPORTIVE-MATERIAL' + authContext: { + permissions: [AppPermission.ViewLanguagePage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'GENERAL.TITLES.SUPPORTIVE-MATERIAL' + }) + }, + }, + { + path: 'references', + loadChildren: () => import('./ui/admin/reference/reference.module').then(m => m.ReferenceModule), + data: { + authContext: { + permissions: [AppPermission.ViewReferencePage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.REFERENCES' + }) }, }, { path: 'reference-type', loadChildren: () => import('./ui/admin/reference-type/reference-type.module').then(m => m.ReferenceTypeModule), data: { - breadcrumb: true, - title: 'GENERAL.TITLES.REFERENCE-TYPES' + authContext: { + permissions: [AppPermission.ViewReferenceTypePage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.REFERENCE-TYPES' + }) }, }, { path: 'tenants', loadChildren: () => import('./ui/admin/tenant/tenant.module').then(m => m.TenantModule), data: { - breadcrumb: true, - title: 'GENERAL.TITLES.TENANTS' + authContext: { + permissions: [AppPermission.ViewTenantPage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.TENANTS' + }) }, }, { diff --git a/dmp-frontend/src/app/core/common/enum/permission.enum.ts b/dmp-frontend/src/app/core/common/enum/permission.enum.ts index 97295175f..376e14a99 100644 --- a/dmp-frontend/src/app/core/common/enum/permission.enum.ts +++ b/dmp-frontend/src/app/core/common/enum/permission.enum.ts @@ -18,6 +18,11 @@ export enum AppPermission { ViewDescriptionTemplateTypePage = "ViewDescriptionTemplateTypePage", ViewDmpBlueprintPage = "ViewDmpBlueprintPage", ViewDescriptionTemplatePage = "ViewDescriptionTemplatePage", + ViewSupportiveMaterialPage = 'ViewSupportiveMaterialPage', + ViewReferenceTypePage = 'ViewReferenceTypePage', + ViewReferencePage = 'ViewReferencePage', + ViewTenantPage = 'ViewTenantPage', + ViewLanguagePage = "ViewLanguagePage", //ReferenceType BrowseReferenceType = "BrowseReferenceType", @@ -34,5 +39,15 @@ export enum AppPermission { EditUser = "EditUser", DeleteUser = "DeleteUser", ExportUsers = "ExportUsers", + + //Reference + BrowseReference = "BrowseReference", + EditReference = "EditReference", + DeleteReference = "DeleteReference", + + //Language + BrowseLanguage = "BrowseLanguage", + EditLanguage = "EditLanguage", + DeleteLanguage = "DeleteLanguage", } diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts index c7aa406d3..4632bf919 100644 --- a/dmp-frontend/src/app/core/core-service.module.ts +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -61,6 +61,7 @@ import { UserSettingsService } from './services/user-settings/user-settings.serv import { UserService } from './services/user/user.service'; import { FileUtils } from './services/utilities/file-utils.service'; import { QueryParamsService } from './services/utilities/query-params.service'; +import { LanguageV2Service } from './services/language/language-v2.service'; // // // This is shared module that provides all the services. Its imported only once on the AppModule. @@ -140,7 +141,8 @@ export class CoreServiceModule { DescriptionTemplateService, ReferenceTypeService, TenantService, - UserService + UserService, + LanguageV2Service ], }; } diff --git a/dmp-frontend/src/app/core/model/language/language.ts b/dmp-frontend/src/app/core/model/language/language.ts new file mode 100644 index 000000000..3203e130a --- /dev/null +++ b/dmp-frontend/src/app/core/model/language/language.ts @@ -0,0 +1,13 @@ +import { BaseEntity, BaseEntityPersist } from "@common/base/base-entity.model"; + +export interface Language extends BaseEntity{ + code: string; + payload: string; +} + +// Persist + +export interface LanguagePersist extends BaseEntityPersist{ + code: string; + payload: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/reference/reference.ts b/dmp-frontend/src/app/core/model/reference/reference.ts index adf834699..f243d3cd5 100644 --- a/dmp-frontend/src/app/core/model/reference/reference.ts +++ b/dmp-frontend/src/app/core/model/reference/reference.ts @@ -1,12 +1,11 @@ -import { IsActive } from "@app/core/common/enum/is-active.enum"; import { ReferenceFieldDataType } from "@app/core/common/enum/reference-field-data-type"; import { ReferenceSourceType } from "@app/core/common/enum/reference-source-type"; import { ReferenceType } from "@app/core/common/enum/reference-type"; import { UUID } from "crypto"; import { DmpModel } from "../dmp/dmp"; +import { BaseEntity, BaseEntityPersist } from "@common/base/base-entity.model"; -export interface Reference { - id: UUID; +export interface Reference extends BaseEntity{ label: string; type: ReferenceType; description: string; @@ -15,9 +14,6 @@ export interface Reference { abbreviation: string; source: string; sourceType: ReferenceSourceType; - isActive: IsActive; - createdAt: Date; - updatedAt: Date; dmpReferences: DmpReference[]; } @@ -61,12 +57,11 @@ export interface FetcherReference { // Persist -export interface ReferencePersist { - id: UUID; +export interface ReferencePersist extends BaseEntityPersist { label: string; type: ReferenceType; description: string; - definition: DefinitionPersist; + definition?: DefinitionPersist; reference: string; abbreviation: string; source: string; @@ -74,7 +69,7 @@ export interface ReferencePersist { } export interface DefinitionPersist { - fields?: FieldPersist[]; + fields: FieldPersist[]; } export interface FieldPersist { diff --git a/dmp-frontend/src/app/core/query/language.lookup.ts b/dmp-frontend/src/app/core/query/language.lookup.ts new file mode 100644 index 000000000..bdeb427b4 --- /dev/null +++ b/dmp-frontend/src/app/core/query/language.lookup.ts @@ -0,0 +1,23 @@ +import { Lookup } from "@common/model/lookup"; +import { Guid } from "@common/types/guid"; +import { IsActive } from "../common/enum/is-active.enum"; + +export class LanguageLookup extends Lookup implements LanguageFilter { + ids: Guid[]; + excludedIds: Guid[]; + like: string; + isActive: IsActive[]; + codes: string[]; + + constructor() { + super(); + } +} + +export interface LanguageFilter { + ids: Guid[]; + excludedIds: Guid[]; + like: string; + isActive: IsActive[]; + codes: string[]; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/language/language-v2.service.ts b/dmp-frontend/src/app/core/services/language/language-v2.service.ts new file mode 100644 index 000000000..d8cc12630 --- /dev/null +++ b/dmp-frontend/src/app/core/services/language/language-v2.service.ts @@ -0,0 +1,93 @@ +import { Injectable } from '@angular/core'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { Language, LanguagePersist } from '@app/core/model/language/language'; +import { LanguageLookup } from '@app/core/query/language.lookup'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; +import { QueryResult } from '@common/model/query-result'; +import { FilterService } from '@common/modules/text-filter/filter-service'; +import { Guid } from '@common/types/guid'; +import { Observable, throwError } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; +import { ConfigurationService } from '../configuration/configuration.service'; +import { BaseHttpV2Service } from '../http/base-http-v2.service'; + +@Injectable() +export class LanguageV2Service { + + constructor(private http: BaseHttpV2Service, private configurationService: ConfigurationService, private filterService: FilterService) { + } + + private get apiBase(): string { return `${this.configurationService.server}v2/language`; } + + query(q: LanguageLookup): Observable> { + const url = `${this.apiBase}/query`; + return this.http.post>(url, q).pipe(catchError((error: any) => throwError(error))); + } + + getSingle(id: Guid, reqFields: string[] = []): Observable { + const url = `${this.apiBase}/${id}`; + const options = { params: { f: reqFields } }; + + return this.http + .get(url, options).pipe( + catchError((error: any) => throwError(error))); + } + + persist(item: LanguagePersist): Observable { + const url = `${this.apiBase}/persist`; + + return this.http + .post(url, item).pipe( + catchError((error: any) => throwError(error))); + } + + delete(id: Guid): Observable { + const url = `${this.apiBase}/${id}`; + + return this.http + .delete(url).pipe( + catchError((error: any) => throwError(error))); + } + + // + // Autocomplete Commons + // + // tslint:disable-next-line: member-ordering + singleAutocompleteConfiguration: SingleAutoCompleteConfiguration = { + initialItems: (data?: any) => this.query(this.buildAutocompleteLookup()).pipe(map(x => x.items)), + filterFn: (searchQuery: string, data?: any) => this.query(this.buildAutocompleteLookup(searchQuery)).pipe(map(x => x.items)), + getSelectedItem: (selectedItem: any) => this.query(this.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), + displayFn: (item: Language) => item.code, + titleFn: (item: Language) => item.code, + valueAssign: (item: Language) => item.id, + }; + + // tslint:disable-next-line: member-ordering + multipleAutocompleteConfiguration: MultipleAutoCompleteConfiguration = { + initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup(null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), + filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup(searchQuery, excludedItems)).pipe(map(x => x.items)), + getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup(null, null, selectedItems)).pipe(map(x => x.items)), + displayFn: (item: Language) => item.code, + titleFn: (item: Language) => item.code, + valueAssign: (item: Language) => item.id, + }; + + private buildAutocompleteLookup(like?: string, excludedIds?: Guid[], ids?: Guid[]): LanguageLookup { + const lookup: LanguageLookup = new LanguageLookup(); + lookup.page = { size: 100, offset: 0 }; + if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; } + if (ids && ids.length > 0) { lookup.ids = ids; } + lookup.isActive = [IsActive.Active]; + lookup.project = { + fields: [ + nameof(x => x.id), + nameof(x => x.code) + ] + }; + lookup.order = { items: [nameof(x => x.code)] }; + if (like) { lookup.like = this.filterService.transformLike(like); } + return lookup; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts index aafb33583..08d8d0d81 100644 --- a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts +++ b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts @@ -22,6 +22,8 @@ import { ReferenceFieldDataType } from '@app/core/common/enum/reference-field-da import { ReferenceTypeSourceType } from '@app/core/common/enum/reference-type-source-type'; import { ReferenceTypeExternalApiHTTPMethodType } from '@app/core/common/enum/reference-type-external-api-http-method-type'; import { UserDescriptionTemplateRole } from '@app/core/common/enum/user-description-template-role'; +import { ReferenceType } from '@app/core/common/enum/reference-type'; +import { ReferenceSourceType } from '@app/core/common/enum/reference-source-type'; @Injectable() export class EnumUtils { @@ -310,4 +312,32 @@ export class EnumUtils { case UserDescriptionTemplateRole.Owner: return this.language.instant('TYPES.USER-DESCRIPTION-TEMPLATE-ROLE.OWNER'); } } + + toReferenceTypeString(status: ReferenceType): string { + switch (status) { + case ReferenceType.Taxonomies: return this.language.instant('TYPES.REFERENCE-TYPE.TAXONOMY'); + case ReferenceType.Licenses: return this.language.instant('TYPES.REFERENCE-TYPE.LICENCE'); + case ReferenceType.Publications: return this.language.instant('TYPES.REFERENCE-TYPE.PUBLICATION'); + case ReferenceType.Journals: return this.language.instant('TYPES.REFERENCE-TYPE.JOURNAL'); + case ReferenceType.PubRepositories: return this.language.instant('TYPES.REFERENCE-TYPE.PUB-REPOSITORY'); + case ReferenceType.DataRepositories: return this.language.instant('TYPES.REFERENCE-TYPE.DATA-REPOSITORY'); + case ReferenceType.Registries: return this.language.instant('TYPES.REFERENCE-TYPE.REGISTRY'); + case ReferenceType.Services: return this.language.instant('TYPES.REFERENCE-TYPE.SERVICE'); + case ReferenceType.Project: return this.language.instant('TYPES.REFERENCE-TYPE.PROJECT'); + case ReferenceType.Funder: return this.language.instant('TYPES.REFERENCE-TYPE.FUNDER'); + case ReferenceType.Datasets: return this.language.instant('TYPES.REFERENCE-TYPE.DATASET'); + case ReferenceType.Organizations: return this.language.instant('TYPES.REFERENCE-TYPE.ORGANISATION'); + case ReferenceType.Grants: return this.language.instant('TYPES.REFERENCE-TYPE.GRANT'); + case ReferenceType.Researcher: return this.language.instant('TYPES.REFERENCE-TYPE.RESEARCHER'); + + } + } + + toReferenceSourceTypeString(status: ReferenceSourceType): string { + switch (status) { + case ReferenceSourceType.Internal: return this.language.instant('TYPES.REFERENCE-SOURCE-TYPE.INTERNAL'); + case ReferenceSourceType.External: return this.language.instant('TYPES.REFERENCE-SOURCE-TYPE.EXTERNAL'); + } + } + } diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html new file mode 100644 index 000000000..47c09eb28 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html @@ -0,0 +1,53 @@ +
                  +
                  +
                  +
                  +

                  {{'LANGUAGE-EDITOR.NEW' | translate}}

                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  + + + {{'LANGUAGE-EDITOR.NEW' | translate}} + + +
                  +
                  + + {{'LANGUAGE-EDITOR.FIELDS.CODE' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'LANGUAGE-EDITOR.FIELDS.PAYLOAD' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  +
                  +
                  +
                  +
                  +
                  \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.scss b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.scss new file mode 100644 index 000000000..66f9e4fa8 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.scss @@ -0,0 +1,43 @@ +.tenant-editor { + margin-top: 1.3rem; + margin-left: 1em; + margin-right: 3em; + + .remove { + background-color: white; + color: black; + } + + .add { + background-color: white; + color: #009700; + } +} + +::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background { + background-color: var(--primary-color-3); + // background-color: #0070c0; +} + +::ng-deep .mat-checkbox-disabled.mat-checkbox-checked .mat-checkbox-background, .mat-checkbox-disabled.mat-checkbox-indeterminate .mat-checkbox-background { + background-color: #b0b0b0; +} + +.action-btn { + border-radius: 30px; + background-color: var(--secondary-color); + border: 1px solid transparent; + padding-left: 2em; + padding-right: 2em; + box-shadow: 0px 3px 6px #1E202029; + + transition-property: background-color, color; + transition-duration: 200ms; + transition-delay: 50ms; + transition-timing-function: ease-in-out; + &:disabled{ + background-color: #CBCBCB; + color: #FFF; + border: 0px; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.ts b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.ts new file mode 100644 index 000000000..4b8554420 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.ts @@ -0,0 +1,186 @@ + +import { Component, OnInit } from '@angular/core'; +import { UntypedFormGroup } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +// import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { DatePipe } from '@angular/common'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { AppPermission } from '@app/core/common/enum/permission.enum'; +import { Language, LanguagePersist } from '@app/core/model/language/language'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { LoggingService } from '@app/core/services/logging/logging-service'; +import { MatomoService } from '@app/core/services/matomo/matomo-service'; +import { FileUtils } from '@app/core/services/utilities/file-utils.service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseEditor } from '@common/base/base-editor'; +import { FormService } from '@common/forms/form-service'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { FilterService } from '@common/modules/text-filter/filter-service'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { map, takeUntil } from 'rxjs/operators'; +import { LanguageEditorResolver } from './language-editor.resolver'; +import { LanguageEditorService } from './language-editor.service'; +import { LanguageEditorModel } from './language-editor.model'; +import { MatChipEditedEvent, MatChipInputEvent } from '@angular/material/chips'; +import { LanguageV2Service } from '@app/core/services/language/language-v2.service'; + + +@Component({ + selector: 'app-language-editor-component', + templateUrl: 'language-editor.component.html', + styleUrls: ['./language-editor.component.scss'], + providers: [LanguageEditorService] +}) +export class LanguageEditorComponent extends BaseEditor implements OnInit { + + isNew = true; + isDeleted = false; + formGroup: UntypedFormGroup = null; + showInactiveDetails = false; + depositCodes: string[] = []; + fileTransformersCodes: string[] = []; + + protected get canDelete(): boolean { + return !this.isDeleted && !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteLanguage); + } + + protected get canSave(): boolean { + return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditLanguage); + } + + protected get canFinalize(): boolean { + return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditLanguage); + } + + + private hasPermission(permission: AppPermission): boolean { + return this.authService.hasPermission(permission) || this.editorModel?.permissions?.includes(permission); + } + + constructor( + // BaseFormEditor injected dependencies + protected dialog: MatDialog, + protected language: TranslateService, + protected formService: FormService, + protected router: Router, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected filterService: FilterService, + protected datePipe: DatePipe, + protected route: ActivatedRoute, + protected queryParamsService: QueryParamsService, + // Rest dependencies. Inject any other needed deps here: + public authService: AuthService, + public enumUtils: EnumUtils, + private languageV2Service: LanguageV2Service, + private logger: LoggingService, + private languageEditorService: LanguageEditorService, + private fileUtils: FileUtils, + private matomoService: MatomoService + ) { + super(dialog, language, formService, router, uiNotificationService, httpErrorHandlingService, filterService, datePipe, route, queryParamsService); + } + + ngOnInit(): void { + this.matomoService.trackPageView('Admin: Languages'); + super.ngOnInit(); + } + + getItem(itemId: Guid, successFunction: (item: Language) => void) { + this.languageV2Service.getSingle(itemId, LanguageEditorResolver.lookupFields()) + .pipe(map(data => data as Language), takeUntil(this._destroyed)) + .subscribe( + data => successFunction(data), + error => this.onCallbackError(error) + ); + } + + prepareForm(data: Language) { + try { + this.editorModel = data ? new LanguageEditorModel().fromModel(data) : new LanguageEditorModel(); + this.isDeleted = data ? data.isActive === IsActive.Inactive : false; + this.buildForm(); + } catch (error) { + this.logger.error('Could not parse Language item: ' + data + error); + this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error); + } + } + + buildForm() { + this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditLanguage)); + this.languageEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); + } + + refreshData(): void { + this.getItem(this.editorModel.id, (data: Language) => this.prepareForm(data)); + } + + refreshOnNavigateToData(id?: Guid): void { + this.formGroup.markAsPristine(); + let route = []; + + if (id === null) { + route.push('../..'); + } else if (this.isNew) { + route.push('../' + id); + } else { + route.push('..'); + } + + this.router.navigate(route, { queryParams: { 'lookup': this.queryParamsService.serializeLookup(this.lookupParams), 'lv': ++this.lv }, replaceUrl: true, relativeTo: this.route }); + } + + persistEntity(onSuccess?: (response) => void): void { + const formData = this.formService.getValue(this.formGroup.value) as LanguagePersist; + + this.languageV2Service.persist(formData) + .pipe(takeUntil(this._destroyed)).subscribe( + complete => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete), + error => this.onCallbackError(error) + ); + } + + formSubmit(): void { + this.formService.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { + return; + } + + this.persistEntity(); + } + + public delete() { + const value = this.formGroup.value; + if (value.id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + data: { + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + 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.languageV2Service.delete(value.id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + clearErrorModel() { + this.editorModel.validationErrorModel.clear(); + this.formService.validateAllFormFields(this.formGroup); + } + +} diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.model.ts b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.model.ts new file mode 100644 index 000000000..c536ff745 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.model.ts @@ -0,0 +1,50 @@ +import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { Language, LanguagePersist } from "@app/core/model/language/language"; +import { BaseEditorModel } from "@common/base/base-form-editor-model"; +import { BackendErrorValidator } from "@common/forms/validation/custom-validator"; +import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model"; +import { Validation, ValidationContext } from "@common/forms/validation/validation-context"; + +export class LanguageEditorModel extends BaseEditorModel implements LanguagePersist { + code: string; + payload: string; + + permissions: string[]; + + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor() { super(); } + + public fromModel(item: Language): LanguageEditorModel { + if (item) { + super.fromModel(item); + this.code = item.code; + this.payload = item.payload; + } + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup { + if (context == null) { context = this.createValidationContext(); } + + return this.formBuilder.group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + code: [{ value: this.code, disabled: disabled }, context.getValidation('code').validators], + payload: [{ value: this.payload, disabled: disabled }, context.getValidation('payload').validators], + hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] + }); + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); + baseValidationArray.push({ key: 'code', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'code')] }); + baseValidationArray.push({ key: 'payload', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'payload')] }); + baseValidationArray.push({ key: 'hash', validators: [] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.resolver.ts b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.resolver.ts new file mode 100644 index 000000000..25ea7e3a7 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.resolver.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Language } from '@app/core/model/language/language'; +import { LanguageV2Service } from '@app/core/services/language/language-v2.service'; +import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; +import { BaseEditorResolver } from '@common/base/base-editor.resolver'; +import { Guid } from '@common/types/guid'; +import { takeUntil, tap } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; + +@Injectable() +export class LanguageEditorResolver extends BaseEditorResolver { + + constructor(private languageV2Service: LanguageV2Service, private breadcrumbService: BreadcrumbService) { + super(); + } + + public static lookupFields(): string[] { + return [ + ...BaseEditorResolver.lookupFields(), + nameof(x => x.id), + nameof(x => x.code), + nameof(x => x.payload), + nameof(x => x.createdAt), + nameof(x => x.updatedAt), + nameof(x => x.hash), + nameof(x => x.isActive) + ] + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + + const fields = [ + ...LanguageEditorResolver.lookupFields() + ]; + const id = route.paramMap.get('id'); + + if (id != null) { + return this.languageV2Service.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.code)), takeUntil(this._destroyed)); + } + } +} diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.service.ts b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.service.ts new file mode 100644 index 000000000..2ffb929ca --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from "@angular/core"; +import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model"; + +@Injectable() +export class LanguageEditorService { + private validationErrorModel: ValidationErrorModel; + + public setValidationErrorModel(validationErrorModel: ValidationErrorModel): void { + this.validationErrorModel = validationErrorModel; + } + + public getValidationErrorModel(): ValidationErrorModel { + return this.validationErrorModel; + } +} diff --git a/dmp-frontend/src/app/ui/admin/language/language.module.ts b/dmp-frontend/src/app/ui/admin/language/language.module.ts new file mode 100644 index 000000000..f188ebe86 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/language.module.ts @@ -0,0 +1,41 @@ +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { NgModule } from "@angular/core"; +import { AutoCompleteModule } from "@app/library/auto-complete/auto-complete.module"; +import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; +import { CommonFormattingModule } from '@common/formatting/common-formatting.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { HybridListingModule } from "@common/modules/hybrid-listing/hybrid-listing.module"; +import { TextFilterModule } from "@common/modules/text-filter/text-filter.module"; +import { UserSettingsModule } from "@common/modules/user-settings/user-settings.module"; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { NgxDropzoneModule } from "ngx-dropzone"; +import { LanguageRoutingModule } from './language.routing'; +import { LanguageEditorComponent } from './editor/language-editor.component'; +import { LanguageListingComponent } from './listing/language-listing.component'; +import { LanguageListingFiltersComponent } from "./listing/filters/language-listing-filters.component"; +import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-editor.module'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + UrlListingModule, + ConfirmationDialogModule, + LanguageRoutingModule, + NgxDropzoneModule, + DragDropModule, + AutoCompleteModule, + HybridListingModule, + TextFilterModule, + UserSettingsModule, + CommonFormattingModule, + RichTextEditorModule + ], + declarations: [ + LanguageEditorComponent, + LanguageListingComponent, + LanguageListingFiltersComponent + ] +}) +export class LanguageModule { } diff --git a/dmp-frontend/src/app/ui/admin/language/language.routing.ts b/dmp-frontend/src/app/ui/admin/language/language.routing.ts new file mode 100644 index 000000000..1e138b019 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/language.routing.ts @@ -0,0 +1,57 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { LanguageEditorComponent } from './editor/language-editor.component'; +import { LanguageListingComponent } from './listing/language-listing.component'; +import { AppPermission } from '@app/core/common/enum/permission.enum'; +import { AuthGuard } from '@app/core/auth-guard.service'; +import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; +import { PendingChangesGuard } from '@common/forms/pending-form-changes/pending-form-changes-guard.service'; +import { LanguageEditorResolver } from './editor/language-editor.resolver'; + +const routes: Routes = [ + { + path: '', + component: LanguageListingComponent, + canActivate: [AuthGuard] + }, + { + path: 'new', + canActivate: [AuthGuard], + component: LanguageEditorComponent, + canDeactivate: [PendingChangesGuard], + data: { + authContext: { + permissions: [AppPermission.EditLanguage] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.NEW-LANGUAGE' + }) + } + }, + { + path: ':id', + canActivate: [AuthGuard], + component: LanguageEditorComponent, + canDeactivate: [PendingChangesGuard], + resolve: { + 'entity': LanguageEditorResolver + }, + data: { + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.EDIT-LANGUAGE' + }), + authContext: { + permissions: [AppPermission.EditLanguage] + } + } + + }, + { path: '**', loadChildren: () => import('@common/modules/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule) }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [LanguageEditorResolver] +}) +export class LanguageRoutingModule { } diff --git a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html new file mode 100644 index 000000000..248db4c57 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html @@ -0,0 +1,36 @@ +
                  + + + + + +
                  +
                  +
                  +

                  {{'TENANT-LISTING.FILTER.TITLE' | translate}}

                  + +
                  + + + {{'TENANT-LISTING.FILTER.IS-ACTIVE' | translate}} + + +
                  + + +
                  +
                  +
                  +
                  + + +
                  diff --git a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss new file mode 100644 index 000000000..ea00a215c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss @@ -0,0 +1,21 @@ +::ng-deep.mat-mdc-menu-panel { + max-width: 100% !important; + height: 100% !important; +} + +:host::ng-deep.mat-mdc-menu-content:not(:empty) { + padding-top: 0 !important; +} + + +.filter-button{ + padding-top: .6rem; + padding-bottom: .6rem; + // .mat-icon{ + // font-size: 1.5em; + // width: 1.2em; + // height: 1.2em; + // } +} + + diff --git a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.ts b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.ts new file mode 100644 index 000000000..066fd15ee --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.ts @@ -0,0 +1,94 @@ +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { TenantFilter } from '@app/core/query/tenant.lookup'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { BaseComponent } from '@common/base/base.component'; +import { nameof } from 'ts-simple-nameof'; + +@Component({ + selector: 'app-language-listing-filters', + templateUrl: './language-listing-filters.component.html', + styleUrls: ['./language-listing-filters.component.scss'] +}) +export class LanguageListingFiltersComponent extends BaseComponent implements OnInit, OnChanges { + + @Input() readonly filter: TenantFilter; + @Output() filterChange = new EventEmitter(); + + // * State + internalFilters: LanguageListingFilters = this._getEmptyFilters(); + + protected appliedFilterCount: number = 0; + constructor( + public enumUtils: EnumUtils, + ) { super(); } + + ngOnInit() { + } + + ngOnChanges(changes: SimpleChanges): void { + const filterChange = changes[nameof(x => x.filter)]?.currentValue as TenantFilter; + if (filterChange) { + this.updateFilters() + } + } + + + onSearchTermChange(searchTerm: string): void { + this.applyFilters() + } + + + protected updateFilters(): void { + this.internalFilters = this._parseToInternalFilters(this.filter); + this.appliedFilterCount = this._computeAppliedFilters(this.internalFilters); + } + + protected applyFilters(): void { + const { isActive, like } = this.internalFilters ?? {} + this.filterChange.emit({ + ...this.filter, + like, + isActive: isActive ? [IsActive.Active] : [IsActive.Inactive] + }) + } + + + private _parseToInternalFilters(inputFilter: TenantFilter): LanguageListingFilters { + if (!inputFilter) { + return this._getEmptyFilters(); + } + + let { excludedIds, ids, isActive, like } = inputFilter; + + return { + isActive: (isActive ?? [])?.includes(IsActive.Active) || !isActive?.length, + like: like + } + + } + + private _getEmptyFilters(): LanguageListingFilters { + return { + isActive: true, + like: null, + } + } + + private _computeAppliedFilters(filters: LanguageListingFilters): number { + let count = 0; + if (filters?.isActive) { + count++ + } + return count; + } + + clearFilters() { + this.internalFilters = this._getEmptyFilters(); + } +} + +interface LanguageListingFilters { + isActive: boolean; + like: string; +} diff --git a/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html new file mode 100644 index 000000000..55be97c8b --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.html @@ -0,0 +1,95 @@ +
                  +
                  + +
                  +
                  +

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

                  + + +
                  +
                  + +
                  +
                  + + + + + + + + +
                  +
                  + + + + +
                  +
                  + + {{item?.name | nullifyValue}} +
                  +
                  + + +
                  +
                  + {{enumUtils.toDescriptionTemplateTypeStatusString(item.status) | nullifyValue}} +
                  +
                  +
                  + + + + {{'LANGUAGE-LISTING.FIELDS.CREATED-AT' | translate}}: + + {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + + +
                  +
                  + + + {{'LANGUAGE-LISTING.FIELDS.UPDATED-AT' | translate}}: + + {{item?.updatedAt | dateTimeFormatter : 'short' | nullifyValue}} + + + +
                  +
                  +
                  + + +
                  +
                  + + + + + +
                  +
                  +
                  \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.scss b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.scss new file mode 100644 index 000000000..e5a0263b1 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.scss @@ -0,0 +1,60 @@ +.language-listing { + margin-top: 1.3rem; + margin-left: 1rem; + margin-right: 2rem; + + .mat-header-row{ + background: #f3f5f8; + } + .mat-card { + margin: 16px 0; + padding: 0px; + } + + .mat-row { + cursor: pointer; + min-height: 4.5em; + } + + mat-row:hover { + background-color: #eef5f6; + } + .mat-fab-bottom-right { + float: right; + z-index: 5; + } +} +.create-btn { + border-radius: 30px; + background-color: var(--secondary-color); + padding-left: 2em; + padding-right: 2em; + // color: #000; + + .button-text{ + display: inline-block; + } +} + +.dlt-btn { + color: rgba(0, 0, 0, 0.54); +} + +.status-chip{ + + border-radius: 20px; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.2em; + font-size: .8em; +} + +.status-chip-finalized{ + color: #568b5a; + background: #9dd1a1 0% 0% no-repeat padding-box; +} + +.status-chip-draft{ + color: #00c4ff; + background: #d3f5ff 0% 0% no-repeat padding-box; +} diff --git a/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.ts b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.ts new file mode 100644 index 000000000..3dfa735ec --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/language/listing/language-listing.component.ts @@ -0,0 +1,164 @@ +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { Language } from '@app/core/model/language/language'; +import { LanguageLookup } from '@app/core/query/language.lookup'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { LanguageV2Service } from '@app/core/services/language/language-v2.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; +import { BaseListingComponent } from '@common/base/base-listing-component'; +import { PipeService } from '@common/formatting/pipe.service'; +import { DataTableDateTimeFormatPipe } from '@common/formatting/pipes/date-time-format.pipe'; +import { QueryResult } from '@common/model/query-result'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { ColumnDefinition, ColumnsChangedEvent, HybridListingComponent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; + +@Component({ + templateUrl: './language-listing.component.html', + styleUrls: ['./language-listing.component.scss'] +}) +export class LanguageListingComponent extends BaseListingComponent implements OnInit { + publish = false; + userSettingsKey = { key: 'LanguageListingUserSettings' }; + propertiesAvailableForOrder: ColumnDefinition[]; + + // @ViewChild('LanguageStatus', { static: true }) LanguageStatus?: TemplateRef; + @ViewChild('actions', { static: true }) actions?: TemplateRef; + @ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent; + + private readonly lookupFields: string[] = [ + nameof(x => x.id), + nameof(x => x.code), + nameof(x => x.updatedAt), + nameof(x => x.createdAt), + nameof(x => x.hash), + nameof(x => x.isActive) + ]; + + rowIdentity = x => x.id; + + constructor( + protected router: Router, + protected route: ActivatedRoute, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected queryParamsService: QueryParamsService, + private languageV2Service: LanguageV2Service, + public authService: AuthService, + private pipeService: PipeService, + public enumUtils: EnumUtils, + private language: TranslateService, + private dialog: MatDialog + ) { + super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService); + // Lookup setup + // Default lookup values are defined in the user settings class. + this.lookup = this.initializeLookup(); + } + + ngOnInit() { + super.ngOnInit(); + } + + protected initializeLookup(): LanguageLookup { + const lookup = new LanguageLookup(); + lookup.metadata = { countAll: true }; + lookup.page = { offset: 0, size: this.ITEMS_PER_PAGE }; + lookup.isActive = [IsActive.Active]; + lookup.order = { items: [this.toDescSortField(nameof(x => x.createdAt))] }; + this.updateOrderUiFields(lookup.order); + + lookup.project = { + fields: this.lookupFields + }; + + return lookup; + } + + protected setupColumns() { + this.gridColumns.push(...[{ + prop: nameof(x => x.code), + sortable: true, + languageName: 'LANGUAGE-LISTING.FIELDS.CODE' + }, + { + prop: nameof(x => x.createdAt), + sortable: true, + languageName: 'LANGUAGE-LISTING.FIELDS.CREATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + prop: nameof(x => x.updatedAt), + sortable: true, + languageName: 'LANGUAGE-LISTING.FIELDS.UPDATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + alwaysShown: true, + cellTemplate: this.actions, + maxWidth: 120 + } + ]); + this.propertiesAvailableForOrder = this.gridColumns.filter(x => x.sortable); + } + + // + // Listing Component functions + // + onColumnsChanged(event: ColumnsChangedEvent) { + super.onColumnsChanged(event); + this.onColumnsChangedInternal(event.properties.map(x => x.toString())); + } + + private onColumnsChangedInternal(columns: string[]) { + // Here are defined the projection fields that always requested from the api. + const fields = new Set(this.lookupFields); + this.gridColumns.map(x => x.prop) + .filter(x => !columns?.includes(x as string)) + .forEach(item => { + fields.delete(item as string) + }); + this.lookup.project = { fields: [...fields] }; + this.onPageLoad({ offset: 0 } as PageLoadEvent); + } + + protected loadListing(): Observable> { + return this.languageV2Service.query(this.lookup); + } + + public deleteType(id: Guid) { + if (id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { + isDeleteConfirmation: true, + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + 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.languageV2Service.delete(id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success); + this.ngOnInit(); + } +} diff --git a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.resolver.ts b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.resolver.ts index b04b55898..ca622335d 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.resolver.ts @@ -11,7 +11,7 @@ import { nameof } from 'ts-simple-nameof'; @Injectable() export class ReferenceTypeEditorResolver extends BaseEditorResolver { - constructor(private ReferenceTypeService: ReferenceTypeService, private breadcrumbService: BreadcrumbService) { + constructor(private referenceTypeService: ReferenceTypeService, private breadcrumbService: BreadcrumbService) { super(); } @@ -81,7 +81,7 @@ export class ReferenceTypeEditorResolver extends BaseEditorResolver { ]; const id = route.paramMap.get('id'); if (id != null) { - return this.ReferenceTypeService.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.code)), takeUntil(this._destroyed)); + return this.referenceTypeService.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.code)), takeUntil(this._destroyed)); } } } diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html new file mode 100644 index 000000000..80e0cadbd --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html @@ -0,0 +1,157 @@ +
                  +
                  +
                  +
                  +

                  {{'REFERENCE-EDITOR.NEW' | translate}}

                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  + + + {{'REFERENCE-EDITOR.NEW' | translate}} + + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.LABEL' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.TYPE' | translate}} + + + {{enumUtils.toReferenceTypeString(type)}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  +

                  {{'REFERENCE-EDITOR.FIELDS.DESCRIPTION' | translate}}

                  +
                  + + +
                  + + {{'GENERAL.VALIDATION.REQUIRED'| translate}} + +
                  +
                  +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.SOURCE' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.SOURCE-TYPE' | translate}} + + + {{enumUtils.toReferenceSourceTypeString(sourceType)}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.REFERENCE' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.ABBREVIATION' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  + + +
                  +

                  + {{'REFERENCE-EDITOR.FIELDS.FIELDS' | translate}} + +

                  +
                  +
                  +
                  +
                  + {{'REFERENCE-EDITOR.FIELDS.FIELD' | translate}} {{fieldIndex + 1}} +
                  +
                  + +
                  +
                  +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.CODE' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.DATA-TYPE' | translate}} + + + {{enumUtils.toReferenceFieldDataTypeString(dataType)}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  + + {{'REFERENCE-EDITOR.FIELDS.VALUE' | translate}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.scss b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.scss new file mode 100644 index 000000000..306d4650e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.scss @@ -0,0 +1,43 @@ +.reference-editor { + margin-top: 1.3rem; + margin-left: 1em; + margin-right: 3em; + + .remove { + background-color: white; + color: black; + } + + .add { + background-color: white; + color: #009700; + } +} + +::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background { + background-color: var(--primary-color-3); + // background-color: #0070c0; +} + +::ng-deep .mat-checkbox-disabled.mat-checkbox-checked .mat-checkbox-background, .mat-checkbox-disabled.mat-checkbox-indeterminate .mat-checkbox-background { + background-color: #b0b0b0; +} + +.action-btn { + border-radius: 30px; + background-color: var(--secondary-color); + border: 1px solid transparent; + padding-left: 2em; + padding-right: 2em; + box-shadow: 0px 3px 6px #1E202029; + + transition-property: background-color, color; + transition-duration: 200ms; + transition-delay: 50ms; + transition-timing-function: ease-in-out; + &:disabled{ + background-color: #CBCBCB; + color: #FFF; + border: 0px; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts new file mode 100644 index 000000000..f18bb26e6 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.ts @@ -0,0 +1,202 @@ + +import { Component, OnInit } from '@angular/core'; +import { FormArray, UntypedFormGroup } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ReferenceService } from '@app/core/services/reference/reference.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +// import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; +import { DatePipe } from '@angular/common'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { AppPermission } from '@app/core/common/enum/permission.enum'; +import { Reference, ReferencePersist } from '@app/core/model/reference/reference'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { LoggingService } from '@app/core/services/logging/logging-service'; +import { MatomoService } from '@app/core/services/matomo/matomo-service'; +import { FileUtils } from '@app/core/services/utilities/file-utils.service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { BaseEditor } from '@common/base/base-editor'; +import { FormService } from '@common/forms/form-service'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { FilterService } from '@common/modules/text-filter/filter-service'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { map, takeUntil } from 'rxjs/operators'; +import { ReferenceEditorResolver } from './reference-editor.resolver'; +import { ReferenceEditorService } from './reference-editor.service'; +import { FieldEditorModel, ReferenceEditorModel } from './reference-editor.model'; +import { ReferenceType } from '@app/core/common/enum/reference-type'; +import { ReferenceSourceType } from '@app/core/common/enum/reference-source-type'; +import { ReferenceFieldDataType } from '@app/core/common/enum/reference-field-data-type'; + + +@Component({ + selector: 'app-reference-editor-component', + templateUrl: 'reference-editor.component.html', + styleUrls: ['./reference-editor.component.scss'], + providers: [ReferenceEditorService] +}) +export class ReferenceEditorComponent extends BaseEditor implements OnInit { + + isNew = true; + isDeleted = false; + formGroup: UntypedFormGroup = null; + showInactiveDetails = false; + public referenceTypeEnum = this.enumUtils.getEnumValues(ReferenceType); + public referenceSourceTypeEnum = this.enumUtils.getEnumValues(ReferenceSourceType); + public referenceFieldDataTypeEnum = this.enumUtils.getEnumValues(ReferenceFieldDataType); + + protected get canDelete(): boolean { + return !this.isDeleted && !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteReference); + } + + protected get canSave(): boolean { + return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditReference); + } + + protected get canFinalize(): boolean { + return !this.isDeleted && this.hasPermission(this.authService.permissionEnum.EditReference); + } + + + private hasPermission(permission: AppPermission): boolean { + return this.authService.hasPermission(permission) || this.editorModel?.permissions?.includes(permission); + } + + constructor( + // BaseFormEditor injected dependencies + protected dialog: MatDialog, + protected language: TranslateService, + protected formService: FormService, + protected router: Router, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected filterService: FilterService, + protected datePipe: DatePipe, + protected route: ActivatedRoute, + protected queryParamsService: QueryParamsService, + // Rest dependencies. Inject any other needed deps here: + public authService: AuthService, + public enumUtils: EnumUtils, + private referenceService: ReferenceService, + private logger: LoggingService, + private referenceEditorService: ReferenceEditorService, + private fileUtils: FileUtils, + private matomoService: MatomoService + ) { + super(dialog, language, formService, router, uiNotificationService, httpErrorHandlingService, filterService, datePipe, route, queryParamsService); + } + + ngOnInit(): void { + this.matomoService.trackPageView('Admin: References'); + super.ngOnInit(); + } + + getItem(itemId: Guid, successFunction: (item: Reference) => void) { + this.referenceService.getSingle(itemId, ReferenceEditorResolver.lookupFields()) + .pipe(map(data => data as Reference), takeUntil(this._destroyed)) + .subscribe( + data => successFunction(data), + error => this.onCallbackError(error) + ); + } + + prepareForm(data: Reference) { + try { + this.editorModel = data ? new ReferenceEditorModel().fromModel(data) : new ReferenceEditorModel(); + this.isDeleted = data ? data.isActive === IsActive.Inactive : false; + this.buildForm(); + } catch (error) { + this.logger.error('Could not parse Reference item: ' + data + error); + this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error); + } + } + + buildForm() { + this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditReference)); + this.referenceEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); + } + + refreshData(): void { + this.getItem(this.editorModel.id, (data: Reference) => this.prepareForm(data)); + } + + refreshOnNavigateToData(id?: Guid): void { + this.formGroup.markAsPristine(); + let route = []; + + if (id === null) { + route.push('../..'); + } else if (this.isNew) { + route.push('../' + id); + } else { + route.push('..'); + } + + this.router.navigate(route, { queryParams: { 'lookup': this.queryParamsService.serializeLookup(this.lookupParams), 'lv': ++this.lv }, replaceUrl: true, relativeTo: this.route }); + } + + persistEntity(onSuccess?: (response) => void): void { + const formData = this.formService.getValue(this.formGroup.value) as ReferencePersist; + + this.referenceService.persist(formData) + .pipe(takeUntil(this._destroyed)).subscribe( + complete => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete), + error => this.onCallbackError(error) + ); + } + + formSubmit(): void { + this.formService.touchAllFormFields(this.formGroup); + if (!this.isFormValid()) { + return; + } + + this.persistEntity(); + } + + public delete() { + const value = this.formGroup.value; + if (value.id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + data: { + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + 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.referenceService.delete(value.id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + clearErrorModel() { + this.editorModel.validationErrorModel.clear(); + this.formService.validateAllFormFields(this.formGroup); + } + + // + // fields + // + addField(): void { + const field: FieldEditorModel = new FieldEditorModel(); + (this.formGroup.get('definition').get('fields') as FormArray).push(field.buildForm()); + } + + removeField(fieldIndex: number): void { + (this.formGroup.get('definition').get('fields') as FormArray).removeAt(fieldIndex); + } + + +} diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.model.ts b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.model.ts new file mode 100644 index 000000000..215f3f824 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.model.ts @@ -0,0 +1,195 @@ +import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { ReferenceFieldDataType } from "@app/core/common/enum/reference-field-data-type"; +import { ReferenceSourceType } from "@app/core/common/enum/reference-source-type"; +import { ReferenceType } from "@app/core/common/enum/reference-type"; +import { Definition, DefinitionPersist, Field, FieldPersist, Reference, ReferencePersist } from "@app/core/model/reference/reference"; +import { BaseEditorModel } from "@common/base/base-form-editor-model"; +import { BackendErrorValidator } from "@common/forms/validation/custom-validator"; +import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model"; +import { Validation, ValidationContext } from "@common/forms/validation/validation-context"; + +export class ReferenceEditorModel extends BaseEditorModel implements ReferencePersist { + label: string; + type: ReferenceType; + description: string; + definition: DefinitionEditorModel = new DefinitionEditorModel(); + reference: string; + abbreviation: string; + source: string; + sourceType: ReferenceSourceType; + + permissions: string[]; + + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor() { super(); } + + public fromModel(item: Reference): ReferenceEditorModel { + if (item) { + super.fromModel(item); + this.label = item.label; + this.type = item.type; + this.description = item.description; + if (item.definition) this.definition = new DefinitionEditorModel().fromModel(item.definition); + this.reference = item.reference; + this.abbreviation = item.abbreviation; + this.source = item.source; + this.sourceType = item.sourceType; + } + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup { + if (context == null) { context = this.createValidationContext(); } + + return this.formBuilder.group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + type: [{ value: this.type, disabled: disabled }, context.getValidation('type').validators], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], + definition: this.definition.buildForm({ + rootPath: `definition.` + }), + reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], + abbreviation: [{ value: this.abbreviation, disabled: disabled }, context.getValidation('abbreviation').validators], + source: [{ value: this.source, disabled: disabled }, context.getValidation('source').validators], + sourceType: [{ value: this.sourceType, disabled: disabled }, context.getValidation('sourceType').validators], + + hash: [{ value: this.hash, disabled: disabled }, context.getValidation('hash').validators] + }); + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); + baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseValidationArray.push({ key: 'type', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'type')] }); + baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] }); + baseValidationArray.push({ key: 'reference', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'reference')] }); + baseValidationArray.push({ key: 'abbreviation', validators: [BackendErrorValidator(this.validationErrorModel, 'abbreviation')] }); + baseValidationArray.push({ key: 'source', validators: [BackendErrorValidator(this.validationErrorModel, 'source')] }); + baseValidationArray.push({ key: 'sourceType', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'sourceType')] }); + baseValidationArray.push({ key: 'hash', validators: [] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} + +export class DefinitionEditorModel implements DefinitionPersist { + fields: FieldEditorModel[]= []; + + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor( + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() + ) { } + + public fromModel(item: Definition): DefinitionEditorModel { + if (item) { + if (item.fields) { item.fields.map(x => this.fields.push(new FieldEditorModel().fromModel(x))); } + } + return this; + } + + buildForm(params?: { + context?: ValidationContext, + disabled?: boolean, + rootPath?: string + }): UntypedFormGroup { + let { context = null, disabled = false, rootPath } = params ?? {} + if (context == null) { + context = DefinitionEditorModel.createValidationContext({ + validationErrorModel: this.validationErrorModel, + rootPath + }); + } + + return this.formBuilder.group({ + fields: this.formBuilder.array( + (this.fields ?? []).map( + (item, index) => new FieldEditorModel( + this.validationErrorModel + ).fromModel(item).buildForm({ + rootPath: `fields[${index}].` + }), context.getValidation('fields') + ) + ), + }); + } + + static createValidationContext(params: { + rootPath?: string, + validationErrorModel: ValidationErrorModel + }): ValidationContext { + const { rootPath = '', validationErrorModel } = params; + + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + baseValidationArray.push({ key: 'fields', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}fields`)] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} + +export class FieldEditorModel implements FieldPersist { + code: string; + dataType: ReferenceFieldDataType; + value: string; + + protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + + constructor( + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() + ) { } + + public fromModel(item: Field): FieldEditorModel { + if (item) { + this.code = item.code; + this.dataType = item.dataType; + this.value = item.value; + } + return this; + } + + buildForm(params?: { + context?: ValidationContext, + disabled?: boolean, + rootPath?: string + }): UntypedFormGroup { + let { context = null, disabled = false, rootPath } = params ?? {} + if (context == null) { + context = FieldEditorModel.createValidationContext({ + validationErrorModel: this.validationErrorModel, + rootPath + }); + } + + return this.formBuilder.group({ + code: [{ value: this.code, disabled: disabled }, context.getValidation('code').validators], + dataType: [{ value: this.dataType, disabled: disabled }, context.getValidation('dataType').validators], + value: [{ value: this.value, disabled: disabled }, context.getValidation('value').validators], + }); + } + + static createValidationContext(params: { + rootPath?: string, + validationErrorModel: ValidationErrorModel + }): ValidationContext { + const { rootPath = '', validationErrorModel } = params; + + const baseContext: ValidationContext = new ValidationContext(); + const baseValidationArray: Validation[] = new Array(); + + baseValidationArray.push({ key: 'code', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}code`)] }); + baseValidationArray.push({ key: 'dataType', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}dataType`)] }); + baseValidationArray.push({ key: 'value', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}value`)] }); + + baseContext.validation = baseValidationArray; + return baseContext; + } +} + diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.resolver.ts b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.resolver.ts new file mode 100644 index 000000000..3a2465f6f --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.resolver.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Reference } from '@app/core/model/reference/reference'; +import { ReferenceService } from '@app/core/services/reference/reference.service'; +import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; +import { BaseEditorResolver } from '@common/base/base-editor.resolver'; +import { Guid } from '@common/types/guid'; +import { takeUntil, tap } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; + +@Injectable() +export class ReferenceEditorResolver extends BaseEditorResolver { + + constructor(private referenceService: ReferenceService, private breadcrumbService: BreadcrumbService) { + super(); + } + + public static lookupFields(): string[] { + return [ + ...BaseEditorResolver.lookupFields(), + nameof(x => x.id), + nameof(x => x.label), + nameof(x => x.type), + nameof(x => x.description), + nameof(x => x.reference), + nameof(x => x.abbreviation), + nameof(x => x.source), + nameof(x => x.sourceType), + nameof(x => x.createdAt), + nameof(x => x.updatedAt), + nameof(x => x.hash), + nameof(x => x.isActive) + ] + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + + const fields = [ + ...ReferenceEditorResolver.lookupFields() + ]; + const id = route.paramMap.get('id'); + + if (id != null) { + return this.referenceService.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.label)), takeUntil(this._destroyed)); + } + } +} diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.service.ts b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.service.ts new file mode 100644 index 000000000..0f94d946e --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from "@angular/core"; +import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model"; + +@Injectable() +export class ReferenceEditorService { + private validationErrorModel: ValidationErrorModel; + + public setValidationErrorModel(validationErrorModel: ValidationErrorModel): void { + this.validationErrorModel = validationErrorModel; + } + + public getValidationErrorModel(): ValidationErrorModel { + return this.validationErrorModel; + } +} diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html new file mode 100644 index 000000000..f129c7105 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html @@ -0,0 +1,36 @@ +
                  + + + + + +
                  +
                  +
                  +

                  {{'REFERENCE-LISTING.FILTER.TITLE' | translate}}

                  + +
                  + + + {{'REFERENCE-LISTING.FILTER.IS-ACTIVE' | translate}} + + +
                  + + +
                  +
                  +
                  +
                  + + +
                  diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss new file mode 100644 index 000000000..ea00a215c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss @@ -0,0 +1,21 @@ +::ng-deep.mat-mdc-menu-panel { + max-width: 100% !important; + height: 100% !important; +} + +:host::ng-deep.mat-mdc-menu-content:not(:empty) { + padding-top: 0 !important; +} + + +.filter-button{ + padding-top: .6rem; + padding-bottom: .6rem; + // .mat-icon{ + // font-size: 1.5em; + // width: 1.2em; + // height: 1.2em; + // } +} + + diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.ts b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.ts new file mode 100644 index 000000000..609bc8186 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.ts @@ -0,0 +1,94 @@ +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { TenantFilter } from '@app/core/query/tenant.lookup'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { BaseComponent } from '@common/base/base.component'; +import { nameof } from 'ts-simple-nameof'; + +@Component({ + selector: 'app-reference-listing-filters', + templateUrl: './reference-listing-filters.component.html', + styleUrls: ['./reference-listing-filters.component.scss'] +}) +export class ReferenceListingFiltersComponent extends BaseComponent implements OnInit, OnChanges { + + @Input() readonly filter: TenantFilter; + @Output() filterChange = new EventEmitter(); + + // * State + internalFilters: ReferenceListingFilters = this._getEmptyFilters(); + + protected appliedFilterCount: number = 0; + constructor( + public enumUtils: EnumUtils, + ) { super(); } + + ngOnInit() { + } + + ngOnChanges(changes: SimpleChanges): void { + const filterChange = changes[nameof(x => x.filter)]?.currentValue as TenantFilter; + if (filterChange) { + this.updateFilters() + } + } + + + onSearchTermChange(searchTerm: string): void { + this.applyFilters() + } + + + protected updateFilters(): void { + this.internalFilters = this._parseToInternalFilters(this.filter); + this.appliedFilterCount = this._computeAppliedFilters(this.internalFilters); + } + + protected applyFilters(): void { + const { isActive, like } = this.internalFilters ?? {} + this.filterChange.emit({ + ...this.filter, + like, + isActive: isActive ? [IsActive.Active] : [IsActive.Inactive] + }) + } + + + private _parseToInternalFilters(inputFilter: TenantFilter): ReferenceListingFilters { + if (!inputFilter) { + return this._getEmptyFilters(); + } + + let { excludedIds, ids, isActive, like } = inputFilter; + + return { + isActive: (isActive ?? [])?.includes(IsActive.Active) || !isActive?.length, + like: like + } + + } + + private _getEmptyFilters(): ReferenceListingFilters { + return { + isActive: true, + like: null, + } + } + + private _computeAppliedFilters(filters: ReferenceListingFilters): number { + let count = 0; + if (filters?.isActive) { + count++ + } + return count; + } + + clearFilters() { + this.internalFilters = this._getEmptyFilters(); + } +} + +interface ReferenceListingFilters { + isActive: boolean; + like: string; +} diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html new file mode 100644 index 000000000..c1a42cc4b --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.html @@ -0,0 +1,86 @@ +
                  +
                  + +
                  +
                  +

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

                  + + +
                  +
                  + +
                  +
                  + + + + + + + + +
                  +
                  + + + + +
                  +
                  + + {{item?.name | nullifyValue}} +
                  +
                  + + + + {{'REFERENCE-LISTING.FIELDS.CREATED-AT' | translate}}: + + {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + + +
                  +
                  + + + {{'REFERENCE-LISTING.FIELDS.UPDATED-AT' | translate}}: + + {{item?.updatedAt | dateTimeFormatter : 'short' | nullifyValue}} + + + +
                  +
                  +
                  + + +
                  +
                  + + + + + +
                  +
                  +
                  \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.scss b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.scss new file mode 100644 index 000000000..6e1b48814 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.scss @@ -0,0 +1,60 @@ +.description-template-type-listing { + margin-top: 1.3rem; + margin-left: 1rem; + margin-right: 2rem; + + .mat-header-row{ + background: #f3f5f8; + } + .mat-card { + margin: 16px 0; + padding: 0px; + } + + .mat-row { + cursor: pointer; + min-height: 4.5em; + } + + mat-row:hover { + background-color: #eef5f6; + } + .mat-fab-bottom-right { + float: right; + z-index: 5; + } +} +.create-btn { + border-radius: 30px; + background-color: var(--secondary-color); + padding-left: 2em; + padding-right: 2em; + // color: #000; + + .button-text{ + display: inline-block; + } +} + +.dlt-btn { + color: rgba(0, 0, 0, 0.54); +} + +.status-chip{ + + border-radius: 20px; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.2em; + font-size: .8em; +} + +.status-chip-finalized{ + color: #568b5a; + background: #9dd1a1 0% 0% no-repeat padding-box; +} + +.status-chip-draft{ + color: #00c4ff; + background: #d3f5ff 0% 0% no-repeat padding-box; +} diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.ts b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.ts new file mode 100644 index 000000000..f1250d2c5 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/listing/reference-listing.component.ts @@ -0,0 +1,175 @@ +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { IsActive } from '@app/core/common/enum/is-active.enum'; +import { Reference } from '@app/core/model/reference/reference'; +import { ReferenceLookup } from '@app/core/query/reference.lookup'; +import { AuthService } from '@app/core/services/auth/auth.service'; +import { ReferenceService } from '@app/core/services/reference/reference.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; +import { BaseListingComponent } from '@common/base/base-listing-component'; +import { PipeService } from '@common/formatting/pipe.service'; +import { DataTableDateTimeFormatPipe } from '@common/formatting/pipes/date-time-format.pipe'; +import { QueryResult } from '@common/model/query-result'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { ColumnDefinition, ColumnsChangedEvent, HybridListingComponent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { nameof } from 'ts-simple-nameof'; + +@Component({ + templateUrl: './REFERENCE-LISTING.component.html', + styleUrls: ['./REFERENCE-LISTING.component.scss'] +}) +export class ReferenceListingComponent extends BaseListingComponent implements OnInit { + publish = false; + userSettingsKey = { key: 'ReferenceListingUserSettings' }; + propertiesAvailableForOrder: ColumnDefinition[]; + + @ViewChild('actions', { static: true }) actions?: TemplateRef; + @ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent; + + private readonly lookupFields: string[] = [ + nameof(x => x.id), + nameof(x => x.label), + nameof(x => x.source), + nameof(x => x.type), + nameof(x => x.updatedAt), + nameof(x => x.createdAt), + nameof(x => x.hash), + nameof(x => x.isActive) + ]; + + rowIdentity = x => x.id; + + constructor( + protected router: Router, + protected route: ActivatedRoute, + protected uiNotificationService: UiNotificationService, + protected httpErrorHandlingService: HttpErrorHandlingService, + protected queryParamsService: QueryParamsService, + private ReferenceService: ReferenceService, + public authService: AuthService, + private pipeService: PipeService, + public enumUtils: EnumUtils, + private language: TranslateService, + private dialog: MatDialog + ) { + super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService); + // Lookup setup + // Default lookup values are defined in the user settings class. + this.lookup = this.initializeLookup(); + } + + ngOnInit() { + super.ngOnInit(); + } + + protected initializeLookup(): ReferenceLookup { + const lookup = new ReferenceLookup(); + lookup.metadata = { countAll: true }; + lookup.page = { offset: 0, size: this.ITEMS_PER_PAGE }; + lookup.isActive = [IsActive.Active]; + lookup.order = { items: [this.toDescSortField(nameof(x => x.createdAt))] }; + this.updateOrderUiFields(lookup.order); + + lookup.project = { + fields: this.lookupFields + }; + + return lookup; + } + + protected setupColumns() { + this.gridColumns.push(...[{ + prop: nameof(x => x.label), + sortable: true, + languageName: 'REFERENCE-LISTING.FIELDS.LABEL' + }, + { + prop: nameof(x => x.source), + sortable: true, + languageName: 'REFERENCE-LISTING.FIELDS.SOURCE', + }, + { + prop: nameof(x => x.type), + sortable: true, + languageName: 'REFERENCE-LISTING.FIELDS.TYPE', + }, + { + prop: nameof(x => x.createdAt), + sortable: true, + languageName: 'REFERENCE-LISTING.FIELDS.CREATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + prop: nameof(x => x.updatedAt), + sortable: true, + languageName: 'REFERENCE-LISTING.FIELDS.UPDATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + alwaysShown: true, + cellTemplate: this.actions, + maxWidth: 120 + } + ]); + this.propertiesAvailableForOrder = this.gridColumns.filter(x => x.sortable); + } + + // + // Listing Component functions + // + onColumnsChanged(event: ColumnsChangedEvent) { + super.onColumnsChanged(event); + this.onColumnsChangedInternal(event.properties.map(x => x.toString())); + } + + private onColumnsChangedInternal(columns: string[]) { + // Here are defined the projection fields that always requested from the api. + const fields = new Set(this.lookupFields); + this.gridColumns.map(x => x.prop) + .filter(x => !columns?.includes(x as string)) + .forEach(item => { + fields.delete(item as string) + }); + this.lookup.project = { fields: [...fields] }; + this.onPageLoad({ offset: 0 } as PageLoadEvent); + } + + protected loadListing(): Observable> { + return this.ReferenceService.query(this.lookup); + } + + public deleteType(id: Guid) { + if (id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { + isDeleteConfirmation: true, + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + 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.ReferenceService.delete(id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success); + this.ngOnInit(); + } +} diff --git a/dmp-frontend/src/app/ui/admin/reference/reference.module.ts b/dmp-frontend/src/app/ui/admin/reference/reference.module.ts new file mode 100644 index 000000000..8bcc715e9 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/reference.module.ts @@ -0,0 +1,41 @@ +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { NgModule } from "@angular/core"; +import { AutoCompleteModule } from "@app/library/auto-complete/auto-complete.module"; +import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; +import { CommonFormattingModule } from '@common/formatting/common-formatting.module'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; +import { HybridListingModule } from "@common/modules/hybrid-listing/hybrid-listing.module"; +import { TextFilterModule } from "@common/modules/text-filter/text-filter.module"; +import { UserSettingsModule } from "@common/modules/user-settings/user-settings.module"; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { NgxDropzoneModule } from "ngx-dropzone"; +import { ReferenceRoutingModule } from './reference.routing'; +import { ReferenceEditorComponent } from './editor/reference-editor.component'; +import { ReferenceListingComponent } from './listing/reference-listing.component'; +import { ReferenceListingFiltersComponent } from './listing/filters/reference-listing-filters.component'; +import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-editor.module'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule, + UrlListingModule, + ConfirmationDialogModule, + ReferenceRoutingModule, + NgxDropzoneModule, + DragDropModule, + AutoCompleteModule, + HybridListingModule, + TextFilterModule, + UserSettingsModule, + CommonFormattingModule, + RichTextEditorModule + ], + declarations: [ + ReferenceEditorComponent, + ReferenceListingComponent, + ReferenceListingFiltersComponent + ] +}) +export class ReferenceModule { } diff --git a/dmp-frontend/src/app/ui/admin/reference/reference.routing.ts b/dmp-frontend/src/app/ui/admin/reference/reference.routing.ts new file mode 100644 index 000000000..32fef48fe --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/reference/reference.routing.ts @@ -0,0 +1,58 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AdminAuthGuard } from '@app/core/admin-auth-guard.service'; +import { ReferenceEditorComponent } from './editor/reference-editor.component'; +import { ReferenceListingComponent } from './listing/reference-listing.component'; +import { AppPermission } from '@app/core/common/enum/permission.enum'; +import { AuthGuard } from '@app/core/auth-guard.service'; +import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; +import { PendingChangesGuard } from '@common/forms/pending-form-changes/pending-form-changes-guard.service'; +import { ReferenceEditorResolver } from './editor/reference-editor.resolver'; + +const routes: Routes = [ + { + path: '', + component: ReferenceListingComponent, + canActivate: [AuthGuard] + }, + { + path: 'new', + canActivate: [AuthGuard], + component: ReferenceEditorComponent, + canDeactivate: [PendingChangesGuard], + data: { + authContext: { + permissions: [AppPermission.EditReference] + }, + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.NEW-REFERENCE' + }) + } + }, + { + path: ':id', + canActivate: [AuthGuard], + component: ReferenceEditorComponent, + canDeactivate: [PendingChangesGuard], + resolve: { + 'entity': ReferenceEditorResolver + }, + data: { + ...BreadcrumbService.generateRouteDataConfiguration({ + title: 'BREADCRUMBS.EDIT-REFERENCE' + }), + authContext: { + permissions: [AppPermission.EditReference] + } + } + + }, + { path: '**', loadChildren: () => import('@common/modules/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule) }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [ReferenceEditorResolver] +}) +export class ReferenceRoutingModule { } diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.resolver.ts b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.resolver.ts index f6d083a27..b2fff3ecc 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.resolver.ts @@ -11,7 +11,7 @@ import { nameof } from 'ts-simple-nameof'; @Injectable() export class TenantEditorResolver extends BaseEditorResolver { - constructor(private TenantService: TenantService, private breadcrumbService: BreadcrumbService) { + constructor(private tenantService: TenantService, private breadcrumbService: BreadcrumbService) { super(); } @@ -53,7 +53,7 @@ export class TenantEditorResolver extends BaseEditorResolver { const id = route.paramMap.get('id'); if (id != null) { - return this.TenantService.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.code)), takeUntil(this._destroyed)); + return this.tenantService.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.code)), takeUntil(this._destroyed)); } } } diff --git a/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html b/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html index 827f5421f..93669a2f5 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/tenant/listing/tenant-listing.component.html @@ -9,7 +9,7 @@
                  @@ -78,15 +75,6 @@ - -
                  @@ -101,7 +89,6 @@ delete {{'TENANT-LISTING.ACTIONS.DELETE' | translate}} -
                  diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts index 3de6e9d34..164399f41 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.component.ts @@ -53,10 +53,11 @@ export const ADMIN_ROUTES: RouteInfo[] = [ { path: '/dmp-blueprints', title: 'SIDE-BAR.DMP-BLUEPRINTS', icon: 'library_books' }, { path: '/description-templates', title: 'SIDE-BAR.DESCRIPTION-TEMPLATES', icon: 'library_books' }, { path: '/description-template-type', title: 'SIDE-BAR.DESCRIPTION-TEMPLATE-TYPES', icon: 'library_books' }, + { path: '/references', title: 'SIDE-BAR.REFERENCES', icon: 'library_books' }, { path: '/reference-type', title: 'SIDE-BAR.REFERENCE-TYPES', icon: 'library_books' }, { path: '/tenants', title: 'SIDE-BAR.TENANTS', icon: 'library_books' }, { path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' }, - { path: '/language-editor', title: 'SIDE-BAR.LANGUAGE-EDITOR', icon: 'language' }, + { path: '/languages', title: 'SIDE-BAR.LANGUAGES', icon: 'language' }, { path: '/supportive-material', title: 'SIDE-BAR.SUPPORTIVE-MATERIAL', icon: 'import_contacts' } ]; diff --git a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html index 9f0804829..93495ca9e 100644 --- a/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html +++ b/dmp-frontend/src/app/ui/supportive-material-editor/supportive-material-editor.component.html @@ -5,7 +5,7 @@
                  - Material type + {{'SUPPORTIVE-MATERIAL-EDITOR.FIELDS.MATERIAL-TYPE' | translate}} {{vis.name | translate}} @@ -15,7 +15,7 @@
                  - Language + {{'SUPPORTIVE-MATERIAL-EDITOR.FIELDS.LANGUAGE' | translate}} {{vis.name | translate}} @@ -48,7 +48,7 @@ }" formControlName="html"> -
                  diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 2cd2e7bfb..f9fc44bb3 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -173,7 +173,8 @@ "LANGUAGE": "Language", "SIGN-IN": "Sign in to account", "REFERENCE-TYPES": "Reference Types", - "TENANTS": "Tenants" + "TENANTS": "Tenants", + "REFERENCES": "References" }, "FILE-TYPES": { "PDF": "PDF", @@ -241,10 +242,18 @@ "EDIT-DMP-BLUEPRINT": "Edit", "NEW-DESCRIPTION-TEMPLATES": "New", "EDIT-DESCRIPTION-TEMPLATES": "Edit", + "REFERENCE-TYPES":"Reference Types", "NEW-REFERENCE-TYPE": "New", "EDIT-REFERENCE-TYPE": "Edit", + "TENANTS":"Tenants", "NEW-TENANT": "New", - "EDIT-TENANT": "Edit" + "EDIT-TENANT": "Edit", + "REFERENCES":"References", + "NEW-REFERENCE": "New", + "EDIT-REFERENCE": "Edit", + "LANGUAGES": "Languages", + "NEW-LANGUAGE": "New", + "EDIT-LANGUAGE": "Edit" }, "COOKIE": { "MESSAGE": "This website uses cookies to enhance the user experience.", @@ -340,7 +349,9 @@ "FEEDBACK": "Send feedback", "SUPPORTIVE-MATERIAL": "Supportive Material", "REFERENCE-TYPES":"Reference Types", - "TENANTS": "Tenants" + "TENANTS": "Tenants", + "REFERENCES": "References", + "LANGUAGES": "Languages" }, "DESCRIPTION-TEMPLATE-EDITOR": { "TITLE": { @@ -1109,6 +1120,88 @@ "SUCCESSFUL-DELETE": "Successful Delete", "UNSUCCESSFUL-DELETE": "This item could not be deleted." }, + "REFERENCE-LISTING": { + "TITLE": "References", + "CREATE": "Create Reference", + "FIELDS": { + "LABEL": "Label", + "SOURCE": "Source", + "TYPE": "Type", + "UPDATED-AT": "Updated", + "CREATED-AT": "Created" + }, + "FILTER": { + "TITLE": "Filters", + "IS-ACTIVE": "Is Active", + "CANCEL": "Cancel", + "APPLY-FILTERS": "Apply filters" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Reference?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + }, + "ACTIONS": { + "DELETE": "Delete", + "EDIT": "Edit" + }, + "SUCCESSFUL-DELETE": "Successful Delete", + "UNSUCCESSFUL-DELETE": "This item could not be deleted." + }, + "LANGUAGE-LISTING": { + "TITLE": "Languages", + "CREATE": "Create Language", + "FIELDS": { + "CODE": "Code", + "UPDATED-AT": "Updated", + "CREATED-AT": "Created" + }, + "FILTER": { + "TITLE": "Filters", + "IS-ACTIVE": "Is Active", + "CANCEL": "Cancel", + "APPLY-FILTERS": "Apply filters" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Language?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + }, + "ACTIONS": { + "DELETE": "Delete", + "EDIT": "Edit" + }, + "SUCCESSFUL-DELETE": "Successful Delete", + "UNSUCCESSFUL-DELETE": "This item could not be deleted." + }, + "SUPPORTIVE-MATERIAL-EDITOR": { + "FIELDS": { + "MATERIAL-TYPE": "Material Type", + "LANGUAGE": "Language" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete" + } + }, + "LANGUAGE-EDITOR": { + "NEW": "New Language", + "FIELDS": { + "CODE": "Code", + "PAYLOAD": "Payload" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Language?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + } + }, "DATASET-UPLOAD": { "TITLE": "Import Dataset", "UPLOAD-BUTTON": "Upload", @@ -1233,6 +1326,36 @@ "CANCEL-BUTTON": "No" } }, + "REFERENCE-EDITOR": { + "NEW": "New Reference", + "FIELDS": { + "LABEL": "Label", + "TYPE": "Type", + "DESCRIPTION": "Description", + "DESCRIPTION-PLACEHOLDER": "Reference description", + "REFERENCE":"reference", + "ABBREVIATION": "abbreviation", + "SOURCE": "source", + "SOURCE-TYPE":"Source Type", + "FIELDS":"Fields", + "FIELD":"Field", + "CODE":"Code", + "DATA-TYPE":"Data Type", + "VALUE":"Value" + }, + "ACTIONS": { + "SAVE": "Save", + "CANCEL": "Cancel", + "DELETE": "Delete", + "ADD-FIELD": "Add Field", + "REMOVE-FIELD": "Remove Field" + }, + "CONFIRM-DELETE-DIALOG": { + "MESSAGE": "Would you like to delete this Rederence?", + "CONFIRM-BUTTON": "Yes, delete", + "CANCEL-BUTTON": "No" + } + }, "DMP-BLUEPRINT-EDITOR": { "TITLE": { "NEW": "New DMP Blueprint", @@ -1874,6 +1997,26 @@ "REFERENCE-TYPE-EXTERNAL-API-HTTP-METHOD-TYPE":{ "GET": "GET", "POST": "POST" + }, + "REFERENCE-TYPE":{ + "TAXONOMY": "Taxonomy", + "LICENCE": "License", + "PUBLICATION": "Publication", + "JOURNAL": "Journal", + "PUB-REPOSITORY": "Publication Repository", + "DATA-REPOSITORY": "Data Repository", + "REGISTRY": "Registry", + "SERVICE": "Service", + "PROJECT": "Project", + "FUNDER": "Funder", + "DATASET": "Dataset", + "ORGANISATION": "Organization", + "GRANT": "Grant", + "RESEARCHER": "Researcher" + }, + "REFERENCE-SOURCE-TYPE":{ + "INTERNAL": "Internal", + "EXTERNAL": "External" } }, "ADDRESEARCHERS-EDITOR": { diff --git a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java index daf7cd69e..9b187527d 100644 --- a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java +++ b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java @@ -106,10 +106,21 @@ public class DatasetMigrationService { List itemDescriptionTemplates = descriptionTemplates.stream().filter(x-> x.getDescriptionTemplateGroupId().equals(item.getProfile().getGroupId()) && x.getDmpId().equals(item.getDmp().getId()) && x.getSectionId().equals(sectionId)).toList(); if (itemDescriptionTemplates.isEmpty()) { - logger.error("Migrate Dataset " + item.getId() + " cannot found DmpDescriptionTemplateEntity for section " + item.getDmpSectionIndex()); - if (descriptionTemplates.stream().filter(x-> x.getDmpId().equals(item.getDmp().getId()) && x.getSectionId().equals(sectionId)).count() > 0) continue; - throw new MyApplicationException("Migrate Dataset " + item.getId() + " cannot found DmpDescriptionTemplateEntity for section " + item.getDmpSectionIndex()); + if (descriptionTemplates.stream().filter(x-> x.getDmpId().equals(item.getDmp().getId()) && x.getSectionId().equals(sectionId)).count() > 0) { + DmpDescriptionTemplateEntity dmpDescriptionTemplateEntity = new DmpDescriptionTemplateEntity(); + dmpDescriptionTemplateEntity.setId(UUID.randomUUID()); + dmpDescriptionTemplateEntity.setDescriptionTemplateGroupId(item.getProfile().getGroupId()); + dmpDescriptionTemplateEntity.setDmpId(item.getDmp().getId()); + dmpDescriptionTemplateEntity.setCreatedAt(item.getCreated() != null ? item.getCreated().toInstant() : Instant.now()); + dmpDescriptionTemplateEntity.setUpdatedAt(item.getModified() != null ? item.getModified().toInstant() : Instant.now()); + dmpDescriptionTemplateEntity.setSectionId(sectionId); + dmpDescriptionTemplateEntity.setIsActive(IsActive.Active); + this.entityManager.persist(dmpDescriptionTemplateEntity); + itemDescriptionTemplates = List.of(dmpDescriptionTemplateEntity); + } else { + throw new MyApplicationException("Migrate Dataset " + item.getId() + " cannot found DmpDescriptionTemplateEntity for section " + item.getDmpSectionIndex()); + } } if (itemDescriptionTemplates.size() > 1) {