SEBSERV-398 - add bulk delete for exam config
This commit is contained in:
parent
25e9b9be1e
commit
f191d59495
6 changed files with 271 additions and 3 deletions
|
@ -715,6 +715,12 @@ public enum ActionDefinition {
|
|||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_LIST,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
|
||||
SEB_EXAM_CONFIG_BULK_DELETE(
|
||||
new LocTextKey("sebserver.examconfig.list.batch.action.delete"),
|
||||
ImageIcon.DELETE,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_LIST,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
|
||||
SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST(
|
||||
new LocTextKey("sebserver.examconfig.action.list.modify.properties"),
|
||||
ImageIcon.EDIT,
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
package ch.ethz.seb.sebserver.gui.content.configs;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API.BatchActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.BatchAction;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.AbstractBatchActionWizard;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodesByIds;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import org.apache.tomcat.util.buf.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SEBExamConfigBatchDeletePopup extends AbstractBatchActionWizard {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SEBExamConfigBatchDeletePopup.class);
|
||||
|
||||
private final static LocTextKey FORM_TITLE = new LocTextKey("sebserver.examconfig.list.batch.delete.title");
|
||||
private final static LocTextKey FORM_INFO = new LocTextKey("sebserver.examconfig.list.batch.delete.info");
|
||||
private final static LocTextKey ACTION_DO_DELETE = new LocTextKey("sebserver.examconfig.list.batch.action.delete");
|
||||
|
||||
protected SEBExamConfigBatchDeletePopup(
|
||||
final PageService pageService,
|
||||
final ServerPushService serverPushService) {
|
||||
|
||||
super(pageService, serverPushService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocTextKey getTitle() {
|
||||
return FORM_TITLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocTextKey getBatchActionInfo() {
|
||||
return FORM_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocTextKey getBatchActionTitle() {
|
||||
return ACTION_DO_DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BatchActionType getBatchActionType() {
|
||||
return BatchActionType.EXAM_CONFIG_DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Supplier<PageContext> createResultPageSupplier(PageContext pageContext, FormHandle<ConfigurationNode> formHandle) {
|
||||
return () -> pageContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void extendBatchActionRequest(PageContext pageContext, RestCall<BatchAction>.RestCallBuilder batchActionRequestBuilder) {
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FormBuilder buildSpecificFormFields(PageContext formContext, FormBuilder formHead, boolean readonly) {
|
||||
return formHead;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processUpdateListAction(PageContext formContext) {
|
||||
this.pageService.executePageAction(this.pageService.pageActionBuilder(formContext)
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_LIST)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySelectionList(
|
||||
final PageContext formContext,
|
||||
final Set<EntityKey> multiSelection) {
|
||||
|
||||
final ResourceService resourceService = this.pageService.getResourceService();
|
||||
|
||||
final String ids = StringUtils.join(
|
||||
multiSelection.stream().map(EntityKey::getModelId).collect(Collectors.toList()),
|
||||
Constants.LIST_SEPARATOR_CHAR);
|
||||
|
||||
final RestService restService = this.pageService.getRestService();
|
||||
final List<ConfigurationNode> selected = new ArrayList<>(restService.getBuilder(GetExamConfigNodesByIds.class)
|
||||
.withQueryParam(API.PARAM_MODEL_ID_LIST, ids)
|
||||
.call()
|
||||
.getOr(Collections.emptyList()));
|
||||
|
||||
selected.sort((examConfig1, examConfig2) -> examConfig1.name.compareTo(examConfig2.name));
|
||||
|
||||
this.pageService.staticListTableBuilder(selected, EntityType.CONFIGURATION_NODE)
|
||||
.withPaging(10)
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_NAME,
|
||||
SEBExamConfigList.NAME_TEXT_KEY,
|
||||
ConfigurationNode::getName))
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_STATUS,
|
||||
SEBExamConfigList.STATUS_TEXT_KEY,
|
||||
resourceService::localizedExamConfigStatusName)
|
||||
)
|
||||
|
||||
.compose(formContext);
|
||||
}
|
||||
}
|
|
@ -53,11 +53,11 @@ public class SEBExamConfigList implements TemplateComposer {
|
|||
new LocTextKey("sebserver.examconfig.list.title");
|
||||
private static final LocTextKey INSTITUTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.institution");
|
||||
private static final LocTextKey NAME_TEXT_KEY =
|
||||
public static final LocTextKey NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.name");
|
||||
private static final LocTextKey DESCRIPTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.description");
|
||||
private static final LocTextKey STATUS_TEXT_KEY =
|
||||
public static final LocTextKey STATUS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.status");
|
||||
private static final LocTextKey TEMPLATE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.template");
|
||||
|
@ -81,6 +81,8 @@ public class SEBExamConfigList implements TemplateComposer {
|
|||
private final SEBExamConfigCreationPopup sebExamConfigCreationPopup;
|
||||
private final SEBExamConfigBatchStateChangePopup sebExamConfigBatchStateChangePopup;
|
||||
private final SEBExamConfigBatchResetToTemplatePopup sebExamConfigBatchResetToTemplatePopup;
|
||||
private final SEBExamConfigBatchDeletePopup sebExamConfigBatchDeletePopup;
|
||||
|
||||
private final CurrentUser currentUser;
|
||||
private final ResourceService resourceService;
|
||||
private final int pageSize;
|
||||
|
@ -91,6 +93,7 @@ public class SEBExamConfigList implements TemplateComposer {
|
|||
final SEBExamConfigCreationPopup sebExamConfigCreationPopup,
|
||||
final SEBExamConfigBatchStateChangePopup sebExamConfigBatchStateChangePopup,
|
||||
final SEBExamConfigBatchResetToTemplatePopup sebExamConfigBatchResetToTemplatePopup,
|
||||
final SEBExamConfigBatchDeletePopup sebExamConfigBatchDeletePopup,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
|
||||
this.pageService = pageService;
|
||||
|
@ -98,6 +101,7 @@ public class SEBExamConfigList implements TemplateComposer {
|
|||
this.sebExamConfigCreationPopup = sebExamConfigCreationPopup;
|
||||
this.sebExamConfigBatchStateChangePopup = sebExamConfigBatchStateChangePopup;
|
||||
this.sebExamConfigBatchResetToTemplatePopup = sebExamConfigBatchResetToTemplatePopup;
|
||||
this.sebExamConfigBatchDeletePopup = sebExamConfigBatchDeletePopup;
|
||||
this.currentUser = pageService.getCurrentUser();
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.pageSize = pageSize;
|
||||
|
@ -188,7 +192,8 @@ public class SEBExamConfigList implements TemplateComposer {
|
|||
ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROP_FROM_LIST,
|
||||
ActionDefinition.SEB_EXAM_CONFIG_COPY_CONFIG_FROM_LIST,
|
||||
ActionDefinition.SEB_EXAM_CONFIG_BULK_STATE_CHANGE,
|
||||
ActionDefinition.SEB_EXAM_CONFIG_BULK_RESET_TO_TEMPLATE))
|
||||
ActionDefinition.SEB_EXAM_CONFIG_BULK_RESET_TO_TEMPLATE,
|
||||
ActionDefinition.SEB_EXAM_CONFIG_BULK_DELETE))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
|
@ -248,6 +253,14 @@ public class SEBExamConfigList implements TemplateComposer {
|
|||
.noEventPropagation()
|
||||
.publishIf(() -> !isLight && examConfigGrant.im(), false)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_BULK_DELETE)
|
||||
.withSelect(
|
||||
configTable::getMultiSelection,
|
||||
this.sebExamConfigBatchDeletePopup.popupCreationFunction(pageContext),
|
||||
EMPTY_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> !isLight && examConfigGrant.im(), false)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG)
|
||||
.withSelect(
|
||||
configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUTION),
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetExamConfigNodesByIds extends RestCall<Collection<ConfigurationNode>> {
|
||||
|
||||
public GetExamConfigNodesByIds() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_LIST,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<Collection<ConfigurationNode>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT + API.LIST_PATH_SEGMENT
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API.BatchActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.BatchAction;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BatchActionExec;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@WebServiceProfile
|
||||
public class ExamConfigDelete implements BatchActionExec {
|
||||
|
||||
private final ConfigurationNodeDAO configurationNodeDAO;
|
||||
private final AuthorizationService authorizationService;
|
||||
private final ExamConfigurationMapDAO examConfigurationMapDAO;
|
||||
|
||||
public ExamConfigDelete(
|
||||
final ExamConfigService sebExamConfigService,
|
||||
final ConfigurationNodeDAO configurationNodeDAO,
|
||||
final AuthorizationService authorizationService,
|
||||
final ExamConfigurationMapDAO examConfigurationMapDAO) {
|
||||
|
||||
this.configurationNodeDAO = configurationNodeDAO;
|
||||
this.authorizationService = authorizationService;
|
||||
this.examConfigurationMapDAO = examConfigurationMapDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchActionType actionType() {
|
||||
return BatchActionType.EXAM_CONFIG_DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public APIMessage checkConsistency(final Map<String, String> actionAttributes) {
|
||||
// no additional check here
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<EntityKey> doSingleAction(final String modelId, final BatchAction batchAction) {
|
||||
return this.configurationNodeDAO
|
||||
.byModelId(modelId)
|
||||
.flatMap(examConfig -> this.authorizationService.check(PrivilegeType.MODIFY, examConfig))
|
||||
.flatMap(examConfig -> checkDeletionRequirements(examConfig))
|
||||
.flatMap(examConfig -> this.configurationNodeDAO.delete(new HashSet<>(Arrays.asList(new EntityKey(
|
||||
modelId,
|
||||
EntityType.CONFIGURATION_NODE))))
|
||||
)
|
||||
.map(res -> res.stream().collect(Collectors.toList()).get(0));
|
||||
}
|
||||
|
||||
private Result<ConfigurationNode> checkDeletionRequirements(ConfigurationNode examConfig){
|
||||
Result<Boolean> isNotActive = this.examConfigurationMapDAO.checkNoActiveExamReferences(examConfig.id);
|
||||
if(!isNotActive.getOrThrow()){
|
||||
return Result.ofError(new APIMessageException(
|
||||
APIMessage.ErrorMessage.INTEGRITY_VALIDATION
|
||||
.of("Exam Configuration has active Exam references")
|
||||
));
|
||||
}
|
||||
|
||||
return Result.of(examConfig);
|
||||
}
|
||||
|
||||
}
|
|
@ -1097,6 +1097,9 @@ sebserver.examconfig.list.batch.action.status=Target Status
|
|||
sebserver.examconfig.list.action.reset=Reset To Template Settings
|
||||
sebserver.examconfig.list.batch.reset.title=Reset To Template Settings
|
||||
sebserver.examconfig.list.batch.action.reset=Reset All
|
||||
sebserver.examconfig.list.batch.action.delete=Delete
|
||||
sebserver.examconfig.list.batch.delete.title=Delete Selected Exam Configurations
|
||||
sebserver.examconfig.list.batch.delete.info=Please Note:<br/> This deletes the exam configuration in SEB Server<br/>
|
||||
sebserver.examconfig.list.batch.action.reset.info=This action process a reset of the SEB settings to its template settings for all selected configurations.<br/>Please note this will be done only for those that has an origin template and are not in state "Used". <br/>Please note also that this action tries to directly publish the changes and if not possible (active SEB client connections) it will report an error even if the settings has been reseted.
|
||||
|
||||
sebserver.examconfig.action.list.modify.properties=Edit Exam Configuration
|
||||
|
|
Loading…
Reference in a new issue