SEBSERV-10 GUI implementation
This commit is contained in:
parent
265624ec4c
commit
cc0f15ab62
23 changed files with 520 additions and 149 deletions
|
@ -26,7 +26,9 @@ public final class API {
|
||||||
public static final String PARAM_MODEL_ID_LIST = "modelIds";
|
public static final String PARAM_MODEL_ID_LIST = "modelIds";
|
||||||
public static final String PARAM_PARENT_MODEL_ID = "parentModelId";
|
public static final String PARAM_PARENT_MODEL_ID = "parentModelId";
|
||||||
public static final String PARAM_ENTITY_TYPE = "entityType";
|
public static final String PARAM_ENTITY_TYPE = "entityType";
|
||||||
|
|
||||||
public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType";
|
public static final String PARAM_BULK_ACTION_TYPE = "bulkActionType";
|
||||||
|
public static final String PARAM_BULK_ACTION_ADD_INCLUDES = "bulkActionAddIncludes";
|
||||||
public static final String PARAM_BULK_ACTION_INCLUDES = "bulkActionIncludes";
|
public static final String PARAM_BULK_ACTION_INCLUDES = "bulkActionIncludes";
|
||||||
public static final String PARAM_VIEW_ID = "viewId";
|
public static final String PARAM_VIEW_ID = "viewId";
|
||||||
public static final String PARAM_INSTRUCTION_TYPE = "instructionType";
|
public static final String PARAM_INSTRUCTION_TYPE = "instructionType";
|
||||||
|
|
|
@ -8,43 +8,60 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content;
|
package ch.ethz.seb.sebserver.gui.content;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
|
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||||
import ch.ethz.seb.sebserver.gui.form.Form;
|
import ch.ethz.seb.sebserver.gui.form.Form;
|
||||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
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.page.PageService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.DeleteUserAccount;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserDependency;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserDependency;
|
||||||
|
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||||
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Component
|
@Component
|
||||||
@GuiProfile
|
@GuiProfile
|
||||||
public class UserAccountDeletePopup {
|
public class UserAccountDeletePopup {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(UserAccountDeletePopup.class);
|
||||||
|
|
||||||
private final static String ARG_WITH_CONFIGS = "WITH_CONFIGS";
|
private final static String ARG_WITH_CONFIGS = "WITH_CONFIGS";
|
||||||
private final static String ARG_WITH_EXAMS = "WITH_EXAMS";
|
private final static String ARG_WITH_EXAMS = "WITH_EXAMS";
|
||||||
|
|
||||||
|
@ -52,6 +69,17 @@ public class UserAccountDeletePopup {
|
||||||
new LocTextKey("sebserver.useraccount.delete.form.title");
|
new LocTextKey("sebserver.useraccount.delete.form.title");
|
||||||
private final static LocTextKey FORM_INFO =
|
private final static LocTextKey FORM_INFO =
|
||||||
new LocTextKey("sebserver.useraccount.delete.form.info");
|
new LocTextKey("sebserver.useraccount.delete.form.info");
|
||||||
|
private final static LocTextKey FORM_REPORT_INFO =
|
||||||
|
new LocTextKey("sebserver.useraccount.delete.form.report.info");
|
||||||
|
private final static LocTextKey FORM_REPORT_LIST_TYPE =
|
||||||
|
new LocTextKey("sebserver.useraccount.delete.form.report.list.type");
|
||||||
|
private final static LocTextKey FORM_REPORT_LIST_NAME =
|
||||||
|
new LocTextKey("sebserver.useraccount.delete.form.report.list.name");
|
||||||
|
private final static LocTextKey FORM_REPORT_LIST_DESC =
|
||||||
|
new LocTextKey("sebserver.useraccount.delete.form.report.list.description");
|
||||||
|
|
||||||
|
private final static LocTextKey FORM_REPORT_NONE =
|
||||||
|
new LocTextKey("sebserver.useraccount.delete.form.report.empty");
|
||||||
private final static LocTextKey FORM_NAME =
|
private final static LocTextKey FORM_NAME =
|
||||||
new LocTextKey("sebserver.useraccount.delete.form.accountName");
|
new LocTextKey("sebserver.useraccount.delete.form.accountName");
|
||||||
private final static LocTextKey FORM_CONFIGS =
|
private final static LocTextKey FORM_CONFIGS =
|
||||||
|
@ -63,6 +91,9 @@ public class UserAccountDeletePopup {
|
||||||
private final static LocTextKey ACTION_REPORT =
|
private final static LocTextKey ACTION_REPORT =
|
||||||
new LocTextKey("sebserver.useraccount.delete.form.action.report");
|
new LocTextKey("sebserver.useraccount.delete.form.action.report");
|
||||||
|
|
||||||
|
private final static LocTextKey DELETE_CONFIRM_TITLE =
|
||||||
|
new LocTextKey("sebserver.useraccount.delete.confirm.title");
|
||||||
|
|
||||||
private final PageService pageService;
|
private final PageService pageService;
|
||||||
|
|
||||||
protected UserAccountDeletePopup(final PageService pageService) {
|
protected UserAccountDeletePopup(final PageService pageService) {
|
||||||
|
@ -76,15 +107,17 @@ public class UserAccountDeletePopup {
|
||||||
new ModelInputWizard<PageContext>(
|
new ModelInputWizard<PageContext>(
|
||||||
action.pageContext().getParent().getShell(),
|
action.pageContext().getParent().getShell(),
|
||||||
this.pageService.getWidgetFactory())
|
this.pageService.getWidgetFactory())
|
||||||
.setLargeDialogWidth();
|
.setVeryLargeDialogWidth();
|
||||||
|
|
||||||
final String page1Id = "DELETE_PAGE";
|
final String page1Id = "DELETE_PAGE";
|
||||||
final String page2Id = "REPORT_PAGE";
|
final String page2Id = "REPORT_PAGE";
|
||||||
final Predicate<PageContext> callback = pc -> doDelete(this.pageService, pc);
|
final Predicate<PageContext> callback = pc -> doDelete(this.pageService, pc);
|
||||||
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage1 =
|
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage1 =
|
||||||
(formHandle, content) -> composeDeleteDialog(content, pageContext);
|
(prefPageContext, content) -> composeDeleteDialog(content,
|
||||||
|
(prefPageContext != null) ? prefPageContext : pageContext);
|
||||||
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage2 =
|
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage2 =
|
||||||
(formHandle, content) -> composeReportDialog(content, pageContext);
|
(prefPageContext, content) -> composeReportDialog(content,
|
||||||
|
(prefPageContext != null) ? prefPageContext : pageContext);
|
||||||
|
|
||||||
final WizardPage<PageContext> page1 = new WizardPage<>(
|
final WizardPage<PageContext> page1 = new WizardPage<>(
|
||||||
page1Id,
|
page1Id,
|
||||||
|
@ -109,15 +142,81 @@ public class UserAccountDeletePopup {
|
||||||
final PageService pageService,
|
final PageService pageService,
|
||||||
final PageContext pageContext) {
|
final PageContext pageContext) {
|
||||||
|
|
||||||
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
try {
|
||||||
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
|
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
||||||
return true;
|
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
|
||||||
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
|
final UserInfo currentUser = pageService.getCurrentUser().get();
|
||||||
|
final boolean ownAccount = currentUser.getModelId().equals(entityKey.modelId);
|
||||||
|
final UserInfo userToDelete = this.pageService.getRestService().getBuilder(GetUserAccount.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
|
.call()
|
||||||
|
.getOrThrow();
|
||||||
|
|
||||||
|
final RestCall<EntityProcessingReport>.RestCallBuilder restCallBuilder = this.pageService.getRestService()
|
||||||
|
.getBuilder(DeleteUserAccount.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
|
.withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.HARD_DELETE.name())
|
||||||
|
.withQueryParam(API.PARAM_BULK_ACTION_ADD_INCLUDES, Constants.TRUE_STRING);
|
||||||
|
|
||||||
|
if (withConfigs) {
|
||||||
|
restCallBuilder.withQueryParam(
|
||||||
|
API.PARAM_BULK_ACTION_INCLUDES,
|
||||||
|
EntityType.CONFIGURATION_NODE.name());
|
||||||
|
}
|
||||||
|
if (withExams) {
|
||||||
|
restCallBuilder.withQueryParam(
|
||||||
|
API.PARAM_BULK_ACTION_INCLUDES,
|
||||||
|
EntityType.EXAM.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
final EntityProcessingReport report = restCallBuilder.call().getOrThrow();
|
||||||
|
|
||||||
|
if (ownAccount) {
|
||||||
|
pageService.logout(pageContext);
|
||||||
|
} else {
|
||||||
|
final PageAction action = this.pageService.pageActionBuilder(pageContext)
|
||||||
|
.newAction(ActionDefinition.USER_ACCOUNT_VIEW_LIST)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
this.pageService.firePageEvent(
|
||||||
|
new ActionEvent(action),
|
||||||
|
action.pageContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String userName = userToDelete.toName().name;
|
||||||
|
final List<EntityKey> dependencies = report.results.stream()
|
||||||
|
.filter(key -> !key.equals(entityKey))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
pageContext.publishPageMessage(
|
||||||
|
DELETE_CONFIRM_TITLE,
|
||||||
|
new LocTextKey(
|
||||||
|
"sebserver.useraccount.delete.confirm.message",
|
||||||
|
userName,
|
||||||
|
dependencies.size(),
|
||||||
|
(report.errors.isEmpty()) ? "no" : String.valueOf((report.errors.size()))));
|
||||||
|
return true;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Unexpected error while trying to delete User Account:", e);
|
||||||
|
pageContext.notifyUnexpectedError(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Supplier<PageContext> composeDeleteDialog(
|
private Supplier<PageContext> composeDeleteDialog(
|
||||||
final Composite parent,
|
final Composite parent,
|
||||||
final PageContext pageContext) {
|
final PageContext pageContext) {
|
||||||
|
|
||||||
|
final Composite grid = this.pageService.getWidgetFactory()
|
||||||
|
.createPopupScrollComposite(parent);
|
||||||
|
|
||||||
|
final Label title = this.pageService.getWidgetFactory()
|
||||||
|
.labelLocalized(grid, CustomVariant.TEXT_H3, FORM_INFO);
|
||||||
|
final GridData gridData = new GridData();
|
||||||
|
gridData.horizontalIndent = 10;
|
||||||
|
gridData.verticalIndent = 10;
|
||||||
|
title.setLayoutData(gridData);
|
||||||
|
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final UserInfo userInfo = this.pageService.getRestService()
|
final UserInfo userInfo = this.pageService.getRestService()
|
||||||
.getBuilder(GetUserAccount.class)
|
.getBuilder(GetUserAccount.class)
|
||||||
|
@ -126,8 +225,10 @@ public class UserAccountDeletePopup {
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
final FormHandle<?> formHandle = this.pageService.formBuilder(
|
final FormHandle<?> formHandle = this.pageService.formBuilder(
|
||||||
pageContext.copyOf(parent))
|
pageContext.copyOf(grid))
|
||||||
.readonly(false)
|
.readonly(false)
|
||||||
|
.withDefaultSpanLabel(3)
|
||||||
|
.withDefaultSpanInput(4)
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
"USE_NAME",
|
"USE_NAME",
|
||||||
FORM_NAME,
|
FORM_NAME,
|
||||||
|
@ -153,36 +254,67 @@ public class UserAccountDeletePopup {
|
||||||
final Composite parent,
|
final Composite parent,
|
||||||
final PageContext pageContext) {
|
final PageContext pageContext) {
|
||||||
|
|
||||||
// get selection
|
final Composite grid = this.pageService.getWidgetFactory()
|
||||||
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
.createPopupScrollCompositeFilled(parent);
|
||||||
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
|
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
|
||||||
|
|
||||||
// get dependencies
|
final Label title = this.pageService.getWidgetFactory()
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
.labelLocalized(grid, CustomVariant.TEXT_H3, FORM_REPORT_INFO);
|
||||||
final RestCall<Set<EntityDependency>>.RestCallBuilder restCallBuilder = this.pageService.getRestService()
|
final GridData gridData = new GridData();
|
||||||
.getBuilder(GetUserDependency.class)
|
gridData.horizontalIndent = 10;
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId);
|
gridData.verticalIndent = 10;
|
||||||
|
title.setLayoutData(gridData);
|
||||||
|
|
||||||
if (withConfigs) {
|
try {
|
||||||
restCallBuilder.withQueryParam(
|
// get selection
|
||||||
API.PARAM_BULK_ACTION_INCLUDES,
|
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
||||||
EntityType.CONFIGURATION_NODE.name());
|
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
|
||||||
|
|
||||||
|
// get dependencies
|
||||||
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
|
final RestCall<Set<EntityDependency>>.RestCallBuilder restCallBuilder = this.pageService.getRestService()
|
||||||
|
.getBuilder(GetUserDependency.class)
|
||||||
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
|
.withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.HARD_DELETE.name())
|
||||||
|
.withQueryParam(API.PARAM_BULK_ACTION_ADD_INCLUDES, Constants.TRUE_STRING);
|
||||||
|
|
||||||
|
if (withConfigs) {
|
||||||
|
restCallBuilder.withQueryParam(
|
||||||
|
API.PARAM_BULK_ACTION_INCLUDES,
|
||||||
|
EntityType.CONFIGURATION_NODE.name());
|
||||||
|
}
|
||||||
|
if (withExams) {
|
||||||
|
restCallBuilder.withQueryParam(
|
||||||
|
API.PARAM_BULK_ACTION_INCLUDES,
|
||||||
|
EntityType.EXAM.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
final Set<EntityDependency> dependencies = restCallBuilder.call().getOrThrow();
|
||||||
|
final List<EntityDependency> list = dependencies.stream().sorted().collect(Collectors.toList());
|
||||||
|
this.pageService.<EntityDependency> staticListTableBuilder(list, null)
|
||||||
|
.withEmptyMessage(FORM_REPORT_NONE)
|
||||||
|
.withColumn(new ColumnDefinition<>(
|
||||||
|
"FORM_REPORT_LIST_TYPE",
|
||||||
|
FORM_REPORT_LIST_TYPE,
|
||||||
|
dep -> i18nSupport
|
||||||
|
.getText("sebserver.overall.types.entityType." + dep.self.entityType.name()) +
|
||||||
|
" (" + dep.self.getModelId() + ")"))
|
||||||
|
.withColumn(new ColumnDefinition<>(
|
||||||
|
"FORM_REPORT_LIST_NAME",
|
||||||
|
FORM_REPORT_LIST_NAME,
|
||||||
|
dep -> dep.name))
|
||||||
|
.withColumn(new ColumnDefinition<>(
|
||||||
|
"FORM_REPORT_LIST_DESC",
|
||||||
|
FORM_REPORT_LIST_DESC,
|
||||||
|
dep -> dep.description))
|
||||||
|
.compose(pageContext.copyOf(grid));
|
||||||
|
|
||||||
|
return () -> pageContext;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Error while trying to compose User Account delete report page: ", e);
|
||||||
|
pageContext.notifyUnexpectedError(e);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
if (withExams) {
|
|
||||||
restCallBuilder.withQueryParam(
|
|
||||||
API.PARAM_BULK_ACTION_INCLUDES,
|
|
||||||
EntityType.EXAM.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
// final EntityTable<ConfigurationNode> configTable =
|
|
||||||
// this.pageService.entityTableBuilder(GetUserDependency.class)
|
|
||||||
// .
|
|
||||||
|
|
||||||
final Set<EntityDependency> dependencies = restCallBuilder.call().getOrThrow();
|
|
||||||
|
|
||||||
// TODO get dependencies in case of selection and show all in a list (type / name)
|
|
||||||
|
|
||||||
return () -> pageContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,8 +133,8 @@ public enum ActionDefinition {
|
||||||
USER_ACCOUNT_DELETE(
|
USER_ACCOUNT_DELETE(
|
||||||
new LocTextKey("sebserver.useraccount.action.delete"),
|
new LocTextKey("sebserver.useraccount.action.delete"),
|
||||||
ImageIcon.DELETE,
|
ImageIcon.DELETE,
|
||||||
PageStateDefinitionImpl.USER_ACCOUNT_LIST,
|
PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
|
||||||
ActionCategory.USER_ACCOUNT_LIST),
|
ActionCategory.FORM),
|
||||||
|
|
||||||
USER_ACCOUNT_CHANGE_PASSWORD(
|
USER_ACCOUNT_CHANGE_PASSWORD(
|
||||||
new LocTextKey("sebserver.useraccount.action.change.password"),
|
new LocTextKey("sebserver.useraccount.action.change.password"),
|
||||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gui.service.page;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -294,7 +295,7 @@ public interface PageService {
|
||||||
* @param apiCall the SEB Server API RestCall that feeds the table with data
|
* @param apiCall the SEB Server API RestCall that feeds the table with data
|
||||||
* @param <T> the type of the Entity of the table
|
* @param <T> the type of the Entity of the table
|
||||||
* @return TableBuilder of specified type */
|
* @return TableBuilder of specified type */
|
||||||
default <T extends Entity> TableBuilder<T> entityTableBuilder(final RestCall<Page<T>> apiCall) {
|
default <T> TableBuilder<T> entityTableBuilder(final RestCall<Page<T>> apiCall) {
|
||||||
return entityTableBuilder(apiCall.getClass().getSimpleName(), apiCall);
|
return entityTableBuilder(apiCall.getClass().getSimpleName(), apiCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,10 +305,12 @@ public interface PageService {
|
||||||
* @param apiCall the SEB Server API RestCall that feeds the table with data
|
* @param apiCall the SEB Server API RestCall that feeds the table with data
|
||||||
* @param <T> the type of the Entity of the table
|
* @param <T> the type of the Entity of the table
|
||||||
* @return TableBuilder of specified type */
|
* @return TableBuilder of specified type */
|
||||||
<T extends Entity> TableBuilder<T> entityTableBuilder(
|
<T> TableBuilder<T> entityTableBuilder(
|
||||||
String name,
|
String name,
|
||||||
RestCall<Page<T>> apiCall);
|
RestCall<Page<T>> apiCall);
|
||||||
|
|
||||||
|
<T> TableBuilder<T> staticListTableBuilder(final List<T> staticList, EntityType entityType);
|
||||||
|
|
||||||
/** Get a new PageActionBuilder for a given PageContext.
|
/** Get a new PageActionBuilder for a given PageContext.
|
||||||
*
|
*
|
||||||
* @param pageContext the PageContext that is used by the new PageActionBuilder
|
* @param pageContext the PageContext that is used by the new PageActionBuilder
|
||||||
|
@ -347,9 +350,29 @@ public interface PageService {
|
||||||
final Composite parent,
|
final Composite parent,
|
||||||
final Function<ScrolledComposite, Composite> contentFunction,
|
final Function<ScrolledComposite, Composite> contentFunction,
|
||||||
final boolean showScrollbars) {
|
final boolean showScrollbars) {
|
||||||
|
return createManagedVScrolledComposite(parent, contentFunction, showScrollbars, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a ScrolledComposite with content supplied the given content creation function.
|
||||||
|
* The content creation function is used to create the content Composite as a child of the
|
||||||
|
* newly created ScrolledComposite.
|
||||||
|
* Also adds an update function within the ScrolledComposite Data mapping. If a child inside
|
||||||
|
* the ScrolledComposite changes its dimensions the method updateScrolledComposite must be
|
||||||
|
* called to update the ScrolledComposite scrolled content.
|
||||||
|
*
|
||||||
|
* @param parent the parent Composite of the ScrolledComposite
|
||||||
|
* @param contentFunction the content creation function
|
||||||
|
* @param showScrollbars indicates whether the scrollbar shall always be shown
|
||||||
|
* @param fill indicates if the content shall be vertically filled
|
||||||
|
* @return the child composite that is scrolled by the newly created ScrolledComposite */
|
||||||
|
static Composite createManagedVScrolledComposite(
|
||||||
|
final Composite parent,
|
||||||
|
final Function<ScrolledComposite, Composite> contentFunction,
|
||||||
|
final boolean showScrollbars,
|
||||||
|
final boolean fill) {
|
||||||
|
|
||||||
final ScrolledComposite scrolledComposite = new ScrolledComposite(parent, SWT.BORDER | SWT.V_SCROLL);
|
final ScrolledComposite scrolledComposite = new ScrolledComposite(parent, SWT.BORDER | SWT.V_SCROLL);
|
||||||
scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
|
scrolledComposite.setLayoutData(new GridData(SWT.FILL, (fill) ? SWT.FILL : SWT.TOP, true, true));
|
||||||
|
|
||||||
final Composite content = contentFunction.apply(scrolledComposite);
|
final Composite content = contentFunction.apply(scrolledComposite);
|
||||||
scrolledComposite.setContent(content);
|
scrolledComposite.setContent(content);
|
||||||
|
|
|
@ -115,15 +115,15 @@ public class ModalInputDialog<T> extends Dialog {
|
||||||
final ModalInputDialogComposer<T> contentComposer) {
|
final ModalInputDialogComposer<T> contentComposer) {
|
||||||
|
|
||||||
// Create the selection dialog window
|
// Create the selection dialog window
|
||||||
final Shell shell = new Shell(getParent(), getStyle());
|
this.shell = new Shell(getParent(), getStyle());
|
||||||
shell.setText(getText());
|
this.shell.setText(getText());
|
||||||
shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
this.shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||||
shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
this.shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||||
shell.setLayout(new GridLayout(2, true));
|
this.shell.setLayout(new GridLayout(2, true));
|
||||||
final GridData gridData2 = new GridData(SWT.FILL, SWT.TOP, false, false);
|
final GridData gridData2 = new GridData(SWT.FILL, SWT.TOP, false, false);
|
||||||
shell.setLayoutData(gridData2);
|
this.shell.setLayoutData(gridData2);
|
||||||
|
|
||||||
final Composite main = new Composite(shell, SWT.NONE);
|
final Composite main = new Composite(this.shell, SWT.NONE);
|
||||||
main.setLayout(new GridLayout());
|
main.setLayout(new GridLayout());
|
||||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
gridData.horizontalSpan = 2;
|
gridData.horizontalSpan = 2;
|
||||||
|
@ -133,7 +133,7 @@ public class ModalInputDialog<T> extends Dialog {
|
||||||
final Supplier<T> valueSupplier = contentComposer.compose(main);
|
final Supplier<T> valueSupplier = contentComposer.compose(main);
|
||||||
gridData.heightHint = calcDialogHeight(main);
|
gridData.heightHint = calcDialogHeight(main);
|
||||||
|
|
||||||
final Button ok = this.widgetFactory.buttonLocalized(shell, OK_TEXT_KEY);
|
final Button ok = this.widgetFactory.buttonLocalized(this.shell, OK_TEXT_KEY);
|
||||||
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);
|
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);
|
||||||
data.widthHint = this.buttonWidth;
|
data.widthHint = this.buttonWidth;
|
||||||
ok.setLayoutData(data);
|
ok.setLayoutData(data);
|
||||||
|
@ -141,16 +141,16 @@ public class ModalInputDialog<T> extends Dialog {
|
||||||
if (valueSupplier != null) {
|
if (valueSupplier != null) {
|
||||||
final T result = valueSupplier.get();
|
final T result = valueSupplier.get();
|
||||||
if (callback.test(result)) {
|
if (callback.test(result)) {
|
||||||
shell.close();
|
this.shell.close();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shell.close();
|
this.shell.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
shell.setDefaultButton(ok);
|
this.shell.setDefaultButton(ok);
|
||||||
|
|
||||||
final Button cancel = this.widgetFactory.buttonLocalized(shell, CANCEL_TEXT_KEY);
|
final Button cancel = this.widgetFactory.buttonLocalized(this.shell, CANCEL_TEXT_KEY);
|
||||||
data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
|
data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
|
||||||
data.widthHint = this.buttonWidth;
|
data.widthHint = this.buttonWidth;
|
||||||
cancel.setLayoutData(data);
|
cancel.setLayoutData(data);
|
||||||
|
@ -158,10 +158,10 @@ public class ModalInputDialog<T> extends Dialog {
|
||||||
if (cancelCallback != null) {
|
if (cancelCallback != null) {
|
||||||
cancelCallback.run();
|
cancelCallback.run();
|
||||||
}
|
}
|
||||||
shell.close();
|
this.shell.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
finishUp(shell);
|
finishUp(this.shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open(
|
public void open(
|
||||||
|
|
|
@ -25,6 +25,8 @@ import org.eclipse.swt.widgets.Button;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Dialog;
|
import org.eclipse.swt.widgets.Dialog;
|
||||||
import org.eclipse.swt.widgets.Shell;
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
|
@ -34,6 +36,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||||
|
|
||||||
public class ModelInputWizard<T> extends Dialog {
|
public class ModelInputWizard<T> extends Dialog {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ModelInputWizard.class);
|
||||||
|
|
||||||
private static final long serialVersionUID = -3314062148477979319L;
|
private static final long serialVersionUID = -3314062148477979319L;
|
||||||
|
|
||||||
private final WidgetFactory widgetFactory;
|
private final WidgetFactory widgetFactory;
|
||||||
|
@ -81,33 +85,92 @@ public class ModelInputWizard<T> extends Dialog {
|
||||||
final WizardPage<T>... pages) {
|
final WizardPage<T>... pages) {
|
||||||
|
|
||||||
// Create the selection dialog window
|
// Create the selection dialog window
|
||||||
final Shell shell = new Shell(getParent(), getStyle());
|
this.shell = new Shell(getParent(), getStyle());
|
||||||
shell.setText(getText());
|
this.shell.setText(getText());
|
||||||
shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
this.shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||||
shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
this.shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||||
shell.setLayout(new GridLayout(1, true));
|
this.shell.setLayout(new GridLayout());
|
||||||
final GridData gridData2 = new GridData(SWT.FILL, SWT.TOP, false, false);
|
final GridData gridData2 = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
shell.setLayoutData(gridData2);
|
this.shell.setLayoutData(gridData2);
|
||||||
|
|
||||||
// the content composite
|
// the content composite
|
||||||
final Composite main = new Composite(shell, SWT.NONE);
|
final Composite main = new Composite(this.shell, SWT.NONE);
|
||||||
main.setLayout(new GridLayout());
|
main.setLayout(new GridLayout());
|
||||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
gridData.widthHint = this.dialogWidth;
|
gridData.widthHint = this.dialogWidth;
|
||||||
main.setLayoutData(gridData);
|
main.setLayoutData(gridData);
|
||||||
|
|
||||||
final Composite actionComp = new Composite(shell, SWT.NONE);
|
final Composite content = new Composite(main, SWT.NONE);
|
||||||
|
content.setLayout(new GridLayout());
|
||||||
|
final GridData gridDataContent = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
|
content.setLayoutData(gridDataContent);
|
||||||
|
content.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||||
|
|
||||||
|
final Composite actionComp = new Composite(main, SWT.NONE);
|
||||||
actionComp.setLayout(new GridLayout());
|
actionComp.setLayout(new GridLayout());
|
||||||
actionComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
final GridData gridData3 = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
|
actionComp.setLayoutData(gridData3);
|
||||||
|
|
||||||
final Composite actionsComp = new Composite(actionComp, SWT.NONE);
|
final Composite actionsComp = new Composite(actionComp, SWT.NONE);
|
||||||
actionsComp.setLayout(new RowLayout(SWT.HORIZONTAL));
|
actionsComp.setLayout(new RowLayout(SWT.HORIZONTAL));
|
||||||
actionComp.setLayoutData(new GridData(SWT.TRAIL, SWT.FILL, true, true));
|
final GridData gridData4 = new GridData(SWT.CENTER, SWT.FILL, true, true);
|
||||||
|
actionComp.setLayoutData(gridData4);
|
||||||
|
|
||||||
final List<WizardPage<T>> pageList = Utils.immutableListOf(pages);
|
final List<WizardPage<T>> pageList = Utils.immutableListOf(pages);
|
||||||
createPage(null, pageList, null, main, actionsComp);
|
createPage(null, pageList, null, content, actionsComp, cancelCallback);
|
||||||
|
finishUp(this.shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPage(
|
||||||
|
final String pageId,
|
||||||
|
final List<WizardPage<T>> pages,
|
||||||
|
final T valueFromPrevPage,
|
||||||
|
final Composite contentComp,
|
||||||
|
final Composite actionsComp,
|
||||||
|
final Runnable cancelCallback) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
final Optional<WizardPage<T>> newPage = (pageId != null)
|
||||||
|
? pages.stream()
|
||||||
|
.filter(p -> pageId.equals(p.id))
|
||||||
|
.findFirst()
|
||||||
|
: pages.stream()
|
||||||
|
.filter(page -> page.isStart)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (!newPage.isPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WizardPage<T> page = newPage.get();
|
||||||
|
final Supplier<T> valueSupplier = page.contentCompose.apply(valueFromPrevPage, contentComp);
|
||||||
|
|
||||||
|
if (page.actions != null) {
|
||||||
|
for (final WizardAction<T> action : page.actions) {
|
||||||
|
final Button actionButton = this.widgetFactory.buttonLocalized(actionsComp, action.name);
|
||||||
|
final RowData data = new RowData();
|
||||||
|
data.width = this.buttonWidth;
|
||||||
|
actionButton.setLayoutData(data);
|
||||||
|
|
||||||
|
actionButton.addListener(SWT.Selection, event -> {
|
||||||
|
if (valueSupplier != null) {
|
||||||
|
final T result = valueSupplier.get();
|
||||||
|
if (action.toPage != null) {
|
||||||
|
PageService.clearComposite(contentComp);
|
||||||
|
PageService.clearComposite(actionsComp);
|
||||||
|
createPage(action.toPage, pages, result, contentComp, actionsComp, cancelCallback);
|
||||||
|
} else {
|
||||||
|
action.callback.test(result);
|
||||||
|
this.shell.close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.shell.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cancelCallback != null) {
|
|
||||||
final Button cancel = this.widgetFactory.buttonLocalized(actionsComp, ModalInputDialog.CANCEL_TEXT_KEY);
|
final Button cancel = this.widgetFactory.buttonLocalized(actionsComp, ModalInputDialog.CANCEL_TEXT_KEY);
|
||||||
final RowData data = new RowData();
|
final RowData data = new RowData();
|
||||||
data.width = this.buttonWidth;
|
data.width = this.buttonWidth;
|
||||||
|
@ -116,60 +179,24 @@ public class ModelInputWizard<T> extends Dialog {
|
||||||
if (cancelCallback != null) {
|
if (cancelCallback != null) {
|
||||||
cancelCallback.run();
|
cancelCallback.run();
|
||||||
}
|
}
|
||||||
shell.close();
|
this.shell.close();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
gridData.heightHint = calcDialogHeight(main);
|
try {
|
||||||
finishUp(shell);
|
final Composite parent = contentComp.getParent();
|
||||||
}
|
final int dialogHeight = calcDialogHeight(parent);
|
||||||
|
((GridData) parent.getLayoutData()).heightHint = dialogHeight;
|
||||||
|
((GridData) contentComp.getLayoutData()).heightHint = dialogHeight - 55;
|
||||||
|
((GridData) actionsComp.getLayoutData()).heightHint = 45;
|
||||||
|
|
||||||
private void createPage(
|
contentComp.getShell().layout(true, true);
|
||||||
final String pageId,
|
} catch (final Exception e) {
|
||||||
final List<WizardPage<T>> pages,
|
log.warn("Failed to calculate dialog height: {}", e.getMessage());
|
||||||
final T valueFromPrevPage,
|
|
||||||
final Composite contentComp,
|
|
||||||
final Composite actionsComp) {
|
|
||||||
|
|
||||||
final Optional<WizardPage<T>> newPage = (pageId != null)
|
|
||||||
? pages.stream()
|
|
||||||
.filter(p -> pageId.equals(p.id))
|
|
||||||
.findFirst()
|
|
||||||
: pages.stream()
|
|
||||||
.filter(page -> page.isStart)
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
if (!newPage.isPresent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final WizardPage<T> page = newPage.get();
|
|
||||||
PageService.clearComposite(contentComp);
|
|
||||||
PageService.clearComposite(actionsComp);
|
|
||||||
|
|
||||||
final Supplier<T> valueSupplier = page.contentCompose.apply(valueFromPrevPage, contentComp);
|
|
||||||
|
|
||||||
if (page.actions != null) {
|
|
||||||
for (final WizardAction<T> action : page.actions) {
|
|
||||||
final Button actionButton = this.widgetFactory.buttonLocalized(actionsComp, action.name);
|
|
||||||
final RowData data = new RowData();
|
|
||||||
data.width = this.buttonWidth;
|
|
||||||
actionButton.setLayoutData(data);
|
|
||||||
|
|
||||||
actionButton.addListener(SWT.Selection, event -> {
|
|
||||||
if (valueSupplier != null) {
|
|
||||||
final T result = valueSupplier.get();
|
|
||||||
if (action.toPage != null) {
|
|
||||||
createPage(action.toPage, pages, result, contentComp, actionsComp);
|
|
||||||
} else {
|
|
||||||
action.callback.test(result);
|
|
||||||
this.shell.close();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.shell.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Unexpected error: ", e);
|
||||||
|
this.shell.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -358,13 +358,25 @@ public class PageServiceImpl implements PageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Entity> TableBuilder<T> entityTableBuilder(
|
public <T> TableBuilder<T> entityTableBuilder(
|
||||||
final String name,
|
final String name,
|
||||||
final RestCall<Page<T>> apiCall) {
|
final RestCall<Page<T>> apiCall) {
|
||||||
|
|
||||||
return new TableBuilder<>(name, this, apiCall);
|
return new TableBuilder<>(name, this, apiCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> TableBuilder<T> staticListTableBuilder(
|
||||||
|
final List<T> staticList,
|
||||||
|
final EntityType entityType) {
|
||||||
|
|
||||||
|
return new TableBuilder<>(
|
||||||
|
(entityType != null)
|
||||||
|
? entityType.name()
|
||||||
|
: "",
|
||||||
|
this, staticList, entityType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void logout(final PageContext pageContext) {
|
public void logout(final PageContext pageContext) {
|
||||||
this.clearState();
|
this.clearState();
|
||||||
|
|
|
@ -12,12 +12,11 @@ import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||||
|
|
||||||
public final class ColumnDefinition<ROW extends Entity> {
|
public final class ColumnDefinition<ROW> {
|
||||||
|
|
||||||
private static final String TOOLTIP_TEXT_KEY_SUFFIX = ".tooltip";
|
private static final String TOOLTIP_TEXT_KEY_SUFFIX = ".tooltip";
|
||||||
|
|
||||||
|
|
|
@ -54,13 +54,12 @@ import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
|
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||||
import io.micrometer.core.instrument.util.StringUtils;
|
import io.micrometer.core.instrument.util.StringUtils;
|
||||||
|
|
||||||
public class EntityTable<ROW extends Entity> {
|
public class EntityTable<ROW> {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(EntityTable.class);
|
private static final Logger log = LoggerFactory.getLogger(EntityTable.class);
|
||||||
|
|
||||||
|
@ -108,7 +107,7 @@ public class EntityTable<ROW extends Entity> {
|
||||||
final boolean markupEnabled,
|
final boolean markupEnabled,
|
||||||
final int type,
|
final int type,
|
||||||
final PageContext pageContext,
|
final PageContext pageContext,
|
||||||
final RestCall<Page<ROW>> restCall,
|
final PageSupplier<ROW> pageSupplier,
|
||||||
final Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> pageSupplierAdapter,
|
final Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> pageSupplierAdapter,
|
||||||
final PageService pageService,
|
final PageService pageService,
|
||||||
final List<ColumnDefinition<ROW>> columns,
|
final List<ColumnDefinition<ROW>> columns,
|
||||||
|
@ -132,7 +131,7 @@ public class EntityTable<ROW extends Entity> {
|
||||||
this.i18nSupport = pageService.getI18nSupport();
|
this.i18nSupport = pageService.getI18nSupport();
|
||||||
this.pageContext = pageContext;
|
this.pageContext = pageContext;
|
||||||
this.widgetFactory = pageService.getWidgetFactory();
|
this.widgetFactory = pageService.getWidgetFactory();
|
||||||
this.pageSupplier = new RestCallPageSupplier<>(restCall);
|
this.pageSupplier = pageSupplier;
|
||||||
this.pageSupplierAdapter = (pageSupplierAdapter != null) ? pageSupplierAdapter : Function.identity();
|
this.pageSupplierAdapter = (pageSupplierAdapter != null) ? pageSupplierAdapter : Function.identity();
|
||||||
this.columns = Utils.immutableListOf(columns);
|
this.columns = Utils.immutableListOf(columns);
|
||||||
this.emptyMessage = emptyMessage;
|
this.emptyMessage = emptyMessage;
|
||||||
|
@ -581,7 +580,11 @@ public class EntityTable<ROW extends Entity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityKey getRowDataId(final TableItem item) {
|
private EntityKey getRowDataId(final TableItem item) {
|
||||||
return getRowData(item).getEntityKey();
|
final ROW rowData = getRowData(item);
|
||||||
|
if (rowData instanceof Entity) {
|
||||||
|
return ((Entity) rowData).getEntityKey();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateValues(final EntityTable<ROW> table) {
|
private void updateValues(final EntityTable<ROW> table) {
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ch.ethz.seb.sebserver.gui.table;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
|
||||||
|
public class StaticListPageSupplier<T> implements PageSupplier<T> {
|
||||||
|
|
||||||
|
private final EntityType entityType;
|
||||||
|
private final List<T> list;
|
||||||
|
|
||||||
|
public StaticListPageSupplier(final List<T> list, final EntityType entityType) {
|
||||||
|
this.list = list;
|
||||||
|
this.entityType = entityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityType getEntityType() {
|
||||||
|
return this.entityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> newBuilder() {
|
||||||
|
return new StaticListTableBuilderAdapter<>(this.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class StaticListTableBuilderAdapter<T> implements Builder<T> {
|
||||||
|
|
||||||
|
private final List<T> list;
|
||||||
|
private int pageNumber;
|
||||||
|
private int pageSize;
|
||||||
|
private String column;
|
||||||
|
private PageSortOrder order;
|
||||||
|
|
||||||
|
private StaticListTableBuilderAdapter(final List<T> list) {
|
||||||
|
this.list = new ArrayList<>(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> withPaging(final int pageNumber, final int pageSize) {
|
||||||
|
this.pageNumber = pageNumber;
|
||||||
|
this.pageSize = pageSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> withSorting(final String column, final PageSortOrder order) {
|
||||||
|
this.column = column;
|
||||||
|
this.order = order;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> withQueryParams(final MultiValueMap<String, String> params) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> withQueryParam(final String name, final String value) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> withURIVariable(final String name, final String id) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder<T> apply(final Function<Builder<T>, Builder<T>> f) {
|
||||||
|
return f.apply(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<Page<T>> getPage() {
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
if (this.list.isEmpty()) {
|
||||||
|
return new Page<>(0, this.pageNumber, this.column, this.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.pageSize <= 0) {
|
||||||
|
return new Page<>(1, 1, this.column, this.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int numOfPages = this.list.size() / this.pageSize;
|
||||||
|
final List<T> subList = this.list.subList(this.pageNumber * this.pageSize,
|
||||||
|
this.pageNumber * this.pageSize + this.pageSize);
|
||||||
|
return new Page<>(numOfPages, this.pageNumber, this.column, subList);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ import org.eclipse.swt.widgets.TableItem;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||||
|
@ -30,11 +30,13 @@ import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||||
|
|
||||||
public class TableBuilder<ROW extends Entity> {
|
public class TableBuilder<ROW> {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final PageService pageService;
|
private final PageService pageService;
|
||||||
final RestCall<Page<ROW>> restCall;
|
final RestCall<Page<ROW>> restCall;
|
||||||
|
final List<ROW> staticList;
|
||||||
|
final EntityType entityType;
|
||||||
private final MultiValueMap<String, String> staticQueryParams;
|
private final MultiValueMap<String, String> staticQueryParams;
|
||||||
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
|
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
|
||||||
LocTextKey emptyMessage;
|
LocTextKey emptyMessage;
|
||||||
|
@ -55,6 +57,22 @@ public class TableBuilder<ROW extends Entity> {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.pageService = pageService;
|
this.pageService = pageService;
|
||||||
this.restCall = restCall;
|
this.restCall = restCall;
|
||||||
|
this.staticList = null;
|
||||||
|
this.entityType = null;
|
||||||
|
this.staticQueryParams = new LinkedMultiValueMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TableBuilder(
|
||||||
|
final String name,
|
||||||
|
final PageService pageService,
|
||||||
|
final List<ROW> staticList,
|
||||||
|
final EntityType entityType) {
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
this.pageService = pageService;
|
||||||
|
this.restCall = null;
|
||||||
|
this.staticList = staticList;
|
||||||
|
this.entityType = entityType;
|
||||||
this.staticQueryParams = new LinkedMultiValueMap<>();
|
this.staticQueryParams = new LinkedMultiValueMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +171,14 @@ public class TableBuilder<ROW extends Entity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityTable<ROW> compose(final PageContext pageContext) {
|
public EntityTable<ROW> compose(final PageContext pageContext) {
|
||||||
return new EntityTable<>(
|
return new EntityTable<ROW>(
|
||||||
this.name,
|
this.name,
|
||||||
this.markupEnabled,
|
this.markupEnabled,
|
||||||
this.type,
|
this.type,
|
||||||
pageContext,
|
pageContext,
|
||||||
this.restCall,
|
(this.restCall != null)
|
||||||
|
? new RestCallPageSupplier<>(this.restCall)
|
||||||
|
: new StaticListPageSupplier<>(this.staticList, this.entityType),
|
||||||
this.restCallAdapter,
|
this.restCallAdapter,
|
||||||
this.pageService,
|
this.pageService,
|
||||||
this.columns,
|
this.columns,
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
@ -41,7 +40,7 @@ import ch.ethz.seb.sebserver.gui.widget.Selection;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||||
|
|
||||||
public class TableFilter<ROW extends Entity> {
|
public class TableFilter<ROW> {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TableFilter.class);
|
private static final Logger log = LoggerFactory.getLogger(TableFilter.class);
|
||||||
|
|
||||||
|
@ -365,8 +364,8 @@ public class TableFilter<ROW extends Entity> {
|
||||||
|
|
||||||
final Supplier<List<Tuple<String>>> _resourceSupplier = resourceSupplier;
|
final Supplier<List<Tuple<String>>> _resourceSupplier = resourceSupplier;
|
||||||
resourceSupplier = () -> {
|
resourceSupplier = () -> {
|
||||||
List<Tuple<String>> list = _resourceSupplier.get();
|
final List<Tuple<String>> list = _resourceSupplier.get();
|
||||||
list.add(new Tuple<>(StringUtils.EMPTY, entityTable.i18nSupport.getText(ALL_TEXT)));
|
list.add(new Tuple<>(StringUtils.EMPTY, TableFilter.this.entityTable.i18nSupport.getText(ALL_TEXT)));
|
||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -302,9 +302,27 @@ public class WidgetFactory {
|
||||||
g.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
g.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||||
return g;
|
return g;
|
||||||
},
|
},
|
||||||
|
false,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Use this to create a scrolled Composite for usual popup forms
|
||||||
|
*
|
||||||
|
* @param parent The parent Composite
|
||||||
|
* @return the scrolled Composite to add the form content */
|
||||||
|
public Composite createPopupScrollCompositeFilled(final Composite parent) {
|
||||||
|
return PageService.createManagedVScrolledComposite(
|
||||||
|
parent,
|
||||||
|
scrolledComposite -> {
|
||||||
|
final Composite g = new Composite(scrolledComposite, SWT.NONE);
|
||||||
|
g.setLayout(new GridLayout());
|
||||||
|
g.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||||
|
return g;
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
public Composite createWarningPanel(final Composite parent) {
|
public Composite createWarningPanel(final Composite parent) {
|
||||||
final Composite composite = new Composite(parent, SWT.NONE);
|
final Composite composite = new Composite(parent, SWT.NONE);
|
||||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||||
|
|
|
@ -449,6 +449,10 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
||||||
.build()
|
.build()
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
if (examsIds.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
return toDependencies(
|
return toDependencies(
|
||||||
this.examConfigurationMapRecordMapper.selectByExample()
|
this.examConfigurationMapRecordMapper.selectByExample()
|
||||||
.where(
|
.where(
|
||||||
|
|
|
@ -335,6 +335,12 @@ public class UserDAOImpl implements UserDAO {
|
||||||
|
|
||||||
final List<Long> ids = extractListOfPKs(all);
|
final List<Long> ids = extractListOfPKs(all);
|
||||||
|
|
||||||
|
// get all user records for later processing
|
||||||
|
final List<UserRecord> users = this.userRecordMapper.selectByExample()
|
||||||
|
.where(UserRecordDynamicSqlSupport.id, isIn(ids))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
// first delete assigned user roles
|
// first delete assigned user roles
|
||||||
this.roleRecordMapper.deleteByExample()
|
this.roleRecordMapper.deleteByExample()
|
||||||
.where(RoleRecordDynamicSqlSupport.userId, isIn(ids))
|
.where(RoleRecordDynamicSqlSupport.userId, isIn(ids))
|
||||||
|
@ -347,8 +353,8 @@ public class UserDAOImpl implements UserDAO {
|
||||||
.build()
|
.build()
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
return ids.stream()
|
return users.stream()
|
||||||
.map(id -> new EntityKey(id, EntityType.USER))
|
.map(rec -> new EntityKey(rec.getUuid(), EntityType.USER))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
|
||||||
public Collection<EntityDependency> getDependencies(
|
public Collection<EntityDependency> getDependencies(
|
||||||
final String modelId,
|
final String modelId,
|
||||||
final BulkActionType bulkActionType,
|
final BulkActionType bulkActionType,
|
||||||
|
final boolean addIncludes,
|
||||||
final List<String> includes) {
|
final List<String> includes) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
||||||
public Collection<EntityDependency> getDependencies(
|
public Collection<EntityDependency> getDependencies(
|
||||||
final String modelId,
|
final String modelId,
|
||||||
final BulkActionType bulkActionType,
|
final BulkActionType bulkActionType,
|
||||||
|
final boolean addIncludes,
|
||||||
final List<String> includes) {
|
final List<String> includes) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
|
||||||
public Collection<EntityDependency> getDependencies(
|
public Collection<EntityDependency> getDependencies(
|
||||||
final String modelId,
|
final String modelId,
|
||||||
final BulkActionType bulkActionType,
|
final BulkActionType bulkActionType,
|
||||||
|
final boolean addIncludes,
|
||||||
final List<String> includes) {
|
final List<String> includes) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class ConfigurationValueController extends EntityController<Configuration
|
||||||
@Override
|
@Override
|
||||||
public EntityProcessingReport hardDelete(
|
public EntityProcessingReport hardDelete(
|
||||||
final String modelId,
|
final String modelId,
|
||||||
|
final boolean addIncludes,
|
||||||
final List<String> includes) {
|
final List<String> includes) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,6 +213,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
||||||
public Collection<EntityDependency> getDependencies(
|
public Collection<EntityDependency> getDependencies(
|
||||||
@PathVariable final String modelId,
|
@PathVariable final String modelId,
|
||||||
@RequestParam(name = API.PARAM_BULK_ACTION_TYPE, required = true) final BulkActionType bulkActionType,
|
@RequestParam(name = API.PARAM_BULK_ACTION_TYPE, required = true) final BulkActionType bulkActionType,
|
||||||
|
@RequestParam(name = API.PARAM_BULK_ACTION_ADD_INCLUDES, defaultValue = "false") final boolean addIncludes,
|
||||||
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {
|
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {
|
||||||
|
|
||||||
this.entityDAO
|
this.entityDAO
|
||||||
|
@ -223,7 +224,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
||||||
bulkActionType,
|
bulkActionType,
|
||||||
this.entityDAO.entityType(),
|
this.entityDAO.entityType(),
|
||||||
Arrays.asList(new EntityKey(modelId, this.entityDAO.entityType())),
|
Arrays.asList(new EntityKey(modelId, this.entityDAO.entityType())),
|
||||||
convertToEntityType(includes));
|
convertToEntityType(addIncludes, includes));
|
||||||
|
|
||||||
this.bulkActionService.collectDependencies(bulkAction);
|
this.bulkActionService.collectDependencies(bulkAction);
|
||||||
return bulkAction.getDependencies();
|
return bulkAction.getDependencies();
|
||||||
|
@ -326,29 +327,32 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
||||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||||
public EntityProcessingReport hardDelete(
|
public EntityProcessingReport hardDelete(
|
||||||
@PathVariable final String modelId,
|
@PathVariable final String modelId,
|
||||||
|
@RequestParam(name = API.PARAM_BULK_ACTION_ADD_INCLUDES, defaultValue = "false") final boolean addIncludes,
|
||||||
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {
|
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {
|
||||||
|
|
||||||
return this.entityDAO.byModelId(modelId)
|
return this.entityDAO.byModelId(modelId)
|
||||||
.flatMap(this::checkWriteAccess)
|
.flatMap(this::checkWriteAccess)
|
||||||
.flatMap(this::validForDelete)
|
.flatMap(this::validForDelete)
|
||||||
.flatMap(entity -> bulkDelete(entity, convertToEntityType(includes)))
|
.flatMap(entity -> bulkDelete(entity, convertToEntityType(addIncludes, includes)))
|
||||||
.flatMap(this::notifyDeleted)
|
.flatMap(this::notifyDeleted)
|
||||||
.flatMap(pair -> this.logBulkAction(pair.b))
|
.flatMap(pair -> this.logBulkAction(pair.b))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EnumSet<EntityType> convertToEntityType(final List<String> includes) {
|
protected EnumSet<EntityType> convertToEntityType(final boolean addIncludes, final List<String> includes) {
|
||||||
final EnumSet<EntityType> includeDependencies = (includes != null)
|
final EnumSet<EntityType> includeDependencies = (includes != null)
|
||||||
? EnumSet.copyOf(includes.stream().map(name -> {
|
? (includes.isEmpty())
|
||||||
try {
|
? EnumSet.noneOf(EntityType.class)
|
||||||
return EntityType.valueOf(name);
|
: EnumSet.copyOf(includes.stream().map(name -> {
|
||||||
} catch (final Exception e) {
|
try {
|
||||||
return null;
|
return EntityType.valueOf(name);
|
||||||
}
|
} catch (final Exception e) {
|
||||||
})
|
return null;
|
||||||
.filter(Objects::nonNull)
|
}
|
||||||
.collect(Collectors.toSet()))
|
})
|
||||||
: null;
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet()))
|
||||||
|
: (addIncludes) ? EnumSet.noneOf(EntityType.class) : null;
|
||||||
return includeDependencies;
|
return includeDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,13 +166,14 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
||||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||||
public EntityProcessingReport hardDelete(
|
public EntityProcessingReport hardDelete(
|
||||||
@PathVariable final String modelId,
|
@PathVariable final String modelId,
|
||||||
|
@RequestParam(name = API.PARAM_BULK_ACTION_ADD_INCLUDES, defaultValue = "false") final boolean addIncludes,
|
||||||
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {
|
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes) {
|
||||||
|
|
||||||
return this.entityDAO.byModelId(modelId)
|
return this.entityDAO.byModelId(modelId)
|
||||||
.flatMap(this::checkWriteAccess)
|
.flatMap(this::checkWriteAccess)
|
||||||
.flatMap(entity -> this.examConfigUpdateService.processExamConfigurationMappingChange(
|
.flatMap(entity -> this.examConfigUpdateService.processExamConfigurationMappingChange(
|
||||||
entity,
|
entity,
|
||||||
e -> bulkDelete(e, convertToEntityType(includes))))
|
e -> bulkDelete(e, convertToEntityType(addIncludes, includes))))
|
||||||
.flatMap(this::notifyDeleted)
|
.flatMap(this::notifyDeleted)
|
||||||
.flatMap(pair -> this.logBulkAction(pair.b))
|
.flatMap(pair -> this.logBulkAction(pair.b))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
|
@ -63,6 +63,7 @@ public abstract class ReadonlyEntityController<T extends Entity, M extends Entit
|
||||||
@Override
|
@Override
|
||||||
public EntityProcessingReport hardDelete(
|
public EntityProcessingReport hardDelete(
|
||||||
final String modelId,
|
final String modelId,
|
||||||
|
final boolean addIncludes,
|
||||||
final List<String> includes) {
|
final List<String> includes) {
|
||||||
throw new UnsupportedOperationException(ONLY_READ_ACCESS);
|
throw new UnsupportedOperationException(ONLY_READ_ACCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ sebserver.overall.types.entityType.CONFIGURATION=Exam Configuration History
|
||||||
sebserver.overall.types.entityType.CONFIGURATION_NODE=Exam Configuration
|
sebserver.overall.types.entityType.CONFIGURATION_NODE=Exam Configuration
|
||||||
sebserver.overall.types.entityType.EXAM_CONFIGURATION_MAP=Exam Configuration Mapping
|
sebserver.overall.types.entityType.EXAM_CONFIGURATION_MAP=Exam Configuration Mapping
|
||||||
sebserver.overall.types.entityType.EXAM=Exam
|
sebserver.overall.types.entityType.EXAM=Exam
|
||||||
|
sebserver.overall.types.entityType.CLIENT_CONNECTION=SEB Client Connection
|
||||||
sebserver.overall.types.entityType.INDICATOR=Indicator
|
sebserver.overall.types.entityType.INDICATOR=Indicator
|
||||||
sebserver.overall.types.entityType.THRESHOLD=Threshold
|
sebserver.overall.types.entityType.THRESHOLD=Threshold
|
||||||
sebserver.overall.types.entityType.INSTITUTION=Institution
|
sebserver.overall.types.entityType.INSTITUTION=Institution
|
||||||
|
@ -256,7 +257,13 @@ sebserver.useraccount.form.password.new.confirm=Confirm New Password
|
||||||
sebserver.useraccount.form.password.new.confirm.tooltip=Please confirm the password
|
sebserver.useraccount.form.password.new.confirm.tooltip=Please confirm the password
|
||||||
|
|
||||||
sebserver.useraccount.delete.form.title=Delete User Account
|
sebserver.useraccount.delete.form.title=Delete User Account
|
||||||
sebserver.useraccount.delete.form.info=Delete this User Account with all dependencies.
|
sebserver.useraccount.delete.form.info.title=Please Note
|
||||||
|
sebserver.useraccount.delete.form.info=Please Note:<br/> This deletes the particular User Account with all selected dependencies.<br/> The User Account and selected dependent exams and exam configurations, will be lost after deletion.<br/> Please use the "Show Report" action below to see a report of all objects that will be<br/> deleted and check them carefully.
|
||||||
|
sebserver.useraccount.delete.form.report.info=The following objects will be deleted within this User Account deletion.<br/>Please check them carefully before delete.
|
||||||
|
sebserver.useraccount.delete.form.report.empty=No dependencies will be deleted.
|
||||||
|
sebserver.useraccount.delete.form.report.list.type=Type
|
||||||
|
sebserver.useraccount.delete.form.report.list.name=Name
|
||||||
|
sebserver.useraccount.delete.form.report.list.description=Description
|
||||||
sebserver.useraccount.delete.form.accountName=Name
|
sebserver.useraccount.delete.form.accountName=Name
|
||||||
sebserver.useraccount.delete.form.deleteAlsoConfigs=Include all Exam Configurations
|
sebserver.useraccount.delete.form.deleteAlsoConfigs=Include all Exam Configurations
|
||||||
sebserver.useraccount.delete.form.deleteAlsoConfigs.tooltip=This includes all Exam Configuration which this uses has created and is owner of
|
sebserver.useraccount.delete.form.deleteAlsoConfigs.tooltip=This includes all Exam Configuration which this uses has created and is owner of
|
||||||
|
@ -264,6 +271,8 @@ sebserver.useraccount.delete.form.deleteAlsoExams=Include all Exams
|
||||||
sebserver.useraccount.delete.form.deleteAlsoExams.tooltip=This includes all Exams which the user has imported and is owner of.<br/>This also includes all Client Connections and all SEB Client Logs that where created within an Exam that is part of this deletion.
|
sebserver.useraccount.delete.form.deleteAlsoExams.tooltip=This includes all Exams which the user has imported and is owner of.<br/>This also includes all Client Connections and all SEB Client Logs that where created within an Exam that is part of this deletion.
|
||||||
sebserver.useraccount.delete.form.action.delete=Delete
|
sebserver.useraccount.delete.form.action.delete=Delete
|
||||||
sebserver.useraccount.delete.form.action.report=Show Report
|
sebserver.useraccount.delete.form.action.report=Show Report
|
||||||
|
sebserver.useraccount.delete.confirm.title=Deletion Successful
|
||||||
|
sebserver.useraccount.delete.confirm.message=The User Account ({0}) was successfully deleted.<br/>Also the following number dependencies where successfully deleted: {1}.<br/><br/>And there where {2} errors.
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# LMS Setup
|
# LMS Setup
|
||||||
|
|
Loading…
Add table
Reference in a new issue