Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-04-23 14:27:20 +03:00
commit da7397e811
40 changed files with 514 additions and 157 deletions

View File

@ -1,92 +0,0 @@
####################################### Build stage #######################################
FROM maven:3.9-eclipse-temurin-21-alpine
ARG MAVEN_ACCOUNT_USR
ARG MAVEN_ACCOUNT_PSW
ARG REVISION
ARG PROFILE
ARG ORACLE_URL
ARG ORACLE_TOKEN
ARG BUILD
ENV server_username=$MAVEN_ACCOUNT_USR
ENV server_password=$MAVEN_ACCOUNT_PSW
ARG CITE_MAVEN_REPO_URL
COPY /dmp-backend/pom.xml /build/
COPY /dmp-backend/core /build/core/
COPY /dmp-backend/web /build/web/
COPY /dmp-backend/settings.xml /root/.m2/settings.xml
RUN rm -f /build/web/src/main/resources/config/*-devel.yml
RUN rm -f /build/web/src/main/resources/logging/*.xml
COPY /notification-service/pom.xml /build-notification/
COPY /notification-service/core /build-notification/core/
COPY /notification-service/web /build-notification/web/
COPY /notification-service/settings.xml /root/.m2/settings.xml
RUN rm -f /build/notification-web/src/main/resources/config/app.env
RUN rm -f /build/notification-web/src/main/resources/config/*-devel.yml
RUN rm -f /build/notification-web/src/main/resources/logging/*.xml
RUN rm -f /build/notification-web/src/main/resources/certificates/*.crt
COPY /annotation-service/pom.xml /build-annotation/
COPY /annotation-service/annotation /build-notification/annotation/
COPY /annotation-service/annotation-web /build-notification/annotation-web/
COPY /annotation-service/settings.xml /root/.m2/settings.xml
RUN rm -f /build/annotation-web/src/main/resources/config/app.env
RUN rm -f /build/annotation-web/src/main/resources/config/*-devel.yml
RUN rm -f /build/annotation-web/src/main/resources/logging/*.xml
RUN rm -f /build/annotation-web/src/main/resources/certificates/*.crt
COPY oracle.local.cite.gr.crt $JAVA_HOME/conf/security
RUN cd "$JAVA_HOME"/conf/security && keytool -cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias oraclecert -file oracle.local.cite.gr.crt
WORKDIR /build/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Dsonar.projectKey=OpenDMP:backend-api -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP API'
WORKDIR /build-notification/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Dsonar.projectKey=OpenDMP:notification-api -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP Notification API'
WORKDIR /build-annotation/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Dsonar.projectKey=OpenDMP:annotation-api -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP Annotation API'
################################## frontend analysis ##########################################
FROM node:20
ARG ORACLE_URL
ARG ORACLE_TOKEN
ARG BUILD_VERSION
ENV ORACLE_URL=$ORACLE_URL
ENV ORACLE_TOKEN=$ORACLE_TOKEN
ENV BUILD_VERSION=$BUILD_VERSION
RUN apt-get -y update && apt-get install -y openjdk-11-jdk locales && apt-get clean
RUN mkdir -p /usr/share/man/man1/
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
locale-gen
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
COPY oracle.local.cite.gr.crt /usr/local/share/ca-certificates/oracle.local.cite.gr.crt
RUN update-ca-certificates
# copy the package.json to install dependencies
COPY /dmp-frontend/package.json ./
COPY /dmp-frontend/package-lock.json ./
# Install the dependencies and make the folder
RUN npm install sonar-scanner --save-dev
RUN npm install --legacy-peer-deps && mkdir /src && mv ./node_modules ./src
WORKDIR /src
COPY . .
RUN npm run sonar-scanner

View File

@ -0,0 +1,30 @@
####################################### Build stage #######################################
FROM maven:3.9-eclipse-temurin-21-alpine
ARG MAVEN_ACCOUNT_USR
ARG MAVEN_ACCOUNT_PSW
ARG REVISION
ARG PROFILE
ARG ORACLE_URL
ARG ORACLE_TOKEN
ENV server_username=$MAVEN_ACCOUNT_USR
ENV server_password=$MAVEN_ACCOUNT_PSW
ARG CITE_MAVEN_REPO_URL
COPY pom.xml /build/
COPY annotation /build/annotation/
COPY annotation-web /build/annotation-web/
COPY settings.xml /root/.m2/settings.xml
RUN rm -f /build/annotation-web/src/main/resources/config/app.env
RUN rm -f /build/annotation-web/src/main/resources/config/*-devel.yml
RUN rm -f /build/annotation-web/src/main/resources/logging/*.xml
RUN rm -f /build/annotation-web/src/main/resources/certificates/*.crt
COPY oracle.local.cite.gr.crt $JAVA_HOME/conf/security
RUN cd "$JAVA_HOME"/conf/security && keytool -cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias oraclecert -file oracle.local.cite.gr.crt
WORKDIR /build/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Dsonar.projectKey=OpenDMP:annotation-api -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP Annotation API'

View File

@ -0,0 +1,29 @@
####################################### Build stage #######################################
FROM maven:3.9-eclipse-temurin-21-alpine
ARG MAVEN_ACCOUNT_USR
ARG MAVEN_ACCOUNT_PSW
ARG REVISION
ARG PROFILE
ARG ORACLE_URL
ARG ORACLE_TOKEN
ENV server_username=$MAVEN_ACCOUNT_USR
ENV server_password=$MAVEN_ACCOUNT_PSW
ARG CITE_MAVEN_REPO_URL
COPY pom.xml /build/
COPY core /build/core/
COPY web /build/web/
COPY settings.xml /root/.m2/settings.xml
RUN rm -f /build/web/src/main/resources/config/*-devel.yml
RUN rm -f /build/web/src/main/resources/logging/*.xml
COPY oracle.local.cite.gr.crt $JAVA_HOME/conf/security
RUN cd "$JAVA_HOME"/conf/security && keytool -cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias oraclecert -file oracle.local.cite.gr.crt
WORKDIR /build/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Dsonar.projectKey=OpenDMP:backend-api -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP API'

View File

@ -6,6 +6,7 @@ import java.util.List;
public class DepositTenantConfigurationEntity { public class DepositTenantConfigurationEntity {
private List<DepositSourceEntity> sources; private List<DepositSourceEntity> sources;
private boolean disableSystemSources;
public List<DepositSourceEntity> getSources() { public List<DepositSourceEntity> getSources() {
return sources; return sources;
@ -14,4 +15,12 @@ public class DepositTenantConfigurationEntity {
public void setSources(List<DepositSourceEntity> sources) { public void setSources(List<DepositSourceEntity> sources) {
this.sources = sources; this.sources = sources;
} }
public boolean getDisableSystemSources() {
return disableSystemSources;
}
public void setDisableSystemSources(boolean disableSystemSources) {
this.disableSystemSources = disableSystemSources;
}
} }

View File

@ -7,6 +7,7 @@ import java.util.List;
public class FileTransformerTenantConfigurationEntity { public class FileTransformerTenantConfigurationEntity {
private List<FileTransformerSourceEntity> sources; private List<FileTransformerSourceEntity> sources;
private boolean disableSystemSources;
public List<FileTransformerSourceEntity> getSources() { public List<FileTransformerSourceEntity> getSources() {
return sources; return sources;
@ -15,4 +16,12 @@ public class FileTransformerTenantConfigurationEntity {
public void setSources(List<FileTransformerSourceEntity> sources) { public void setSources(List<FileTransformerSourceEntity> sources) {
this.sources = sources; this.sources = sources;
} }
public boolean getDisableSystemSources() {
return disableSystemSources;
}
public void setDisableSystemSources(boolean disableSystemSources) {
this.disableSystemSources = disableSystemSources;
}
} }

View File

@ -51,6 +51,7 @@ public class DepositTenantConfigurationBuilder extends BaseBuilder<DepositTenant
for (DepositTenantConfigurationEntity d : data) { for (DepositTenantConfigurationEntity d : data) {
DepositTenantConfiguration m = new DepositTenantConfiguration(); DepositTenantConfiguration m = new DepositTenantConfiguration();
if (!sourcesFields.isEmpty() && d.getSources() != null){ if (!sourcesFields.isEmpty() && d.getSources() != null){
if (fields.hasField(this.asIndexer(DepositTenantConfiguration._disableSystemSources))) m.setDisableSystemSources(d.getDisableSystemSources());
m.setSources(this.builderFactory.builder(DepositSourceBuilder.class).encrypted(true).authorize(this.authorize).build(sourcesFields, d.getSources())); m.setSources(this.builderFactory.builder(DepositSourceBuilder.class).encrypted(true).authorize(this.authorize).build(sourcesFields, d.getSources()));
} }
models.add(m); models.add(m);

View File

@ -51,6 +51,7 @@ public class FileTransformerTenantConfigurationBuilder extends BaseBuilder<FileT
for (FileTransformerTenantConfigurationEntity d : data) { for (FileTransformerTenantConfigurationEntity d : data) {
FileTransformerTenantConfiguration m = new FileTransformerTenantConfiguration(); FileTransformerTenantConfiguration m = new FileTransformerTenantConfiguration();
if (!sourcesFields.isEmpty() && d.getSources() != null){ if (!sourcesFields.isEmpty() && d.getSources() != null){
if (fields.hasField(this.asIndexer(FileTransformerTenantConfiguration._disableSystemSources))) m.setDisableSystemSources(d.getDisableSystemSources());
m.setSources(this.builderFactory.builder(FileTransformerSourceBuilder.class).encrypted(true).authorize(this.authorize).build(sourcesFields, d.getSources())); m.setSources(this.builderFactory.builder(FileTransformerSourceBuilder.class).encrypted(true).authorize(this.authorize).build(sourcesFields, d.getSources()));
} }
models.add(m); models.add(m);

View File

@ -20,6 +20,8 @@ import java.util.List;
public class DepositTenantConfigurationPersist { public class DepositTenantConfigurationPersist {
private List<DepositSourcePersist> sources; private List<DepositSourcePersist> sources;
public static final String _sources = "sources"; public static final String _sources = "sources";
private Boolean disableSystemSources;
public static final String _disableSystemSources = "disableSystemSources";
public List<DepositSourcePersist> getSources() { public List<DepositSourcePersist> getSources() {
return sources; return sources;
@ -29,6 +31,14 @@ public class DepositTenantConfigurationPersist {
this.sources = sources; this.sources = sources;
} }
public Boolean getDisableSystemSources() {
return disableSystemSources;
}
public void setDisableSystemSources(Boolean disableSystemSources) {
this.disableSystemSources = disableSystemSources;
}
@Component(DepositTenantConfigurationPersist.DepositTenantConfigurationPersistValidator.ValidatorName) @Component(DepositTenantConfigurationPersist.DepositTenantConfigurationPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class DepositTenantConfigurationPersistValidator extends BaseValidator<DepositTenantConfigurationPersist> { public static class DepositTenantConfigurationPersistValidator extends BaseValidator<DepositTenantConfigurationPersist> {
@ -54,6 +64,9 @@ public class DepositTenantConfigurationPersist {
@Override @Override
protected List<Specification> specifications(DepositTenantConfigurationPersist item) { protected List<Specification> specifications(DepositTenantConfigurationPersist item) {
return Arrays.asList( return Arrays.asList(
this.spec()
.must(() -> !this.isNull(item.getDisableSystemSources()))
.failOn(DepositTenantConfigurationPersist._disableSystemSources).failWith(messageSource.getMessage("Validation_Required", new Object[]{DepositTenantConfigurationPersist._disableSystemSources}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.must(() -> !this.isListNullOrEmpty(item.getSources())) .must(() -> !this.isListNullOrEmpty(item.getSources()))
.failOn(DepositTenantConfigurationPersist._sources).failWith(messageSource.getMessage("Validation_Required", new Object[]{DepositTenantConfigurationPersist._sources}, LocaleContextHolder.getLocale())), .failOn(DepositTenantConfigurationPersist._sources).failWith(messageSource.getMessage("Validation_Required", new Object[]{DepositTenantConfigurationPersist._sources}, LocaleContextHolder.getLocale())),

View File

@ -19,6 +19,8 @@ public class FileTransformerTenantConfigurationPersist {
private List<FileTransformerSourcePersist> sources; private List<FileTransformerSourcePersist> sources;
public static final String _sources = "sources"; public static final String _sources = "sources";
private Boolean disableSystemSources;
public static final String _disableSystemSources = "disableSystemSources";
public List<FileTransformerSourcePersist> getSources() { public List<FileTransformerSourcePersist> getSources() {
return sources; return sources;
@ -28,6 +30,14 @@ public class FileTransformerTenantConfigurationPersist {
this.sources = sources; this.sources = sources;
} }
public Boolean getDisableSystemSources() {
return disableSystemSources;
}
public void setDisableSystemSources(Boolean disableSystemSources) {
this.disableSystemSources = disableSystemSources;
}
@Component(FileTransformerTenantConfigurationPersist.FileTransformerTenantConfigurationPersistValidator.ValidatorName) @Component(FileTransformerTenantConfigurationPersist.FileTransformerTenantConfigurationPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class FileTransformerTenantConfigurationPersistValidator extends BaseValidator<FileTransformerTenantConfigurationPersist> { public static class FileTransformerTenantConfigurationPersistValidator extends BaseValidator<FileTransformerTenantConfigurationPersist> {
@ -53,6 +63,9 @@ public class FileTransformerTenantConfigurationPersist {
@Override @Override
protected List<Specification> specifications(FileTransformerTenantConfigurationPersist item) { protected List<Specification> specifications(FileTransformerTenantConfigurationPersist item) {
return Arrays.asList( return Arrays.asList(
this.spec()
.must(() -> !this.isNull(item.getDisableSystemSources()))
.failOn(FileTransformerTenantConfigurationPersist._disableSystemSources).failWith(messageSource.getMessage("Validation_Required", new Object[]{FileTransformerTenantConfigurationPersist._disableSystemSources}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.must(() -> !this.isListNullOrEmpty(item.getSources())) .must(() -> !this.isListNullOrEmpty(item.getSources()))
.failOn(FileTransformerTenantConfigurationPersist._sources).failWith(messageSource.getMessage("Validation_Required", new Object[]{FileTransformerTenantConfigurationPersist._sources}, LocaleContextHolder.getLocale())), .failOn(FileTransformerTenantConfigurationPersist._sources).failWith(messageSource.getMessage("Validation_Required", new Object[]{FileTransformerTenantConfigurationPersist._sources}, LocaleContextHolder.getLocale())),

View File

@ -8,6 +8,8 @@ import java.util.List;
public class DepositTenantConfiguration { public class DepositTenantConfiguration {
private List<DepositSource> sources; private List<DepositSource> sources;
public static final String _sources = "sources"; public static final String _sources = "sources";
private Boolean disableSystemSources;
public static final String _disableSystemSources = "disableSystemSources";
public List<DepositSource> getSources() { public List<DepositSource> getSources() {
return sources; return sources;
@ -16,4 +18,12 @@ public class DepositTenantConfiguration {
public void setSources(List<DepositSource> sources) { public void setSources(List<DepositSource> sources) {
this.sources = sources; this.sources = sources;
} }
public Boolean getDisableSystemSources() {
return disableSystemSources;
}
public void setDisableSystemSources(Boolean disableSystemSources) {
this.disableSystemSources = disableSystemSources;
}
} }

View File

@ -9,6 +9,8 @@ public class FileTransformerTenantConfiguration {
private List<FileTransformerSource> sources; private List<FileTransformerSource> sources;
public static final String _sources = "sources"; public static final String _sources = "sources";
private Boolean disableSystemSources;
public static final String _disableSystemSources = "disableSystemSources";
public List<FileTransformerSource> getSources() { public List<FileTransformerSource> getSources() {
return sources; return sources;
@ -17,4 +19,12 @@ public class FileTransformerTenantConfiguration {
public void setSources(List<FileTransformerSource> sources) { public void setSources(List<FileTransformerSource> sources) {
this.sources = sources; this.sources = sources;
} }
public Boolean getDisableSystemSources() {
return disableSystemSources;
}
public void setDisableSystemSources(Boolean disableSystemSources) {
this.disableSystemSources = disableSystemSources;
}
} }

View File

@ -128,7 +128,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
TenantConfigurationQuery tenantConfigurationQuery = this.queryFactory.query(TenantConfigurationQuery.class).excludedIds(data.getId()).isActive(IsActive.Active).types(data.getType()); TenantConfigurationQuery tenantConfigurationQuery = this.queryFactory.query(TenantConfigurationQuery.class).excludedIds(data.getId()).isActive(IsActive.Active).types(data.getType());
if (data.getTenantId() == null) tenantConfigurationQuery.tenantIsSet(false); if (data.getTenantId() == null) tenantConfigurationQuery.tenantIsSet(false);
else tenantConfigurationQuery.tenantIsSet(false).tenantIds(data.getTenantId()); else tenantConfigurationQuery.tenantIsSet(true).tenantIds(data.getTenantId());
if (tenantConfigurationQuery.count() > 0)throw new MyValidationException(this.errors.getMultipleTenantConfigurationTypeNotAllowed().getCode(), this.errors.getMultipleTenantConfigurationTypeNotAllowed().getMessage()); if (tenantConfigurationQuery.count() > 0)throw new MyValidationException(this.errors.getMultipleTenantConfigurationTypeNotAllowed().getCode(), this.errors.getMultipleTenantConfigurationTypeNotAllowed().getMessage());
switch (data.getType()){ switch (data.getType()){
@ -156,6 +156,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
private @NotNull DepositTenantConfigurationEntity buildDepositTenantConfigurationEntity(DepositTenantConfigurationPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { private @NotNull DepositTenantConfigurationEntity buildDepositTenantConfigurationEntity(DepositTenantConfigurationPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
DepositTenantConfigurationEntity data = new DepositTenantConfigurationEntity(); DepositTenantConfigurationEntity data = new DepositTenantConfigurationEntity();
if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data; if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data;
data.setDisableSystemSources(persist.getDisableSystemSources());
data.setSources(new ArrayList<>()); data.setSources(new ArrayList<>());
for (DepositSourcePersist depositSourcePersist : persist.getSources()) { for (DepositSourcePersist depositSourcePersist : persist.getSources()) {
data.getSources().add(this.buildDepositSourceEntity(depositSourcePersist)); data.getSources().add(this.buildDepositSourceEntity(depositSourcePersist));
@ -179,6 +180,7 @@ public class TenantConfigurationServiceImpl implements TenantConfigurationServic
private @NotNull FileTransformerTenantConfigurationEntity buildFileTransformerTenantConfigurationEntity(FileTransformerTenantConfigurationPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { private @NotNull FileTransformerTenantConfigurationEntity buildFileTransformerTenantConfigurationEntity(FileTransformerTenantConfigurationPersist persist) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
FileTransformerTenantConfigurationEntity data = new FileTransformerTenantConfigurationEntity(); FileTransformerTenantConfigurationEntity data = new FileTransformerTenantConfigurationEntity();
if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data; if (persist == null || this.conventionService.isListNullOrEmpty(persist.getSources())) return data;
data.setDisableSystemSources(persist.getDisableSystemSources());
data.setSources(new ArrayList<>()); data.setSources(new ArrayList<>());
for (FileTransformerSourcePersist depositSourcePersist : persist.getSources()) { for (FileTransformerSourcePersist depositSourcePersist : persist.getSources()) {
data.getSources().add(this.buildFileTransformerSourceEntity(depositSourcePersist)); data.getSources().add(this.buildFileTransformerSourceEntity(depositSourcePersist));

View File

@ -120,7 +120,7 @@ public class TenantConfigurationController {
TenantConfigurationQuery query = this.queryFactory.query(TenantConfigurationQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).isActive(IsActive.Active).types(TenantConfigurationType.of(type)); TenantConfigurationQuery query = this.queryFactory.query(TenantConfigurationQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).isActive(IsActive.Active).types(TenantConfigurationType.of(type));
if (this.tenantScope.isDefaultTenant()) query.tenantIsSet(false); if (this.tenantScope.isDefaultTenant()) query.tenantIsSet(false);
else query.tenantIsSet(false).tenantIds(this.tenantScope.getTenant()); else query.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
TenantConfiguration model = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(fieldSet, query.firstAs(fieldSet)); TenantConfiguration model = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(fieldSet, query.firstAs(fieldSet));

View File

@ -0,0 +1,31 @@
FROM node:20
ARG ORACLE_URL
ARG ORACLE_TOKEN
ARG BUILD_VERSION
ENV ORACLE_URL=$ORACLE_URL
ENV ORACLE_TOKEN=$ORACLE_TOKEN
ENV BUILD_VERSION=$BUILD_VERSION
RUN apt-get -y update && apt-get install -y openjdk-11-jdk locales && apt-get clean
RUN mkdir -p /usr/share/man/man1/
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
locale-gen
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
COPY oracle.local.cite.gr.crt /usr/local/share/ca-certificates/oracle.local.cite.gr.crt
RUN update-ca-certificates
# copy the package.json to install dependencies
COPY /dmp-frontend/package.json ./
COPY /dmp-frontend/package-lock.json ./
# Install the dependencies and make the folder
RUN npm install sonar-scanner --save-dev
RUN npm install --legacy-peer-deps && mkdir /src && mv ./node_modules ./src
WORKDIR /src
COPY . .
RUN npm run sonar-scanner

View File

@ -28,12 +28,13 @@
"cookieconsent": "^3.1.1", "cookieconsent": "^3.1.1",
"dragula": "^3.7.3", "dragula": "^3.7.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"moment": "^2.30.1",
"keycloak-angular": "^15.2.1", "keycloak-angular": "^15.2.1",
"keycloak-js": "^24.0.2", "keycloak-js": "^24.0.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.45", "moment-timezone": "^0.5.45",
"ng-dialog-animation": "^9.0.4", "ng-dialog-animation": "^9.0.4",
"ng2-dragula": "^5.0.1", "ng2-dragula": "^5.0.1",
"ngx-colors": "^3.5.3",
"ngx-cookie-service": "^17.1.0", "ngx-cookie-service": "^17.1.0",
"ngx-cookieconsent": "^6.0.0", "ngx-cookieconsent": "^6.0.0",
"ngx-dropzone": "^3.0.0", "ngx-dropzone": "^3.0.0",

View File

@ -6,7 +6,7 @@ import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { environment } from '../environments/environment'; import { environment } from '../environments/environment';
import { AuthService } from './core/services/auth/auth.service'; import { AuthService, LoginStatus } from './core/services/auth/auth.service';
import { CultureService } from './core/services/culture/culture-service'; import { CultureService } from './core/services/culture/culture-service';
// import { BreadCrumbResolverService } from './ui/misc/breadcrumb/service/breadcrumb.service'; // import { BreadCrumbResolverService } from './ui/misc/breadcrumb/service/breadcrumb.service';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -20,6 +20,10 @@ import { MatomoService } from './core/services/matomo/matomo-service';
import { SideNavService } from './core/services/sidenav/side-nav.sevice'; import { SideNavService } from './core/services/sidenav/side-nav.sevice';
import { MatSidenav } from '@angular/material/sidenav'; import { MatSidenav } from '@angular/material/sidenav';
import { TimezoneService } from './core/services/timezone/timezone-service'; import { TimezoneService } from './core/services/timezone/timezone-service';
import { TenantConfigurationService } from './core/services/tenant-configuration/tenant-configuration.service';
import { TenantConfigurationType } from './core/common/enum/tenant-configuration-type';
import { CssColorsTenantConfiguration, TenantConfiguration } from './core/model/tenant-configuaration/tenant-configuration';
import { nameof } from 'ts-simple-nameof';
declare const gapi: any; declare const gapi: any;
@ -56,6 +60,7 @@ export class AppComponent implements OnInit, AfterViewInit {
private configurationService: ConfigurationService, private configurationService: ConfigurationService,
private location: Location, private location: Location,
private matomoService: MatomoService, private matomoService: MatomoService,
private tenantConfigurationService: TenantConfigurationService,
private sidenavService: SideNavService private sidenavService: SideNavService
) { ) {
this.initializeServices(); this.initializeServices();
@ -229,6 +234,36 @@ export class AppComponent implements OnInit, AfterViewInit {
this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileCulture() ? this.cultureService.cultureSelected(this.authentication.getUserProfileCulture()) : this.cultureService.cultureSelected(this.configurationService.defaultCulture); this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileCulture() ? this.cultureService.cultureSelected(this.authentication.getUserProfileCulture()) : this.cultureService.cultureSelected(this.configurationService.defaultCulture);
this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileTimezone() ? this.timezoneService.timezoneSelected(this.authentication.getUserProfileTimezone()) : this.timezoneService.timezoneSelected(this.configurationService.defaultTimezone); this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileTimezone() ? this.timezoneService.timezoneSelected(this.authentication.getUserProfileTimezone()) : this.timezoneService.timezoneSelected(this.configurationService.defaultTimezone);
this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileLanguage() ? this.language.changeLanguage(this.authentication.getUserProfileLanguage()) : (this.language.getDefaultLanguagesCode()); this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileLanguage() ? this.language.changeLanguage(this.authentication.getUserProfileLanguage()) : (this.language.getDefaultLanguagesCode());
this.authentication.getAuthenticationStateObservable().subscribe(authenticationState => {
if (authenticationState.loginStatus === LoginStatus.LoggedIn) {
this.loadCssColors();
}
});
this.loadCssColors();
}
private loadCssColors() {
if (this.authentication.currentAccountIsAuthenticated() && this.authentication.selectedTenant()) {
this.tenantConfigurationService.getCurrentTenantType(TenantConfigurationType.CssColors, [
nameof<TenantConfiguration>(x => x.type),
[nameof<TenantConfiguration>(x => x.cssColors), nameof<CssColorsTenantConfiguration>(x => x.primaryColor)].join('.'),
[nameof<TenantConfiguration>(x => x.cssColors), nameof<CssColorsTenantConfiguration>(x => x.primaryColor2)].join('.'),
[nameof<TenantConfiguration>(x => x.cssColors), nameof<CssColorsTenantConfiguration>(x => x.primaryColor3)].join('.'),
[nameof<TenantConfiguration>(x => x.cssColors), nameof<CssColorsTenantConfiguration>(x => x.secondaryColor)].join('.'),
])
.pipe(map(data => data as TenantConfiguration))
.subscribe(
data => {
if (data?.cssColors) {
if (data.cssColors.primaryColor) document.documentElement.style.setProperty(`--primary-color`, data.cssColors.primaryColor);
if (data.cssColors.primaryColor2) document.documentElement.style.setProperty(`--primary-color-2`, data.cssColors.primaryColor2);
if (data.cssColors.primaryColor3) document.documentElement.style.setProperty(`--primary-color-3`, data.cssColors.primaryColor3);
if (data.cssColors.secondaryColor) document.documentElement.style.setProperty(`--secondary-color`, data.cssColors.secondaryColor);
}
},
);
}
} }
toggleNavbar(event) { toggleNavbar(event) {

View File

@ -26,10 +26,12 @@ export interface DefaultUserLocaleTenantConfiguration{
} }
export interface DepositTenantConfiguration{ export interface DepositTenantConfiguration{
disableSystemSources: boolean;
sources: DepositSource[]; sources: DepositSource[];
} }
export interface FileTransformerTenantConfiguration{ export interface FileTransformerTenantConfiguration{
disableSystemSources: boolean;
sources: FileTransformerSource[]; sources: FileTransformerSource[];
} }
@ -80,10 +82,12 @@ export interface DefaultUserLocaleTenantConfigurationPersist{
} }
export interface DepositTenantConfigurationPersist{ export interface DepositTenantConfigurationPersist{
disableSystemSources: boolean;
sources: DepositSourcePersist[]; sources: DepositSourcePersist[];
} }
export interface FileTransformerTenantConfigurationPersist{ export interface FileTransformerTenantConfigurationPersist{
disableSystemSources: boolean;
sources: FileTransformerSourcePersist[]; sources: FileTransformerSourcePersist[];
} }

View File

@ -1,30 +1,61 @@
<div *ngIf="formGroup" class="container-fluid css-colors"> <div *ngIf="formGroup" class="container-fluid css-colors">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<mat-form-field class="w-100"> <div class="row">
<mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR' | translate}}</mat-label>
<input matInput type="text" name="primaryColor" [formControl]="formGroup.get('cssColors')?.get('primaryColor')" required> <mat-form-field class="col-6">
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('primaryColor')?.getError('backendError').message}}</mat-error> <mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR' | translate}}</mat-label>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <input matInput [formControl]="formGroup.get('cssColors')?.get('primaryColorInput')" required />
</mat-form-field> <ngx-colors
<mat-form-field class="w-100"> class="suffix"
<mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR-2' | translate}}</mat-label> matSuffix
<input matInput type="text" name="primaryColor2" [formControl]="formGroup.get('cssColors')?.get('primaryColor2')" required> ngx-colors-trigger
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor2')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('primaryColor2')?.getError('backendError').message}}</mat-error> [formControl]="formGroup.get('cssColors')?.get('primaryColor')"
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor2')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> ></ngx-colors>
</mat-form-field> <mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('primaryColor')?.getError('backendError').message}}</mat-error>
<mat-form-field class="w-100"> <mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR-3' | translate}}</mat-label> <mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor')?.hasError('invalidColor')">{{'GENERAL.VALIDATION.INVALID-COLOR' | translate}}</mat-error>
<input matInput type="text" name="primaryColor3" [formControl]="formGroup.get('cssColors')?.get('primaryColor3')" required> </mat-form-field>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor3')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('primaryColor3')?.getError('backendError').message}}</mat-error> <mat-form-field class="col-6">
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor3')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR-2' | translate}}</mat-label>
</mat-form-field> <input matInput [formControl]="formGroup.get('cssColors')?.get('primaryColor2Input')" required />
<mat-form-field class="w-100"> <ngx-colors
<mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.SECONDARY-COLOR' | translate}}</mat-label> class="suffix"
<input matInput type="text" name="secondaryColor" [formControl]="formGroup.get('cssColors')?.get('secondaryColor')" required> matSuffix
<mat-error *ngIf="formGroup.get('cssColors')?.get('secondaryColor')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('secondaryColor')?.getError('backendError').message}}</mat-error> ngx-colors-trigger
<mat-error *ngIf="formGroup.get('cssColors')?.get('secondaryColor')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> [formControl]="formGroup.get('cssColors')?.get('primaryColor2')"
</mat-form-field> ></ngx-colors>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor2')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('primaryColor2')?.getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor2')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor2')?.hasError('invalidColor')">{{'GENERAL.VALIDATION.INVALID-COLOR' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="col-6">
<mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR-3' | translate}}</mat-label>
<input matInput [formControl]="formGroup.get('cssColors')?.get('primaryColor3Input')" required />
<ngx-colors
class="suffix"
matSuffix
ngx-colors-trigger
[formControl]="formGroup.get('cssColors')?.get('primaryColor3')"
></ngx-colors>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor3')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('primaryColor3')?.getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor3')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="formGroup.get('cssColors')?.get('primaryColor3')?.hasError('invalidColor')">{{'GENERAL.VALIDATION.INVALID-COLOR' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="col-6">
<mat-label>{{'TENANT-CONFIGURATION-EDITOR.FIELDS.SECONDARY-COLOR' | translate}}</mat-label>
<input matInput [formControl]="formGroup.get('cssColors')?.get('secondaryColorInput')" required />
<ngx-colors
class="suffix"
matSuffix
ngx-colors-trigger
[formControl]="formGroup.get('cssColors')?.get('secondaryColor')"
></ngx-colors>
<mat-error *ngIf="formGroup.get('cssColors')?.get('secondaryColor')?.hasError('backendError')">{{formGroup.get('cssColors')?.get('secondaryColor')?.getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('cssColors')?.get('secondaryColor')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="formGroup.get('cssColors')?.get('secondaryColor')?.hasError('invalidColor')">{{'GENERAL.VALIDATION.INVALID-COLOR' | translate}}</mat-error>
</mat-form-field>
</div>
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="row actions-row"> <div class="row actions-row">

View File

@ -78,6 +78,50 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem
this.formGroup.disable(); this.formGroup.disable();
} }
}); });
}
private bindColorInputs() {
this.formGroup.get('cssColors')?.get('primaryColorInput').valueChanges.subscribe((color) => {
this.formGroup.get('cssColors')?.get('primaryColor').setValue(color, {
emitEvent: false,
});
});
this.formGroup.get('cssColors')?.get('primaryColor').valueChanges.subscribe((color) =>
this.formGroup.get('cssColors')?.get('primaryColorInput').setValue(color, {
emitEvent: false,
})
);
this.formGroup.get('cssColors')?.get('primaryColor2Input').valueChanges.subscribe((color) => {
this.formGroup.get('cssColors')?.get('primaryColor2').setValue(color, {
emitEvent: false,
});
});
this.formGroup.get('cssColors')?.get('primaryColor2').valueChanges.subscribe((color) =>
this.formGroup.get('cssColors')?.get('primaryColor2Input').setValue(color, {
emitEvent: false,
})
);
this.formGroup.get('cssColors')?.get('primaryColor3Input').valueChanges.subscribe((color) => {
this.formGroup.get('cssColors')?.get('primaryColor3').setValue(color, {
emitEvent: false,
});
});
this.formGroup.get('cssColors')?.get('primaryColor3').valueChanges.subscribe((color) =>
this.formGroup.get('cssColors')?.get('primaryColor3Input').setValue(color, {
emitEvent: false,
})
);
this.formGroup.get('cssColors')?.get('secondaryColorInput').valueChanges.subscribe((color) => {
this.formGroup.get('cssColors')?.get('secondaryColor').setValue(color, {
emitEvent: false,
});
});
this.formGroup.get('cssColors')?.get('secondaryColor').valueChanges.subscribe((color) =>
this.formGroup.get('cssColors')?.get('secondaryColorInput').setValue(color, {
emitEvent: false,
})
);
} }
getItem(successFunction: (item: TenantConfiguration) => void) { getItem(successFunction: (item: TenantConfiguration) => void) {
@ -119,8 +163,9 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem
prepareForm(data: TenantConfiguration) { prepareForm(data: TenantConfiguration) {
try { try {
this.editorModel = data ? new TenantConfigurationEditorModel().fromModel(data) : new TenantConfigurationEditorModel(); this.editorModel = data ? new TenantConfigurationEditorModel().fromModel(data) : new TenantConfigurationEditorModel();
this.buildForm(); this.buildForm();
this.bindColorInputs();
} catch (error) { } catch (error) {
this.logger.error('Could not parse TenantConfiguration item: ' + data + error); this.logger.error('Could not parse TenantConfiguration item: ' + data + error);
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error); this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
@ -172,7 +217,7 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem
const dialogRef = this.dialog.open(ConfirmationDialogComponent, { const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px', maxWidth: '300px',
data: { data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.RESET-TO-DEFAULT'), message: this.language.instant('TENANT-CONFIGURATION-EDITOR.RESET-TO-DEFAULT-DIALOG.RESET-TO-DEFAULT'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
} }

View File

@ -5,6 +5,7 @@ import { BaseEditorModel } from "@common/base/base-form-editor-model";
import { BackendErrorValidator } from "@common/forms/validation/custom-validator"; import { BackendErrorValidator } from "@common/forms/validation/custom-validator";
import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model"; import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model";
import { Validation, ValidationContext } from "@common/forms/validation/validation-context"; import { Validation, ValidationContext } from "@common/forms/validation/validation-context";
import { validColorValidator } from "ngx-colors";
export class TenantConfigurationEditorModel extends BaseEditorModel implements TenantConfigurationPersist { export class TenantConfigurationEditorModel extends BaseEditorModel implements TenantConfigurationPersist {
type: TenantConfigurationType; type: TenantConfigurationType;
@ -91,7 +92,12 @@ export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantC
primaryColor2: [{ value: this.primaryColor2, disabled: disabled }, context.getValidation('primaryColor2').validators], primaryColor2: [{ value: this.primaryColor2, disabled: disabled }, context.getValidation('primaryColor2').validators],
primaryColor3: [{ value: this.primaryColor3, disabled: disabled }, context.getValidation('primaryColor3').validators], primaryColor3: [{ value: this.primaryColor3, disabled: disabled }, context.getValidation('primaryColor3').validators],
secondaryColor: [{ value: this.secondaryColor, disabled: disabled }, context.getValidation('secondaryColor').validators], secondaryColor: [{ value: this.secondaryColor, disabled: disabled }, context.getValidation('secondaryColor').validators],
}); primaryColorInput: [{ value: this.primaryColor, disabled: disabled}, context.getValidation('primaryColorInput').validators ],
primaryColor2Input: [{ value: this.primaryColor2, disabled: disabled}, context.getValidation('primaryColor2Input').validators ],
primaryColor3Input: [{ value: this.primaryColor3, disabled: disabled}, context.getValidation('primaryColor3Input').validators ],
secondaryColorInput: [{ value: this.secondaryColor, disabled: disabled}, context.getValidation('secondaryColorInput').validators ],
},
{ updateOn: "change" });
return form; return form;
} }
@ -105,10 +111,14 @@ export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantC
const baseContext: ValidationContext = new ValidationContext(); const baseContext: ValidationContext = new ValidationContext();
const baseValidationArray: Validation[] = new Array<Validation>(); const baseValidationArray: Validation[] = new Array<Validation>();
baseValidationArray.push({ key: 'primaryColor', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor`)] }); baseValidationArray.push({ key: 'primaryColor', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor`)] });
baseValidationArray.push({ key: 'primaryColor2', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor2`)] }); baseValidationArray.push({ key: 'primaryColor2', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor2`)] });
baseValidationArray.push({ key: 'primaryColor3', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor3`)] }); baseValidationArray.push({ key: 'primaryColor3', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor3`)] });
baseValidationArray.push({ key: 'secondaryColor', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}secondaryColor`)] }); baseValidationArray.push({ key: 'secondaryColor', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}secondaryColor`)] });
baseValidationArray.push({ key: 'primaryColorInput', validators: [validColorValidator()] });
baseValidationArray.push({ key: 'primaryColor2Input', validators: [validColorValidator()] });
baseValidationArray.push({ key: 'primaryColor3Input', validators: [validColorValidator()] });
baseValidationArray.push({ key: 'secondaryColorInput', validators: [validColorValidator()] });
baseContext.validation = baseValidationArray; baseContext.validation = baseValidationArray;
return baseContext; return baseContext;

View File

@ -185,7 +185,7 @@ export class DefaultUserLocaleEditorComponent extends BasePendingChangesComponen
const dialogRef = this.dialog.open(ConfirmationDialogComponent, { const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px', maxWidth: '300px',
data: { data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.RESET-TO-DEFAULT'), message: this.language.instant('TENANT-CONFIGURATION-EDITOR.RESET-TO-DEFAULT-DIALOG.RESET-TO-DEFAULT'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
} }

View File

@ -1,10 +1,16 @@
<div *ngIf="formGroup" class="container-fluid deposit"> <div *ngIf="formGroup" class="container-fluid deposit">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h3> <div class="row">{{label}}</div>
{{label}} <div class="row">
<button mat-button class="action-btn" type="button" (click)="addSource()" [disabled]="formGroup.disabled">{{'TENANT-CONFIGURATION-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button> <mat-checkbox [formControl]="formGroup.get('depositPlugins').get('disableSystemSources')">
</h3> {{'TENANT-CONFIGURATION-EDITOR.FIELDS.DISABLE-SYSTEM-SOURCES' | translate}}
<mat-error *ngIf=" formGroup.get('depositPlugins')?.get('disableSystemSources')?.hasError('backendError')">{{ formGroup?.get('depositPlugins')?.get('disableSystemSources')?.getError('backendError')?.message}}</mat-error>
<mat-error *ngIf=" formGroup.get('depositPlugins')?.get('disableSystemSources')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-checkbox>
</div>
<button mat-button class="action-btn" type="button" (click)="addSource()" [disabled]="formGroup.disabled">{{'TENANT-CONFIGURATION-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button>
<div *ngFor="let source of formGroup.get('depositPlugins').get('sources').controls; let sourceIndex=index;" class="row mb-3"> <div *ngFor="let source of formGroup.get('depositPlugins').get('sources').controls; let sourceIndex=index;" class="row mb-3">
<div class="col-12"> <div class="col-12">
<div class="row mb-3 d-flex align-items-center"> <div class="row mb-3 d-flex align-items-center">

View File

@ -172,7 +172,7 @@ export class DepositEditorComponent extends BasePendingChangesComponent implemen
const dialogRef = this.dialog.open(ConfirmationDialogComponent, { const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px', maxWidth: '300px',
data: { data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.RESET-TO-DEFAULT'), message: this.language.instant('TENANT-CONFIGURATION-EDITOR.RESET-TO-DEFAULT-DIALOG.RESET-TO-DEFAULT'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
} }

View File

@ -66,6 +66,7 @@ export class TenantConfigurationEditorModel extends BaseEditorModel implements T
} }
export class DepositTenantConfigurationEditorModel implements DepositTenantConfigurationPersist { export class DepositTenantConfigurationEditorModel implements DepositTenantConfigurationPersist {
disableSystemSources: boolean = false;
sources: DepositSourceEditorModel[] = []; sources: DepositSourceEditorModel[] = [];
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
@ -76,6 +77,7 @@ export class DepositTenantConfigurationEditorModel implements DepositTenantConfi
public fromModel(item: DepositTenantConfiguration): DepositTenantConfigurationEditorModel { public fromModel(item: DepositTenantConfiguration): DepositTenantConfigurationEditorModel {
if (item) { if (item) {
this.disableSystemSources = item.disableSystemSources;
if (item.sources) { item.sources.map(x => this.sources.push(new DepositSourceEditorModel(this.validationErrorModel).fromModel(x))); } if (item.sources) { item.sources.map(x => this.sources.push(new DepositSourceEditorModel(this.validationErrorModel).fromModel(x))); }
} }
return this; return this;
@ -95,6 +97,7 @@ export class DepositTenantConfigurationEditorModel implements DepositTenantConfi
} }
const form: UntypedFormGroup = this.formBuilder.group({ const form: UntypedFormGroup = this.formBuilder.group({
disableSystemSources: [{ value: this.disableSystemSources, disabled: disabled }, context.getValidation('disableSystemSources').validators],
sources: this.formBuilder.array( sources: this.formBuilder.array(
(this.sources ?? []).map( (this.sources ?? []).map(
(item, index) => item.buildForm({ (item, index) => item.buildForm({
@ -116,6 +119,7 @@ export class DepositTenantConfigurationEditorModel implements DepositTenantConfi
const baseContext: ValidationContext = new ValidationContext(); const baseContext: ValidationContext = new ValidationContext();
const baseValidationArray: Validation[] = new Array<Validation>(); const baseValidationArray: Validation[] = new Array<Validation>();
baseValidationArray.push({ key: 'disableSystemSources', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}disableSystemSources`)] });
baseValidationArray.push({ key: 'sources', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}sources`)] }); baseValidationArray.push({ key: 'sources', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}sources`)] });
baseContext.validation = baseValidationArray; baseContext.validation = baseValidationArray;
return baseContext; return baseContext;

View File

@ -29,6 +29,7 @@ export class DepositEditorResolver extends BaseEditorResolver {
[nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.sources), nameof<DepositSource>(x => x.url)].join('.'), [nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.sources), nameof<DepositSource>(x => x.url)].join('.'),
[nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.sources), nameof<DepositSource>(x => x.pdfTransformerId)].join('.'), [nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.sources), nameof<DepositSource>(x => x.pdfTransformerId)].join('.'),
[nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.sources), nameof<DepositSource>(x => x.rdaTransformerId)].join('.'), [nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.sources), nameof<DepositSource>(x => x.rdaTransformerId)].join('.'),
[nameof<TenantConfiguration>(x => x.depositPlugins), nameof<DepositTenantConfiguration>(x => x.disableSystemSources)].join('.'),
nameof<TenantConfiguration>(x => x.createdAt), nameof<TenantConfiguration>(x => x.createdAt),

View File

@ -1,10 +1,15 @@
<div *ngIf="formGroup" class="container-fluid file-transformer"> <div *ngIf="formGroup" class="container-fluid file-transformer">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h3> <div class="row">{{label}}</div>
{{label}} <div class="row">
<button mat-button class="action-btn" type="button" (click)="addSource()" [disabled]="formGroup.disabled">{{'TENANT-CONFIGURATION-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button> <mat-checkbox [formControl]="formGroup.get('fileTransformerPlugins').get('disableSystemSources')">
</h3> {{'TENANT-CONFIGURATION-EDITOR.FIELDS.DISABLE-SYSTEM-SOURCES' | translate}}
<mat-error *ngIf=" formGroup.get('fileTransformerPlugins')?.get('disableSystemSources')?.hasError('backendError')">{{ formGroup?.get('fileTransformerPlugins')?.get('disableSystemSources')?.getError('backendError')?.message}}</mat-error>
<mat-error *ngIf=" formGroup.get('fileTransformerPlugins')?.get('disableSystemSources')?.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-checkbox>
</div>
<button mat-button class="action-btn row" type="button" (click)="addSource()" [disabled]="formGroup.disabled">{{'TENANT-CONFIGURATION-EDITOR.ACTIONS.ADD-SOURCE' | translate}}</button>
<div *ngFor="let source of formGroup.get('fileTransformerPlugins').get('sources').controls; let sourceIndex=index;" class="row mb-3"> <div *ngFor="let source of formGroup.get('fileTransformerPlugins').get('sources').controls; let sourceIndex=index;" class="row mb-3">
<div class="col-12"> <div class="col-12">
<div class="row mb-3 d-flex align-items-center"> <div class="row mb-3 d-flex align-items-center">

View File

@ -172,7 +172,7 @@ export class FileTransformerEditorComponent extends BasePendingChangesComponent
const dialogRef = this.dialog.open(ConfirmationDialogComponent, { const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px', maxWidth: '300px',
data: { data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.RESET-TO-DEFAULT'), message: this.language.instant('TENANT-CONFIGURATION-EDITOR.RESET-TO-DEFAULT-DIALOG.RESET-TO-DEFAULT'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
} }

View File

@ -66,6 +66,7 @@ export class TenantConfigurationEditorModel extends BaseEditorModel implements T
} }
export class FileTransformerTenantConfigurationEditorModel implements FileTransformerTenantConfigurationPersist { export class FileTransformerTenantConfigurationEditorModel implements FileTransformerTenantConfigurationPersist {
disableSystemSources: boolean = false;
sources: FileTransformerSourceEditorModel[] = []; sources: FileTransformerSourceEditorModel[] = [];
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
@ -76,6 +77,7 @@ export class FileTransformerTenantConfigurationEditorModel implements FileTransf
public fromModel(item: FileTransformerTenantConfiguration): FileTransformerTenantConfigurationEditorModel { public fromModel(item: FileTransformerTenantConfiguration): FileTransformerTenantConfigurationEditorModel {
if (item) { if (item) {
this.disableSystemSources = item.disableSystemSources;
if (item.sources) { item.sources.map(x => this.sources.push(new FileTransformerSourceEditorModel(this.validationErrorModel).fromModel(x))); } if (item.sources) { item.sources.map(x => this.sources.push(new FileTransformerSourceEditorModel(this.validationErrorModel).fromModel(x))); }
} }
return this; return this;
@ -95,6 +97,7 @@ export class FileTransformerTenantConfigurationEditorModel implements FileTransf
} }
const form: UntypedFormGroup = this.formBuilder.group({ const form: UntypedFormGroup = this.formBuilder.group({
disableSystemSources: [{ value: this.disableSystemSources, disabled: disabled }, context.getValidation('disableSystemSources').validators],
sources: this.formBuilder.array( sources: this.formBuilder.array(
(this.sources ?? []).map( (this.sources ?? []).map(
(item, index) => item.buildForm({ (item, index) => item.buildForm({
@ -116,6 +119,7 @@ export class FileTransformerTenantConfigurationEditorModel implements FileTransf
const baseContext: ValidationContext = new ValidationContext(); const baseContext: ValidationContext = new ValidationContext();
const baseValidationArray: Validation[] = new Array<Validation>(); const baseValidationArray: Validation[] = new Array<Validation>();
baseValidationArray.push({ key: 'disableSystemSources', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}disableSystemSources`)] });
baseValidationArray.push({ key: 'sources', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}sources`)] }); baseValidationArray.push({ key: 'sources', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}sources`)] });
baseContext.validation = baseValidationArray; baseContext.validation = baseValidationArray;
return baseContext; return baseContext;

View File

@ -27,6 +27,7 @@ export class FileTransformerEditorResolver extends BaseEditorResolver {
[nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.sources), nameof<FileTransformerSource>(x => x.transformerId)].join('.'), [nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.sources), nameof<FileTransformerSource>(x => x.transformerId)].join('.'),
[nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.sources), nameof<FileTransformerSource>(x => x.scope)].join('.'), [nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.sources), nameof<FileTransformerSource>(x => x.scope)].join('.'),
[nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.sources), nameof<FileTransformerSource>(x => x.url)].join('.'), [nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.sources), nameof<FileTransformerSource>(x => x.url)].join('.'),
[nameof<TenantConfiguration>(x => x.fileTransformerPlugins), nameof<FileTransformerTenantConfiguration>(x => x.disableSystemSources)].join('.'),
nameof<TenantConfiguration>(x => x.createdAt), nameof<TenantConfiguration>(x => x.createdAt),

View File

@ -182,7 +182,7 @@ export class LogoEditorComponent extends BasePendingChangesComponent implements
const dialogRef = this.dialog.open(ConfirmationDialogComponent, { const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px', maxWidth: '300px',
data: { data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.RESET-TO-DEFAULT'), message: this.language.instant('TENANT-CONFIGURATION-EDITOR.RESET-TO-DEFAULT-DIALOG.RESET-TO-DEFAULT'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
} }

View File

@ -18,6 +18,7 @@ import { FormattingModule } from '@app/core/formatting.module';
import { DepositEditorComponent } from './editor/deposit/deposit-editor.component'; import { DepositEditorComponent } from './editor/deposit/deposit-editor.component';
import { FileTransformerEditorComponent } from './editor/file-transformer/file-transformer-editor.component'; import { FileTransformerEditorComponent } from './editor/file-transformer/file-transformer-editor.component';
import { LogoEditorComponent } from './editor/logo/logo-editor.component'; import { LogoEditorComponent } from './editor/logo/logo-editor.component';
import { NgxColorsModule } from 'ngx-colors';
@NgModule({ @NgModule({
imports: [ imports: [
@ -33,7 +34,8 @@ import { LogoEditorComponent } from './editor/logo/logo-editor.component';
TextFilterModule, TextFilterModule,
UserSettingsModule, UserSettingsModule,
CommonFormattingModule, CommonFormattingModule,
RichTextEditorModule RichTextEditorModule,
NgxColorsModule
], ],
declarations: [ declarations: [
TenantConfigurationEditorComponent, TenantConfigurationEditorComponent,

View File

@ -190,7 +190,7 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp
let result: Map<string, DescriptionPropertyDefinitionFieldSetEditorModel> = new Map<string, DescriptionPropertyDefinitionFieldSetEditorModel>(); let result: Map<string, DescriptionPropertyDefinitionFieldSetEditorModel> = new Map<string, DescriptionPropertyDefinitionFieldSetEditorModel>();
definitionSection?.fieldSets?.forEach(definitionFieldSet => { definitionSection?.fieldSets?.forEach(definitionFieldSet => {
const fieldSetResult = this.calculateFieldSetProperties(definitionFieldSet, item, descriptionReferences); const fieldSetResult = this.calculateFieldSetProperties(definitionFieldSet, 0, item, descriptionReferences);
if (fieldSetResult != null) { if (fieldSetResult != null) {
result.set(definitionFieldSet.id, fieldSetResult); result.set(definitionFieldSet.id, fieldSetResult);
} }
@ -208,7 +208,7 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp
return result; return result;
} }
public calculateFieldSetProperties(definitionFieldSet: DescriptionTemplateFieldSet, item: DescriptionPropertyDefinition, descriptionReferences: DescriptionReference[]): DescriptionPropertyDefinitionFieldSetEditorModel { public calculateFieldSetProperties(definitionFieldSet: DescriptionTemplateFieldSet, ordinal: number, item: DescriptionPropertyDefinition, descriptionReferences: DescriptionReference[]): DescriptionPropertyDefinitionFieldSetEditorModel {
if (definitionFieldSet == null) return null; if (definitionFieldSet == null) return null;
// current saved values // current saved values
@ -229,7 +229,7 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp
}) })
fieldSetValue.items = [{ fieldSetValue.items = [{
fields: fields, fields: fields,
ordinal: 0 ordinal: ordinal
} as DescriptionPropertyDefinitionFieldSetItem] } as DescriptionPropertyDefinitionFieldSetItem]
} }

View File

@ -14,6 +14,7 @@ import { Guid } from '@common/types/guid';
import { AnnotationDialogComponent } from '@app/ui/annotations/annotation-dialog-component/annotation-dialog.component'; import { AnnotationDialogComponent } from '@app/ui/annotations/annotation-dialog-component/annotation-dialog.component';
import { AnnotationEntityType } from '@app/core/common/enum/annotation-entity-type'; import { AnnotationEntityType } from '@app/core/common/enum/annotation-entity-type';
import { DescriptionFormAnnotationService } from '../../description-form-annotation.service'; import { DescriptionFormAnnotationService } from '../../description-form-annotation.service';
import { DescriptionPropertyDefinitionFieldSet } from '@app/core/model/description/description';
@Component({ @Component({
selector: 'app-description-form-field-set', selector: 'app-description-form-field-set',
@ -88,17 +89,21 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
if (formArray.disabled) { if (formArray.disabled) {
return; return;
} }
const properties: DescriptionPropertyDefinitionFieldSet = this.propertiesFormGroup.value;
const item: DescriptionPropertyDefinitionFieldSetEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).calculateFieldSetProperties(this.fieldSet, null, null); let ordinal = 0;
if (properties?.items && properties.items.map(x => x.ordinal).filter(val => !isNaN(val)).length > 0) {
ordinal = Math.max(...properties.items.map(x => x.ordinal).filter(val => !isNaN(val))) + 1;
}
const item: DescriptionPropertyDefinitionFieldSetEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).calculateFieldSetProperties(this.fieldSet, ordinal, null, null);
formArray.push((item.buildForm({ rootPath: `properties.fieldSets[${this.fieldSet.id}].` }).get('items') as UntypedFormArray).at(0)); formArray.push((item.buildForm({ rootPath: `properties.fieldSets[${this.fieldSet.id}].` }).get('items') as UntypedFormArray).at(0));
this.visibilityRulesService.reloadVisibility();
} }
deleteMultiplicityField(fieldSetIndex: number): void { deleteMultiplicityField(fieldSetIndex: number): void {
const formArray = this.propertiesFormGroup.get('items') as UntypedFormArray; const formArray = this.propertiesFormGroup.get('items') as UntypedFormArray;
formArray.removeAt(fieldSetIndex); formArray.removeAt(fieldSetIndex);
formArray.controls.forEach((fieldSet, index) => { formArray.controls.forEach((fieldSet, index) => {
fieldSet.get('ordinal').setValue(index + 1); fieldSet.get('ordinal').setValue(index);
}); });
//Reapply validators //Reapply validators
@ -110,6 +115,8 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
} }
); );
formArray.markAsDirty(); formArray.markAsDirty();
this.visibilityRulesService.reloadVisibility();
} }
editTableMultiplicityFieldInDialog(fieldSetIndex: number) { editTableMultiplicityFieldInDialog(fieldSetIndex: number) {

View File

@ -127,8 +127,8 @@
</ng-container> </ng-container>
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.BOOLEAN_DECISION" class="col-12"> <div *ngSwitchCase="descriptionTemplateFieldTypeEnum.BOOLEAN_DECISION" class="col-12">
<mat-radio-group [formControl]="propertiesFormGroup?.get(field.id).get('textValue')" [required]="isRequired"> <mat-radio-group [formControl]="propertiesFormGroup?.get(field.id).get('textValue')" [required]="isRequired">
<mat-radio-button class="radio-button-item" name="{{propertiesFormGroup?.get(field.id).value}}" value="true">{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.ACTIONS.YES" | translate }}</mat-radio-button> <mat-radio-button class="radio-button-item" value="true">{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.ACTIONS.YES" | translate }}</mat-radio-button>
<mat-radio-button class="radio-button-item" name="{{propertiesFormGroup?.get(field.id).value}}" value="false">{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.ACTIONS.NO" | translate }}</mat-radio-button> <mat-radio-button class="radio-button-item" value="false">{{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.ACTIONS.NO" | translate }}</mat-radio-button>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}</mat-error> <mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('backendError')">{{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}</mat-error>
</mat-radio-group> </mat-radio-group>
<small class="text-danger d-block" *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('required') && propertiesFormGroup?.get(field.id).get('textValue').touched">{{'GENERAL.VALIDATION.REQUIRED' | translate}} <small class="text-danger d-block" *ngIf="propertiesFormGroup?.get(field.id).get('textValue').hasError('required') && propertiesFormGroup?.get(field.id).get('textValue').touched">{{'GENERAL.VALIDATION.REQUIRED' | translate}}

View File

@ -8,7 +8,9 @@
<div class="icon-bar3"></div> <div class="icon-bar3"></div>
</div> </div>
<a class="logo" [routerLink]="['home']"><img class="logo-image" src="../../../assets/images/nav-logo.png"></a> <a class="logo" [routerLink]="['home']"><img class="logo-image" src="../../../assets/images/nav-logo.png"></a>
<ng-container>
<a class="extra-logo" [routerLink]="['home']"><img class="extra-logo-image" [src]="extraImageURL"></a>
</ng-container>
<button class="navbar-toggler ml-auto" type="button" [matMenuTriggerFor]="toggleMenu"> <button class="navbar-toggler ml-auto" type="button" [matMenuTriggerFor]="toggleMenu">
<img *ngIf="this.isAuthenticated();else loginoption" mat-card-avatar class="my-mat-card-avatar" [src]="getPrincipalAvatar() ?? getDefaultAvatar()" (error)="this.applyFallbackAvatar($event)"> <img *ngIf="this.isAuthenticated();else loginoption" mat-card-avatar class="my-mat-card-avatar" [src]="getPrincipalAvatar() ?? getDefaultAvatar()" (error)="this.applyFallbackAvatar($event)">
</button> </button>

View File

@ -34,9 +34,17 @@ $mat-card-header-size: 40px !default;
margin-left: 5px; margin-left: 5px;
height: 100%; height: 100%;
} }
.extra-logo {
margin-left: 5px;
height: 100%;
}
.logo-image { .logo-image {
height: 100%; height: 100%;
} }
.extra-logo-image {
height: 100%;
}
.faq-title { .faq-title {
text-align: left; text-align: left;

View File

@ -5,13 +5,13 @@ import { MatMenuTrigger } from '@angular/material/menu';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { AppRole } from '@app/core/common/enum/app-role'; import { AppRole } from '@app/core/common/enum/app-role';
import { User } from '@app/core/model/user/user'; import { User } from '@app/core/model/user/user';
import { AuthService } from '@app/core/services/auth/auth.service'; import { AuthService, LoginStatus } from '@app/core/services/auth/auth.service';
import { LanguageService } from '@app/core/services/language/language.service'; import { LanguageService } from '@app/core/services/language/language.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { ProgressIndicationService } from '@app/core/services/progress-indication/progress-indication-service'; import { ProgressIndicationService } from '@app/core/services/progress-indication/progress-indication-service';
import { SideNavService } from '@app/core/services/sidenav/side-nav.sevice'; import { SideNavService } from '@app/core/services/sidenav/side-nav.sevice';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators'; import { map, takeUntil } from 'rxjs/operators';
import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component'; import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/start-new-dmp-dialog.component';
import { FaqDialogComponent } from '../faq/dialog/faq-dialog.component'; import { FaqDialogComponent } from '../faq/dialog/faq-dialog.component';
import { UserDialogComponent } from './user-dialog/user-dialog.component'; import { UserDialogComponent } from './user-dialog/user-dialog.component';
@ -19,6 +19,13 @@ import { MineInAppNotificationListingDialogComponent } from '@notification-servi
import { InAppNotificationService } from '@notification-service/services/http/inapp-notification.service'; import { InAppNotificationService } from '@notification-service/services/http/inapp-notification.service';
import { timer } from 'rxjs'; import { timer } from 'rxjs';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { TenantConfigurationService } from '@app/core/services/tenant-configuration/tenant-configuration.service';
import { LogoTenantConfiguration, TenantConfiguration } from '@app/core/model/tenant-configuaration/tenant-configuration';
import { TenantConfigurationType } from '@app/core/common/enum/tenant-configuration-type';
import { nameof } from 'ts-simple-nameof';
import { StorageFile } from '@app/core/model/storage-file/storage-file';
import { StorageFileService } from '@app/core/services/storage-file/storage-file.service';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
@Component({ @Component({
selector: 'app-navbar', selector: 'app-navbar',
@ -40,6 +47,7 @@ export class NavbarComponent extends BaseComponent implements OnInit {
inAppNotificationCount = 0; inAppNotificationCount = 0;
@Output() sidebarToggled: EventEmitter<any> = new EventEmitter(); @Output() sidebarToggled: EventEmitter<any> = new EventEmitter();
@ViewChild(MatMenuTrigger) trigger: MatMenuTrigger; @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger;
extraImageURL: SafeUrl;
constructor(location: Location, constructor(location: Location,
private element: ElementRef, private element: ElementRef,
@ -50,8 +58,11 @@ export class NavbarComponent extends BaseComponent implements OnInit {
private languageService: LanguageService, private languageService: LanguageService,
private matomoService: MatomoService, private matomoService: MatomoService,
private sidenavService: SideNavService, private sidenavService: SideNavService,
private tenantConfigurationService: TenantConfigurationService,
private inappNotificationService: InAppNotificationService, private inappNotificationService: InAppNotificationService,
private configurationService: ConfigurationService private configurationService: ConfigurationService,
private storageFileService: StorageFileService,
private sanitizer: DomSanitizer
) { ) {
super(); super();
this.location = location; this.location = location;
@ -87,6 +98,33 @@ export class NavbarComponent extends BaseComponent implements OnInit {
.subscribe(x => { .subscribe(x => {
this.countUnreadInappNotifications(); this.countUnreadInappNotifications();
}); });
this.authentication.getAuthenticationStateObservable().subscribe(authenticationState => {
if (authenticationState.loginStatus === LoginStatus.LoggedIn) {
this.loadLogo();
}
});
this.loadLogo();
}
private loadLogo() {
if (this.authentication.currentAccountIsAuthenticated() && this.authentication.selectedTenant()) {
this.tenantConfigurationService.getCurrentTenantType(TenantConfigurationType.Logo, [
nameof<TenantConfiguration>(x => x.type),
[nameof<TenantConfiguration>(x => x.logo), nameof<LogoTenantConfiguration>(x => x.storageFile), nameof<StorageFile>(x => x.id)].join('.'),
])
.pipe(map(data => data as TenantConfiguration), takeUntil(this._destroyed))
.subscribe(
data => {
if (data?.logo?.storageFile?.id) {
this.storageFileService.download(data?.logo?.storageFile?.id).pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body]);
this.extraImageURL = this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(response.body))
});
}
},
);
}
} }
private countUnreadInappNotifications() { private countUnreadInappNotifications() {

View File

@ -4,6 +4,7 @@
"GENERAL": { "GENERAL": {
"VALIDATION": { "VALIDATION": {
"REQUIRED": "Required", "REQUIRED": "Required",
"INVALID-COLOR": "Invalid color",
"URL": { "URL": {
"LABEL": "URL", "LABEL": "URL",
"MESSAGE": "Please provide a valid URL" "MESSAGE": "Please provide a valid URL"
@ -186,6 +187,7 @@
"PREFILLING-SOURCES": "Prefilling Sources", "PREFILLING-SOURCES": "Prefilling Sources",
"NEW-PREFILLING-SOURCE": "New", "NEW-PREFILLING-SOURCE": "New",
"EDIT-PREFILLING-SOURCE": "Edit", "EDIT-PREFILLING-SOURCE": "Edit",
"TENANT-CONFIGURATION": "Tenant Configuration",
"ENTITY-LOCKS": "Entity Locks" "ENTITY-LOCKS": "Entity Locks"
}, },
"COOKIE": { "COOKIE": {
@ -250,6 +252,7 @@
"NOTIFICATION-TEMPLATES": "Notification Templates", "NOTIFICATION-TEMPLATES": "Notification Templates",
"NOTIFICATIONS": "Notifications", "NOTIFICATIONS": "Notifications",
"PREFILLING-SOURCES": "Prefilling Sources", "PREFILLING-SOURCES": "Prefilling Sources",
"TENANT-CONFIGURATION": "Tenant Configuration",
"ENTITY-LOCKS": "Entity Locks" "ENTITY-LOCKS": "Entity Locks"
}, },
"DESCRIPTION-TEMPLATE-PREVIEW": { "DESCRIPTION-TEMPLATE-PREVIEW": {
@ -296,6 +299,60 @@
"MESSAGE": "Are you sure you want to perform this action?" "MESSAGE": "Are you sure you want to perform this action?"
} }
}, },
"TENANT-CONFIGURATION-EDITOR": {
"TITLE": "Tenant Configuration",
"DEFAULT-USER-LOCALE":{
"TITLE": "Default User Locale",
"HINT": "Default locale assigned to new users"
},
"CSS-COLORS":{
"TITLE": "App Colors",
"HINT": "App color theme"
},
"LOGO":{
"TITLE": "Extra Logo",
"HINT": "Add extra logo"
},
"DEPOSIT-PLUGINS":{
"TITLE": "Deposit Plugins",
"HINT": "Change deposit plugins"
},
"FILE-TRANSFORMER-PLUGINS":{
"TITLE": "File Transformer Plugins",
"HINT": "Change file transformer plugins"
},
"FIELDS": {
"TIMEZONE": "Timezone",
"CULTURE": "Culture",
"LANGUAGE": "Language",
"PRIMARY-COLOR": "Primary Color",
"PRIMARY-COLOR-2": "Primary Color 2",
"PRIMARY-COLOR-3": "Primary Color 2",
"SECONDARY-COLOR": "Secondary Color",
"DISABLE-SYSTEM-SOURCES": "Disable System Sources",
"DEPOSIT-PLUGINS": "Plugin",
"FILE-TRANSFORMER-PLUGINS": "Plugin",
"REPOSITORY-ID": "Repository Id",
"TRANSFORMER-ID": "Transformer Id",
"URL": "Url",
"ISSUER-URL": "Issuer Url",
"CLIENT-ID": "Client Id",
"CLIENT-SECRET": "Client Secret",
"SCOPE": "Scope",
"PDF-TRANSFORMER-ID": "Pdf Transformer Id",
"RDA-TRANSFORMER-ID": "Rda Transformer Id"
},
"RESET-TO-DEFAULT-DIALOG":{
"RESET-TO-DEFAULT": "Reset To Default"
},
"ACTIONS": {
"SAVE": "Save",
"UPLOAD": "Upload",
"DOWNLOAD": "Download",
"ADD-SOURCE": "Add Source",
"RESET-TO-DEFAULT": "Reset To Default"
}
},
"DESCRIPTION-TEMPLATE-EDITOR": { "DESCRIPTION-TEMPLATE-EDITOR": {
"TITLE": { "TITLE": {
"NEW": "New API Client", "NEW": "New API Client",

View File

@ -0,0 +1,30 @@
####################################### Build stage #######################################
FROM maven:3.9-eclipse-temurin-21-alpine
ARG MAVEN_ACCOUNT_USR
ARG MAVEN_ACCOUNT_PSW
ARG REVISION
ARG PROFILE
ARG ORACLE_URL
ARG ORACLE_TOKEN
ENV server_username=$MAVEN_ACCOUNT_USR
ENV server_password=$MAVEN_ACCOUNT_PSW
ARG CITE_MAVEN_REPO_URL
COPY pom.xml /build/
COPY notification /build/notification/
COPY notification-web /build/notification-web/
COPY settings.xml /root/.m2/settings.xml
RUN rm -f /build/notification-web/src/main/resources/config/app.env
RUN rm -f /build/notification-web/src/main/resources/config/*-devel.yml
RUN rm -f /build/notification-web/src/main/resources/logging/*.xml
RUN rm -f /build/notification-web/src/main/resources/certificates/*.crt
COPY oracle.local.cite.gr.crt $JAVA_HOME/conf/security
RUN cd "$JAVA_HOME"/conf/security && keytool -cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias oraclecert -file oracle.local.cite.gr.crt
WORKDIR /build/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Dsonar.projectKey=OpenDMP:notification-api -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP Notification API'