diff --git a/findbugs-excludes.xml b/findbugs-excludes.xml
index 76bfcb37..b18fa80f 100644
--- a/findbugs-excludes.xml
+++ b/findbugs-excludes.xml
@@ -22,6 +22,9 @@
+
+
+
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserAccount.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserAccount.java
index 6675553e..ab94296e 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserAccount.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/user/UserAccount.java
@@ -14,11 +14,12 @@ import java.util.Set;
import org.joda.time.DateTimeZone;
+import ch.ethz.seb.sebserver.gbl.model.Activatable;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
/** Defines a User-Account object */
-public interface UserAccount extends GrantEntity {
+public interface UserAccount extends GrantEntity, Activatable {
/** The model id of the User-Account (UUID) */
@Override
@@ -42,6 +43,7 @@ public interface UserAccount extends GrantEntity {
Boolean getActive();
/** Indicates whether the User-Account is active or not */
+ @Override
boolean isActive();
/** The language of the User-Account */
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java
index 7ac7f32b..d44db572 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java
@@ -614,7 +614,7 @@ public class ExamForm implements TemplateComposer {
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA))
.newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
.withSelectionSupplier(() -> {
- final ExamConfigurationMap selectedROWData = table.getSelectedROWData();
+ final ExamConfigurationMap selectedROWData = table.getSingleSelectedROWData();
final HashSet result = new HashSet<>();
if (selectedROWData != null) {
result.add(new EntityKey(
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java
index 91f77c57..3d310ffa 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java
@@ -220,7 +220,7 @@ public class ExamList implements TemplateComposer {
}
static final PageAction modifyExam(final PageAction action, final EntityTable table) {
- final Exam exam = table.getSelectedROWData();
+ final Exam exam = table.getSingleSelectedROWData();
if (exam == null) {
throw new PageMessageException(EMPTY_SELECTION_TEXT_KEY);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java
index 995dbf34..6352bf3e 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionForm.java
@@ -26,7 +26,6 @@ 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.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.impl.DefaultPageLayout;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.DeactivateInstitution;
@@ -143,7 +142,7 @@ public class InstitutionForm implements TemplateComposer {
.newAction(ActionDefinition.INSTITUTION_DEACTIVATE)
.withEntityKey(entityKey)
.withSimpleRestCall(this.restService, DeactivateInstitution.class)
- .withConfirm(PageUtils.confirmDeactivation(institution, this.restService))
+ .withConfirm(this.pageService.confirmDeactivation(institution))
.publishIf(() -> writeGrant && isReadonly && institution.isActive())
.newAction(ActionDefinition.INSTITUTION_ACTIVATE)
@@ -157,6 +156,12 @@ public class InstitutionForm implements TemplateComposer {
.ignoreMoveAwayFromEdit()
.publishIf(() -> !isReadonly)
+ .newAction(ActionDefinition.INSTITUTION_SAVE_AND_ACTIVATE)
+ .withEntityKey(entityKey)
+ .withExec(formHandle::saveAndActivate)
+ .ignoreMoveAwayFromEdit()
+ .publishIf(() -> !isReadonly && !institution.isActive())
+
.newAction(ActionDefinition.INSTITUTION_CANCEL_MODIFY)
.withEntityKey(entityKey)
.withExec(this.pageService.backToCurrentFunction())
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java
index f9b86e75..7ef51caa 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/InstitutionList.java
@@ -120,6 +120,11 @@ public class InstitutionList implements TemplateComposer {
.newAction(ActionDefinition.INSTITUTION_MODIFY_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
+ .publishIf(() -> instGrant.m() && table.hasAnyContent())
+
+ .newAction(ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY)
+ .withExec(this.pageService.activationToggleActionFunction(table, EMPTY_SELECTION_TEXT_KEY))
+ .withConfirm(this.pageService.confirmDeactivation(table))
.publishIf(() -> instGrant.m() && table.hasAnyContent());
}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java
index 28e73d6c..5fb7d1c4 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java
@@ -40,7 +40,6 @@ 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.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
@@ -266,7 +265,7 @@ public class LmsSetupForm implements TemplateComposer {
.newAction(ActionDefinition.LMS_SETUP_DEACTIVATE)
.withEntityKey(entityKey)
.withSimpleRestCall(restService, DeactivateLmsSetup.class)
- .withConfirm(PageUtils.confirmDeactivation(lmsSetup, restService))
+ .withConfirm(this.pageService.confirmDeactivation(lmsSetup))
.publishIf(() -> writeGrant && readonly && institutionActive && lmsSetup.isActive())
.newAction(ActionDefinition.LMS_SETUP_ACTIVATE)
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java
index ab527b88..96b36c4a 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java
@@ -194,7 +194,7 @@ public class QuizDiscoveryList implements TemplateComposer {
.newAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS)
.withExec(action -> this.showDetails(
action,
- t.getSelectedROWData(),
+ t.getSingleSelectedROWData(),
institutionNameFunction))
.noEventPropagation()
.create())
@@ -214,7 +214,7 @@ public class QuizDiscoveryList implements TemplateComposer {
table::getSelection,
action -> this.showDetails(
action,
- table.getSelectedROWData(),
+ table.getSingleSelectedROWData(),
institutionNameFunction),
EMPTY_SELECTION_TEXT)
.noEventPropagation()
@@ -235,7 +235,7 @@ public class QuizDiscoveryList implements TemplateComposer {
private PageAction importQuizData(final PageAction action, final EntityTable table) {
action.getSingleSelection();
- final QuizData selectedROWData = table.getSelectedROWData();
+ final QuizData selectedROWData = table.getSingleSelectedROWData();
if (selectedROWData.endTime != null) {
final DateTime now = DateTime.now(DateTimeZone.UTC);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java
index 560008b3..8c96b1eb 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientConfigForm.java
@@ -30,7 +30,6 @@ 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.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
import ch.ethz.seb.sebserver.gui.service.remote.download.SebClientConfigDownload;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
@@ -183,7 +182,7 @@ public class SebClientConfigForm implements TemplateComposer {
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_DEACTIVATE)
.withEntityKey(entityKey)
.withSimpleRestCall(this.restService, DeactivateClientConfig.class)
- .withConfirm(PageUtils.confirmDeactivation(clientConfig, this.restService))
+ .withConfirm(this.pageService.confirmDeactivation(clientConfig))
.publishIf(() -> writeGrant && isReadonly && clientConfig.isActive())
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_ACTIVATE)
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java
index 2df6448a..6b13ac21 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java
@@ -219,7 +219,7 @@ public class SebClientLogs implements TemplateComposer {
.withDefaultAction(t -> actionBuilder
.newAction(ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS)
- .withExec(action -> this.showDetails(action, t.getSelectedROWData()))
+ .withExec(action -> this.showDetails(action, t.getSingleSelectedROWData()))
.noEventPropagation()
.create())
@@ -229,7 +229,7 @@ public class SebClientLogs implements TemplateComposer {
.newAction(ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS)
.withSelect(
table::getSelection,
- action -> this.showDetails(action, table.getSelectedROWData()),
+ action -> this.showDetails(action, table.getSingleSelectedROWData()),
EMPTY_SELECTION_TEXT)
.noEventPropagation()
.publishIf(table::hasAnyContent);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java
index a728646d..7407c218 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigPropForm.java
@@ -347,7 +347,7 @@ public class SebExamConfigPropForm implements TemplateComposer {
}
private ExamConfigurationMap getSelectedExamMapping(final EntityTable table) {
- final ExamConfigurationMap selectedROWData = table.getSelectedROWData();
+ final ExamConfigurationMap selectedROWData = table.getSingleSelectedROWData();
if (selectedROWData == null) {
throw new PageMessageException(ExamList.EMPTY_SELECTION_TEXT_KEY);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java
index 2b1d5b9b..deab98a2 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserAccountForm.java
@@ -37,7 +37,6 @@ 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.TemplateComposer;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.ActivateUserAccount;
@@ -225,7 +224,7 @@ public class UserAccountForm implements TemplateComposer {
.newAction(ActionDefinition.USER_ACCOUNT_DEACTIVATE)
.withEntityKey(entityKey)
.withSimpleRestCall(restService, DeactivateUserAccount.class)
- .withConfirm(PageUtils.confirmDeactivation(userAccount, restService))
+ .withConfirm(this.pageService.confirmDeactivation(userAccount))
.publishIf(() -> writeGrant && readonly && institutionActive && userAccount.isActive())
.newAction(ActionDefinition.USER_ACCOUNT_ACTIVATE)
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java
index a24466b3..2310c621 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java
@@ -191,7 +191,7 @@ public class UserActivityLogs implements TemplateComposer {
.withDefaultAction(t -> actionBuilder
.newAction(ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS)
- .withExec(action -> this.showDetails(action, t.getSelectedROWData()))
+ .withExec(action -> this.showDetails(action, t.getSingleSelectedROWData()))
.noEventPropagation()
.create())
@@ -201,7 +201,7 @@ public class UserActivityLogs implements TemplateComposer {
.newAction(ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS)
.withSelect(
table::getSelection,
- action -> this.showDetails(action, table.getSelectedROWData()),
+ action -> this.showDetails(action, table.getSingleSelectedROWData()),
EMPTY_SELECTION_TEXT)
.noEventPropagation()
.publishIf(table::hasAnyContent);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java
index dc451b81..6a71b08f 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/action/ActionDefinition.java
@@ -36,6 +36,11 @@ public enum ActionDefinition {
ImageIcon.EDIT,
PageStateDefinitionImpl.INSTITUTION_EDIT,
ActionCategory.INSTITUTION_LIST),
+ INSTITUTION_TOGGLE_ACTIVITY(
+ new LocTextKey("sebserver.overall.action.toggle-activity"),
+ ImageIcon.SWITCH,
+ PageStateDefinitionImpl.INSTITUTION_LIST,
+ ActionCategory.INSTITUTION_LIST),
INSTITUTION_MODIFY(
new LocTextKey("sebserver.institution.action.modify"),
ImageIcon.EDIT,
@@ -51,6 +56,11 @@ public enum ActionDefinition {
ImageIcon.SAVE,
PageStateDefinitionImpl.INSTITUTION_VIEW,
ActionCategory.FORM),
+ INSTITUTION_SAVE_AND_ACTIVATE(
+ new LocTextKey("sebserver.institution.action.activate"),
+ ImageIcon.ACTIVE,
+ PageStateDefinitionImpl.INSTITUTION_VIEW,
+ ActionCategory.FORM),
INSTITUTION_ACTIVATE(
new LocTextKey("sebserver.institution.action.activate"),
ImageIcon.TOGGLE_OFF,
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java
index d26360a9..39b65bdc 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java
@@ -15,6 +15,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity;
@@ -29,6 +30,7 @@ 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.FormBinding;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall.CallType;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
public class FormHandle {
@@ -79,6 +81,16 @@ public class FormHandle {
return handleFormPost(doAPIPost(), action);
}
+ public final PageAction saveAndActivate(final PageAction action) {
+ final PageAction handleFormPost = handleFormPost(doAPIPost(), action);
+ final EntityType entityType = this.post.getEntityType();
+ this.pageService.getRestService().getBuilder(entityType, CallType.ACTIVATION_ACTIVATE)
+ .withURIVariable(API.PARAM_MODEL_ID, handleFormPost.getEntityKey().getModelId())
+ .call()
+ .getOrThrow();
+ return handleFormPost;
+ }
+
/** process a form post by first resetting all field validation errors (if there are some)
* then collecting all input data from the form by form-binding to a either a JSON string in
* HTTP PUT case or to an form-URL-encoded string on HTTP POST case. And PUT or POST the data
@@ -136,7 +148,7 @@ public class FormHandle {
return true;
} else {
log.error("Unexpected error while trying to post form: {}", error.getMessage());
- final EntityType resultType = this.post.getResultType();
+ final EntityType resultType = this.post.getEntityType();
if (resultType != null) {
this.pageContext.notifySaveError(resultType, error);
} else {
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java
index 7c1fa296..40dd68d7 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java
@@ -8,23 +8,28 @@
package ch.ethz.seb.sebserver.gui.service.page;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Set;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
+import ch.ethz.seb.sebserver.gbl.model.Activatable;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.Page;
@@ -42,6 +47,7 @@ import ch.ethz.seb.sebserver.gui.service.page.impl.PageState;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
import ch.ethz.seb.sebserver.gui.table.TableBuilder;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@@ -99,6 +105,45 @@ public interface PageService {
return action -> (currentState != null) ? currentState.gotoAction : action;
}
+ /** Get a page action execution function for switching the activity of currently selected
+ * entities from a given entity-table.
+ *
+ * @param table the entity table
+ * @param noSelectionText LocTextKey for missing selection message
+ * @return page action execution function for switching the activity */
+ Function activationToggleActionFunction(
+ EntityTable table,
+ LocTextKey noSelectionText);
+
+ /** Get a message supplier to notify deactivation dependencies to the user for all given entities
+ *
+ * @param entities Set of entities to collect the dependencies for
+ * @return a message supplier to notify deactivation dependencies to the user */
+ Supplier confirmDeactivation(final Set extends T> entities);
+
+ /** Get a message supplier to notify deactivation dependencies to the user for given entity
+ *
+ * @param entity the entity instance
+ * @return a message supplier to notify deactivation dependencies to the user */
+ default Supplier confirmDeactivation(final T entity) {
+ return confirmDeactivation(new HashSet<>(Arrays.asList(entity)));
+ }
+
+ /** Get a message supplier to notify deactivation dependencies to the user for given entity table selection
+ *
+ * @param table the entity table
+ * @return a message supplier to notify deactivation dependencies to the user */
+ default Supplier confirmDeactivation(final EntityTable table) {
+ return () -> {
+ return confirmDeactivation(table
+ .getSelectedROWData()
+ .stream()
+ .filter(e -> e.isActive()) // NOTE: Activatable::isActive leads to an error here!?
+ .collect(Collectors.toSet()))
+ .get();
+ };
+ }
+
/** Publishes a given PageEvent to the current page tree
* This goes through the page-tree and collects all listeners the are listen to
* the specified page event type.
@@ -229,6 +274,16 @@ public interface PageService {
}
}
+ static void clearComposite(final Composite parent) {
+ if (parent == null) {
+ return;
+ }
+
+ for (final Control control : parent.getChildren()) {
+ control.dispose();
+ }
+ }
+
public class PageActionBuilder {
private final PageService pageService;
private final PageContext originalPageContext;
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/ComposerServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/ComposerServiceImpl.java
index 4a62563b..36306cd7 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/ComposerServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/ComposerServiceImpl.java
@@ -115,7 +115,7 @@ public class ComposerServiceImpl implements ComposerService {
if (composer.validate(pageContext)) {
- PageUtils.clearComposite(pageContext.getParent());
+ PageService.clearComposite(pageContext.getParent());
try {
composer.compose(pageContext);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java
index dc026c18..bd586ea0 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageServiceImpl.java
@@ -10,9 +10,14 @@ package ch.ethz.seb.sebserver.gui.service.page.impl;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Comparator;
import java.util.List;
+import java.util.Set;
import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
import javax.servlet.http.HttpSession;
@@ -22,8 +27,13 @@ import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
+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.JSONMapper;
+import ch.ethz.seb.sebserver.gbl.model.Activatable;
import ch.ethz.seb.sebserver.gbl.model.Entity;
+import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
@@ -34,6 +44,7 @@ import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
import ch.ethz.seb.sebserver.gui.service.page.ComposerService;
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.PageStateDefinition.Type;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
@@ -41,8 +52,10 @@ import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
+import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall.CallType;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
+import ch.ethz.seb.sebserver.gui.table.EntityTable;
import ch.ethz.seb.sebserver.gui.table.TableBuilder;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@@ -51,6 +64,11 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@GuiProfile
public class PageServiceImpl implements PageService {
+ private static final LocTextKey CONFIRM_DEACTIVATION_NO_DEP_KEY =
+ new LocTextKey("sebserver.dialog.confirm.deactivation.noDependencies");
+
+ private static final String CONFIRM_DEACTIVATION_KEY = "sebserver.dialog.confirm.deactivation";
+
private static final Logger log = LoggerFactory.getLogger(PageServiceImpl.class);
private static final LocTextKey MSG_GO_AWAY_FROM_EDIT =
@@ -183,6 +201,80 @@ public class PageServiceImpl implements PageService {
}
}
+ @Override
+ public Supplier confirmDeactivation(final Set extends T> entities) {
+ final RestService restService = this.resourceService.getRestService();
+ return () -> {
+ if (entities == null || entities.isEmpty()) {
+ return null;
+ }
+
+ try {
+ final int dependencies = entities.stream()
+ .flatMap(entity -> {
+ final RestCall>.RestCallBuilder builder =
+ restService.> getBuilder(
+ entity.entityType(),
+ CallType.GET_DEPENDENCIES);
+
+ return builder
+ .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(entity.getModelId()))
+ .withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.DEACTIVATE.name())
+ .call()
+ .getOrThrow().stream();
+ })
+ .collect(Collectors.toList())
+ .size();
+ if (dependencies > 0) {
+ return new LocTextKey(CONFIRM_DEACTIVATION_KEY, String.valueOf(dependencies));
+ } else {
+ return CONFIRM_DEACTIVATION_NO_DEP_KEY;
+ }
+
+ } catch (final Exception e) {
+ log.warn("Failed to get dependencyies. Error: {}", e.getMessage());
+ return new LocTextKey(CONFIRM_DEACTIVATION_KEY, "");
+ }
+ };
+ }
+
+ @Override
+ public Function activationToggleActionFunction(
+ final EntityTable table,
+ final LocTextKey noSelectionText) {
+
+ return action -> {
+ final Set selectedROWData = table.getSelectedROWData();
+ if (selectedROWData == null || selectedROWData.isEmpty()) {
+ throw new PageMessageException(noSelectionText);
+ }
+
+ final RestService restService = this.resourceService.getRestService();
+ final EntityType entityType = table.getEntityType();
+
+ final Collection errors = new ArrayList<>();
+ for (final T entity : selectedROWData) {
+ if (entity.isActive()) {
+ restService.getBuilder(entityType, CallType.ACTIVATION_DEACTIVATE)
+ .withURIVariable(API.PARAM_MODEL_ID, entity.getModelId())
+ .call()
+ .onError(errors::add);
+ } else {
+ restService.getBuilder(entityType, CallType.ACTIVATION_ACTIVATE)
+ .withURIVariable(API.PARAM_MODEL_ID, entity.getModelId())
+ .call()
+ .onError(errors::add);
+ }
+ }
+
+ if (!errors.isEmpty()) {
+ // TODO notify message for user
+ }
+
+ return action;
+ };
+ }
+
private void exec(final PageAction pageAction, final Consumer> callback) {
pageAction.applyAction(result -> {
if (!result.hasError()) {
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageUtils.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageUtils.java
deleted file mode 100644
index 34629253..00000000
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageUtils.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2019 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.service.page.impl;
-
-import java.util.Set;
-import java.util.function.Supplier;
-
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import ch.ethz.seb.sebserver.gbl.api.API;
-import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
-import ch.ethz.seb.sebserver.gbl.model.Entity;
-import ch.ethz.seb.sebserver.gbl.model.EntityKey;
-import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall.CallType;
-import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
-
-public final class PageUtils {
-
- private static final Logger log = LoggerFactory.getLogger(PageUtils.class);
-
- public static void clearComposite(final Composite parent) {
- if (parent == null) {
- return;
- }
-
- for (final Control control : parent.getChildren()) {
- control.dispose();
- }
- }
-
- public static final Supplier confirmDeactivation(
- final Entity entity,
- final RestService restService) {
-
- return () -> {
- try {
- final RestCall>.RestCallBuilder builder =
- restService.> getBuilder(
- entity.entityType(),
- CallType.GET_DEPENDENCIES);
-
- if (builder == null) {
- throw new RuntimeException("No RestCall builder found for entity type: " + entity.entityType());
- }
-
- final Set dependencies = builder
- .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(entity.getModelId()))
- .withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.DEACTIVATE.name())
- .call()
- .getOrThrow();
- final int size = dependencies.size();
- if (size > 0) {
- return new LocTextKey("sebserver.dialog.confirm.deactivation", String.valueOf(size));
- } else {
- return new LocTextKey("sebserver.dialog.confirm.deactivation.noDependencies");
- }
- } catch (final Exception e) {
- log.info("Failed to get dependencyies for Entity: {} error: ", entity, e.getMessage());
- return new LocTextKey("sebserver.dialog.confirm.deactivation", "");
- }
- };
- }
-
-}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java
index 42221ac7..d8214c55 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java
@@ -94,7 +94,7 @@ public abstract class RestCall {
return this;
}
- public EntityType getResultType() {
+ public EntityType getEntityType() {
if (this.typeKey != null) {
return this.typeKey.entityType;
}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java
index 1a665bea..2eb0ddef 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java
@@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.Constants;
+import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
@@ -203,6 +204,14 @@ public class EntityTable {
this.sortOrder);
}
+ public EntityType getEntityType() {
+ if (this.restCall != null) {
+ return this.restCall.getEntityType();
+ }
+
+ return null;
+ }
+
public PageContext getPageContext() {
if (this.pageContext == null) {
return null;
@@ -303,7 +312,7 @@ public class EntityTable {
return getRowData(item);
}
- public ROW getSelectedROWData() {
+ public ROW getSingleSelectedROWData() {
final TableItem[] selection = this.table.getSelection();
if (selection == null || selection.length == 0) {
return null;
@@ -312,6 +321,18 @@ public class EntityTable {
return getRowData(selection[0]);
}
+ public Set getSelectedROWData() {
+ final TableItem[] selection = this.table.getSelection();
+ if (selection == null || selection.length == 0) {
+ return Collections.emptySet();
+ }
+
+ return Arrays.asList(selection)
+ .stream()
+ .map(this::getRowData)
+ .collect(Collectors.toSet());
+ }
+
public Set getSelection() {
return getSelection(null);
}
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/TableNavigator.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/TableNavigator.java
index 1bc89167..ae6fd238 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/table/TableNavigator.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/TableNavigator.java
@@ -17,7 +17,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import ch.ethz.seb.sebserver.gbl.model.Page;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public class TableNavigator {
@@ -40,7 +40,7 @@ public class TableNavigator {
public Page> update(final Page> pageData) {
// clear all
- PageUtils.clearComposite(this.composite);
+ PageService.clearComposite(this.composite);
if (pageData.isEmpty()) {
// show empty message
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelection.java
index 9ae8111c..c464b904 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelection.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelection.java
@@ -24,7 +24,7 @@ import org.eclipse.swt.widgets.Listener;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public final class MultiSelection extends Composite implements Selection {
@@ -61,7 +61,7 @@ public final class MultiSelection extends Composite implements Selection {
final String selectionValue = getSelectionValue();
this.selected.clear();
this.labels.clear();
- PageUtils.clearComposite(this);
+ PageService.clearComposite(this);
for (final Tuple tuple : mapping) {
final Label label = new Label(this, SWT.NONE);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCheckbox.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCheckbox.java
index cda8a360..cadc32d2 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCheckbox.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/MultiSelectionCheckbox.java
@@ -24,7 +24,7 @@ import org.eclipse.swt.widgets.Listener;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
public final class MultiSelectionCheckbox extends Composite implements Selection {
@@ -54,7 +54,7 @@ public final class MultiSelectionCheckbox extends Composite implements Selection
public void applyNewMapping(final List> mapping) {
final String selectionValue = getSelectionValue();
this.checkboxes.clear();
- PageUtils.clearComposite(this);
+ PageService.clearComposite(this);
for (final Tuple tuple : mapping) {
final Button button = new Button(this, SWT.CHECK);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/RadioSelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/RadioSelection.java
index b7491851..f93b2304 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/RadioSelection.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/RadioSelection.java
@@ -21,7 +21,7 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Listener;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
-import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
+import ch.ethz.seb.sebserver.gui.service.page.PageService;
public final class RadioSelection extends Composite implements Selection {
@@ -51,7 +51,7 @@ public final class RadioSelection extends Composite implements Selection {
public void applyNewMapping(final List> mapping) {
final String selectionValue = getSelectionValue();
this.radioButtons.clear();
- PageUtils.clearComposite(this);
+ PageService.clearComposite(this);
for (final Tuple tuple : mapping) {
final Button button = new Button(this, SWT.RADIO);
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java
index 065830b9..9541a308 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java
@@ -82,6 +82,7 @@ public class WidgetFactory {
INACTIVE("inactive.png"),
TOGGLE_ON("toggle_on.png"),
TOGGLE_OFF("toggle_off.png"),
+ SWITCH("switch.png"),
YES("yes.png"),
NO("no.png"),
SAVE("save.png"),
@@ -440,7 +441,7 @@ public class WidgetFactory {
}
public Table tableLocalized(final Composite parent) {
- final Table table = new Table(parent, SWT.SINGLE | SWT.NO_SCROLL);
+ final Table table = new Table(parent, SWT.MULTI | SWT.NO_SCROLL);
this.polyglotPageService.injectI18n(table);
return table;
}
diff --git a/src/main/resources/config/application-dev-gui.properties b/src/main/resources/config/application-dev-gui.properties
index d94a661e..6687ad78 100644
--- a/src/main/resources/config/application-dev-gui.properties
+++ b/src/main/resources/config/application-dev-gui.properties
@@ -16,7 +16,7 @@ sebserver.gui.webservice.mock-lms-enabled=true
sebserver.gui.theme=css/sebserver.css
-sebserver.gui.list.page.size=20
+sebserver.gui.list.page.size=15
sebserver.gui.date.displayformat=MM/dd/yyyy HH:mm
sebserver.gui.date.displayformat.timezone=|ZZ
sebserver.gui.multilingual=true
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
index c038efd6..a77df066 100644
--- a/src/main/resources/messages.properties
+++ b/src/main/resources/messages.properties
@@ -28,6 +28,7 @@ sebserver.overall.date.to=To
sebserver.overall.action.add=Add;
sebserver.overall.action.remove=Remove
sebserver.overall.action.select=Please Select
+sebserver.overall.action.toggle-activity=Switch Activity
sebserver.overall.types.activityType.CREATE=Create New
sebserver.overall.types.activityType.IMPORT=Import
diff --git a/src/main/resources/static/images/switch.png b/src/main/resources/static/images/switch.png
new file mode 100644
index 00000000..7a701e07
Binary files /dev/null and b/src/main/resources/static/images/switch.png differ