Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
928babb9d5
|
@ -114,6 +114,7 @@ public class AuditableAction {
|
|||
|
||||
public static final EventId StorageFile_Download = new EventId(14000, "StorageFile_Download");
|
||||
public static final EventId StorageFile_Upload = new EventId(14001, "StorageFile_Upload");
|
||||
public static final EventId StorageFile_Query = new EventId(14002, "StorageFile_Query");
|
||||
|
||||
public static final EventId Dashboard_MyRecentActivityItems = new EventId(15000, "Dashboard_MyRecentActivityItems");
|
||||
public static final EventId Dashboard_MyDashboardStatistics = new EventId(15001, "Dashboard_MyDashboardStatistics");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package eu.eudat.types;
|
||||
package eu.eudat.commons.metrics;
|
||||
|
||||
public class MetricNames {
|
||||
public static final String DATASET_TEMPLATE = "argos_dmp_templates";
|
|
@ -3,6 +3,7 @@ package eu.eudat.model.builder.descriptionpropertiesdefinition;
|
|||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.commons.enums.FieldType;
|
||||
import eu.eudat.commons.types.description.FieldEntity;
|
||||
import eu.eudat.commons.types.descriptiontemplate.fielddata.LabelAndMultiplicityDataEntity;
|
||||
import eu.eudat.commons.types.descriptiontemplate.fielddata.SelectDataEntity;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.model.Reference;
|
||||
|
@ -72,12 +73,16 @@ public class FieldBuilder extends BaseBuilder<Field, FieldEntity> {
|
|||
if (fields.hasField(this.asIndexer(Field._dateValue)) && FieldType.isDateType(fieldType)) m.setDateValue(d.getDateValue());
|
||||
if (fields.hasField(this.asIndexer(Field._textValue)) && FieldType.isTextType(fieldType)) m.setTextValue(d.getTextValue());
|
||||
if (fields.hasField(this.asIndexer(Field._textListValue)) && FieldType.isTextListType(fieldType)) {
|
||||
boolean isSelectMultiSelect = true;
|
||||
if(this.fieldEntity != null && this.fieldEntity.getData() != null && this.fieldEntity.getData().getFieldType().equals(FieldType.SELECT) && this.fieldEntity.getData() instanceof SelectDataEntity){
|
||||
isSelectMultiSelect = ((SelectDataEntity) this.fieldEntity.getData()).getMultipleSelect();
|
||||
}
|
||||
if (fieldType.equals(FieldType.SELECT) && !isSelectMultiSelect && !this.conventionService.isListNullOrEmpty(d.getTextListValue())){
|
||||
m.setTextValue(d.getTextListValue().stream().findFirst().orElse(null));
|
||||
boolean isMultiSelect = true;
|
||||
if(this.fieldEntity != null && this.fieldEntity.getData() != null && (this.fieldEntity.getData().getFieldType().equals(FieldType.SELECT) || this.fieldEntity.getData().getFieldType().equals(FieldType.INTERNAL_ENTRIES_DMPS) || this.fieldEntity.getData().getFieldType().equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS))){
|
||||
if (this.fieldEntity.getData() instanceof SelectDataEntity) isMultiSelect = ((SelectDataEntity) this.fieldEntity.getData()).getMultipleSelect();
|
||||
else if (this.fieldEntity.getData() instanceof LabelAndMultiplicityDataEntity) isMultiSelect = ((LabelAndMultiplicityDataEntity) this.fieldEntity.getData()).getMultipleSelect();
|
||||
|
||||
if (!isMultiSelect && !this.conventionService.isListNullOrEmpty(d.getTextListValue())){
|
||||
m.setTextValue(d.getTextListValue().stream().findFirst().orElse(null));
|
||||
}else{
|
||||
m.setTextListValue(d.getTextListValue());
|
||||
}
|
||||
} else{
|
||||
m.setTextListValue(d.getTextListValue());
|
||||
}
|
||||
|
|
|
@ -516,22 +516,38 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
}
|
||||
}
|
||||
else if (FieldType.isTextListType(fieldType)) {
|
||||
if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType) && !this.conventionService.isListNullOrEmpty(persist.getTextListValue())){
|
||||
List<UUID> ids = persist.getTextListValue().stream().map(UUID::fromString).toList();
|
||||
Set<UUID> existingIds = this.queryFactory.query(DmpQuery.class).ids(ids).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(Dmp._id)).stream().map(DmpEntity::getId).collect(Collectors.toSet());
|
||||
for (UUID id : ids){
|
||||
if (!existingIds.contains(id)) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
List<UUID> ids = new ArrayList<>();
|
||||
if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType)) {
|
||||
if (!this.conventionService.isListNullOrEmpty(persist.getTextListValue())) persist.getTextListValue().stream().map(UUID::fromString).toList();
|
||||
else if (!this.conventionService.isNullOrEmpty(persist.getTextValue())) ids.add(UUID.fromString(persist.getTextValue()));
|
||||
|
||||
if (ids.size() > 0){
|
||||
Set<UUID> existingIds = this.queryFactory.query(DmpQuery.class).ids(ids).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(Dmp._id)).stream().map(DmpEntity::getId).collect(Collectors.toSet());
|
||||
for (UUID id : ids){
|
||||
if (!existingIds.contains(id)) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
}
|
||||
}
|
||||
} if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType) && !this.conventionService.isListNullOrEmpty(persist.getTextListValue())){
|
||||
List<UUID> ids = persist.getTextListValue().stream().map(UUID::fromString).toList();
|
||||
Set<UUID> existingIds = this.queryFactory.query(DescriptionQuery.class).ids(ids).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(Description._id)).stream().map(DescriptionEntity::getId).collect(Collectors.toSet());
|
||||
for (UUID id : ids){
|
||||
if (!existingIds.contains(id)) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
} if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType)){
|
||||
if ( !this.conventionService.isListNullOrEmpty(persist.getTextListValue())) ids = persist.getTextListValue().stream().map(UUID::fromString).toList();
|
||||
else if (!this.conventionService.isNullOrEmpty(persist.getTextValue())) ids.add(UUID.fromString(persist.getTextValue()));
|
||||
|
||||
if (ids.size() > 0) {
|
||||
Set<UUID> existingIds = this.queryFactory.query(DescriptionQuery.class).ids(ids).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(Description._id)).stream().map(DescriptionEntity::getId).collect(Collectors.toSet());
|
||||
for (UUID id : ids){
|
||||
if (!existingIds.contains(id)) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ids.isEmpty()){
|
||||
if (ids.size() > 1) data.setTextListValue(persist.getTextListValue());
|
||||
else data.setTextListValue(List.of(persist.getTextValue()));
|
||||
}else{
|
||||
data.setTextListValue(persist.getTextListValue());
|
||||
}
|
||||
if (fieldType.equals(FieldType.SELECT) && this.conventionService.isListNullOrEmpty(persist.getTextListValue()) && !this.conventionService.isNullOrEmpty(persist.getTextValue())){
|
||||
data.setTextListValue(List.of(persist.getTextValue()));
|
||||
} else{
|
||||
} else if (fieldType.equals(FieldType.SELECT) || fieldType.equals(FieldType.TAGS)){
|
||||
data.setTextListValue(persist.getTextListValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package eu.eudat.service.metrics;
|
||||
|
||||
import io.prometheus.client.Gauge;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.util.Map;
|
||||
|
||||
public interface MetricsService {
|
||||
void calculate(Map<String, Gauge> gauges) throws InvalidApplicationException;
|
||||
Map<String, Gauge> gaugesBuild();
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package eu.eudat.service.metrics;
|
||||
|
||||
import eu.eudat.commons.enums.DmpStatus;
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.metrics.MetricNames;
|
||||
import eu.eudat.data.TenantEntityManager;
|
||||
import eu.eudat.query.DmpQuery;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
import io.prometheus.client.Gauge;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Service
|
||||
public class MetricsServiceImpl implements MetricsService {
|
||||
private final PrometheusMeterRegistry registry;
|
||||
private final QueryFactory queryFactory;
|
||||
private final TenantEntityManager entityManager;
|
||||
|
||||
public MetricsServiceImpl(PrometheusMeterRegistry registry, QueryFactory queryFactory, TenantEntityManager entityManager) {
|
||||
this.registry = registry;
|
||||
this.queryFactory = queryFactory;
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculate(Map<String, Gauge> gauges) throws InvalidApplicationException {
|
||||
try {
|
||||
this.entityManager.disableTenantFilters();
|
||||
|
||||
this.setGauseValue(gauges, MetricNames.DMP, calculateFinalizedDmps(), MetricNames.FINALIZED);
|
||||
}finally {
|
||||
this.entityManager.enableTenantFilters();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Gauge> gaugesBuild() {
|
||||
registry.clear();
|
||||
|
||||
return Stream.of( new Object[][]{
|
||||
{MetricNames.DMP, Gauge.build().name(MetricNames.DMP).help("Number of managed DMPs").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.DMP, Gauge.build().name(MetricNames.NEXUS + MetricNames.DMP).help("Number of managed DMPs during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.FUNDERS, Gauge.build().name(MetricNames.FUNDERS).help("Number of registered Funders").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.GRANTS, Gauge.build().name(MetricNames.GRANTS).help("Number of registered Grants").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.PROJECT, Gauge.build().name(MetricNames.PROJECT).help("Number of registered Projects").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.RESEARCHER, Gauge.build().name(MetricNames.RESEARCHER).help("Number of Colaborators/Researchers").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.FUNDERS, Gauge.build().name(MetricNames.NEXUS + MetricNames.FUNDERS).help("Number of registered Funders during Nexus").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.GRANTS, Gauge.build().name(MetricNames.NEXUS + MetricNames.GRANTS).help("Number of registered Grants during Nexus").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.PROJECT, Gauge.build().name(MetricNames.NEXUS + MetricNames.PROJECT).help("Number of registered Projects during Nexus").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.RESEARCHER, Gauge.build().name(MetricNames.NEXUS + MetricNames.RESEARCHER).help("Number of Colaborators/Researchers during Nexus").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.DATASET, Gauge.build().name(MetricNames.DATASET).help("Number of managed Dataset Descriptions").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.DATASET, Gauge.build().name(MetricNames.NEXUS + MetricNames.DATASET).help("Number of managed Dataset Descriptions during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.NEXUS + MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.USERS, Gauge.build().name(MetricNames.USERS).help("Number of users").labelNames("type").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.LANGUAGES, Gauge.build().name(MetricNames.LANGUAGES).help("Number of Languages").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.DMP_WITH_GRANT, Gauge.build().name(MetricNames.DMP_WITH_GRANT).help("Number of Grants based on the status of the DMP that is using them").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.DMP_WITH_GRANT, Gauge.build().name(MetricNames.NEXUS + MetricNames.DMP_WITH_GRANT).help("Number of Grants based on the status of the DMP that is using them during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.INSTALLATIONS, Gauge.build().name(MetricNames.INSTALLATIONS).help("Number of Installations").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.INSTALLATIONS, Gauge.build().name(MetricNames.NEXUS + MetricNames.INSTALLATIONS).help("Number of Installations").register(registry.getPrometheusRegistry())},
|
||||
|
||||
}).collect(Collectors.toMap(data -> (String)data[0], data -> (Gauge) data[1]));
|
||||
}
|
||||
|
||||
private double calculateFinalizedDmps(){
|
||||
return this.queryFactory.query(DmpQuery.class).statuses(DmpStatus.Finalized).isActive(IsActive.Active).count();
|
||||
}
|
||||
|
||||
private void setGauseValue(Map<String, Gauge> gauges, String name, Double amount, String label) {
|
||||
if(label != null) {
|
||||
gauges.get(name).labels(label).set(amount);
|
||||
} else {
|
||||
gauges.get(name).set(amount);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package eu.eudat.service.metrics;
|
||||
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.fake.FakeRequestScope;
|
||||
import eu.eudat.commons.metrics.MetricNames;
|
||||
import eu.eudat.commons.scope.tenant.TenantScope;
|
||||
import eu.eudat.data.QueueInboxEntity;
|
||||
import eu.eudat.data.StorageFileEntity;
|
||||
import eu.eudat.data.TenantEntity;
|
||||
import eu.eudat.data.TenantEntityManager;
|
||||
import eu.eudat.integrationevent.inbox.EventProcessingStatus;
|
||||
import eu.eudat.model.StorageFile;
|
||||
import eu.eudat.model.Tenant;
|
||||
import eu.eudat.query.QueueInboxQuery;
|
||||
import eu.eudat.query.StorageFileQuery;
|
||||
import eu.eudat.query.TenantQuery;
|
||||
import eu.eudat.service.storage.StorageFileService;
|
||||
import gr.cite.queueinbox.entity.QueueInboxStatus;
|
||||
import gr.cite.queueinbox.repository.CandidateInfo;
|
||||
import gr.cite.tools.data.query.Ordering;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
import io.prometheus.client.Gauge;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.EntityTransaction;
|
||||
import jakarta.persistence.OptimisticLockException;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Service
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public class UpdateMetricsTask implements Closeable, ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UpdateMetricsTask.class));
|
||||
private final UpdateMetricsTaskProperties _config;
|
||||
private final ApplicationContext applicationContext;
|
||||
private ScheduledExecutorService scheduler;
|
||||
private Map<String, Gauge> gauges;
|
||||
|
||||
public UpdateMetricsTask(
|
||||
UpdateMetricsTaskProperties config,
|
||||
ApplicationContext applicationContext) {
|
||||
this._config = config;
|
||||
this.applicationContext = applicationContext;
|
||||
this.gauges = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
long intervalSeconds = this._config .getIntervalSeconds();
|
||||
if (this._config .getEnable() && intervalSeconds > 0) {
|
||||
logger.info("File clean up run in {} seconds", intervalSeconds);
|
||||
|
||||
scheduler = Executors.newScheduledThreadPool(1);
|
||||
scheduler.scheduleAtFixedRate(this::process, 10, intervalSeconds, TimeUnit.SECONDS);
|
||||
} else {
|
||||
scheduler = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (scheduler != null) this.scheduler.close();
|
||||
}
|
||||
|
||||
protected void process() {
|
||||
if (!this._config.getEnable()) return;
|
||||
try {
|
||||
this.ensureGauges();
|
||||
this.calculate();
|
||||
} catch (Exception ex) {
|
||||
logger.error("Problem processing file cleanups. Breaking for next interval", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureGauges() {
|
||||
if (this.gauges != null) return;
|
||||
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||
MetricsService metricsService = this.applicationContext.getBean(MetricsService.class);
|
||||
this.gauges = metricsService.gaugesBuild();
|
||||
} catch (Exception ex) {
|
||||
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculate() {
|
||||
EntityManager entityManager = null;
|
||||
|
||||
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||
try {
|
||||
|
||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||
|
||||
entityManager = entityManagerFactory.createEntityManager();
|
||||
|
||||
TenantEntityManager tenantEntityManager = this.applicationContext.getBean(TenantEntityManager.class);
|
||||
tenantEntityManager.setEntityManager(entityManager);
|
||||
TenantScope tenantScope = this.applicationContext.getBean(TenantScope.class);
|
||||
tenantScope.setTenant(null, tenantScope.getDefaultTenantCode());
|
||||
|
||||
MetricsService metricsService = this.applicationContext.getBean(MetricsService.class);
|
||||
|
||||
metricsService.calculate(this.gauges);
|
||||
} finally {
|
||||
if (entityManager != null) entityManager.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package eu.eudat.service.metrics;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(UpdateMetricsTaskProperties.class)
|
||||
public class UpdateMetricsTaskConfiguration {
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package eu.eudat.service.metrics;
|
||||
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "metrics.task")
|
||||
public class UpdateMetricsTaskProperties {
|
||||
private boolean enable;
|
||||
private int intervalSeconds;
|
||||
|
||||
public boolean getEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public int getIntervalSeconds() {
|
||||
return intervalSeconds;
|
||||
}
|
||||
|
||||
public void setIntervalSeconds(int intervalSeconds) {
|
||||
this.intervalSeconds = intervalSeconds;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,27 @@
|
|||
package eu.eudat.controllers;
|
||||
|
||||
import eu.eudat.audit.AuditableAction;
|
||||
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.convention.ConventionService;
|
||||
import eu.eudat.data.StorageFileEntity;
|
||||
import eu.eudat.model.StorageFile;
|
||||
import eu.eudat.model.builder.StorageFileBuilder;
|
||||
import eu.eudat.model.persist.StorageFilePersist;
|
||||
import eu.eudat.query.StorageFileQuery;
|
||||
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.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.ValidatorFactory;
|
||||
|
@ -25,8 +29,8 @@ 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.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -45,6 +49,7 @@ public class StorageFileController {
|
|||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(StorageFileController.class));
|
||||
private final AuditService auditService;
|
||||
private final QueryFactory queryFactory;
|
||||
private final BuilderFactory builderFactory;
|
||||
private final MessageSource messageSource;
|
||||
private final StorageFileService storageFileService;
|
||||
private final StorageFileProperties config;
|
||||
|
@ -55,13 +60,14 @@ public class StorageFileController {
|
|||
public StorageFileController(
|
||||
AuditService auditService,
|
||||
QueryFactory queryFactory,
|
||||
MessageSource messageSource,
|
||||
BuilderFactory builderFactory, MessageSource messageSource,
|
||||
StorageFileService storageFileService,
|
||||
StorageFileProperties config,
|
||||
UserScope userScope,
|
||||
AuthorizationService authorizationService, ConventionService conventionService, ValidatorFactory validatorFactory) {
|
||||
this.auditService = auditService;
|
||||
this.queryFactory = queryFactory;
|
||||
this.builderFactory = builderFactory;
|
||||
this.messageSource = messageSource;
|
||||
this.storageFileService = storageFileService;
|
||||
this.config = config;
|
||||
|
@ -71,21 +77,23 @@ public class StorageFileController {
|
|||
this.validatorFactory = validatorFactory;
|
||||
}
|
||||
|
||||
@GetMapping("/name/{id}")
|
||||
public String getName(@PathVariable("id") UUID id) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("get name" ).And("id", id));
|
||||
@GetMapping("{id}")
|
||||
public StorageFile get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("retrieving " + StorageFile.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
||||
|
||||
this.authorizationService.authorizeForce(Permission.BrowseStorageFile);
|
||||
|
||||
StorageFileEntity storageFile = this.queryFactory.query(StorageFileQuery.class).ids(id).firstAs(new BaseFieldSet().ensure(StorageFile._fullName));
|
||||
if (storageFile == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, StorageFile.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
StorageFileQuery query = this.queryFactory.query(StorageFileQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).ids(id);
|
||||
StorageFile model = this.builderFactory.builder(StorageFileBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(fieldSet, query.firstAs(fieldSet));
|
||||
if (model == 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<String, Object>("id", id)
|
||||
this.auditService.track(AuditableAction.StorageFile_Query, Map.ofEntries(
|
||||
new AbstractMap.SimpleEntry<String, Object>("id", id),
|
||||
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
|
||||
));
|
||||
|
||||
|
||||
return storageFile.getName();
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,8 +123,8 @@ public class StorageFileController {
|
|||
return addedFiles;
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
public ResponseEntity<ByteArrayResource> get(@PathVariable("id") UUID id) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
@GetMapping("download/{id}")
|
||||
public ResponseEntity<byte[]> get(@PathVariable("id") UUID id) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("download" ).And("id", id));
|
||||
|
||||
this.authorizationService.authorizeForce(Permission.BrowseStorageFile);
|
||||
|
@ -134,10 +142,14 @@ public class StorageFileController {
|
|||
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));
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentLength(file.length);
|
||||
responseHeaders.setContentType(MediaType.valueOf(contentType));
|
||||
responseHeaders.set("Content-Disposition", "attachment; filename=\"" + storageFile.getName() + (storageFile.getExtension().startsWith(".") ? "" : ".") + storageFile.getExtension() + "\"");
|
||||
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
|
||||
|
||||
return new ResponseEntity<>(file, responseHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package eu.eudat.logic.managers;
|
||||
|
||||
import eu.eudat.commons.enums.DescriptionTemplateStatus;
|
||||
import eu.eudat.types.MetricNames;
|
||||
import eu.eudat.commons.metrics.MetricNames;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
import io.prometheus.client.Gauge;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
@ -75,37 +75,37 @@ public class MetricsManager {
|
|||
public MetricsManager(PrometheusMeterRegistry registry) {
|
||||
registry.clear();
|
||||
this.gauges = Stream.of( new Object[][]{
|
||||
{MetricNames.DMP, Gauge.build().name(MetricNames.DMP).help("Number of managed DMPs").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.DMP, Gauge.build().name(MetricNames.NEXUS + MetricNames.DMP).help("Number of managed DMPs during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.FUNDERS, Gauge.build().name(MetricNames.FUNDERS).help("Number of registered Funders").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.GRANTS, Gauge.build().name(MetricNames.GRANTS).help("Number of registered Grants").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.PROJECT, Gauge.build().name(MetricNames.PROJECT).help("Number of registered Projects").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.RESEARCHER, Gauge.build().name(MetricNames.RESEARCHER).help("Number of Colaborators/Researchers").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.FUNDERS, Gauge.build().name(MetricNames.NEXUS + MetricNames.FUNDERS).help("Number of registered Funders during Nexus").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.GRANTS, Gauge.build().name(MetricNames.NEXUS + MetricNames.GRANTS).help("Number of registered Grants during Nexus").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.PROJECT, Gauge.build().name(MetricNames.NEXUS + MetricNames.PROJECT).help("Number of registered Projects during Nexus").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.RESEARCHER, Gauge.build().name(MetricNames.NEXUS + MetricNames.RESEARCHER).help("Number of Colaborators/Researchers during Nexus").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.DATASET, Gauge.build().name(MetricNames.DATASET).help("Number of managed Dataset Descriptions").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.DATASET, Gauge.build().name(MetricNames.NEXUS + MetricNames.DATASET).help("Number of managed Dataset Descriptions during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.NEXUS + MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.USERS, Gauge.build().name(MetricNames.USERS).help("Number of users").labelNames("type").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.LANGUAGES, Gauge.build().name(MetricNames.LANGUAGES).help("Number of Languages").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.DMP_WITH_GRANT, Gauge.build().name(MetricNames.DMP_WITH_GRANT).help("Number of Grants based on the status of the DMP that is using them").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.NEXUS + MetricNames.DMP_WITH_GRANT, Gauge.build().name(MetricNames.NEXUS + MetricNames.DMP_WITH_GRANT).help("Number of Grants based on the status of the DMP that is using them during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
|
||||
{MetricNames.INSTALLATIONS, Gauge.build().name(MetricNames.INSTALLATIONS).help("Number of Installations").register(registry.getPrometheusRegistry())},
|
||||
{MetricNames.NEXUS + MetricNames.INSTALLATIONS, Gauge.build().name(MetricNames.NEXUS + MetricNames.INSTALLATIONS).help("Number of Installations").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.DMP, Gauge.build().name(MetricNames.DMP).help("Number of managed DMPs").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.NEXUS + MetricNames.DMP, Gauge.build().name(MetricNames.NEXUS + MetricNames.DMP).help("Number of managed DMPs during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.FUNDERS, Gauge.build().name(MetricNames.FUNDERS).help("Number of registered Funders").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.GRANTS, Gauge.build().name(MetricNames.GRANTS).help("Number of registered Grants").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.PROJECT, Gauge.build().name(MetricNames.PROJECT).help("Number of registered Projects").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.RESEARCHER, Gauge.build().name(MetricNames.RESEARCHER).help("Number of Colaborators/Researchers").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.NEXUS + MetricNames.FUNDERS, Gauge.build().name(MetricNames.NEXUS + MetricNames.FUNDERS).help("Number of registered Funders during Nexus").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.NEXUS + MetricNames.GRANTS, Gauge.build().name(MetricNames.NEXUS + MetricNames.GRANTS).help("Number of registered Grants during Nexus").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.NEXUS + MetricNames.PROJECT, Gauge.build().name(MetricNames.NEXUS + MetricNames.PROJECT).help("Number of registered Projects during Nexus").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.NEXUS + MetricNames.RESEARCHER, Gauge.build().name(MetricNames.NEXUS + MetricNames.RESEARCHER).help("Number of Colaborators/Researchers during Nexus").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.DATASET, Gauge.build().name(MetricNames.DATASET).help("Number of managed Dataset Descriptions").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.NEXUS + MetricNames.DATASET, Gauge.build().name(MetricNames.NEXUS + MetricNames.DATASET).help("Number of managed Dataset Descriptions during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.NEXUS + MetricNames.DATASET_TEMPLATE, Gauge.build().name(MetricNames.NEXUS + MetricNames.DATASET_TEMPLATE).help("Number of dataset Templates during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.USERS, Gauge.build().name(MetricNames.USERS).help("Number of users").labelNames("type").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.LANGUAGES, Gauge.build().name(MetricNames.LANGUAGES).help("Number of Languages").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.DMP_WITH_GRANT, Gauge.build().name(MetricNames.DMP_WITH_GRANT).help("Number of Grants based on the status of the DMP that is using them").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.NEXUS + MetricNames.DMP_WITH_GRANT, Gauge.build().name(MetricNames.NEXUS + MetricNames.DMP_WITH_GRANT).help("Number of Grants based on the status of the DMP that is using them during Nexus").labelNames("status").register(registry.getPrometheusRegistry())},
|
||||
//
|
||||
// {MetricNames.INSTALLATIONS, Gauge.build().name(MetricNames.INSTALLATIONS).help("Number of Installations").register(registry.getPrometheusRegistry())},
|
||||
// {MetricNames.NEXUS + MetricNames.INSTALLATIONS, Gauge.build().name(MetricNames.NEXUS + MetricNames.INSTALLATIONS).help("Number of Installations").register(registry.getPrometheusRegistry())},
|
||||
|
||||
}).collect(Collectors.toMap(data -> (String)data[0], data -> (Gauge) data[1]));
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ spring:
|
|||
optional:classpath:config/dashboard.yml[.yml], optional:classpath:config/dashboard-${spring.profiles.active}.yml[.yml], optional:file:../config/dashboard-${spring.profiles.active}.yml[.yml],
|
||||
optional:classpath:config/transformer.yml[.yml], optional:classpath:config/transformer-${spring.profiles.active}.yml[.yml], optional:file:../config/transformer-${spring.profiles.active}.yml[.yml],
|
||||
optional:classpath:config/authorization.yml[.yml], optional:classpath:config/authorization-${spring.profiles.active}.yml[.yml], optional:file:../config/authorization-${spring.profiles.active}.yml[.yml],
|
||||
optional:classpath:config/metrics.yml[.yml], optional:classpath:config/metrics-${spring.profiles.active}.yml[.yml], optional:file:../config/metrics-${spring.profiles.active}.yml[.yml],
|
||||
optional:classpath:config/lock.yml[.yml], optional:classpath:config/lock-${spring.profiles.active}.yml[.yml], optional:file:../config/lock-${spring.profiles.active}.yml[.yml]
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
metrics:
|
||||
task:
|
||||
enable: true
|
||||
intervalSeconds: 600
|
||||
management:
|
||||
endpoint:
|
||||
metrics:
|
||||
enabled: true
|
||||
prometheus:
|
||||
enabled: true
|
||||
health:
|
||||
show-details: always
|
||||
web:
|
||||
base-path: /
|
||||
exposure:
|
||||
include: ["prometheus","health","metrics" ]
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
export:
|
||||
prometheus:
|
||||
enabled: true
|
||||
enable:
|
||||
http: true
|
||||
jvm: true
|
||||
jdbc: true
|
||||
tomcat: true
|
||||
logback: true
|
||||
hikaricp: true
|
||||
cache: true
|
|
@ -2,7 +2,7 @@ web:
|
|||
security:
|
||||
enabled: true
|
||||
authorized-endpoints: [ api ]
|
||||
allowed-endpoints: [ api/public, api/dmp/public, api/description/public, /api/supportive-material/public, api/language/public, api/contact-support/public, api/dashboard/public ]
|
||||
allowed-endpoints: [ api/public, api/dmp/public, api/description/public, /api/supportive-material/public, api/language/public, api/contact-support/public, api/dashboard/public, prometheus, health, metrics ]
|
||||
idp:
|
||||
api-key:
|
||||
enabled: false
|
||||
|
|
|
@ -21,20 +21,25 @@ export class StorageFileService {
|
|||
|
||||
private get apiBase(): string { return `${this.configurationService.server}storage-file`; }
|
||||
|
||||
getName(id: Guid ): Observable<string> {
|
||||
const url = `${this.apiBase}/name/${id}`;
|
||||
getSingle(id: Guid, reqFields: string[] = []): Observable<StorageFile> {
|
||||
const url = `${this.apiBase}/${id}`;
|
||||
const options = { params: { f: reqFields } };
|
||||
|
||||
return this.http
|
||||
.get<string>(url).pipe(
|
||||
.get<StorageFile>(url, options).pipe(
|
||||
catchError((error: any) => throwError(error)));
|
||||
}
|
||||
|
||||
download(id: Guid ): Observable<HttpResponse<Blob>> {
|
||||
const url = `${this.apiBase}/${id}`;
|
||||
const url = `${this.apiBase}/download/${id}`;
|
||||
|
||||
const params = new BaseHttpParams();
|
||||
params.interceptorContext = {
|
||||
excludedInterceptors: [InterceptorType.JSONContentType, InterceptorType.ResponsePayload]
|
||||
};
|
||||
|
||||
return this.http
|
||||
.get<HttpResponse<Blob>>(url).pipe(
|
||||
catchError((error: any) => throwError(error)));
|
||||
.get(url, {params: params, responeType: 'blob', observe: 'response'});
|
||||
}
|
||||
|
||||
uploadTempFiles(item: File): Observable<StorageFile[]> {
|
||||
|
|
|
@ -178,8 +178,8 @@
|
|||
|
||||
<app-description-template-editor-external-datasets-field-component *ngSwitchCase="descriptionTemplateFieldTypeEnum.EXTERNAL_DATASETS" class="col-12" [form]="form"></app-description-template-editor-external-datasets-field-component>
|
||||
|
||||
<app-description-template-editor-multiplicity-field-component *ngSwitchCase="descriptionTemplateFieldTypeEnum.INTERNAL_ENTRIES_DMPS" class="col-12" [form]="form"></app-description-template-editor-multiplicity-field-component>
|
||||
<app-description-template-editor-multiplicity-field-component *ngSwitchCase="descriptionTemplateFieldTypeEnum.INTERNAL_ENTRIES_DESCRIPTIONS" class="col-12" [form]="form"></app-description-template-editor-multiplicity-field-component>
|
||||
<app-description-template-editor-label-and-multiplicity-field-component *ngSwitchCase="descriptionTemplateFieldTypeEnum.INTERNAL_ENTRIES_DMPS" class="col-12" [form]="form"></app-description-template-editor-label-and-multiplicity-field-component>
|
||||
<app-description-template-editor-label-and-multiplicity-field-component *ngSwitchCase="descriptionTemplateFieldTypeEnum.INTERNAL_ENTRIES_DESCRIPTIONS" class="col-12" [form]="form"></app-description-template-editor-label-and-multiplicity-field-component>
|
||||
|
||||
</div>
|
||||
</ng-container>
|
|
@ -47,13 +47,13 @@
|
|||
<div class="row">
|
||||
<mat-form-field class="col-md-12">
|
||||
<ng-container *ngIf="field.data.multipleSelect">
|
||||
<app-multiple-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" [configuration]="multipleAutoCompleteConfiguration">
|
||||
<app-multiple-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" [configuration]="descriptionService.multipleAutocompleteConfiguration">
|
||||
</app-multiple-auto-complete>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!(field.data.multipleSelect)">
|
||||
<app-single-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textValue')" [configuration]="singleAutoCompleteConfiguration" [required]="isRequired">
|
||||
<app-single-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textValue')" [configuration]="descriptionService.singleAutocompleteConfiguration" [required]="isRequired">
|
||||
</app-single-auto-complete>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
|
@ -62,17 +62,17 @@
|
|||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.INTERNAL_DMP_ENTRIES_DMPS" class="col-12">
|
||||
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.INTERNAL_ENTRIES_DMPS" class="col-12">
|
||||
<div class="row">
|
||||
<mat-form-field class="col-md-12">
|
||||
<ng-container *ngIf="field.data.multipleSelect">
|
||||
<app-multiple-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" [configuration]="multipleAutoCompleteConfiguration">
|
||||
<app-multiple-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" [configuration]="dmpService.multipleAutocompleteConfiguration">
|
||||
</app-multiple-auto-complete>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!(field.data.multipleSelect)">
|
||||
<app-single-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textValue')" [configuration]="singleAutoCompleteConfiguration" [required]="isRequired">
|
||||
<app-single-auto-complete placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}" [formControl]="propertiesFormGroup?.get(field.id).get('textValue')" [configuration]="dmpService.singleAutocompleteConfiguration" [required]="isRequired">
|
||||
</app-single-auto-complete>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
|
@ -107,9 +107,9 @@
|
|||
</ng-container>
|
||||
<ng-container *ngSwitchCase="descriptionTemplateFieldTypeEnum.UPLOAD">
|
||||
<div class="col-12 d-flex justify-content-center">
|
||||
<ngx-dropzone #drop class="drop-file col-12" (change)="fileChangeEvent($event, true)" [multiple]="false" [accept]="typesToString()" [disabled]="propertiesFormGroup?.get(field.id).get('textValue').disabled">
|
||||
<ngx-dropzone-preview *ngIf="propertiesFormGroup?.get(field.id).get('textValue').value && fileNameDisplay" class="file-preview" [removable]="true" (removed)="onRemove()">
|
||||
<ngx-dropzone-label class="file-label">{{ fileNameDisplay}}</ngx-dropzone-label>
|
||||
<ngx-dropzone class="drop-file col-12" (change)="fileChangeEvent($event, true)" [multiple]="false" [accept]="typesToString()" [disabled]="propertiesFormGroup?.get(field.id).get('textValue').disabled">
|
||||
<ngx-dropzone-preview *ngIf="propertiesFormGroup?.get(field.id).get('textValue').value" class="file-preview" [removable]="true" (removed)="onRemove()">
|
||||
<ngx-dropzone-label class="file-label">{{ fileNameDisplay }}</ngx-dropzone-label>
|
||||
</ngx-dropzone-preview>
|
||||
</ngx-dropzone>
|
||||
</div>
|
||||
|
@ -157,7 +157,7 @@
|
|||
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.TAGS" class="col-12">
|
||||
<div class="row">
|
||||
<mat-form-field class="col-md-12">
|
||||
<app-multiple-auto-complete [configuration]="tagsAutoCompleteConfiguration" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" placeholder="{{('DATASET-EDITOR.FIELDS.TAGS' | translate) + (isRequired? ' *': '')}}"></app-multiple-auto-complete>
|
||||
<app-multiple-auto-complete [configuration]="tagService.multipleAutocompleteConfiguration" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}"></app-multiple-auto-complete>
|
||||
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
|
|
@ -6,10 +6,13 @@ import { MatDialog } from "@angular/material/dialog";
|
|||
import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type';
|
||||
import { DescriptionTemplateFieldValidationType } from '@app/core/common/enum/description-template-field-validation-type';
|
||||
import { DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateLabelAndMultiplicityData, DescriptionTemplateUploadData } from '@app/core/model/description-template/description-template';
|
||||
import { StorageFile } from '@app/core/model/storage-file/storage-file';
|
||||
import { DescriptionService } from '@app/core/services/description/description.service';
|
||||
import { DmpService } from '@app/core/services/dmp/dmp.service';
|
||||
import { SnackBarNotificationLevel, UiNotificationService } from "@app/core/services/notification/ui-notification-service";
|
||||
import { ReferenceService } from '@app/core/services/reference/reference.service';
|
||||
import { StorageFileService } from '@app/core/services/storage-file/storage-file.service';
|
||||
import { TagService } from '@app/core/services/tag/tag.service';
|
||||
import { FileUtils } from '@app/core/services/utilities/file-utils.service';
|
||||
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
|
||||
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
||||
|
@ -21,6 +24,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import * as FileSaver from 'file-saver';
|
||||
import { Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
||||
import { nameof } from 'ts-simple-nameof';
|
||||
|
||||
@Component({
|
||||
selector: 'app-description-form-field',
|
||||
|
@ -70,11 +74,13 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
|
|||
];
|
||||
|
||||
filesToUpload: FileList;
|
||||
fileNameDisplay: string;
|
||||
fileNameDisplay: string = null;
|
||||
|
||||
constructor(
|
||||
private language: TranslateService,
|
||||
private dmpService: DmpService,
|
||||
public dmpService: DmpService,
|
||||
public descriptionService: DescriptionService,
|
||||
public tagService: TagService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private uiNotificationService: UiNotificationService,
|
||||
public dialog: MatDialog,
|
||||
|
@ -92,8 +98,24 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
|
|||
|
||||
ngOnInit() {
|
||||
|
||||
if(this.field?.data?.fieldType == DescriptionTemplateFieldType.UPLOAD && this.field && this.field.id && (this.propertiesFormGroup?.get(this.field.id).get('textValue').value != undefined)) this.getUploadFileName();
|
||||
if(this.field?.data?.fieldType == DescriptionTemplateFieldType.UPLOAD && this.field && this.field.id && (this.propertiesFormGroup?.get(this.field.id).get('textValue').value != undefined) && !this.fileNameDisplay) {
|
||||
const id = Guid.parse((this.propertiesFormGroup?.get(this.field.id).get('textValue').value as string));
|
||||
|
||||
const fields = [
|
||||
nameof<StorageFile>(x => x.id),
|
||||
nameof<StorageFile>(x => x.name),
|
||||
]
|
||||
|
||||
this.storageFileService.getSingle(id, fields).pipe(takeUntil(this._destroyed)).subscribe(storageFile => {
|
||||
this.fileNameDisplay = storageFile.name;
|
||||
this.applyFieldType();
|
||||
});
|
||||
} else {
|
||||
this.applyFieldType();
|
||||
}
|
||||
}
|
||||
|
||||
private applyFieldType(){
|
||||
this.isRequired = this.field.validations?.includes(DescriptionTemplateFieldValidationType.Required);
|
||||
|
||||
switch (this.field?.data?.fieldType) {
|
||||
|
@ -140,12 +162,6 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
|
|||
// this.form.disable();
|
||||
// }
|
||||
break;
|
||||
case DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS:
|
||||
this.makeAutocompleteConfiguration(this.searchDatasets.bind(this), "label");
|
||||
break;
|
||||
case DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS:
|
||||
this.makeAutocompleteConfiguration(this.searchDmps.bind(this), "label");
|
||||
break;
|
||||
}
|
||||
|
||||
// this.form = this.visibilityRulesService.getFormGroup(this.field.id);
|
||||
|
@ -161,28 +177,6 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
|
|||
});
|
||||
}
|
||||
|
||||
searchDatasets(query: string) {
|
||||
//TODO refactor
|
||||
return null;
|
||||
// let fields: Array<string> = new Array();
|
||||
// const datasetsAutocompleteRequestItem: DataTableRequest<DatasetCriteria> = new DataTableRequest(0, 25, { fields: fields });
|
||||
// datasetsAutocompleteRequestItem.criteria = new DatasetCriteria();
|
||||
// datasetsAutocompleteRequestItem.criteria.like = query;
|
||||
// //TODO: refactor this
|
||||
// // return this.datasetService.getPaged(datasetsAutocompleteRequestItem).pipe(map(item => item.data));
|
||||
// return null;
|
||||
}
|
||||
|
||||
searchDmps(query: string) {
|
||||
//TODO refactor
|
||||
return null;
|
||||
// let fields: Array<string> = new Array();
|
||||
// const dmpsAutocompleteRequestItem: DataTableRequest<DmpCriteria> = new DataTableRequest(0, 25, { fields: fields });
|
||||
// dmpsAutocompleteRequestItem.criteria = new DmpCriteria();
|
||||
// dmpsAutocompleteRequestItem.criteria.like = query;
|
||||
// return this.dmpService.getPaged(dmpsAutocompleteRequestItem).pipe(map(item => item.data));
|
||||
}
|
||||
|
||||
makeAutocompleteConfiguration(myfunc: Function, title: string, subtitle?: string): void {
|
||||
if (!((this.field.data as DescriptionTemplateLabelAndMultiplicityData).multipleSelect)) {
|
||||
this.singleAutoCompleteConfiguration = {
|
||||
|
@ -275,16 +269,6 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
|
|||
|
||||
}
|
||||
|
||||
private getUploadFileName(){
|
||||
const id = Guid.parse((this.propertiesFormGroup?.get(this.field.id).get('textValue').value as string));
|
||||
|
||||
this.storageFileService.getName(id)
|
||||
.pipe(takeUntil(this._destroyed)).subscribe((name) => {
|
||||
this.fileNameDisplay = name;
|
||||
}, error => {
|
||||
this.fileNameDisplay = null;
|
||||
})
|
||||
}
|
||||
|
||||
public upload() {
|
||||
this.storageFileService.uploadTempFiles(this.filesToUpload[0])
|
||||
|
@ -364,13 +348,12 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
|
|||
if (this.propertiesFormGroup?.get(this.field.id).get('textValue').value) {
|
||||
const id = Guid.parse((this.propertiesFormGroup?.get(this.field.id).get('textValue').value as string));
|
||||
|
||||
this.storageFileService.download(id).subscribe((response) => {
|
||||
const blob = new Blob([response.body]);
|
||||
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
|
||||
FileSaver.saveAs(blob, filename);
|
||||
}, error => {
|
||||
this.onCallbackUploadFail(error.error);
|
||||
})
|
||||
this.storageFileService.download(id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(response => {
|
||||
const blob = new Blob([response.body]);
|
||||
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
|
||||
FileSaver.saveAs(blob, filename);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue