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_PARENT_MODEL_ID = "parentModelId";
|
||||
public static final String PARAM_ENTITY_TYPE = "entityType";
|
||||
|
||||
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_VIEW_ID = "viewId";
|
||||
public static final String PARAM_INSTRUCTION_TYPE = "instructionType";
|
||||
|
|
|
@ -8,43 +8,60 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
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.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.BulkActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
|
||||
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.profile.GuiProfile;
|
||||
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.FormBuilder;
|
||||
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.page.PageContext;
|
||||
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.WizardAction;
|
||||
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.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.GetUserDependency;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
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_EXAMS = "WITH_EXAMS";
|
||||
|
||||
|
@ -52,6 +69,17 @@ public class UserAccountDeletePopup {
|
|||
new LocTextKey("sebserver.useraccount.delete.form.title");
|
||||
private final static LocTextKey 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 =
|
||||
new LocTextKey("sebserver.useraccount.delete.form.accountName");
|
||||
private final static LocTextKey FORM_CONFIGS =
|
||||
|
@ -63,6 +91,9 @@ public class UserAccountDeletePopup {
|
|||
private final static LocTextKey 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;
|
||||
|
||||
protected UserAccountDeletePopup(final PageService pageService) {
|
||||
|
@ -76,15 +107,17 @@ public class UserAccountDeletePopup {
|
|||
new ModelInputWizard<PageContext>(
|
||||
action.pageContext().getParent().getShell(),
|
||||
this.pageService.getWidgetFactory())
|
||||
.setLargeDialogWidth();
|
||||
.setVeryLargeDialogWidth();
|
||||
|
||||
final String page1Id = "DELETE_PAGE";
|
||||
final String page2Id = "REPORT_PAGE";
|
||||
final Predicate<PageContext> callback = pc -> doDelete(this.pageService, pc);
|
||||
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 =
|
||||
(formHandle, content) -> composeReportDialog(content, pageContext);
|
||||
(prefPageContext, content) -> composeReportDialog(content,
|
||||
(prefPageContext != null) ? prefPageContext : pageContext);
|
||||
|
||||
final WizardPage<PageContext> page1 = new WizardPage<>(
|
||||
page1Id,
|
||||
|
@ -109,15 +142,81 @@ public class UserAccountDeletePopup {
|
|||
final PageService pageService,
|
||||
final PageContext pageContext) {
|
||||
|
||||
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
||||
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
|
||||
return true;
|
||||
try {
|
||||
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
||||
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(
|
||||
final Composite parent,
|
||||
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 UserInfo userInfo = this.pageService.getRestService()
|
||||
.getBuilder(GetUserAccount.class)
|
||||
|
@ -126,8 +225,10 @@ public class UserAccountDeletePopup {
|
|||
.get();
|
||||
|
||||
final FormHandle<?> formHandle = this.pageService.formBuilder(
|
||||
pageContext.copyOf(parent))
|
||||
pageContext.copyOf(grid))
|
||||
.readonly(false)
|
||||
.withDefaultSpanLabel(3)
|
||||
.withDefaultSpanInput(4)
|
||||
.addField(FormBuilder.text(
|
||||
"USE_NAME",
|
||||
FORM_NAME,
|
||||
|
@ -153,36 +254,67 @@ public class UserAccountDeletePopup {
|
|||
final Composite parent,
|
||||
final PageContext pageContext) {
|
||||
|
||||
// get selection
|
||||
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
||||
final boolean withExams = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_EXAMS));
|
||||
final Composite grid = this.pageService.getWidgetFactory()
|
||||
.createPopupScrollCompositeFilled(parent);
|
||||
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
|
||||
|
||||
// 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);
|
||||
final Label title = this.pageService.getWidgetFactory()
|
||||
.labelLocalized(grid, CustomVariant.TEXT_H3, FORM_REPORT_INFO);
|
||||
final GridData gridData = new GridData();
|
||||
gridData.horizontalIndent = 10;
|
||||
gridData.verticalIndent = 10;
|
||||
title.setLayoutData(gridData);
|
||||
|
||||
if (withConfigs) {
|
||||
restCallBuilder.withQueryParam(
|
||||
API.PARAM_BULK_ACTION_INCLUDES,
|
||||
EntityType.CONFIGURATION_NODE.name());
|
||||
try {
|
||||
// get selection
|
||||
final boolean withConfigs = BooleanUtils.toBoolean(pageContext.getAttribute(ARG_WITH_CONFIGS));
|
||||
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(
|
||||
new LocTextKey("sebserver.useraccount.action.delete"),
|
||||
ImageIcon.DELETE,
|
||||
PageStateDefinitionImpl.USER_ACCOUNT_LIST,
|
||||
ActionCategory.USER_ACCOUNT_LIST),
|
||||
PageStateDefinitionImpl.USER_ACCOUNT_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
||||
USER_ACCOUNT_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.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
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 <T> the type of the Entity of the table
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -304,10 +305,12 @@ public interface PageService {
|
|||
* @param apiCall the SEB Server API RestCall that feeds the table with data
|
||||
* @param <T> the type of the Entity of the table
|
||||
* @return TableBuilder of specified type */
|
||||
<T extends Entity> TableBuilder<T> entityTableBuilder(
|
||||
<T> TableBuilder<T> entityTableBuilder(
|
||||
String name,
|
||||
RestCall<Page<T>> apiCall);
|
||||
|
||||
<T> TableBuilder<T> staticListTableBuilder(final List<T> staticList, EntityType entityType);
|
||||
|
||||
/** Get a new PageActionBuilder for a given PageContext.
|
||||
*
|
||||
* @param pageContext the PageContext that is used by the new PageActionBuilder
|
||||
|
@ -347,9 +350,29 @@ public interface PageService {
|
|||
final Composite parent,
|
||||
final Function<ScrolledComposite, Composite> contentFunction,
|
||||
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);
|
||||
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);
|
||||
scrolledComposite.setContent(content);
|
||||
|
|
|
@ -115,15 +115,15 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
final ModalInputDialogComposer<T> contentComposer) {
|
||||
|
||||
// Create the selection dialog window
|
||||
final Shell shell = new Shell(getParent(), getStyle());
|
||||
shell.setText(getText());
|
||||
shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||
shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||
shell.setLayout(new GridLayout(2, true));
|
||||
this.shell = new Shell(getParent(), getStyle());
|
||||
this.shell.setText(getText());
|
||||
this.shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||
this.shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||
this.shell.setLayout(new GridLayout(2, true));
|
||||
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());
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
gridData.horizontalSpan = 2;
|
||||
|
@ -133,7 +133,7 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
final Supplier<T> valueSupplier = contentComposer.compose(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);
|
||||
data.widthHint = this.buttonWidth;
|
||||
ok.setLayoutData(data);
|
||||
|
@ -141,16 +141,16 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
if (valueSupplier != null) {
|
||||
final T result = valueSupplier.get();
|
||||
if (callback.test(result)) {
|
||||
shell.close();
|
||||
this.shell.close();
|
||||
}
|
||||
} 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.widthHint = this.buttonWidth;
|
||||
cancel.setLayoutData(data);
|
||||
|
@ -158,10 +158,10 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
if (cancelCallback != null) {
|
||||
cancelCallback.run();
|
||||
}
|
||||
shell.close();
|
||||
this.shell.close();
|
||||
});
|
||||
|
||||
finishUp(shell);
|
||||
finishUp(this.shell);
|
||||
}
|
||||
|
||||
public void open(
|
||||
|
|
|
@ -25,6 +25,8 @@ import org.eclipse.swt.widgets.Button;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Dialog;
|
||||
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.gui.service.i18n.LocTextKey;
|
||||
|
@ -34,6 +36,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
|||
|
||||
public class ModelInputWizard<T> extends Dialog {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ModelInputWizard.class);
|
||||
|
||||
private static final long serialVersionUID = -3314062148477979319L;
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
|
@ -81,33 +85,92 @@ public class ModelInputWizard<T> extends Dialog {
|
|||
final WizardPage<T>... pages) {
|
||||
|
||||
// Create the selection dialog window
|
||||
final Shell shell = new Shell(getParent(), getStyle());
|
||||
shell.setText(getText());
|
||||
shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||
shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||
shell.setLayout(new GridLayout(1, true));
|
||||
final GridData gridData2 = new GridData(SWT.FILL, SWT.TOP, false, false);
|
||||
shell.setLayoutData(gridData2);
|
||||
this.shell = new Shell(getParent(), getStyle());
|
||||
this.shell.setText(getText());
|
||||
this.shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||
this.shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||
this.shell.setLayout(new GridLayout());
|
||||
final GridData gridData2 = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
this.shell.setLayoutData(gridData2);
|
||||
|
||||
// the content composite
|
||||
final Composite main = new Composite(shell, SWT.NONE);
|
||||
final Composite main = new Composite(this.shell, SWT.NONE);
|
||||
main.setLayout(new GridLayout());
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
gridData.widthHint = this.dialogWidth;
|
||||
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.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);
|
||||
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);
|
||||
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 RowData data = new RowData();
|
||||
data.width = this.buttonWidth;
|
||||
|
@ -116,60 +179,24 @@ public class ModelInputWizard<T> extends Dialog {
|
|||
if (cancelCallback != null) {
|
||||
cancelCallback.run();
|
||||
}
|
||||
shell.close();
|
||||
this.shell.close();
|
||||
});
|
||||
}
|
||||
|
||||
gridData.heightHint = calcDialogHeight(main);
|
||||
finishUp(shell);
|
||||
}
|
||||
try {
|
||||
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(
|
||||
final String pageId,
|
||||
final List<WizardPage<T>> pages,
|
||||
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();
|
||||
}
|
||||
});
|
||||
contentComp.getShell().layout(true, true);
|
||||
} catch (final Exception e) {
|
||||
log.warn("Failed to calculate dialog height: {}", e.getMessage());
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error: ", e);
|
||||
this.shell.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -358,13 +358,25 @@ public class PageServiceImpl implements PageService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T extends Entity> TableBuilder<T> entityTableBuilder(
|
||||
public <T> TableBuilder<T> entityTableBuilder(
|
||||
final String name,
|
||||
final RestCall<Page<T>> 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
|
||||
public void logout(final PageContext pageContext) {
|
||||
this.clearState();
|
||||
|
|
|
@ -12,12 +12,11 @@ import java.util.List;
|
|||
import java.util.function.Function;
|
||||
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.gui.service.i18n.LocTextKey;
|
||||
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";
|
||||
|
||||
|
|
|
@ -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.PageService;
|
||||
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.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||
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);
|
||||
|
||||
|
@ -108,7 +107,7 @@ public class EntityTable<ROW extends Entity> {
|
|||
final boolean markupEnabled,
|
||||
final int type,
|
||||
final PageContext pageContext,
|
||||
final RestCall<Page<ROW>> restCall,
|
||||
final PageSupplier<ROW> pageSupplier,
|
||||
final Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> pageSupplierAdapter,
|
||||
final PageService pageService,
|
||||
final List<ColumnDefinition<ROW>> columns,
|
||||
|
@ -132,7 +131,7 @@ public class EntityTable<ROW extends Entity> {
|
|||
this.i18nSupport = pageService.getI18nSupport();
|
||||
this.pageContext = pageContext;
|
||||
this.widgetFactory = pageService.getWidgetFactory();
|
||||
this.pageSupplier = new RestCallPageSupplier<>(restCall);
|
||||
this.pageSupplier = pageSupplier;
|
||||
this.pageSupplierAdapter = (pageSupplierAdapter != null) ? pageSupplierAdapter : Function.identity();
|
||||
this.columns = Utils.immutableListOf(columns);
|
||||
this.emptyMessage = emptyMessage;
|
||||
|
@ -581,7 +580,11 @@ public class EntityTable<ROW extends Entity> {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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.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.gui.service.i18n.LocTextKey;
|
||||
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.remote.webservice.api.RestCall;
|
||||
|
||||
public class TableBuilder<ROW extends Entity> {
|
||||
public class TableBuilder<ROW> {
|
||||
|
||||
private final String name;
|
||||
private final PageService pageService;
|
||||
final RestCall<Page<ROW>> restCall;
|
||||
final List<ROW> staticList;
|
||||
final EntityType entityType;
|
||||
private final MultiValueMap<String, String> staticQueryParams;
|
||||
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
|
||||
LocTextKey emptyMessage;
|
||||
|
@ -55,6 +57,22 @@ public class TableBuilder<ROW extends Entity> {
|
|||
this.name = name;
|
||||
this.pageService = pageService;
|
||||
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<>();
|
||||
}
|
||||
|
||||
|
@ -153,12 +171,14 @@ public class TableBuilder<ROW extends Entity> {
|
|||
}
|
||||
|
||||
public EntityTable<ROW> compose(final PageContext pageContext) {
|
||||
return new EntityTable<>(
|
||||
return new EntityTable<ROW>(
|
||||
this.name,
|
||||
this.markupEnabled,
|
||||
this.type,
|
||||
pageContext,
|
||||
this.restCall,
|
||||
(this.restCall != null)
|
||||
? new RestCallPageSupplier<>(this.restCall)
|
||||
: new StaticListPageSupplier<>(this.staticList, this.entityType),
|
||||
this.restCallAdapter,
|
||||
this.pageService,
|
||||
this.columns,
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.util.LinkedMultiValueMap;
|
|||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
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.util.Tuple;
|
||||
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.ImageIcon;
|
||||
|
||||
public class TableFilter<ROW extends Entity> {
|
||||
public class TableFilter<ROW> {
|
||||
|
||||
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;
|
||||
resourceSupplier = () -> {
|
||||
List<Tuple<String>> list = _resourceSupplier.get();
|
||||
list.add(new Tuple<>(StringUtils.EMPTY, entityTable.i18nSupport.getText(ALL_TEXT)));
|
||||
final List<Tuple<String>> list = _resourceSupplier.get();
|
||||
list.add(new Tuple<>(StringUtils.EMPTY, TableFilter.this.entityTable.i18nSupport.getText(ALL_TEXT)));
|
||||
return list;
|
||||
};
|
||||
|
||||
|
|
|
@ -302,9 +302,27 @@ public class WidgetFactory {
|
|||
g.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
return g;
|
||||
},
|
||||
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) {
|
||||
final Composite composite = new Composite(parent, SWT.NONE);
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||
|
|
|
@ -449,6 +449,10 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO {
|
|||
.build()
|
||||
.execute();
|
||||
|
||||
if (examsIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return toDependencies(
|
||||
this.examConfigurationMapRecordMapper.selectByExample()
|
||||
.where(
|
||||
|
|
|
@ -335,6 +335,12 @@ public class UserDAOImpl implements UserDAO {
|
|||
|
||||
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
|
||||
this.roleRecordMapper.deleteByExample()
|
||||
.where(RoleRecordDynamicSqlSupport.userId, isIn(ids))
|
||||
|
@ -347,8 +353,8 @@ public class UserDAOImpl implements UserDAO {
|
|||
.build()
|
||||
.execute();
|
||||
|
||||
return ids.stream()
|
||||
.map(id -> new EntityKey(id, EntityType.USER))
|
||||
return users.stream()
|
||||
.map(rec -> new EntityKey(rec.getUuid(), EntityType.USER))
|
||||
.collect(Collectors.toList());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
|
|||
public Collection<EntityDependency> getDependencies(
|
||||
final String modelId,
|
||||
final BulkActionType bulkActionType,
|
||||
final boolean addIncludes,
|
||||
final List<String> includes) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -118,6 +118,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
|||
public Collection<EntityDependency> getDependencies(
|
||||
final String modelId,
|
||||
final BulkActionType bulkActionType,
|
||||
final boolean addIncludes,
|
||||
final List<String> includes) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ public class ConfigurationController extends ReadonlyEntityController<Configurat
|
|||
public Collection<EntityDependency> getDependencies(
|
||||
final String modelId,
|
||||
final BulkActionType bulkActionType,
|
||||
final boolean addIncludes,
|
||||
final List<String> includes) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ public class ConfigurationValueController extends EntityController<Configuration
|
|||
@Override
|
||||
public EntityProcessingReport hardDelete(
|
||||
final String modelId,
|
||||
final boolean addIncludes,
|
||||
final List<String> includes) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -213,6 +213,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
public Collection<EntityDependency> getDependencies(
|
||||
@PathVariable final String modelId,
|
||||
@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) {
|
||||
|
||||
this.entityDAO
|
||||
|
@ -223,7 +224,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
bulkActionType,
|
||||
this.entityDAO.entityType(),
|
||||
Arrays.asList(new EntityKey(modelId, this.entityDAO.entityType())),
|
||||
convertToEntityType(includes));
|
||||
convertToEntityType(addIncludes, includes));
|
||||
|
||||
this.bulkActionService.collectDependencies(bulkAction);
|
||||
return bulkAction.getDependencies();
|
||||
|
@ -326,29 +327,32 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public EntityProcessingReport hardDelete(
|
||||
@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) {
|
||||
|
||||
return this.entityDAO.byModelId(modelId)
|
||||
.flatMap(this::checkWriteAccess)
|
||||
.flatMap(this::validForDelete)
|
||||
.flatMap(entity -> bulkDelete(entity, convertToEntityType(includes)))
|
||||
.flatMap(entity -> bulkDelete(entity, convertToEntityType(addIncludes, includes)))
|
||||
.flatMap(this::notifyDeleted)
|
||||
.flatMap(pair -> this.logBulkAction(pair.b))
|
||||
.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)
|
||||
? EnumSet.copyOf(includes.stream().map(name -> {
|
||||
try {
|
||||
return EntityType.valueOf(name);
|
||||
} catch (final Exception e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet()))
|
||||
: null;
|
||||
? (includes.isEmpty())
|
||||
? EnumSet.noneOf(EntityType.class)
|
||||
: EnumSet.copyOf(includes.stream().map(name -> {
|
||||
try {
|
||||
return EntityType.valueOf(name);
|
||||
} catch (final Exception e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet()))
|
||||
: (addIncludes) ? EnumSet.noneOf(EntityType.class) : null;
|
||||
return includeDependencies;
|
||||
}
|
||||
|
||||
|
|
|
@ -166,13 +166,14 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public EntityProcessingReport hardDelete(
|
||||
@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) {
|
||||
|
||||
return this.entityDAO.byModelId(modelId)
|
||||
.flatMap(this::checkWriteAccess)
|
||||
.flatMap(entity -> this.examConfigUpdateService.processExamConfigurationMappingChange(
|
||||
entity,
|
||||
e -> bulkDelete(e, convertToEntityType(includes))))
|
||||
e -> bulkDelete(e, convertToEntityType(addIncludes, includes))))
|
||||
.flatMap(this::notifyDeleted)
|
||||
.flatMap(pair -> this.logBulkAction(pair.b))
|
||||
.getOrThrow();
|
||||
|
|
|
@ -63,6 +63,7 @@ public abstract class ReadonlyEntityController<T extends Entity, M extends Entit
|
|||
@Override
|
||||
public EntityProcessingReport hardDelete(
|
||||
final String modelId,
|
||||
final boolean addIncludes,
|
||||
final List<String> includes) {
|
||||
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.EXAM_CONFIGURATION_MAP=Exam Configuration Mapping
|
||||
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.THRESHOLD=Threshold
|
||||
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.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.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
|
||||
|
@ -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.action.delete=Delete
|
||||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue