diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java index c78a8a92..26edd117 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/sebconfig/ConfigurationNode.java @@ -39,7 +39,8 @@ public final class ConfigurationNode implements GrantEntity { public enum ConfigurationStatus { CONSTRUCTION, READY_TO_USE, - IN_USE + IN_USE, + ARCHIVED } @JsonProperty(CONFIGURATION_NODE.ATTR_ID) diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigList.java index 0be2a2d7..96da9d56 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigList.java @@ -95,7 +95,7 @@ public class SEBExamConfigList implements TemplateComposer { this.statusFilter = new TableFilterAttribute( CriteriaType.SINGLE_SELECTION, ConfigurationNode.FILTER_ATTR_STATUS, - this.resourceService::examConfigStatusResources); + this.resourceService::examConfigStatusFilterResources); } @Override diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java index d0da5c07..7b18d193 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/ResourceService.java @@ -450,8 +450,17 @@ public class ResourceService { .collect(Collectors.toList()); } - public List> examConfigStatusResources() { - return examConfigStatusResources(false); + public List> examConfigStatusFilterResources() { + return Arrays.stream(ConfigurationStatus.values()) + .map(type -> new Tuple3<>( + type.name(), + this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()), + Utils.formatLineBreaks(this.i18nSupport.getText( + this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()) + + Constants.TOOLTIP_TEXT_KEY_SUFFIX, + StringUtils.EMPTY)))) + .sorted(RESOURCE_COMPARATOR) + .collect(Collectors.toList()); } public List> examConfigStatusResources(final boolean isAttachedToExam) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java index e0bcc4f2..76cd4929 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageAction.java @@ -181,7 +181,7 @@ public final class PageAction { if (confirmMessage != null) { this.pageContext.applyConfirmDialog(confirmMessage, confirm -> callback.accept((confirm) - ? exec() + ? exec().onError(error -> this.pageContext.notifyUnexpectedError(error)) : Result.ofRuntimeError("Confirm denied"))); } else { callback.accept(exec()); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java index 5e1fd011..67508293 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamConfigurationMapDAO.java @@ -67,6 +67,13 @@ public interface ExamConfigurationMapDAO extends * @return Result referencing the List of exam identifiers (PK) for a given configuration identifier */ Result> getExamIdsForConfigId(Long configurationId); - Result checkForDeletion(Long configurationNodeId); + /** Use this to check if a specified exam configuration don't have any relations + * to an currently active exam, meaning in upcoming or running state. + * Exams in finished state are not active and will not go into account here. + * + * @param configurationNodeId the identifier of exam configuration to check + * @return Result refer to true if config has no relations to active exams, or false of it has or refer to an error + * if happened */ + Result checkNoActiveExamReferences(Long configurationNodeId); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java index f55032d5..36dfed99 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationNodeDAOImpl.java @@ -19,6 +19,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.mybatis.dynamic.sql.SqlBuilder; import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter; import org.mybatis.dynamic.sql.select.QueryExpressionDSL; @@ -123,17 +124,15 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { .on(InstitutionRecordDynamicSqlSupport.id, SqlBuilder.equalTo(ConfigurationNodeRecordDynamicSqlSupport.institutionId)) .where( - ConfigurationNodeRecordDynamicSqlSupport.status, - SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())) + ConfigurationNodeRecordDynamicSqlSupport.institutionId, + SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId())) : this.configurationNodeRecordMapper .selectByExample() .where( - ConfigurationNodeRecordDynamicSqlSupport.status, - SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())); + ConfigurationNodeRecordDynamicSqlSupport.institutionId, + SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId())); - return whereClause.and( - ConfigurationNodeRecordDynamicSqlSupport.institutionId, - SqlBuilder.isEqualToWhenPresent(filterMap.getInstitutionId())) + whereClause .and( ConfigurationNodeRecordDynamicSqlSupport.name, SqlBuilder.isLikeWhenPresent(filterMap.getName())) @@ -145,7 +144,20 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO { SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeType())) .and( ConfigurationNodeRecordDynamicSqlSupport.templateId, - SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeTemplateId())) + SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeTemplateId())); + + final String status = filterMap.getConfigNodeStatus(); + if (StringUtils.isBlank(status)) { + whereClause.and( + ConfigurationNodeRecordDynamicSqlSupport.status, + SqlBuilder.isNotEqualToWhenPresent(ConfigurationStatus.ARCHIVED.name())); + } else { + whereClause.and( + ConfigurationNodeRecordDynamicSqlSupport.status, + SqlBuilder.isEqualToWhenPresent(filterMap.getConfigNodeStatus())); + } + + return whereClause .build() .execute() .stream() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java index f965f8a9..ff364d13 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java @@ -375,7 +375,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { @Override @Transactional(readOnly = true) - public Result checkForDeletion(final Long configurationNodeId) { + public Result checkNoActiveExamReferences(final Long configurationNodeId) { return Result.tryCatch(() -> !this.examConfigurationMapRecordMapper.selectByExample() .where( ExamConfigurationMapRecordDynamicSqlSupport.configurationNodeId, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java index 44d0185c..9468efda 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ConfigurationNodeController.java @@ -511,13 +511,34 @@ public class ConfigurationNodeController extends EntityController validForDelete(final ConfigurationNode entity) { return Result.tryCatch(() -> { - if (!this.examConfigurationMapDAO.checkForDeletion(entity.id).getOr(false)) { + if (!this.examConfigurationMapDAO.checkNoActiveExamReferences(entity.id).getOr(false)) { throw new APIMessageException( APIMessage.ErrorMessage.INTEGRITY_VALIDATION .of("Exam configuration has references to at least one upcoming or running exam.")); diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 039772cd..373be9d3 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -863,6 +863,7 @@ sebserver.examconfig.form.attached-to.tooltip=This SEB exam configuration is cur sebserver.examconfig.status.CONSTRUCTION=Under Construction sebserver.examconfig.status.READY_TO_USE=Ready To Use sebserver.examconfig.status.IN_USE=In Use +sebserver.examconfig.status.ARCHIVED=Archived sebserver.examconfig.props.from.unpublished.message=Note: There are unpublished changes to this Settings. Use 'Save/Publish Settings' to make sure the settings are active. sebserver.examconfig.props.from.title=SEB Settings ({0})