evaluator-plugin
This commit is contained in:
parent
d774254a1f
commit
ec2db903c4
|
@ -95,6 +95,11 @@
|
|||
<artifactId>oidc-authn</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.opencdmp</groupId>
|
||||
<artifactId>evaluator-base</artifactId>
|
||||
<version>0.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
|
|
|
@ -154,6 +154,8 @@ public class AuditableAction {
|
|||
|
||||
public static final EventId FileTransformer_GetAvailableConfigurations = new EventId(20000, "FileTransformer_GetAvailableConfigurations");
|
||||
|
||||
public static final EventId Evaluator_GetAvailableConfigurations = new EventId(20001, "Evaluator_GetAvailableConfigurations");
|
||||
|
||||
public static final EventId ContactSupport_Sent = new EventId(210000, "ContactSupport_Sent");
|
||||
public static final EventId ContactSupport_PublicSent = new EventId(210001, "ContactSupport_PublicSent");
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ public final class Permission {
|
|||
public static String AssignPlanUsers = "AssignPlanUsers";
|
||||
public static String InvitePlanUsers = "InvitePlanUsers";
|
||||
public static String AnnotatePlan = "AnnotatePlan";
|
||||
public static String EvaluatePlan = "EvaluatePlan";
|
||||
|
||||
//PlanStatus
|
||||
public static String BrowsePlanStatus = "BrowsePlanStatus";
|
||||
|
@ -137,6 +138,7 @@ public final class Permission {
|
|||
public static String DeleteDescription = "DeleteDescription";
|
||||
public static String CloneDescription = "CloneDescription";
|
||||
public static String ExportDescription = "ExportDescription";
|
||||
public static String EvaluateDescription = "EvaluateDescription";
|
||||
|
||||
//DescriptionTag
|
||||
public static String BrowseDescriptionTag = "BrowseDescriptionTag";
|
||||
|
|
|
@ -11,7 +11,8 @@ public enum TenantConfigurationType implements DatabaseEnum<Short> {
|
|||
FileTransformerPlugins((short) 1),
|
||||
DefaultUserLocale((short) 2),
|
||||
Logo((short) 3),
|
||||
CssColors((short) 4);
|
||||
CssColors((short) 4),
|
||||
EvaluatorPlugins((short) 5);
|
||||
|
||||
private final Short value;
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package org.opencdmp.commons.types.evaluator;
|
||||
|
||||
public class EvaluatorSourceEntity {
|
||||
|
||||
private String url;
|
||||
private String evaluatorId;
|
||||
private String issuerUrl;
|
||||
private String clientId;
|
||||
private String clientSecret;
|
||||
private String scope;
|
||||
private int maxInMemorySizeInBytes;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getEvaluatorId() {
|
||||
return evaluatorId;
|
||||
}
|
||||
|
||||
public void setEvaluatorId(String evaluatorId) {
|
||||
this.evaluatorId = evaluatorId;
|
||||
}
|
||||
|
||||
public String getIssuerUrl() {
|
||||
return issuerUrl;
|
||||
}
|
||||
|
||||
public void setIssuerUrl(String issuerUrl) {
|
||||
this.issuerUrl = issuerUrl;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public int getMaxInMemorySizeInBytes() {
|
||||
return maxInMemorySizeInBytes;
|
||||
}
|
||||
|
||||
public void setMaxInMemorySizeInBytes(int maxInMemorySizeInBytes) {
|
||||
this.maxInMemorySizeInBytes = maxInMemorySizeInBytes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.opencdmp.commons.types.tenantconfiguration;
|
||||
|
||||
import org.opencdmp.commons.types.evaluator.EvaluatorSourceEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EvaluatorTenantConfigurationEntity {
|
||||
|
||||
private List<EvaluatorSourceEntity> sources;
|
||||
private boolean disableSystemSources;
|
||||
|
||||
public List<EvaluatorSourceEntity> getSources() {
|
||||
return sources;
|
||||
}
|
||||
|
||||
public void setSources(List<EvaluatorSourceEntity> sources) {
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
public boolean getDisableSystemSources(){
|
||||
return disableSystemSources;
|
||||
}
|
||||
public void setDisableSystemSources(boolean disableSystemSources) {
|
||||
this.disableSystemSources = disableSystemSources;
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
|
|||
private FileEnvelopeModel pdfFile;
|
||||
private FileEnvelopeModel rdaJsonFile;
|
||||
private String repositoryId;
|
||||
private String evaluatorId;
|
||||
private boolean disableDescriptions;
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
|
@ -95,6 +96,11 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
|
|||
return this;
|
||||
}
|
||||
|
||||
public PlanCommonModelBuilder setEvaluatorId(String evaluatorId){
|
||||
this.evaluatorId = evaluatorId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PlanCommonModelBuilder setDisableDescriptions(boolean disableDescriptions) {
|
||||
this.disableDescriptions = disableDescriptions;
|
||||
return this;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package org.opencdmp.model.evaluator;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class EvaluateRequestModel {
|
||||
|
||||
private UUID id;
|
||||
private String evaluatorId;
|
||||
private String format;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getEvaluatorId() {
|
||||
return evaluatorId;
|
||||
}
|
||||
|
||||
public void setEvaluatorId(String evaluatorId) {
|
||||
this.evaluatorId = evaluatorId;
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.opencdmp.model.evaluator;
|
||||
|
||||
import org.opencdmp.evaluatorbase.enums.EvaluatorEntityType;
|
||||
import org.opencdmp.evaluatorbase.models.misc.RankConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EvaluatorConfiguration {
|
||||
private String evaluatorId;
|
||||
private RankConfig rankConfig;
|
||||
private List<EvaluatorEntityType> evaluatorEntityTypes;
|
||||
private boolean useSharedStorage;
|
||||
private boolean hasLogo;
|
||||
|
||||
public String getEvaluatorId() {
|
||||
return evaluatorId;
|
||||
}
|
||||
|
||||
public void setEvaluatorId(String evaluatorId) {
|
||||
this.evaluatorId = evaluatorId;
|
||||
}
|
||||
|
||||
public RankConfig getRankConfig() {
|
||||
return rankConfig;
|
||||
}
|
||||
|
||||
public void setRankConfig(RankConfig rankConfig) {
|
||||
this.rankConfig = rankConfig;
|
||||
}
|
||||
|
||||
public List<EvaluatorEntityType> getEvaluatorEntityTypes() {
|
||||
return evaluatorEntityTypes;
|
||||
}
|
||||
|
||||
public void setEvaluatorEntityTypes(List<EvaluatorEntityType> evaluatorEntityTypes) {
|
||||
this.evaluatorEntityTypes = evaluatorEntityTypes;
|
||||
}
|
||||
|
||||
public boolean isUseSharedStorage() {
|
||||
return useSharedStorage;
|
||||
}
|
||||
|
||||
public void setUseSharedStorage(boolean useSharedStorage) {
|
||||
this.useSharedStorage = useSharedStorage;
|
||||
}
|
||||
|
||||
public boolean isHasLogo() {
|
||||
return hasLogo;
|
||||
}
|
||||
|
||||
public void setHasLogo(boolean hasLogo) {
|
||||
this.hasLogo = hasLogo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package org.opencdmp.model.evaluator;
|
||||
|
||||
public class EvaluatorSource {
|
||||
|
||||
private String url;
|
||||
|
||||
public static final String _url = "url";
|
||||
|
||||
private String evaluatorId;
|
||||
|
||||
public static final String _evaluatorId = "evaluatorId";
|
||||
|
||||
private String issuerUrl;
|
||||
|
||||
public static final String _issuerUrl = "issuerUrl";
|
||||
|
||||
private String clientId;
|
||||
|
||||
public static final String _clientId = "clientId";
|
||||
|
||||
private String clientSecret;
|
||||
|
||||
public static final String _clientSecret = "clientSecret";
|
||||
|
||||
private String scope;
|
||||
|
||||
public static final String _scope = "scope";
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getEvaluatorId() {
|
||||
return evaluatorId;
|
||||
}
|
||||
|
||||
public void setEvaluatorId(String evaluatorId) {
|
||||
this.evaluatorId = evaluatorId;
|
||||
}
|
||||
|
||||
public String getIssuerUrl() {
|
||||
return issuerUrl;
|
||||
}
|
||||
|
||||
public void setIssuerUrl(String issuerUrl) {
|
||||
this.issuerUrl = issuerUrl;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package org.opencdmp.model.tenantconfiguration;
|
|||
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.commons.enums.TenantConfigurationType;
|
||||
import org.opencdmp.commons.types.tenantconfiguration.EvaluatorTenantConfigurationEntity;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
@ -36,6 +37,10 @@ public class TenantConfiguration {
|
|||
|
||||
public static final String _fileTransformerPlugins = "fileTransformerPlugins";
|
||||
|
||||
private EvaluatorTenantConfigurationEntity evaluatorPlugins;
|
||||
|
||||
public static final String _evaluatorPlugins = "evaluatorPlugins";
|
||||
|
||||
private LogoTenantConfiguration logo;
|
||||
|
||||
public static final String _logo = "logo";
|
||||
|
@ -150,4 +155,12 @@ public class TenantConfiguration {
|
|||
public void setType(TenantConfigurationType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public EvaluatorTenantConfigurationEntity getEvaluatorPlugins() {
|
||||
return evaluatorPlugins;
|
||||
}
|
||||
|
||||
public void setEvaluatorPlugins(EvaluatorTenantConfigurationEntity evaluatorPlugins) {
|
||||
this.evaluatorPlugins = evaluatorPlugins;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import com.sun.jdi.InvalidTypeException;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.logging.MapLogEntry;
|
||||
import org.opencdmp.commonmodels.models.description.DescriptionModel;
|
||||
import org.opencdmp.commonmodels.models.plan.PlanModel;
|
||||
import org.opencdmp.evaluatorbase.interfaces.EvaluatorClient;
|
||||
import org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration;
|
||||
import org.opencdmp.evaluatorbase.models.misc.RankModel;
|
||||
import org.opencdmp.service.filetransformer.FileTransformerRepository;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class EvaluatorClientImpl implements EvaluatorClient {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileTransformerRepository.class));
|
||||
|
||||
private final WebClient transformerClient;
|
||||
|
||||
public EvaluatorClientImpl(WebClient transformerClient) {
|
||||
this.transformerClient = transformerClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RankModel rankPlan(PlanModel planModel) throws InvalidApplicationException, IOException, InvalidTypeException {
|
||||
logger.debug(new MapLogEntry("rankPlan").And("planModel", planModel));
|
||||
|
||||
return this.transformerClient.post().uri("/rank/plan").bodyValue(planModel) // Send planModel in the body
|
||||
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(RankModel.class)).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RankModel rankDescription(DescriptionModel descriptionModel) throws InvalidApplicationException, IOException {
|
||||
logger.debug(new MapLogEntry("rankDescription").And("descriptionModel", descriptionModel));
|
||||
return this.transformerClient.post().uri("/rank/description").bodyValue(descriptionModel) // Send descriptionModel in the body
|
||||
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(RankModel.class)).block();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluatorConfiguration getConfiguration() {
|
||||
logger.debug(new MapLogEntry("getConfiguration"));
|
||||
return this.transformerClient.get().uri("/config")
|
||||
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<EvaluatorConfiguration>() {})).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogo() {
|
||||
logger.debug(new MapLogEntry("getLogo"));
|
||||
return this.transformerClient.get().uri("/logo").exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({EvaluatorProperties.class})
|
||||
public class EvaluatorConfiguration {
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import gr.cite.tools.cache.CacheOptions;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "cache.evaluator-config-by-id")
|
||||
public class EvaluatorConfigurationCacheOptions extends CacheOptions {
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import gr.cite.tools.cache.CacheService;
|
||||
import org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Service
|
||||
public class EvaluatorConfigurationCacheService extends CacheService<EvaluatorConfigurationCacheService.EvaluatorConfigurationCacheValue> {
|
||||
|
||||
public static class EvaluatorConfigurationCacheValue {
|
||||
|
||||
public EvaluatorConfigurationCacheValue() {
|
||||
}
|
||||
|
||||
public EvaluatorConfigurationCacheValue(String repositoryId, String tenantCode, EvaluatorConfiguration configuration) {
|
||||
this.evaluatorId = repositoryId;
|
||||
this.configuration = configuration;
|
||||
this.tenantCode = tenantCode == null ? "" : tenantCode;
|
||||
}
|
||||
|
||||
private String evaluatorId;
|
||||
private String tenantCode;
|
||||
|
||||
public String getEvaluatorId() {
|
||||
return evaluatorId;
|
||||
}
|
||||
|
||||
public void setEvaluatorId(String evaluatorId) {
|
||||
this.evaluatorId = evaluatorId;
|
||||
}
|
||||
|
||||
private EvaluatorConfiguration configuration;
|
||||
|
||||
public EvaluatorConfiguration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
public void setConfiguration(EvaluatorConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public String getTenantCode() {
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
public void setTenantCode(String tenantCode) {
|
||||
this.tenantCode = tenantCode;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public EvaluatorConfigurationCacheService(EvaluatorConfigurationCacheOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<EvaluatorConfigurationCacheService.EvaluatorConfigurationCacheValue> valueClass() {
|
||||
return EvaluatorConfigurationCacheService.EvaluatorConfigurationCacheValue.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keyOf(EvaluatorConfigurationCacheService.EvaluatorConfigurationCacheValue value) {
|
||||
return this.buildKey(value.getEvaluatorId(), value.getTenantCode());
|
||||
}
|
||||
|
||||
|
||||
public String buildKey(String evaluatorId, String tenantCod) {
|
||||
HashMap<String, String> keyParts = new HashMap<>();
|
||||
keyParts.put("$evaluatorId$", evaluatorId);
|
||||
keyParts.put("$tenantCode$", tenantCod);
|
||||
return this.generateKey(keyParts);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import org.opencdmp.commons.types.evaluator.EvaluatorSourceEntity;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ConfigurationProperties(prefix = "evaluator")
|
||||
public class EvaluatorProperties {
|
||||
|
||||
private List<EvaluatorSourceEntity> sources;
|
||||
|
||||
public List<EvaluatorSourceEntity> getSources() {
|
||||
return sources;
|
||||
}
|
||||
|
||||
public void setSources(List<EvaluatorSourceEntity> sources) {
|
||||
this.sources = sources;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import com.sun.jdi.InvalidTypeException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface EvaluatorService {
|
||||
|
||||
org.opencdmp.evaluatorbase.models.misc.RankModel rankPlan(UUID planId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, InvalidTypeException;
|
||||
|
||||
org.opencdmp.evaluatorbase.models.misc.RankModel rankDescription(UUID descriptionId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException;
|
||||
|
||||
List<org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration> getAvailableEvaluators() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
|
||||
|
||||
String getLogo(String evaluatorId) throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
|
||||
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.sun.jdi.InvalidTypeException;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeCacheService;
|
||||
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeFilterFunction;
|
||||
import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeModel;
|
||||
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 gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.logging.MapLogEntry;
|
||||
import org.opencdmp.authorization.AuthorizationFlags;
|
||||
import org.opencdmp.authorization.Permission;
|
||||
import org.opencdmp.commonmodels.models.description.DescriptionModel;
|
||||
import org.opencdmp.commons.JsonHandlingService;
|
||||
import org.opencdmp.commons.enums.*;
|
||||
import org.opencdmp.commons.scope.tenant.TenantScope;
|
||||
import org.opencdmp.commons.types.evaluator.EvaluatorSourceEntity;
|
||||
import org.opencdmp.depositbase.repository.DepositClient;
|
||||
import org.opencdmp.evaluatorbase.interfaces.EvaluatorClient;
|
||||
import org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration;
|
||||
import org.opencdmp.commons.types.tenantconfiguration.EvaluatorTenantConfigurationEntity;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.data.DescriptionEntity;
|
||||
import org.opencdmp.data.PlanEntity;
|
||||
import org.opencdmp.data.TenantConfigurationEntity;
|
||||
import org.opencdmp.data.TenantEntityManager;
|
||||
import org.opencdmp.evaluatorbase.models.misc.RankModel;
|
||||
import org.opencdmp.event.TenantConfigurationTouchedEvent;
|
||||
import org.opencdmp.model.builder.commonmodels.DepositConfigurationBuilder;
|
||||
import org.opencdmp.model.builder.commonmodels.description.DescriptionCommonModelBuilder;
|
||||
import org.opencdmp.model.builder.commonmodels.plan.PlanCommonModelBuilder;
|
||||
import org.opencdmp.model.description.Description;
|
||||
import org.opencdmp.model.plan.Plan;
|
||||
import org.opencdmp.commonmodels.models.plan.PlanModel;
|
||||
import org.opencdmp.model.tenantconfiguration.TenantConfiguration;
|
||||
import org.opencdmp.query.DescriptionQuery;
|
||||
import org.opencdmp.query.PlanQuery;
|
||||
import org.opencdmp.query.TenantConfigurationQuery;
|
||||
import org.opencdmp.service.accounting.AccountingService;
|
||||
import org.opencdmp.service.encryption.EncryptionService;
|
||||
import org.opencdmp.service.tenant.TenantProperties;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.opencdmp.authorization.AuthorizationFlags.Public;
|
||||
|
||||
@Service
|
||||
public class EvaluatorServiceImpl implements EvaluatorService {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(EvaluatorServiceImpl.class));
|
||||
private final EvaluatorProperties evaluatorProperties;
|
||||
private final Map<String, EvaluatorClientImpl> clients;
|
||||
private final TokenExchangeCacheService tokenExchangeCacheService;
|
||||
private final EvaluatorConfigurationCacheService evaluatorConfigurationCacheService;
|
||||
private final AuthorizationService authorizationService;
|
||||
private final QueryFactory queryFactory;
|
||||
private final BuilderFactory builderFactory;
|
||||
private final MessageSource messageSource;
|
||||
private final ConventionService conventionService;
|
||||
private final TenantScope tenantScope;
|
||||
private final EncryptionService encryptionService;
|
||||
private final TenantProperties tenantProperties;
|
||||
private final JsonHandlingService jsonHandlingService;
|
||||
private final EvaluatorSourcesCacheService evaluatorSourcesCacheService;
|
||||
private final AccountingService accountingService;
|
||||
private final TenantEntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
public EvaluatorServiceImpl(EvaluatorProperties evaluatorProperties, Map<String, EvaluatorClientImpl> clients, TokenExchangeCacheService tokenExchangeCacheService, EvaluatorConfigurationCacheService evaluatorConfigurationCacheService, AuthorizationService authorizationService, QueryFactory queryFactory, BuilderFactory builderFactory, MessageSource messageSource, ConventionService conventionService, TenantScope tenantScope, EncryptionService encryptionService, TenantProperties tenantProperties, JsonHandlingService jsonHandlingService, EvaluatorSourcesCacheService evaluatorSourcesCacheService, AccountingService accountingService, TenantEntityManager entityManager) {
|
||||
this.evaluatorProperties = evaluatorProperties;
|
||||
this.clients = clients;
|
||||
this.tokenExchangeCacheService = tokenExchangeCacheService;
|
||||
this.evaluatorConfigurationCacheService = evaluatorConfigurationCacheService;
|
||||
this.authorizationService = authorizationService;
|
||||
this.queryFactory = queryFactory;
|
||||
this.builderFactory = builderFactory;
|
||||
this.messageSource = messageSource;
|
||||
this.conventionService = conventionService;
|
||||
this.tenantScope = tenantScope;
|
||||
this.encryptionService = encryptionService;
|
||||
this.tenantProperties = tenantProperties;
|
||||
this.jsonHandlingService = jsonHandlingService;
|
||||
this.evaluatorSourcesCacheService = evaluatorSourcesCacheService;
|
||||
this.accountingService = accountingService;
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
private EvaluatorClientImpl getEvaluatorClient(String repoId) throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
String repositoryIdByTenant = this.getRepositoryIdByTenant(repoId);
|
||||
if (this.clients.containsKey(repositoryIdByTenant)) {
|
||||
return this.clients.get(repositoryIdByTenant);
|
||||
}
|
||||
|
||||
EvaluatorSourceEntity source = this.getEvaluatorSources().stream()
|
||||
.filter(evaluatorSourceEntity -> evaluatorSourceEntity.getEvaluatorId().equals(repoId))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
try {
|
||||
TokenExchangeModel tokenExchangeModel = new TokenExchangeModel(
|
||||
"evaluator:" + repositoryIdByTenant,
|
||||
source.getIssuerUrl(),
|
||||
source.getClientId(),
|
||||
source.getClientSecret(),
|
||||
source.getScope()
|
||||
);
|
||||
|
||||
TokenExchangeFilterFunction tokenExchangeFilterFunction = new TokenExchangeFilterFunction(
|
||||
this.tokenExchangeCacheService,
|
||||
tokenExchangeModel
|
||||
);
|
||||
|
||||
EvaluatorClientImpl repository = new EvaluatorClientImpl(
|
||||
WebClient.builder().baseUrl(source.getUrl() + "/api/evaluator")
|
||||
.filters(exchangeFilterFunctions -> {
|
||||
exchangeFilterFunctions.add(tokenExchangeFilterFunction);
|
||||
exchangeFilterFunctions.add(logRequest());
|
||||
exchangeFilterFunctions.add(logResponse());
|
||||
})
|
||||
.codecs(codecs -> {
|
||||
codecs.defaultCodecs().maxInMemorySize(source.getMaxInMemorySizeInBytes());
|
||||
codecs.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper().registerModule(new JavaTimeModule()), MediaType.APPLICATION_JSON));
|
||||
codecs.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(new ObjectMapper().registerModule(new JavaTimeModule()), MediaType.APPLICATION_JSON));
|
||||
})
|
||||
.build()
|
||||
);
|
||||
|
||||
this.clients.put(repositoryIdByTenant, repository);
|
||||
return repository;
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception occurred while creating EvaluatorClientImpl", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<EvaluatorSourceEntity> getEvaluatorSources() throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
String tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : "";
|
||||
EvaluatorSourcesCacheService.EvaluatorSourceCacheValue cacheValue = this.evaluatorSourcesCacheService.lookup(this.evaluatorSourcesCacheService.buildKey(tenantCode));
|
||||
if (cacheValue == null) {
|
||||
List<EvaluatorSourceEntity> evaluatorSourceEntities = new ArrayList<>(this.evaluatorProperties.getSources());
|
||||
|
||||
if (this.tenantScope.isSet() && this.tenantScope.isMultitenant()) {
|
||||
TenantConfigurationQuery tenantConfigurationQuery = this.queryFactory.query(TenantConfigurationQuery.class).disableTracking().isActive(IsActive.Active).types(TenantConfigurationType.EvaluatorPlugins);
|
||||
if (this.tenantScope.isDefaultTenant()) tenantConfigurationQuery.tenantIsSet(false);
|
||||
else tenantConfigurationQuery.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
|
||||
TenantConfigurationEntity tenantConfiguration = tenantConfigurationQuery.firstAs(new BaseFieldSet().ensure(TenantConfiguration._evaluatorPlugins));
|
||||
|
||||
if (tenantConfiguration != null && !this.conventionService.isNullOrEmpty(tenantConfiguration.getValue())) {
|
||||
EvaluatorTenantConfigurationEntity evaluatorTenantConfigurationEntity = this.jsonHandlingService.fromJsonSafe(EvaluatorTenantConfigurationEntity.class, tenantConfiguration.getValue());
|
||||
if (evaluatorTenantConfigurationEntity != null) {
|
||||
if (evaluatorTenantConfigurationEntity.getDisableSystemSources()) evaluatorSourceEntities = new ArrayList<>();
|
||||
evaluatorSourceEntities.addAll(this.buildEvaluatorSourceItems(evaluatorTenantConfigurationEntity.getSources()));
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheValue = new EvaluatorSourcesCacheService.EvaluatorSourceCacheValue(tenantCode, evaluatorSourceEntities);
|
||||
this.evaluatorSourcesCacheService.put(cacheValue);
|
||||
}
|
||||
return cacheValue.getSources();
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleTenantConfigurationTouchedEvent(TenantConfigurationTouchedEvent event) {
|
||||
if (!event.getType().equals(TenantConfigurationType.FileTransformerPlugins)) return;
|
||||
EvaluatorSourcesCacheService.EvaluatorSourceCacheValue evaluatorSourceCacheValue = this.evaluatorSourcesCacheService.lookup(this.evaluatorSourcesCacheService.buildKey(event.getTenantCode()));
|
||||
if (evaluatorSourceCacheValue != null && evaluatorSourceCacheValue.getSources() != null){
|
||||
for (EvaluatorSourceEntity source : evaluatorSourceCacheValue.getSources()){
|
||||
String repositoryIdByTenant = source.getEvaluatorId() + "_" + event.getTenantCode();
|
||||
this.clients.remove(repositoryIdByTenant);
|
||||
this.evaluatorConfigurationCacheService.evict(this.evaluatorConfigurationCacheService.buildKey(source.getEvaluatorId(), event.getTenantCode()));
|
||||
}
|
||||
}
|
||||
this.evaluatorConfigurationCacheService.evict(this.evaluatorSourcesCacheService.buildKey(event.getTenantCode()));
|
||||
}
|
||||
|
||||
private List<EvaluatorSourceEntity> buildEvaluatorSourceItems(List<EvaluatorSourceEntity> sources) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
List<EvaluatorSourceEntity> items = new ArrayList<>();
|
||||
if (this.conventionService.isListNullOrEmpty(sources)) return items;
|
||||
for (EvaluatorSourceEntity source : sources){
|
||||
EvaluatorSourceEntity item = new EvaluatorSourceEntity();
|
||||
item.setEvaluatorId(source.getEvaluatorId());
|
||||
item.setUrl(source.getUrl());
|
||||
item.setIssuerUrl(source.getIssuerUrl());
|
||||
item.setClientId(source.getClientId());
|
||||
if (!this.conventionService.isNullOrEmpty(source.getClientSecret())) item.setClientSecret(this.encryptionService.decryptAES(source.getClientSecret(), this.tenantProperties.getConfigEncryptionAesKey(), this.tenantProperties.getConfigEncryptionAesIv()));
|
||||
item.setScope(source.getScope());
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private String getRepositoryIdByTenant(String repositoryId) throws InvalidApplicationException {
|
||||
if (this.tenantScope.isSet() && this.tenantScope.isMultitenant()) {
|
||||
return repositoryId + "_" + this.tenantScope.getTenantCode();
|
||||
} else {
|
||||
return repositoryId;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration> getAvailableEvaluators() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
|
||||
this.authorizationService.authorizeForce(Permission.BrowsePlan, Permission.DeferredAffiliation);
|
||||
List<org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration> configurations = new ArrayList<>();
|
||||
|
||||
for(EvaluatorSourceEntity evaluatorSource : this.getEvaluatorSources()){
|
||||
|
||||
String tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : "";
|
||||
EvaluatorConfigurationCacheService.EvaluatorConfigurationCacheValue cacheValue = this.evaluatorConfigurationCacheService.lookup(this.evaluatorConfigurationCacheService.buildKey(evaluatorSource.getEvaluatorId(), tenantCode));
|
||||
|
||||
if(cacheValue == null){
|
||||
try{
|
||||
EvaluatorClientImpl evaluatorClient = this.getEvaluatorClient(evaluatorSource.getEvaluatorId());
|
||||
if(evaluatorClient == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{evaluatorSource.getEvaluatorId(), EvaluatorClientImpl.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
EvaluatorConfiguration configuration = evaluatorClient.getConfiguration();
|
||||
cacheValue = new EvaluatorConfigurationCacheService.EvaluatorConfigurationCacheValue(evaluatorSource.getEvaluatorId(), tenantCode, configuration);
|
||||
this.evaluatorConfigurationCacheService.put(cacheValue);
|
||||
}catch (Exception e){
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if(cacheValue != null){
|
||||
configurations.add(cacheValue.getConfiguration());
|
||||
}
|
||||
}
|
||||
|
||||
return configurations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RankModel rankPlan(UUID planId, String evaluatorId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, InvalidTypeException {
|
||||
this.authorizationService.authorizeForce(Permission.EvaluatePlan);
|
||||
EvaluatorClientImpl repository = this.getEvaluatorClient(evaluatorId);
|
||||
|
||||
if(repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, EvaluatorClientImpl.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
PlanEntity planEntity = this.queryFactory.query(PlanQuery.class).disableTracking().ids(planId).first();
|
||||
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planId, PlanEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
PlanModel evaluatorModel = this.builderFactory.builder(PlanCommonModelBuilder.class).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).setEvaluatorId(repository.getConfiguration().getEvaluatorId()).isPublic(isPublic).authorize(AuthorizationFlags.All).build(planEntity);
|
||||
if(evaluatorModel == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planId, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
this.accountingService.increase(UsageLimitTargetMetric.FILE_TRANSFORMER_EXPORT_PLAN_EXECUTION_COUNT.getValue());
|
||||
this.increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric.FILE_TRANSFORMER_EXPORT_PLAN_EXECUTION_COUNT_FOR, evaluatorId);
|
||||
|
||||
return repository.rankPlan(evaluatorModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RankModel rankDescription(UUID descriptionId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException {
|
||||
this.authorizationService.authorizeForce(Permission.EvaluateDescription);
|
||||
EvaluatorClientImpl repository = this.getEvaluatorClient(repositoryId);
|
||||
|
||||
if(repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, EvaluatorClientImpl.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
DescriptionEntity descriptionEntity = this.queryFactory.query(DescriptionQuery.class).disableTracking().ids(descriptionId).first();
|
||||
if (descriptionEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, DescriptionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
DescriptionModel descriptionEvaluatorModel = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(repository.getConfiguration().getEvaluatorId()).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).isPublic(isPublic).authorize(AuthorizationFlags.All).build(descriptionEntity);
|
||||
if (descriptionEvaluatorModel == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
this.accountingService.increase(UsageLimitTargetMetric.FILE_TRANSFORMER_EXPORT_DESCRIPTIONS_EXECUTION_COUNT.getValue());
|
||||
this.increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric.FILE_TRANSFORMER_EXPORT_DESCRIPTIONS_EXECUTION_COUNT_FOR, repositoryId);
|
||||
|
||||
return repository.rankDescription(descriptionEvaluatorModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogo(String evaluatorId) throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
|
||||
this.authorizationService.authorizeForce(Permission.BrowseDeposit, Permission.DeferredAffiliation);
|
||||
EvaluatorClient evaluatorClient = this.getEvaluatorClient(evaluatorId);
|
||||
if(evaluatorClient == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{evaluatorId, EvaluatorClient.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
return evaluatorClient.getLogo();
|
||||
}
|
||||
|
||||
private static ExchangeFilterFunction logRequest() {
|
||||
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
|
||||
logger.debug(new MapLogEntry("Request").And("method", clientRequest.method().toString()).And("url", clientRequest.url()));
|
||||
return Mono.just(clientRequest);
|
||||
});
|
||||
}
|
||||
|
||||
private static ExchangeFilterFunction logResponse() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(response -> {
|
||||
if (response.statusCode().isError()) {
|
||||
return response.mutate().build().bodyToMono(String.class)
|
||||
.flatMap(body -> {
|
||||
logger.error(new MapLogEntry("Response").And("method", response.request().getMethod().toString()).And("url", response.request().getURI()).And("status", response.statusCode().toString()).And("body", body));
|
||||
return Mono.just(response);
|
||||
});
|
||||
}
|
||||
return Mono.just(response);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric metric, String repositoryId) throws InvalidApplicationException {
|
||||
this.accountingService.increase(metric.getValue() + repositoryId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import gr.cite.tools.cache.CacheOptions;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "cache.evaluator-sources-by-tenant")
|
||||
public class EvaluatorSourcesCacheOptions extends CacheOptions {
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.opencdmp.service.evaluator;
|
||||
|
||||
import gr.cite.tools.cache.CacheService;
|
||||
import org.opencdmp.commons.types.evaluator.EvaluatorSourceEntity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class EvaluatorSourcesCacheService extends CacheService<EvaluatorSourcesCacheService.EvaluatorSourceCacheValue> {
|
||||
|
||||
public static class EvaluatorSourceCacheValue {
|
||||
|
||||
public EvaluatorSourceCacheValue() {
|
||||
}
|
||||
|
||||
public EvaluatorSourceCacheValue(String tenantCode, List<EvaluatorSourceEntity> sources) {
|
||||
this.tenantCode = tenantCode;
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
private String tenantCode;
|
||||
|
||||
private List<EvaluatorSourceEntity> sources;
|
||||
|
||||
|
||||
public String getTenantCode() {
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
public void setTenantCode(String tenantCode) {
|
||||
this.tenantCode = tenantCode;
|
||||
}
|
||||
|
||||
public List<EvaluatorSourceEntity> getSources() {
|
||||
return sources;
|
||||
}
|
||||
|
||||
public void setSources(List<EvaluatorSourceEntity> sources) {
|
||||
this.sources = sources;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public EvaluatorSourcesCacheService(EvaluatorSourcesCacheOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<EvaluatorSourceCacheValue> valueClass() {
|
||||
return EvaluatorSourceCacheValue.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keyOf(EvaluatorSourceCacheValue value) {
|
||||
return this.buildKey(value.getTenantCode());
|
||||
}
|
||||
|
||||
public String buildKey(String tenantCod) {
|
||||
HashMap<String, String> keyParts = new HashMap<>();
|
||||
keyParts.put("$tenantCode$", tenantCod);
|
||||
return this.generateKey(keyParts);
|
||||
}
|
||||
}
|
|
@ -151,8 +151,6 @@ public class FileTransformerServiceImpl implements FileTransformerService {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<FileTransformerSourceEntity> getFileTransformerSources() throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
String tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : "";
|
||||
FileTransformerSourcesCacheService.FileTransformerSourceCacheValue cacheValue = this.fileTransformerSourcesCacheService.lookup(this.fileTransformerSourcesCacheService.buildKey(tenantCode));
|
||||
|
|
|
@ -844,8 +844,6 @@ public class PlanServiceImpl implements PlanService {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void updateVersionStatusAndSave(PlanEntity data, PlanStatus previousStatus, PlanStatus newStatus) throws InvalidApplicationException {
|
||||
if (previousStatus.equals(newStatus))
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package org.opencdmp.controllers;
|
||||
|
||||
import gr.cite.tools.auditing.AuditService;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.logging.MapLogEntry;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import org.opencdmp.audit.AuditableAction;
|
||||
import org.opencdmp.controllers.swagger.SwaggerHelpers;
|
||||
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
|
||||
import org.opencdmp.controllers.swagger.annotation.Swagger404;
|
||||
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
||||
import org.opencdmp.evaluatorbase.interfaces.EvaluatorConfiguration;
|
||||
import org.opencdmp.evaluatorbase.models.misc.RankModel;
|
||||
import org.opencdmp.model.evaluator.EvaluateRequestModel;
|
||||
import org.opencdmp.model.file.ExportRequestModel;
|
||||
import org.opencdmp.service.evaluator.EvaluatorService;
|
||||
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 javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(value = "/api/evaluator")
|
||||
@SwaggerCommonErrorResponses
|
||||
public class EvaluatorController {
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(EvaluatorController.class));
|
||||
|
||||
private final EvaluatorService evaluatorService;
|
||||
|
||||
private final AuditService auditService;
|
||||
|
||||
@Autowired
|
||||
public EvaluatorController(EvaluatorService evaluatorService, AuditService auditService){
|
||||
this.evaluatorService = evaluatorService;
|
||||
this.auditService = auditService;
|
||||
}
|
||||
|
||||
@GetMapping("/available")
|
||||
@OperationWithTenantHeader(summary = "Fetch all evaluators", description = SwaggerHelpers.Evaluator.endpoint_get_available_evaluators,
|
||||
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
|
||||
array = @ArraySchema(
|
||||
schema = @Schema(
|
||||
implementation = EvaluatorConfiguration.class
|
||||
)))
|
||||
))
|
||||
public List<EvaluatorConfiguration> getAvailableConfigurations() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
logger.debug(new MapLogEntry("getAvailableConfigurations"));
|
||||
|
||||
List<EvaluatorConfiguration> model = this.evaluatorService.getAvailableEvaluators();
|
||||
this.auditService.track(AuditableAction.Evaluator_GetAvailableConfigurations);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@PostMapping("/rank-plan")
|
||||
@OperationWithTenantHeader(summary = "Rank a plan", description = SwaggerHelpers.Evaluator.endpoint_rank_plans,
|
||||
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
||||
public ResponseEntity<RankModel> rankPlan(@RequestBody EvaluateRequestModel requestModel) throws Exception {
|
||||
logger.debug(new MapLogEntry("ranking plan"));
|
||||
|
||||
RankModel rankModel = this.evaluatorService.rankPlan(requestModel.getId(), requestModel.getEvaluatorId(), requestModel.getFormat(), true);
|
||||
|
||||
return new ResponseEntity<>(rankModel, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/rank-description")
|
||||
@OperationWithTenantHeader(summary = "Rank a description", description = SwaggerHelpers.Evaluator.endpoint_rank_descriptions,
|
||||
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
||||
public ResponseEntity<RankModel> rankDescription(@RequestBody EvaluateRequestModel requestModel) throws Exception {
|
||||
logger.debug(new MapLogEntry("ranking description"));
|
||||
|
||||
RankModel rankModel = this.evaluatorService.rankDescription(requestModel.getId(), requestModel.getEvaluatorId(), requestModel.getFormat(), true);
|
||||
|
||||
return new ResponseEntity<>(rankModel, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/{evaluatorId}/logo")
|
||||
@OperationWithTenantHeader(summary = "Fetch a specific evaluator logo by id", description = SwaggerHelpers.Deposit.endpoint_get_logo,
|
||||
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
|
||||
schema = @Schema(
|
||||
implementation = String.class
|
||||
))
|
||||
))
|
||||
@Swagger404
|
||||
public String getLogo(
|
||||
@Parameter(name = "evaluatorId", description = "The id of an evaluator of which to fetch the logo", example = "zenodo", required = true) @PathVariable("evaluatorId") String evaluatorId
|
||||
) throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
|
||||
logger.debug(new MapLogEntry("get logo" + EvaluatorConfiguration.class.getSimpleName()).And("evaluatorId", evaluatorId));
|
||||
|
||||
String logo = this.evaluatorService.getLogo(evaluatorId);
|
||||
this.auditService.track(AuditableAction.Deposit_GetLogo, Map.ofEntries(
|
||||
new AbstractMap.SimpleEntry<String, Object>("evaluatorId", evaluatorId)
|
||||
));
|
||||
|
||||
return logo;
|
||||
}
|
||||
}
|
|
@ -2589,6 +2589,24 @@ public final class SwaggerHelpers {
|
|||
|
||||
}
|
||||
|
||||
public static final class Evaluator {
|
||||
|
||||
public static final String endpoint_get_available_evaluators =
|
||||
"""
|
||||
This endpoint is used to fetch all the available evaluators.</br>
|
||||
""";
|
||||
|
||||
public static final String endpoint_rank_plans =
|
||||
"""
|
||||
This endpoint is used to rank a plan using a specific evaluator.</br>
|
||||
""";
|
||||
|
||||
public static final String endpoint_rank_descriptions =
|
||||
"""
|
||||
This endpoint is used to rank a description using a specific evaluator.</br>
|
||||
""";
|
||||
}
|
||||
|
||||
public static final class EntityDoi {
|
||||
|
||||
public static final String endpoint_query =
|
||||
|
|
|
@ -29,6 +29,7 @@ spring:
|
|||
optional:classpath:config/public-api.yml[.yml], optional:classpath:config/public-api-${spring.profiles.active}.yml[.yml], optional:file:../config/public-api-${spring.profiles.active}.yml[.yml],
|
||||
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/file-transformer.yml[.yml], optional:classpath:config/file-transformer-${spring.profiles.active}.yml[.yml], optional:file:../config/file-transformer-${spring.profiles.active}.yml[.yml],
|
||||
optional:classpath:config/evaluator.yml[.yml], optional:classpath:config/evaluator-${spring.profiles.active}.yml[.yml], optional:file:../config/evaluator-${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/field-set-expander.yml[.yml], optional:classpath:config/field-set-expander-${spring.profiles.active}.yml[.yml], optional:file:../config/field-set-expander-${spring.profiles.active}.yml[.yml],
|
||||
|
|
|
@ -50,12 +50,24 @@ cache:
|
|||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 600
|
||||
- names: [ "evaluatorConfigById" ]
|
||||
allowNullValues: true
|
||||
initialCapacity: 100
|
||||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 600
|
||||
- names: [ "fileTransformerSourcesByTenant" ]
|
||||
allowNullValues: true
|
||||
initialCapacity: 100
|
||||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 600
|
||||
- names: [ "evaluatorSourcesByTenant" ]
|
||||
allowNullValues: true
|
||||
initialCapacity: 100
|
||||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 600
|
||||
- names: [ "tokenExchangeKey" ]
|
||||
allowNullValues: true
|
||||
initialCapacity: 100
|
||||
|
@ -120,9 +132,15 @@ cache:
|
|||
fileTransformerConfigById:
|
||||
name: fileTransformerConfigById
|
||||
keyPattern: file_transformer_config_by_id_$transformerId$_$tenantCode$:v0
|
||||
evaluatorConfigById:
|
||||
name: evaluatorConfigById
|
||||
keyPattern: evaluator_config_by_id_$evaluatorId$_$tenantCode$:v0
|
||||
fileTransformerSourcesByTenant:
|
||||
name: fileTransformerSourcesByTenant
|
||||
keyPattern: ile_transformer_sources_by_tenant_$tenantCode$:v0
|
||||
evaluatorSourcesByTenant:
|
||||
name: evaluatorSourcesByTenant
|
||||
keyPattern: evaluator_sources_by_tenant_$tenantCode$:v0
|
||||
token-exchange-key:
|
||||
name: tokenExchangeKey
|
||||
keyPattern: resolve_$keyhash$:v0
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
evaluator:
|
||||
sources:
|
||||
- url: http://localhost:8084
|
||||
evaluatorId: fair
|
||||
issuer-url: ${IDP_ISSUER_URI_TOKEN}
|
||||
client-id: ${IDP_APIKEY_CLIENT_ID}
|
||||
client-secret: ${IDP_APIKEY_CLIENT_SECRET}
|
||||
scope: ${IDP_APIKEY_SCOPE}
|
||||
maxInMemorySizeInBytes: 6554000
|
|
@ -0,0 +1,2 @@
|
|||
evaluator:
|
||||
sources: []
|
|
@ -365,6 +365,17 @@ permissions:
|
|||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
EvaluateDescription:
|
||||
roles:
|
||||
- Admin
|
||||
- TenantAdmin
|
||||
plan:
|
||||
roles:
|
||||
- Owner
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
CloneDescription:
|
||||
roles:
|
||||
- Admin
|
||||
|
@ -652,6 +663,17 @@ permissions:
|
|||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
EvaluatePlan:
|
||||
roles:
|
||||
- Admin
|
||||
- TenantAdmin
|
||||
plan:
|
||||
roles:
|
||||
- Owner
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
ClonePlan:
|
||||
roles:
|
||||
- Admin
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
"cookieconsent": "^3.1.1",
|
||||
"dragula": "^3.7.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"keycloak-angular": "^15.2.1",
|
||||
"keycloak-js": "^24.0.5",
|
||||
"keycloak-angular": "^16.0.1",
|
||||
"keycloak-js": "^25.0.0",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.45",
|
||||
"ng-dialog-animation": "^9.0.4",
|
||||
|
@ -8856,23 +8856,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/keycloak-angular": {
|
||||
"version": "15.2.1",
|
||||
"resolved": "https://registry.npmjs.org/keycloak-angular/-/keycloak-angular-15.2.1.tgz",
|
||||
"integrity": "sha512-7w8bkJQ9OBtBJt5eNfqnRG2IL9btvp8Stf2fpVipSE1C/qtd5UQ31skx735PMPgMTUFsdz/0VA32Gmsng54+Xg==",
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/keycloak-angular/-/keycloak-angular-16.0.1.tgz",
|
||||
"integrity": "sha512-ytkL32R/tfHEyZ3txQtgH1y0WofW/D36zTbo2agDCYUtZETq0wAQ3E/4bVDUAr6ZKwotgAnIyOORfErnvDkXng==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^17",
|
||||
"@angular/core": "^17",
|
||||
"@angular/router": "^17",
|
||||
"keycloak-js": "^18 || ^19 || ^20 || ^21 || ^22 || ^23 || ^24"
|
||||
"@angular/common": "^18",
|
||||
"@angular/core": "^18",
|
||||
"@angular/router": "^18",
|
||||
"keycloak-js": "^18 || ^19 || ^20 || ^21 || ^22 || ^23 || ^24 || ^25"
|
||||
}
|
||||
},
|
||||
"node_modules/keycloak-js": {
|
||||
"version": "24.0.5",
|
||||
"resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-24.0.5.tgz",
|
||||
"integrity": "sha512-VQOSn3j13DPB6OuavKAq+sRjDERhIKrXgBzekoHRstifPuyULILguugX6yxRUYFSpn3OMYUXmSX++tkdCupOjA==",
|
||||
"version": "25.0.6",
|
||||
"resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-25.0.6.tgz",
|
||||
"integrity": "sha512-Km+dc+XfNvY6a4az5jcxTK0zPk52ns9mAxLrHj7lF3V+riVYvQujfHmhayltJDjEpSOJ4C8a57LFNNKnNnRP2g==",
|
||||
"dependencies": {
|
||||
"js-sha256": "^0.11.0",
|
||||
"jwt-decode": "^4.0.0"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
export enum EvaluatorEntityType {
|
||||
Plan = 0,
|
||||
Description = 1
|
||||
}
|
|
@ -84,6 +84,7 @@ export enum AppPermission {
|
|||
AssignPlanUsers = "AssignPlanUsers",
|
||||
InvitePlanUsers = "InvitePlanUsers",
|
||||
AnnotatePlan = "AnnotatePlan",
|
||||
EvaluatePlan = "EvaluatePlan",
|
||||
|
||||
//PlanStatus
|
||||
BrowsePlanStatus = "BrowsePlanStatus",
|
||||
|
@ -121,6 +122,7 @@ export enum AppPermission {
|
|||
DeleteDescription = "DeleteDescription",
|
||||
CloneDescription = "CloneDescription",
|
||||
ExportDescription = "ExportDescription",
|
||||
EvaluateDescription = "EvaluateDescription",
|
||||
|
||||
//DescriptionTag
|
||||
BrowseDescriptionTag = "BrowseDescriptionTag",
|
||||
|
|
|
@ -52,6 +52,7 @@ import { PlanStatusService } from './services/plan/plan-status.service';
|
|||
import { DescriptionStatusService } from './services/description-status/description-status.service';
|
||||
import { PlanWorkflowService } from './services/plan/plan-workflow.service';
|
||||
import { DescriptionWorkflowService } from './services/description-workflow/description-workflow.service';
|
||||
import { EvaluatorHttpService } from './services/evaluator/evaluator.http.service';
|
||||
//
|
||||
//
|
||||
// This is shared module that provides all the services. Its imported only once on the AppModule.
|
||||
|
@ -112,6 +113,7 @@ export class CoreServiceModule {
|
|||
CanDeactivateGuard,
|
||||
FileTransformerService,
|
||||
FileTransformerHttpService,
|
||||
EvaluatorHttpService,
|
||||
SemanticsService,
|
||||
PrefillingSourceService,
|
||||
VisibilityRulesService,
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { RankType } from "./rank-type";
|
||||
import { EvaluatorEntityType } from "@app/core/common/enum/evaluator-entity-type";
|
||||
import { RankConfig } from "./rank-config";
|
||||
|
||||
export class EvaluatorConfiguration{
|
||||
evaluatorId: string;
|
||||
rankType: RankType[];
|
||||
evaluatorEntityTypes: EvaluatorEntityType[];
|
||||
rankConfig: RankConfig[];
|
||||
hasLogo: boolean;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { EvaluatorEntityType } from "@app/core/common/enum/evaluator-entity-type";
|
||||
import { RankType } from "./rank-type";
|
||||
import { SelectionConfiguration } from "./evaluator-selection";
|
||||
import { ValueRangeConfiguration } from "./evaluator-value-range";
|
||||
|
||||
export interface EvaluatorFormat {
|
||||
rankType: RankType[];
|
||||
selectionConfiguration: SelectionConfiguration;
|
||||
valueRangeConfiguration: ValueRangeConfiguration;
|
||||
evaluatorId: string;
|
||||
entityTypes: EvaluatorEntityType[];
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export enum NumberType {
|
||||
Decimal = 0,
|
||||
Integer = 1
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export class RankModel {
|
||||
rank: number;
|
||||
details: string;
|
||||
messages: { [key: string]: string };
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { ValueSet } from "./evaluator-value-set";
|
||||
|
||||
export class SelectionConfiguration {
|
||||
valueSetList: ValueSet[];
|
||||
|
||||
constructor(valueSetList: ValueSet[]) {
|
||||
this.valueSetList = valueSetList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export enum SuccessStatus {
|
||||
Fail = 0,
|
||||
Pass = 1
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { NumberType } from "./evaluator-number-type.model";
|
||||
|
||||
export class ValueRangeConfiguration {
|
||||
numberType: NumberType;
|
||||
min: number;
|
||||
max: number;
|
||||
minPassValue: number;
|
||||
|
||||
constructor(numberType: NumberType, min: number, max: number, minPassValue: number) {
|
||||
this.numberType = numberType;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.minPassValue = minPassValue;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import { SuccessStatus } from "./evaluator-success-status.model";
|
||||
|
||||
export class ValueSet {
|
||||
key: number;
|
||||
successStatus: SuccessStatus;
|
||||
|
||||
constructor(key: number, successStatus: SuccessStatus) {
|
||||
this.key = key;
|
||||
this.successStatus = successStatus;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { RankType } from "./rank-type";
|
||||
import { ValueRangeConfiguration } from "./evaluator-value-range";
|
||||
import { SelectionConfiguration } from "./evaluator-selection";
|
||||
|
||||
export class RankConfig{
|
||||
rankType: RankType;
|
||||
valueRangeConfiguration?: ValueRangeConfiguration;
|
||||
selectionConfiguration?: SelectionConfiguration;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export enum RankType {
|
||||
ValueRange = 0,
|
||||
Selection = 1
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BaseService } from '@common/base/base.service';
|
||||
import { Guid } from '@common/types/guid';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { ConfigurationService } from '../configuration/configuration.service';
|
||||
import { BaseHttpV2Service } from '../http/base-http-v2.service';
|
||||
import { EvaluatorFormat } from '@app/core/model/evaluator/evaluator-format.model';
|
||||
import { RankModel } from '@app/core/model/evaluator/evaluator-plan-model.model';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class EvaluatorHttpService extends BaseService {
|
||||
|
||||
private headers = new HttpHeaders();
|
||||
|
||||
constructor(
|
||||
private http: BaseHttpV2Service,
|
||||
private configurationService: ConfigurationService
|
||||
) { super(); }
|
||||
|
||||
private get apiBase(): string { return `${this.configurationService.server}evaluator`; }
|
||||
|
||||
getAvailableConfigurations(): Observable<EvaluatorFormat[]> {
|
||||
const url = `${this.apiBase}/available`;
|
||||
return this.http.get<EvaluatorFormat[]>(url).pipe(catchError((error: any) => throwError(error)));
|
||||
}
|
||||
|
||||
rankPlan(id: Guid, evaluatorId: string, format: string): Observable<RankModel> {
|
||||
const url = `${this.apiBase}/rank-plan`;
|
||||
return this.http.post<RankModel>(url, {id: id, evaluatorId: evaluatorId, format: format}, {responseType: 'json', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
|
||||
}
|
||||
|
||||
rankDescription(id: Guid, evaluatorId: string, format: string): Observable<RankModel> {
|
||||
const url = `${this.apiBase}/rank-description`;
|
||||
return this.http.post<RankModel>(url, {id: id, evaluatorId: evaluatorId, format: format}, {responseType: 'json', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
|
||||
}
|
||||
|
||||
getLogo(evaluatorId: string): Observable<string>{
|
||||
const url = `${this.apiBase}/${evaluatorId}/logo`;
|
||||
return this.http.get<string>(url).pipe(catchError((error: any) => throwError(error)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
import { Component, EventEmitter, Input, OnInit, Output, Injectable } from '@angular/core';
|
||||
import { BaseService } from '@common/base/base.service';
|
||||
import { catchError, takeUntil } from 'rxjs/operators';
|
||||
import { EvaluatorHttpService } from './evaluator.http.service';
|
||||
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||
import { AuthService } from '../auth/auth.service';
|
||||
import { EvaluatorEntityType } from '@app/core/common/enum/evaluator-entity-type';
|
||||
import { EvaluatorConfiguration } from '@app/core/model/evaluator/evaluator-configuration';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Guid } from '@common/types/guid';
|
||||
import {
|
||||
SnackBarNotificationLevel,
|
||||
UiNotificationService
|
||||
} from '@app/core/services/notification/ui-notification-service';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { tap, share } from 'rxjs/operators';
|
||||
import { RankModel } from '@app/core/model/evaluator/evaluator-plan-model.model';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class EvaluatorService extends BaseService {
|
||||
|
||||
constructor(
|
||||
private evaluatorHttpService: EvaluatorHttpService,
|
||||
private authentication: AuthService,
|
||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||
private language: TranslateService,
|
||||
private uiNotificationService: UiNotificationService,
|
||||
) { super(); }
|
||||
|
||||
private _initialized: boolean = false;
|
||||
private _loading: boolean = false;
|
||||
|
||||
private _availableEvaluators: EvaluatorConfiguration[] = [];
|
||||
|
||||
get availableEvaluators(): EvaluatorConfiguration[] {
|
||||
if (!this.authentication.currentAccountIsAuthenticated()) {
|
||||
return [];
|
||||
}
|
||||
if (!this._initialized && !this._loading) this.init(); // if not initialized and loading calls init to initialize the evaluators.
|
||||
return this._availableEvaluators;
|
||||
}
|
||||
|
||||
public availableEvaluatorsFor(entityType: EvaluatorEntityType) {
|
||||
// Filter evaluators by entity type
|
||||
// The fetch logo config should be here.
|
||||
if (this.availableEvaluators) {
|
||||
const filteredEvaluators = this.availableEvaluators.filter(x => {
|
||||
return x.evaluatorEntityTypes && x.evaluatorEntityTypes.includes(entityType);
|
||||
});
|
||||
|
||||
return filteredEvaluators;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
init() {
|
||||
this._loading = true;
|
||||
this.evaluatorHttpService.getAvailableConfigurations()
|
||||
.pipe(takeUntil(this._destroyed), catchError((error) => {
|
||||
this._loading = false;
|
||||
this._initialized = true;
|
||||
this.httpErrorHandlingService.handleBackedRequestError(error);
|
||||
return [];
|
||||
}))
|
||||
.subscribe(items => {
|
||||
this._availableEvaluators = items;
|
||||
this._loading = false;
|
||||
this._initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
rankPlan(id: Guid, evaluatorId: string, format: string, isPublic: boolean = false): Observable<RankModel> {
|
||||
this._loading = true;
|
||||
|
||||
return this.evaluatorHttpService.rankPlan(id, evaluatorId, format).pipe(
|
||||
tap({
|
||||
next: (doi) => {
|
||||
this.onCallbackSuccess();
|
||||
},
|
||||
error: (error) => {
|
||||
this.onCallbackError(error);
|
||||
// Ensure loading state is turned off in case of error
|
||||
this._loading = false;
|
||||
},
|
||||
complete: () => {
|
||||
this._loading = false;
|
||||
}
|
||||
}),
|
||||
catchError((error) => {
|
||||
// Ensure loading state is turned off in case of error
|
||||
this._loading = false;
|
||||
return throwError(error);
|
||||
}),
|
||||
share()
|
||||
);
|
||||
}
|
||||
|
||||
rankDescription(id: Guid, evaluatorId: string, format: string, isPublic: boolean = false): Observable<RankModel> {
|
||||
this._loading = true;
|
||||
return this.evaluatorHttpService.rankDescription(id, evaluatorId, format)
|
||||
.pipe(
|
||||
takeUntil(this._destroyed),
|
||||
tap(response => {
|
||||
this._loading = false;
|
||||
this.onCallbackSuccess();
|
||||
}),
|
||||
catchError(error => {
|
||||
this._loading = false;
|
||||
this.onCallbackError(error);
|
||||
return throwError(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getLogo(evaluatorId: string): Observable<string> {
|
||||
return this.evaluatorHttpService.getLogo(evaluatorId).pipe(
|
||||
catchError((error) => {
|
||||
this.httpErrorHandlingService.handleBackedRequestError(error);
|
||||
return throwError(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
onCallbackSuccess(): void {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('PLAN-EDITOR.SNACK-BAR.SUCCESSFUL-EVALUATION'), SnackBarNotificationLevel.Success);
|
||||
}
|
||||
|
||||
onCallbackError(error) {
|
||||
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('PLAN-EDITOR.SNACK-BAR.UNSUCCESSFUL-EVALUATION'), SnackBarNotificationLevel.Error);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ import { FormattingModule } from '@app/core/formatting.module';
|
|||
import { DescriptionRoutingModule, PublicDescriptionRoutingModule } from '@app/ui/description/description.routing';
|
||||
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
import { EvaluateDescriptionDialogModule } from './evaluate-description-dialog/evaluate-description-dialog.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -24,6 +25,7 @@ export class DescriptionModule { }
|
|||
CommonFormsModule,
|
||||
FormattingModule,
|
||||
PublicDescriptionRoutingModule,
|
||||
EvaluateDescriptionDialogModule,
|
||||
],
|
||||
declarations: [
|
||||
],
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<h1 mat-dialog-title>{{ 'DESCRIPTION-EVALUATE-DIALOG.HEADER' | translate }}</h1>
|
||||
<div mat-dialog-content>
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{'DESCRIPTION-EVALUATE-DIALOG.DETAILS-SUB-HEADER' | translate}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div *ngIf="data.rankData" class="dialog-content">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>{{'DESCRIPTION-EVALUATE-DIALOG.RANK-BODY' | translate}}</mat-label>
|
||||
<input matInput [value]="data.rankData.body.rank" disabled>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>{{'DESCRIPTION-EVALUATE-DIALOG.DETAILS-BODY' | translate}}</mat-label>
|
||||
<textarea matInput [value]="data.rankData.body.details" rows="4" disabled></textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="data.rankData.body.messages">
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{'DESCRIPTION-EVALUATE-DIALOG.MESSAGES-BODY' | translate}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<ul>
|
||||
<li *ngFor="let entry of data.rankData.body.messages | keyvalue">
|
||||
<strong>{{ entry.key }}:</strong> {{ entry.value }}
|
||||
</li>
|
||||
</ul>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
.dialog-content {
|
||||
display: flex;
|
||||
flex-direction: column; /* Stack form fields vertically */
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
margin-bottom: 16px; /* Space between fields */
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EvaluateDescriptionDialogComponent } from './evaluate-description-dialog.component';
|
||||
|
||||
describe('EvaluateDescriptionDialogComponent', () => {
|
||||
let component: EvaluateDescriptionDialogComponent;
|
||||
let fixture: ComponentFixture<EvaluateDescriptionDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [EvaluateDescriptionDialogComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(EvaluateDescriptionDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { RankModel } from '@app/core/model/evaluator/evaluator-plan-model.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-evaluate-description-dialog',
|
||||
templateUrl: './evaluate-description-dialog.component.html',
|
||||
styleUrl: './evaluate-description-dialog.component.scss'
|
||||
})
|
||||
export class EvaluateDescriptionDialogComponent {
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<EvaluateDescriptionDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { rankData: RankModel }
|
||||
) { }
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { EvaluateDescriptionDialogComponent } from './evaluate-description-dialog.component';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
NgIf,
|
||||
CommonUiModule
|
||||
],
|
||||
declarations: [EvaluateDescriptionDialogComponent],
|
||||
exports: [EvaluateDescriptionDialogComponent]
|
||||
})
|
||||
export class EvaluateDescriptionDialogModule { }
|
|
@ -175,6 +175,28 @@
|
|||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="evaluatorService.availableEvaluatorsFor(evaluatorEntityTypeEnum.Description).length > 0">
|
||||
<div class="row mb-3 align-items-center">
|
||||
<div class="col-auto pr-0">
|
||||
<button mat-mini-fab class="frame-btn" [matMenuTriggerFor]="rankMenu">
|
||||
<mat-icon class="mat-mini-fab-icon">open_in_new</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto pl-0">
|
||||
<p class="mb-0 mr-0 pl-2 frame-txt" [matMenuTriggerFor]="rankMenu">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.EVALUATE' | translate }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<mat-menu #rankMenu="matMenu" xPosition="before">
|
||||
<button mat-menu-item *ngFor='let evaluator of evaluatorService.availableEvaluatorsFor(evaluatorEntityTypeEnum.Description)'
|
||||
(click)="onEvaluateDescription(description.id, evaluator.evaluatorId, evaluator.format, isPublicView)">
|
||||
<span class="evaluator-id pr-2">{{ (evaluator.evaluatorId?.toUpperCase()) | translate }}</span>
|
||||
<img *ngIf="evaluator.hasLogo" class="logo" [src]="logos.get(evaluator.evaluatorId)">
|
||||
<img *ngIf="!evaluator.hasLogo" class="logo" src="assets/images/repository-placeholder.png">
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #exportMenu="matMenu" xPosition="before">
|
||||
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description)' (click)="fileTransformerService.exportDescription(description.id, fileTransformer.repositoryId, fileTransformer.format, isPublicView)">
|
||||
<i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
|
||||
|
|
|
@ -273,4 +273,9 @@
|
|||
}
|
||||
.deleted-item {
|
||||
color: #cf1407;
|
||||
}
|
||||
.logo {
|
||||
margin-right: 16px;
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { EvaluateDescriptionDialogComponent } from './../evaluate-description-dialog/evaluate-description-dialog.component';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { UntypedFormBuilder, Validators } from '@angular/forms';
|
||||
|
@ -44,6 +45,12 @@ import { map, takeUntil } from 'rxjs/operators';
|
|||
import { nameof } from 'ts-simple-nameof';
|
||||
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
|
||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||
import { EvaluatorService } from '@app/core/services/evaluator/evaluator.service';
|
||||
import { EvaluatorEntityType } from '@app/core/common/enum/evaluator-entity-type';
|
||||
import { SafeResourceUrl } from '@angular/platform-browser';
|
||||
import { LoggingService } from '@app/core/services/logging/logging-service';
|
||||
import { RankModel } from '@app/core/model/evaluator/evaluator-plan-model.model';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -66,6 +73,8 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
planStatusEnum = PlanStatusEnum;
|
||||
planUserRoleEnum = PlanUserRole;
|
||||
fileTransformerEntityTypeEnum = FileTransformerEntityType;
|
||||
evaluatorEntityTypeEnum = EvaluatorEntityType;
|
||||
logos: Map<string, SafeResourceUrl> = new Map<string, SafeResourceUrl>();
|
||||
|
||||
canEdit = false;
|
||||
canCopy = false;
|
||||
|
@ -73,6 +82,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
canFinalize = false;
|
||||
canAnnotate = false;
|
||||
canInvitePlanUsers = false;
|
||||
canEvaluate = false;
|
||||
canAssignPlanUsers(): boolean {
|
||||
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
||||
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
||||
|
@ -106,6 +116,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
private breadcrumbService: BreadcrumbService,
|
||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||
private userService: UserService,
|
||||
private evaluatorService: EvaluatorService,
|
||||
private logger: LoggingService,
|
||||
private sanitizer: DomSanitizer,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -118,6 +131,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
this.canCopy = false;
|
||||
this.canFinalize = false;
|
||||
this.canInvitePlanUsers = false;
|
||||
this.canEvaluate = false;
|
||||
// Gets description data using parameter id
|
||||
this.route.params
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
|
@ -155,6 +169,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
this.canInvitePlanUsers = this.isActive && (this.authService.hasPermission(AppPermission.InvitePlanUsers) ||
|
||||
this.description.authorizationFlags?.some(x => x === AppPermission.InvitePlanUsers)) && this.description.belongsToCurrentTenant != false;
|
||||
|
||||
this.canEvaluate = this.isActive && (this.authService.hasPermission(AppPermission.EvaluateDescription) ||
|
||||
this.description.authorizationFlags?.some(x => x === AppPermission.EvaluateDescription)) && this.description.belongsToCurrentTenant != false;
|
||||
|
||||
},
|
||||
error: (error: any) => {
|
||||
this.httpErrorHandlingService.handleBackedRequestError(error);
|
||||
|
@ -216,6 +233,52 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
return this.language.instant('DESCRIPTION-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
|
||||
}
|
||||
|
||||
// onEvaluateDescription(planId: Guid, evaluatorId: string, format: string, isPublicView: boolean) {
|
||||
// this.evaluatorService.rankDescription(planId, evaluatorId, format).subscribe(
|
||||
// response => {
|
||||
// const dialogRef = this.dialog.open(EvaluateDescriptionDialogComponent, {
|
||||
// data: { rankData: response }
|
||||
// });
|
||||
|
||||
// dialogRef.afterClosed().subscribe(result => {
|
||||
// this.logger.debug("Dialog closed with result: ", result);
|
||||
// });
|
||||
// },
|
||||
// error => {
|
||||
// this.logger.error("Error ranking description: ", error);
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
onEvaluateDescription(planId: Guid, evaluatorId: string, format: string, isPublicView: boolean) {
|
||||
this.evaluatorService.rankDescription(planId, evaluatorId, format).subscribe(
|
||||
(response: RankModel) => {
|
||||
this.evaluatorService.getLogo(evaluatorId).subscribe(
|
||||
(logo: string) => {
|
||||
|
||||
this.logos.set(evaluatorId,this.sanitizer.bypassSecurityTrustResourceUrl('data:image/png;base64, ' + logo));
|
||||
|
||||
const dialogRef = this.dialog.open(EvaluateDescriptionDialogComponent, {
|
||||
data: {
|
||||
rankData: response,
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
this.logger.debug("Dialog closed with result:", result);
|
||||
});
|
||||
},
|
||||
error => {
|
||||
this.logger.error("Error fetching evaluator logo:", error);
|
||||
}
|
||||
);
|
||||
},
|
||||
error => {
|
||||
this.logger.error("Error ranking description:", error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
checkLockStatus(id: Guid) {
|
||||
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe({
|
||||
|
@ -522,6 +585,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
[nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'),
|
||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.InvitePlanUsers].join('.'),
|
||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.AnnotateDescription].join('.'),
|
||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.EvaluateDescription].join('.'),
|
||||
|
||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
|
||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),
|
||||
|
|
|
@ -235,6 +235,29 @@
|
|||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="canEvaluatePlan() && evaluatorService.availableEvaluatorsFor(evaluatorEntityTypeEnum.Plan).length > 0">
|
||||
<div class="row mb-3 align-items-center">
|
||||
<div class="col-auto pr-0">
|
||||
<button mat-mini-fab class="frame-btn" [matMenuTriggerFor]="rankMenu">
|
||||
<mat-icon class="mat-mini-fab-icon">open_in_new</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto pl-0">
|
||||
<p class="mb-0 pl-2 frame-txt" [matMenuTriggerFor]="rankMenu">{{ 'PLAN-OVERVIEW.ACTIONS.EVALUATE' | translate }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<mat-menu #rankMenu="matMenu" xPosition="before">
|
||||
<button mat-menu-item *ngFor='let evaluator of evaluatorService.availableEvaluatorsFor(evaluatorEntityTypeEnum.Plan)'
|
||||
(click)="onEvaluatePlan(plan.id, evaluator.evaluatorId, evaluator.format, isPublicView)">
|
||||
<span class="evaluator-id pr-2">{{ (evaluator.evaluatorId?.toUpperCase()) | translate }}</span>
|
||||
<img *ngIf="evaluator.hasLogo" class="logo" [src]="logos.get(evaluator.evaluatorId)">
|
||||
<img *ngIf="!evaluator.hasLogo" class="logo" src="assets/images/repository-placeholder.png">
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #exportMenu="matMenu" xPosition="before">
|
||||
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan)' (click)="fileTransformerService.exportPlan(plan.id, fileTransformer.repositoryId, fileTransformer.format, isPublicView)">
|
||||
<i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
|
||||
|
|
|
@ -299,4 +299,10 @@
|
|||
|
||||
.deleted-item {
|
||||
color: #cf1407;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin-right: 16px;
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
}
|
|
@ -50,6 +50,13 @@ import { PlanFinalizeDialogComponent, PlanFinalizeDialogOutput } from '../plan-f
|
|||
import { PlanInvitationDialogComponent } from '../invitation/dialog/plan-invitation-dialog.component';
|
||||
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
|
||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||
import { EvaluatorService } from '@app/core/services/evaluator/evaluator.service';
|
||||
import { EvaluatorEntityType } from '@app/core/common/enum/evaluator-entity-type';
|
||||
import { PlanEvaluateDialogComponent } from '../plan-evaluate-dialog/plan-evaluate-dialog.component';
|
||||
import { RankModel } from '@app/core/model/evaluator/evaluator-plan-model.model';
|
||||
import { SafeResourceUrl } from '@angular/platform-browser';
|
||||
import { LoggingService } from '@app/core/services/logging/logging-service';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-plan-overview',
|
||||
|
@ -69,6 +76,8 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
|||
textMessage: any;
|
||||
selectedModel: EntityDoi;
|
||||
fileTransformerEntityTypeEnum = FileTransformerEntityType;
|
||||
evaluatorEntityTypeEnum = EvaluatorEntityType
|
||||
logos: Map<string, SafeResourceUrl> = new Map<string, SafeResourceUrl>();
|
||||
|
||||
@ViewChild('doi')
|
||||
doi: ElementRef;
|
||||
|
@ -107,6 +116,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
|||
private breadcrumbService: BreadcrumbService,
|
||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||
private userService: UserService,
|
||||
private evaluatorService: EvaluatorService,
|
||||
private logger: LoggingService,
|
||||
private sanitizer: DomSanitizer,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -298,6 +310,60 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
|||
return (authorizationFlags?.some(x => x === AppPermission.ExportPlan) || this.authentication.hasPermission(AppPermission.ExportPlan));
|
||||
}
|
||||
|
||||
canEvaluatePlan(): boolean {
|
||||
const authorizationFlags = !this.isPublicView ? (this.plan as Plan).authorizationFlags : [];
|
||||
return (authorizationFlags?.some(x => x === AppPermission.EvaluatePlan) || this.authentication.hasPermission(AppPermission.EvaluatePlan));
|
||||
}
|
||||
|
||||
// onEvaluatePlan(planId: Guid, evaluatorId: string, format: string, isPublicView: boolean) {
|
||||
// this.evaluatorService.rankPlan(planId, evaluatorId, format).subscribe(
|
||||
// (response: RankModel) => {
|
||||
|
||||
// const dialogRef = this.dialog.open(PlanEvaluateDialogComponent, {
|
||||
// data: { rankData: response }
|
||||
// });
|
||||
|
||||
// dialogRef.afterClosed().subscribe(result => {
|
||||
// this.logger.debug("Dialog closed with result:", result);
|
||||
// });
|
||||
// },
|
||||
// error => {
|
||||
|
||||
// this.logger.error("Error ranking plan:", error);
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
onEvaluatePlan(planId: Guid, evaluatorId: string, format: string, isPublicView: boolean) {
|
||||
this.evaluatorService.rankPlan(planId, evaluatorId, format).subscribe(
|
||||
(response: RankModel) => {
|
||||
this.evaluatorService.getLogo(evaluatorId).subscribe(
|
||||
(logo: string) => {
|
||||
|
||||
this.logos.set(evaluatorId,this.sanitizer.bypassSecurityTrustResourceUrl('data:image/png;base64, ' + logo));
|
||||
|
||||
const dialogRef = this.dialog.open(PlanEvaluateDialogComponent, {
|
||||
data: {
|
||||
rankData: response,
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
this.logger.debug("Dialog closed with result:", result);
|
||||
});
|
||||
},
|
||||
error => {
|
||||
this.logger.error("Error fetching evaluator logo:", error);
|
||||
}
|
||||
);
|
||||
},
|
||||
error => {
|
||||
this.logger.error("Error ranking plan:", error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
canInvitePlanUsers(): boolean {
|
||||
const authorizationFlags = !this.isPublicView ? (this.plan as Plan).authorizationFlags : [];
|
||||
return (
|
||||
|
@ -650,6 +716,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
|||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.ClonePlan].join('.'),
|
||||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.FinalizePlan].join('.'),
|
||||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.ExportPlan].join('.'),
|
||||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.EvaluatePlan].join('.'),
|
||||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.InvitePlanUsers].join('.'),
|
||||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.AssignPlanUsers].join('.'),
|
||||
[nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<h1 mat-dialog-title>{{ 'PLAN-EVALUATE-DIALOG.HEADER' | translate }}</h1>
|
||||
<div mat-dialog-content>
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{'PLAN-EVALUATE-DIALOG.DETAILS-SUB-HEADER' | translate}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div *ngIf="data.rankData" class="dialog-content">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>{{'PLAN-EVALUATE-DIALOG.RANK-BODY' | translate}}</mat-label>
|
||||
<input matInput [value]="data.rankData.body.rank" disabled>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>{{'PLAN-EVALUATE-DIALOG.DETAILS-BODY' | translate}}</mat-label>
|
||||
<textarea matInput [value]="data.rankData.body.details" rows="4" disabled></textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="data.rankData.body.messages">
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{'PLAN-EVALUATE-DIALOG.MESSAGES-BODY' | translate}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<ul>
|
||||
<li *ngFor="let entry of data.rankData.body.messages | keyvalue">
|
||||
<strong>{{ entry.key }}:</strong> {{ entry.value }}
|
||||
</li>
|
||||
</ul>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
.dialog-content {
|
||||
display: flex;
|
||||
flex-direction: column; /* Stack form fields vertically */
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
margin-bottom: 16px; /* Space between fields */
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PlanEvaluateDialogComponent } from './plan-evaluate-dialog.component';
|
||||
|
||||
describe('PlanEvaluateDialogComponent', () => {
|
||||
let component: PlanEvaluateDialogComponent;
|
||||
let fixture: ComponentFixture<PlanEvaluateDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PlanEvaluateDialogComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PlanEvaluateDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { RankModel } from '@app/core/model/evaluator/evaluator-plan-model.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-plan-evaluate-dialog',
|
||||
templateUrl: './plan-evaluate-dialog.component.html',
|
||||
styleUrl: './plan-evaluate-dialog.component.scss'
|
||||
})
|
||||
export class PlanEvaluateDialogComponent {
|
||||
// Injecting the dialog data into the component
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<PlanEvaluateDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { rankData: RankModel },
|
||||
) { }
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { PlanEvaluateDialogComponent } from './plan-evaluate-dialog.component';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
NgIf,
|
||||
CommonUiModule,
|
||||
],
|
||||
declarations: [PlanEvaluateDialogComponent],
|
||||
exports: [PlanEvaluateDialogComponent]
|
||||
})
|
||||
export class EvaluatePlanDialogModule { }
|
|
@ -4,6 +4,7 @@ import { PlanRoutingModule, PublicPlanRoutingModule } from '@app/ui/plan/plan.ro
|
|||
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
import { InvitationAcceptedComponent } from './invitation/accepted/plan-invitation-accepted.component';
|
||||
import { EvaluatePlanDialogModule } from './plan-evaluate-dialog/plan-evaluate-dialog.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -11,6 +12,7 @@ import { InvitationAcceptedComponent } from './invitation/accepted/plan-invitati
|
|||
CommonFormsModule,
|
||||
FormattingModule,
|
||||
PlanRoutingModule,
|
||||
EvaluatePlanDialogModule,
|
||||
],
|
||||
declarations: [
|
||||
InvitationAcceptedComponent
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
"defaultBlueprintId": "86635178-36a6-484f-9057-a934e4eeecd5",
|
||||
"keycloak": {
|
||||
"enabled": true,
|
||||
"address": null,
|
||||
"realm": null,
|
||||
"address": "http://dev03.local.cite.gr:60201",
|
||||
"realm": "dmp-development",
|
||||
"flow": "standard",
|
||||
"clientId": null,
|
||||
"clientId": "dmp_webapp",
|
||||
"silentCheckSsoRedirectUri": "http://localhost:4200/assets/silent-check-sso.html",
|
||||
"scope": "openid profile email address phone dmp_web dmp_notification identity_provider",
|
||||
"clientSecret": null,
|
||||
|
@ -22,11 +22,11 @@
|
|||
"inAppNotificationsCountInterval": "30",
|
||||
"notification_service": {
|
||||
"enabled": true,
|
||||
"address": "http://localhost:8086/api/"
|
||||
"address": "http://dev04.local.cite.gr:55330/api/notification/"
|
||||
},
|
||||
"annotation_service": {
|
||||
"enabled": true,
|
||||
"address": "http://localhost:8087/api/",
|
||||
"address": "http://dev04.local.cite.gr:55330/api/annotation/",
|
||||
"statusIcons": [
|
||||
{
|
||||
"internalStatus": "0",
|
||||
|
@ -70,7 +70,7 @@
|
|||
"name": "Default",
|
||||
"providerClass": "defaultIcon"
|
||||
},
|
||||
"authProviders": [
|
||||
"authProviders": [
|
||||
{
|
||||
"name": "google",
|
||||
"providerClass": "googleIcon",
|
||||
|
@ -99,14 +99,14 @@
|
|||
"externalUrl": "/splash/resources/co-branding.html",
|
||||
"accessLevel": "public"
|
||||
},
|
||||
{
|
||||
"title": "SIDE-BAR.SUPPORT",
|
||||
{
|
||||
"title": "SIDE-BAR.SUPPORT",
|
||||
"icon": "help",
|
||||
"routerPath": "/contact-support",
|
||||
"accessLevel": "authenticated"
|
||||
},
|
||||
{
|
||||
"title": "SIDE-BAR.SUPPORT",
|
||||
{
|
||||
"title": "SIDE-BAR.SUPPORT",
|
||||
"icon": "help",
|
||||
"externalUrl": "/splash/contact.html",
|
||||
"accessLevel": "unauthenticated"
|
||||
|
|
|
@ -190,6 +190,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -854,7 +857,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -996,7 +1000,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1933,7 +1938,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "DOIa ez da behar bezala sortu",
|
||||
"SUCCESSFUL-DOI": "DOIa ondo sortu da",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1951,6 +1958,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG":{
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG":{
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "DOI Erstellung fehlgeschlagen",
|
||||
"SUCCESSFUL-DOI": "DOI Erstellung erfolgreich",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG":{
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG":{
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -855,7 +858,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -997,7 +1001,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Unsuccessful DOI creation",
|
||||
"SUCCESSFUL-DOI": "Successful DOI creation",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION": "Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG":{
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG":{
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Fallo en la creación del DOI",
|
||||
"SUCCESSFUL-DOI": "Creación del DOI correcta",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Αποτυχία δημιουργίας Μονοσήμαντων Αναγνωριστικών Ψηφιακών Αντικειμένων (DOI)",
|
||||
"SUCCESSFUL-DOI": "Επιτυχία δημιουργίας Μονοσήμαντων Αναγνωριστικών Ψηφιακών Αντικειμένων (DOI)",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Neuspješno generiran DOI",
|
||||
"SUCCESSFUL-DOI": "Uspješno generiran DOI",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Nie udało się utworzyć DOI",
|
||||
"SUCCESSFUL-DOI": "Utworzono DOI",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Criação de DOI sem sucesso",
|
||||
"SUCCESSFUL-DOI": "Criação de DOI com sucesso",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Neúspešné vytvorenie DOI",
|
||||
"SUCCESSFUL-DOI": "Úspešné vytvorenie DOI",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Neuspešno registrovan DOI",
|
||||
"SUCCESSFUL-DOI": "Uspešno registrovan DOI",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
"JSON": "RDA JSON",
|
||||
"DOCX": "Document"
|
||||
},
|
||||
"EVALUATOR": {
|
||||
"FAIR": "FAIR Evaluator"
|
||||
},
|
||||
"LANGUAGES": {
|
||||
"en": "English",
|
||||
"gr": "Greek",
|
||||
|
@ -857,7 +860,8 @@
|
|||
"NEW-VERSION": "Start new version",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"UNDO-FINALIZATION-DIALOG": {
|
||||
"TITLE": "Undo Finalization?",
|
||||
|
@ -999,7 +1003,8 @@
|
|||
"EXPORT": "Export",
|
||||
"INVITE-SHORT": "Invite",
|
||||
"REMOVE-AUTHOR": "Remove",
|
||||
"PREVIEW": "Preview"
|
||||
"PREVIEW": "Preview",
|
||||
"EVALUATE": "Evaluate"
|
||||
},
|
||||
"COPY-DIALOG": {
|
||||
"COPY": "Copy",
|
||||
|
@ -1936,7 +1941,9 @@
|
|||
"SNACK-BAR": {
|
||||
"UNSUCCESSFUL-DOI": "Başarısız DOI oluşturma",
|
||||
"SUCCESSFUL-DOI": "Başarılı DOI oluşumu",
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added"
|
||||
"SUCCESSFUL-PLAN-CONTACT": "User added",
|
||||
"SUCCESSFUL-EVALUATION": "Successful evaluation",
|
||||
"UNSUCCESSFUL-EVALUATION":"Unsuccessful evaluation"
|
||||
},
|
||||
"DESCRIPTION-TEMPLATE-LIST": {
|
||||
"TITLE": "Available Description Templates",
|
||||
|
@ -1954,6 +1961,20 @@
|
|||
"MESSAGE": "Somebody else is modifying the Plan at this moment. You may view the Plan but you cannot make any changes."
|
||||
}
|
||||
},
|
||||
"PLAN-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"DESCRIPTION-EVALUATE-DIALOG": {
|
||||
"HEADER": "Ranking Information",
|
||||
"DETAILS-SUB-HEADER": "Details",
|
||||
"RANK-BODY": "Rank",
|
||||
"DETAILS-BODY": "Details",
|
||||
"MESSAGES-BODY": "Messages"
|
||||
},
|
||||
"REFERENCE-FIELD": {
|
||||
"COULD-NOT-FIND-MESSAGE": "Couldn't find it?",
|
||||
"ACTIONS": {
|
||||
|
|
Loading…
Reference in New Issue