SEBSERV-38 refactoring of PageAction handling

This commit is contained in:
anhefti 2019-04-01 10:48:05 +02:00
parent 98deb870eb
commit 6c27f2aeeb
43 changed files with 1404 additions and 1053 deletions

View file

@ -31,17 +31,20 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
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.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
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.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.ActivateExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeactivateExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeleteIndicator;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicators;
@ -62,7 +65,7 @@ public class ExamForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(ExamForm.class);
private final PageFormService pageFormService;
private final PageService pageService;
private final ResourceService resourceService;
private final static LocTextKey listTitleKey =
@ -77,10 +80,10 @@ public class ExamForm implements TemplateComposer {
new LocTextKey("sebserver.exam.indicator.list.pleaseSelect");
protected ExamForm(
final PageFormService pageFormService,
final PageService pageService,
final ResourceService resourceService) {
this.pageFormService = pageFormService;
this.pageService = pageService;
this.resourceService = resourceService;
}
@ -88,7 +91,7 @@ public class ExamForm implements TemplateComposer {
public void compose(final PageContext pageContext) {
final CurrentUser currentUser = this.resourceService.getCurrentUser();
final RestService restService = this.resourceService.getRestService();
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final I18nSupport i18nSupport = this.resourceService.getI18nSupport();
final UserInfo user = currentUser.get();
@ -131,7 +134,7 @@ public class ExamForm implements TemplateComposer {
final boolean modifyGrant = userGrantCheck.m();
// The Exam form
final FormHandle<Exam> formHandle = this.pageFormService.getBuilder(
final FormHandle<Exam> formHandle = this.pageService.formBuilder(
formContext.copyOf(content), 4)
.readonly(readonly)
.putStaticValueIf(isNotNew,
@ -204,34 +207,36 @@ public class ExamForm implements TemplateComposer {
? restService.getRestCall(ImportAsExam.class)
: restService.getRestCall(SaveExam.class));
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(formContext
.clearEntityKeys()
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZZ_DATA));
// propagate content actions to action-pane
formContext.clearEntityKeys()
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZZ_DATA)
actionBuilder
.createAction(ActionDefinition.EXAM_MODIFY)
.newAction(ActionDefinition.EXAM_MODIFY)
.withEntityKey(entityKey)
.publishIf(() -> modifyGrant && readonly)
.createAction(ActionDefinition.EXAM_SAVE)
.newAction(ActionDefinition.EXAM_SAVE)
.withExec(formHandle::processFormSave)
.ignoreMoveAwayFromEdit()
.publishIf(() -> !readonly && modifyGrant)
.createAction(ActionDefinition.EXAM_CANCEL_MODIFY)
.newAction(ActionDefinition.EXAM_CANCEL_MODIFY)
.withEntityKey(entityKey)
.withAttribute(AttributeKeys.IMPORT_FROM_QUIZZ_DATA, String.valueOf(importFromQuizData))
.withExec(ExamForm::cancelModify)
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
.withExec(this::cancelModify)
.publishIf(() -> !readonly)
.createAction(ActionDefinition.EXAM_DEACTIVATE)
.newAction(ActionDefinition.EXAM_DEACTIVATE)
.withEntityKey(entityKey)
.withExec(restService::activation)
.withSimpleRestCall(restService, DeactivateExam.class)
.withConfirm(PageUtils.confirmDeactivation(exam, restService))
.publishIf(() -> writeGrant && readonly && exam.isActive())
.createAction(ActionDefinition.EXAM_ACTIVATE)
.newAction(ActionDefinition.EXAM_ACTIVATE)
.withEntityKey(entityKey)
.withExec(restService::activation)
.withSimpleRestCall(restService, ActivateExam.class)
.publishIf(() -> writeGrant && readonly && !exam.isActive());
// additional data in read-only view
@ -244,7 +249,7 @@ public class ExamForm implements TemplateComposer {
listTitleKey);
final EntityTable<Indicator> indicatorTable =
widgetFactory.entityTableBuilder(restService.getRestCall(GetIndicators.class))
this.pageService.entityTableBuilder(restService.getRestCall(GetIndicators.class))
.withEmptyMessage(new LocTextKey("sebserver.exam.indicator.list.empty"))
.withPaging(3)
.withColumn(new ColumnDefinition<>(
@ -265,19 +270,18 @@ public class ExamForm implements TemplateComposer {
.compose(content);
formContext.clearEntityKeys()
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZZ_DATA)
actionBuilder
.createAction(ActionDefinition.EXAM_INDICATOR_NEW)
.newAction(ActionDefinition.EXAM_INDICATOR_NEW)
.withParentEntityKey(entityKey)
.publishIf(() -> modifyGrant)
.createAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
.withParentEntityKey(entityKey)
.withSelect(indicatorTable::getSelection, PageAction::applySingleSelection, emptySelectionTextKey)
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent())
.createAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
.withEntityKey(entityKey)
.withSelect(indicatorTable::getSelection, this::deleteSelectedIndicator, emptySelectionTextKey)
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent());
@ -338,17 +342,20 @@ public class ExamForm implements TemplateComposer {
.toString();
}
public static PageAction cancelModify(final PageAction action) {
private PageAction cancelModify(final PageAction action) {
final boolean importFromQuizData = BooleanUtils.toBoolean(
action.pageContext().getAttribute(AttributeKeys.IMPORT_FROM_QUIZZ_DATA));
if (importFromQuizData) {
final PageContext pageContext = action.pageContext();
final PageAction activityHomeAction = pageContext.createAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST);
action.pageContext().firePageEvent(new ActionEvent(activityHomeAction, false));
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(action.pageContext());
final PageAction activityHomeAction = actionBuilder
.newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
.create();
this.pageService.firePageEvent(new ActionEvent(activityHomeAction), action.pageContext());
return activityHomeAction;
}
return PageAction.onEmptyEntityKeyGoToActivityHome(action);
this.pageService.onEmptyEntityKeyGoTo(action, ActionDefinition.EXAM_VIEW_LIST);
return action;
}
}

View file

@ -28,9 +28,11 @@ import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
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.PageAction;
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.PageActionBuilder;
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.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExams;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
@ -46,7 +48,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@GuiProfile
public class ExamList implements TemplateComposer {
private final WidgetFactory widgetFactory;
private final PageService pageService;
private final ResourceService resourceService;
private final int pageSize;
@ -67,11 +69,11 @@ public class ExamList implements TemplateComposer {
new TableFilterAttribute(CriteriaType.DATE, QuizData.FILTER_ATTR_START_TIME);
protected ExamList(
final WidgetFactory widgetFactory,
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size}") final Integer pageSize) {
this.widgetFactory = widgetFactory;
this.pageService = pageService;
this.resourceService = resourceService;
this.pageSize = (pageSize != null) ? pageSize : 20;
@ -88,20 +90,23 @@ public class ExamList implements TemplateComposer {
@Override
public void compose(final PageContext pageContext) {
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final CurrentUser currentUser = this.resourceService.getCurrentUser();
final RestService restService = this.resourceService.getRestService();
final I18nSupport i18nSupport = this.resourceService.getI18nSupport();
// content page layout with title
final Composite content = this.widgetFactory.defaultPageLayout(
final Composite content = widgetFactory.defaultPageLayout(
pageContext.getParent(),
new LocTextKey("sebserver.exam.list.title"));
final boolean isSEBAdmin = currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
// table
final EntityTable<Exam> table =
this.widgetFactory.entityTableBuilder(restService.getRestCall(GetExams.class))
this.pageService.entityTableBuilder(restService.getRestCall(GetExams.class))
.withEmptyMessage(new LocTextKey("sebserver.exam.list.empty"))
.withPaging(this.pageSize)
.withColumnIf(() -> isSEBAdmin,
@ -136,23 +141,23 @@ public class ExamList implements TemplateComposer {
columnTitleTypeKey,
this::examTypeName,
true))
.withDefaultAction(pageContext
.clearEntityKeys()
.createAction(ActionDefinition.EXAM_VIEW_FROM_LIST))
.withDefaultAction(actionBuilder
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
.create())
.compose(content);
// propagate content actions to action-pane
final GrantCheck userGrant = currentUser.grantCheck(EntityType.EXAM);
pageContext.clearEntityKeys()
actionBuilder
.createAction(ActionDefinition.EXAM_IMPORT)
.newAction(ActionDefinition.EXAM_IMPORT)
.publishIf(userGrant::im)
.createAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, emptySelectionTextKey)
.publishIf(table::hasAnyContent)
.createAction(ActionDefinition.EXAM_MODIFY_FROM_LIST)
.newAction(ActionDefinition.EXAM_MODIFY_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, emptySelectionTextKey)
.publishIf(() -> userGrant.im() && table.hasAnyContent());

View file

@ -23,11 +23,10 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
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.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExam;
@ -43,21 +42,21 @@ public class IndicatorForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(IndicatorForm.class);
private final PageFormService pageFormService;
private final PageService pageService;
private final ResourceService resourceService;
protected IndicatorForm(
final PageFormService pageFormService,
final PageService pageService,
final ResourceService resourceService) {
this.pageFormService = pageFormService;
this.pageService = pageService;
this.resourceService = resourceService;
}
@Override
public void compose(final PageContext pageContext) {
final RestService restService = this.resourceService.getRestService();
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final EntityKey entityKey = pageContext.getEntityKey();
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
final boolean isNew = entityKey == null;
@ -97,7 +96,7 @@ public class IndicatorForm implements TemplateComposer {
formContext.getParent(),
titleKey);
final FormHandle<Indicator> formHandle = this.pageFormService.getBuilder(
final FormHandle<Indicator> formHandle = this.pageService.formBuilder(
formContext.copyOf(content), 4)
.readonly(isReadonly)
.putStaticValueIf(() -> !isNew,
@ -136,16 +135,19 @@ public class IndicatorForm implements TemplateComposer {
: restService.getRestCall(SaveIndicator.class));
// propagate content actions to action-pane
formContext.clearEntityKeys()
.createAction(ActionDefinition.EXAM_INDICATOR_SAVE)
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
.newAction(ActionDefinition.EXAM_INDICATOR_SAVE)
.withEntityKey(parentEntityKey)
.withExec(formHandle::processFormSave)
.ignoreMoveAwayFromEdit()
.publishIf(() -> !isReadonly)
.createAction(ActionDefinition.EXAM_INDICATOR_CANCEL_MODIFY)
.newAction(ActionDefinition.EXAM_INDICATOR_CANCEL_MODIFY)
.withEntityKey(parentEntityKey)
.withExec(PageAction::onEmptyEntityKeyGoToActivityHome)
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
action,
ActionDefinition.EXAM_VIEW_LIST))
.publishIf(() -> !isReadonly);
}

View file

@ -26,14 +26,15 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
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.SebClientConfigDownload;
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;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.NewInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.SaveInstitution;
@ -48,18 +49,18 @@ public class InstitutionForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(InstitutionForm.class);
private final PageFormService pageFormService;
private final PageService pageService;
private final RestService restService;
private final CurrentUser currentUser;
private final SebClientConfigDownload sebClientConfigDownload;
protected InstitutionForm(
final PageFormService pageFormService,
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final SebClientConfigDownload sebClientConfigDownload) {
this.pageFormService = pageFormService;
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.sebClientConfigDownload = sebClientConfigDownload;
@ -68,7 +69,7 @@ public class InstitutionForm implements TemplateComposer {
@Override
public void compose(final PageContext pageContext) {
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final EntityKey entityKey = pageContext.getEntityKey();
final boolean isNew = entityKey == null;
// get data or create new. Handle error if happen
@ -114,7 +115,7 @@ public class InstitutionForm implements TemplateComposer {
titleKey);
// The Institution form
final FormHandle<Institution> formHandle = this.pageFormService.getBuilder(
final FormHandle<Institution> formHandle = this.pageService.formBuilder(
formContext.copyOf(content), 4)
.readonly(isReadonly)
.putStaticValueIf(() -> !isNew,
@ -139,20 +140,20 @@ public class InstitutionForm implements TemplateComposer {
// propagate content actions to action-pane
final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
formContext.clearEntityKeys()
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
.createAction(ActionDefinition.INSTITUTION_NEW)
.newAction(ActionDefinition.INSTITUTION_NEW)
.publishIf(() -> writeGrant && isReadonly)
.createAction(ActionDefinition.USER_ACCOUNT_NEW)
.newAction(ActionDefinition.USER_ACCOUNT_NEW)
.withParentEntityKey(entityKey)
.publishIf(() -> userWriteGrant && isReadonly && institution.isActive())
.createAction(ActionDefinition.INSTITUTION_MODIFY)
.newAction(ActionDefinition.INSTITUTION_MODIFY)
.withEntityKey(entityKey)
.publishIf(() -> modifyGrant && isReadonly)
.createAction(ActionDefinition.INSTITUTION_EXPORT_SEB_CONFIG)
.newAction(ActionDefinition.INSTITUTION_EXPORT_SEB_CONFIG)
.withEntityKey(entityKey)
.withExec(action -> {
final String downloadURL = this.sebClientConfigDownload.downloadSEBClientConfigURL(
@ -162,26 +163,28 @@ public class InstitutionForm implements TemplateComposer {
})
.publishIf(() -> sebConfigWriteGrant && isReadonly && institution.isActive())
.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
.newAction(ActionDefinition.INSTITUTION_DEACTIVATE)
.withEntityKey(entityKey)
.withExec(this.restService::activation)
.withSimpleRestCall(this.restService, DeactivateInstitution.class)
.withConfirm(PageUtils.confirmDeactivation(institution, this.restService))
.publishIf(() -> writeGrant && isReadonly && institution.isActive())
.createAction(ActionDefinition.INSTITUTION_ACTIVATE)
.newAction(ActionDefinition.INSTITUTION_ACTIVATE)
.withEntityKey(entityKey)
.withExec(this.restService::activation)
.withSimpleRestCall(this.restService, ActivateInstitution.class)
.publishIf(() -> writeGrant && isReadonly && !institution.isActive())
.createAction(ActionDefinition.INSTITUTION_SAVE)
.newAction(ActionDefinition.INSTITUTION_SAVE)
.withEntityKey(entityKey)
.withExec(formHandle::processFormSave)
.ignoreMoveAwayFromEdit()
.publishIf(() -> !isReadonly)
.createAction(ActionDefinition.INSTITUTION_CANCEL_MODIFY)
.newAction(ActionDefinition.INSTITUTION_CANCEL_MODIFY)
.withEntityKey(entityKey)
.withExec(PageAction::onEmptyEntityKeyGoToActivityHome)
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
action,
ActionDefinition.INSTITUTION_VIEW_LIST))
.publishIf(() -> !isReadonly);
}

View file

@ -18,16 +18,17 @@ import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
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.PageActionBuilder;
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.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutions;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.GrantCheck;
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
import ch.ethz.seb.sebserver.gui.table.EntityTable;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@Lazy
@Component
@ -47,29 +48,32 @@ public class InstitutionList implements TemplateComposer {
private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
new LocTextKey("sebserver.institution.info.pleaseSelect");
private final WidgetFactory widgetFactory;
private final PageService pageService;
private final RestService restService;
private final CurrentUser currentUser;
protected InstitutionList(
final WidgetFactory widgetFactory,
final PageService pageService,
final RestService restService,
final CurrentUser currentUser) {
this.widgetFactory = widgetFactory;
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
}
@Override
public void compose(final PageContext pageContext) {
final Composite content = this.widgetFactory.defaultPageLayout(
final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
pageContext.getParent(),
TITLE_TEXT_KEY);
final PageActionBuilder pageActionBuilder =
this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
// table
final EntityTable<Institution> table =
this.widgetFactory.entityTableBuilder(this.restService.getRestCall(GetInstitutions.class))
this.pageService.entityTableBuilder(this.restService.getRestCall(GetInstitutions.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(3)
.withColumn(new ColumnDefinition<>(
@ -87,27 +91,28 @@ public class InstitutionList implements TemplateComposer {
ACTIVE_TEXT_KEY,
entity -> entity.active,
true))
.withDefaultAction(pageContext
.clearEntityKeys()
.createAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST))
.withDefaultAction(pageActionBuilder
.newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
.create())
.compose(content);
// propagate content actions to action-pane
final GrantCheck instGrant = this.currentUser.grantCheck(EntityType.INSTITUTION);
final GrantCheck userGrant = this.currentUser.grantCheck(EntityType.USER);
pageContext.clearEntityKeys()
.createAction(ActionDefinition.INSTITUTION_NEW)
pageActionBuilder
.newAction(ActionDefinition.INSTITUTION_NEW)
.publishIf(instGrant::w)
.createAction(ActionDefinition.USER_ACCOUNT_NEW)
.newAction(ActionDefinition.USER_ACCOUNT_NEW)
.publishIf(userGrant::w)
.createAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
.newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> table.hasAnyContent())
.createAction(ActionDefinition.INSTITUTION_MODIFY_FROM_LIST)
.newAction(ActionDefinition.INSTITUTION_MODIFY_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> instGrant.m() && table.hasAnyContent());
;

View file

@ -30,16 +30,19 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
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.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.ActivateLmsSetup;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.DeactivateLmsSetup;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetup;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.NewLmsSetup;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.SaveLmsSetup;
@ -55,14 +58,14 @@ public class LmsSetupForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(LmsSetupForm.class);
private final PageFormService pageFormService;
private final PageService pageService;
private final ResourceService resourceService;
protected LmsSetupForm(
final PageFormService pageFormService,
final PageService pageService,
final ResourceService resourceService) {
this.pageFormService = pageFormService;
this.pageService = pageService;
this.resourceService = resourceService;
}
@ -70,7 +73,7 @@ public class LmsSetupForm implements TemplateComposer {
public void compose(final PageContext pageContext) {
final CurrentUser currentUser = this.resourceService.getCurrentUser();
final RestService restService = this.resourceService.getRestService();
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final UserInfo user = currentUser.get();
final EntityKey entityKey = pageContext.getEntityKey();
@ -122,7 +125,7 @@ public class LmsSetupForm implements TemplateComposer {
// The LMS Setup form
final LmsType lmsType = lmsSetup.getLmsType();
final FormHandle<LmsSetup> formHandle = this.pageFormService.getBuilder(
final FormHandle<LmsSetup> formHandle = this.pageService.formBuilder(
formContext.copyOf(content), 4)
.readonly(readonly)
.putStaticValueIf(isNotNew,
@ -174,49 +177,58 @@ public class LmsSetupForm implements TemplateComposer {
;
// propagate content actions to action-pane
formContext.clearEntityKeys()
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
.createAction(ActionDefinition.LMS_SETUP_NEW)
.newAction(ActionDefinition.LMS_SETUP_NEW)
.publishIf(() -> writeGrant && readonly && institutionActive)
.createAction(ActionDefinition.LMS_SETUP_MODIFY)
.newAction(ActionDefinition.LMS_SETUP_MODIFY)
.withEntityKey(entityKey)
.publishIf(() -> modifyGrant && readonly && institutionActive)
.createAction(ActionDefinition.LMS_SETUP_TEST)
.newAction(ActionDefinition.LMS_SETUP_TEST)
.withEntityKey(entityKey)
.withExec(action -> this.testLmsSetup(action, formHandle))
.publishIf(() -> modifyGrant && isNotNew.getAsBoolean() && institutionActive)
.createAction(ActionDefinition.LMS_SETUP_DEACTIVATE)
.newAction(ActionDefinition.LMS_SETUP_DEACTIVATE)
.withEntityKey(entityKey)
.withExec(restService::activation)
.withSimpleRestCall(restService, DeactivateLmsSetup.class)
.withConfirm(PageUtils.confirmDeactivation(lmsSetup, restService))
.publishIf(() -> writeGrant && readonly && institutionActive && lmsSetup.isActive())
.createAction(ActionDefinition.LMS_SETUP_ACTIVATE)
.newAction(ActionDefinition.LMS_SETUP_ACTIVATE)
.withEntityKey(entityKey)
.withExec(action -> activate(action, formHandle))
.publishIf(() -> writeGrant && readonly && institutionActive && !lmsSetup.isActive())
.createAction(ActionDefinition.LMS_SETUP_SAVE)
.newAction(ActionDefinition.LMS_SETUP_SAVE)
.withEntityKey(entityKey)
.withExec(formHandle::processFormSave)
.ignoreMoveAwayFromEdit()
.publishIf(() -> !readonly)
.createAction(ActionDefinition.LMS_SETUP_CANCEL_MODIFY)
.newAction(ActionDefinition.LMS_SETUP_CANCEL_MODIFY)
.withEntityKey(entityKey)
.withExec(PageAction::onEmptyEntityKeyGoToActivityHome)
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
action,
ActionDefinition.LMS_SETUP_VIEW_LIST))
.publishIf(() -> !readonly);
}
/** Save and test connection before activation */
private PageAction activate(final PageAction action, final FormHandle<LmsSetup> formHandle) {
final RestService restService = this.resourceService.getRestService();
// first test the LMS Setup. If this fails the action execution will stops
final PageAction testLmsSetup = this.testLmsSetup(action, formHandle);
final PageAction activation = restService.activation(testLmsSetup);
return activation;
// if LMS Setup test was successful, the activation action applies
this.resourceService.getRestService().getBuilder(ActivateLmsSetup.class)
.withURIVariable(
API.PARAM_MODEL_ID,
action.pageContext().getAttribute(AttributeKeys.ENTITY_ID))
.call()
.onErrorDo(t -> action.pageContext().notifyError(t));
return testLmsSetup;
}
/** LmsSetup test action implementation */

View file

@ -25,9 +25,11 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
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.PageActionBuilder;
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.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.GetLmsSetups;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
@ -63,16 +65,16 @@ public class LmsSetupList implements TemplateComposer {
new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
private final TableFilterAttribute typeFilter;
private final WidgetFactory widgetFactory;
private final PageService pageService;
private final ResourceService resourceService;
private final int pageSize;
protected LmsSetupList(
final WidgetFactory widgetFactory,
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size}") final Integer pageSize) {
this.widgetFactory = widgetFactory;
this.pageService = pageService;
this.resourceService = resourceService;
this.pageSize = (pageSize != null) ? pageSize : 20;
@ -89,20 +91,21 @@ public class LmsSetupList implements TemplateComposer {
@Override
public void compose(final PageContext pageContext) {
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final CurrentUser currentUser = this.resourceService.getCurrentUser();
final RestService restService = this.resourceService.getRestService();
// content page layout with title
final Composite content = this.widgetFactory.defaultPageLayout(
final Composite content = widgetFactory.defaultPageLayout(
pageContext.getParent(),
TITLE_TEXT_KEY);
final boolean isSEBAdmin = currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
// table
final EntityTable<LmsSetup> table =
this.widgetFactory.entityTableBuilder(restService.getRestCall(GetLmsSetups.class))
this.pageService.entityTableBuilder(restService.getRestCall(GetLmsSetups.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withColumnIf(() -> isSEBAdmin,
@ -129,23 +132,23 @@ public class LmsSetupList implements TemplateComposer {
ACTIVITY_TEXT_KEY,
entity -> entity.active,
true))
.withDefaultAction(pageContext
.clearEntityKeys()
.createAction(ActionDefinition.LMS_SETUP_VIEW_FROM_LIST))
.withDefaultAction(actionBuilder
.newAction(ActionDefinition.LMS_SETUP_VIEW_FROM_LIST)
.create())
.compose(content);
// propagate content actions to action-pane
final GrantCheck userGrant = currentUser.grantCheck(EntityType.LMS_SETUP);
pageContext.clearEntityKeys()
actionBuilder
.createAction(ActionDefinition.LMS_SETUP_NEW)
.newAction(ActionDefinition.LMS_SETUP_NEW)
.publishIf(userGrant::iw)
.createAction(ActionDefinition.LMS_SETUP_VIEW_FROM_LIST)
.newAction(ActionDefinition.LMS_SETUP_VIEW_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> table.hasAnyContent())
.createAction(ActionDefinition.LMS_SETUP_MODIFY_FROM_LIST)
.newAction(ActionDefinition.LMS_SETUP_MODIFY_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> userGrant.im() && table.hasAnyContent());

View file

@ -26,11 +26,11 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.activity.ActivitiesPane;
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.event.ActionEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
import ch.ethz.seb.sebserver.gui.service.page.impl.MainPageState;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
@ -41,8 +41,6 @@ public class MainPage implements TemplateComposer {
static final Logger log = LoggerFactory.getLogger(MainPage.class);
public static final String ATTR_MAIN_PAGE_STATE = "MAIN_PAGE_STATE";
private static final int ACTIVITY_PANE_WEIGHT = 15;
private static final int CONTENT_PANE_WEIGHT = 65;
private static final int ACTION_PANE_WEIGHT = 20;
@ -54,14 +52,19 @@ public class MainPage implements TemplateComposer {
private static final int[] OPENED_SASH_WEIGHTS = new int[] { 0, 100, 0 };
private final WidgetFactory widgetFactory;
private final PageService pageStateService;
public MainPage(
final WidgetFactory widgetFactory,
final PageService pageStateService) {
public MainPage(final WidgetFactory widgetFactory) {
this.widgetFactory = widgetFactory;
this.pageStateService = pageStateService;
}
@Override
public void compose(final PageContext pageContext) {
MainPageState.clear();
this.pageStateService.clear();
final Composite parent = pageContext.getParent();
parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
@ -123,7 +126,7 @@ public class MainPage implements TemplateComposer {
contentObjects.setData(
PageEventListener.LISTENER_ATTRIBUTE_KEY,
new ContentActionEventListener(event -> pageContext.composerService().compose(
event.action.definition.contentPaneComposer,
event.action.definition.targetState.contentPaneComposer(),
event.action.pageContext().copyOf(contentObjects)), 2));
final Composite actionPane = new Composite(mainSash, SWT.NONE);
@ -134,7 +137,7 @@ public class MainPage implements TemplateComposer {
actionPane.setData(
PageEventListener.LISTENER_ATTRIBUTE_KEY,
new ContentActionEventListener(event -> pageContext.composerService().compose(
event.action.definition.actionPaneComposer,
event.action.definition.targetState.actionPaneComposer(),
event.action.pageContext().copyOf(actionPane)), 1));
pageContext.composerService().compose(

View file

@ -22,15 +22,16 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
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.ModalInputDialog;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.quiz.GetQuizzes;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
@ -70,17 +71,16 @@ public class QuizDiscoveryList implements TemplateComposer {
// dependencies
private final WidgetFactory widgetFactory;
private final ResourceService resourceService;
private final PageFormService pageFormService;
private final PageService pageService;
private final int pageSize;
protected QuizDiscoveryList(
final PageFormService pageFormService,
final WidgetFactory widgetFactory,
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size}") final Integer pageSize) {
this.pageFormService = pageFormService;
this.widgetFactory = widgetFactory;
this.pageService = pageService;
this.widgetFactory = pageService.getWidgetFactory();
this.resourceService = resourceService;
this.pageSize = (pageSize != null) ? pageSize : 20;
@ -101,9 +101,11 @@ public class QuizDiscoveryList implements TemplateComposer {
pageContext.getParent(),
TITLE_TEXT_KEY);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
// table
final EntityTable<QuizData> table =
this.widgetFactory.entityTableBuilder(restService.getRestCall(GetQuizzes.class))
this.pageService.entityTableBuilder(restService.getRestCall(GetQuizzes.class))
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
.withPaging(this.pageSize)
.withColumn(new ColumnDefinition<>(
@ -133,22 +135,22 @@ public class QuizDiscoveryList implements TemplateComposer {
i18nSupport.getUsersTimeZoneTitleSuffix()),
quizData -> quizData.endTime,
true))
.withDefaultAction(t -> pageContext
.clearEntityKeys()
.createAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS)
.withDefaultAction(t -> actionBuilder
.newAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS)
.withExec(action -> this.showDetails(action, t.getSelectedROWData()))
.noEventPropagation())
.noEventPropagation()
.create())
.compose(content);
// propagate content actions to action-pane
final GrantCheck lmsSetupGrant = currentUser.grantCheck(EntityType.LMS_SETUP);
final GrantCheck examGrant = currentUser.grantCheck(EntityType.EXAM);
pageContext.clearEntityKeys()
actionBuilder
.createAction(ActionDefinition.LMS_SETUP_NEW)
.newAction(ActionDefinition.LMS_SETUP_NEW)
.publishIf(lmsSetupGrant::iw)
.createAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS)
.newAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS)
.withSelect(
table::getSelection,
action -> this.showDetails(action, table.getSelectedROWData()),
@ -156,7 +158,7 @@ public class QuizDiscoveryList implements TemplateComposer {
.noEventPropagation()
.publishIf(table::hasAnyContent)
.createAction(ActionDefinition.QUIZ_DISCOVERY_EXAM_IMPORT)
.newAction(ActionDefinition.QUIZ_DISCOVERY_EXAM_IMPORT)
.withSelect(
table::getSelection,
action -> this.importQuizData(action, table),
@ -195,7 +197,7 @@ public class QuizDiscoveryList implements TemplateComposer {
private void createDetailsForm(final QuizData quizData, final PageContext pc) {
this.widgetFactory.labelSeparator(pc.getParent());
this.pageFormService.getBuilder(pc, 4)
this.pageService.formBuilder(pc, 4)
.readonly(true)
.addField(FormBuilder.singleSelection(
QuizData.QUIZ_ATTR_LMS_SETUP_ID,

View file

@ -23,12 +23,12 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
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.PageAction;
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.PageAction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.ChangePassword;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
@ -46,27 +46,26 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
* password that is also required must match the administrators current password. */
public class UserAccountChangePasswordForm implements TemplateComposer {
private final PageFormService pageFormService;
private final PageService pageService;
private final RestService restService;
private final CurrentUser currentUser;
private final I18nSupport i18nSupport;
protected UserAccountChangePasswordForm(
final PageFormService pageFormService,
final PageService pageService,
final RestService restService,
final CurrentUser currentUser,
final I18nSupport i18nSupport) {
final CurrentUser currentUser) {
this.pageFormService = pageFormService;
this.pageService = pageService;
this.restService = restService;
this.currentUser = currentUser;
this.i18nSupport = i18nSupport;
this.i18nSupport = pageService.getI18nSupport();
}
@Override
public void compose(final PageContext pageContext) {
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final EntityKey entityKey = pageContext.getEntityKey();
final UserInfo userInfo = this.restService
@ -82,7 +81,7 @@ public class UserAccountChangePasswordForm implements TemplateComposer {
final boolean ownAccount = this.currentUser.get().uuid.equals(entityKey.getModelId());
// The Password Change form
final FormHandle<UserInfo> formHandle = this.pageFormService.getBuilder(
final FormHandle<UserInfo> formHandle = this.pageService.formBuilder(
pageContext.copyOf(content), 4)
.readonly(false)
.putStaticValueIf(() -> entityKey != null,
@ -103,9 +102,11 @@ public class UserAccountChangePasswordForm implements TemplateComposer {
.withCondition(() -> entityKey != null))
.buildFor(this.restService.getRestCall(ChangePassword.class));
pageContext.createAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSOWRD_SAVE)
this.pageService.pageActionBuilder(pageContext)
.newAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSOWRD_SAVE)
.withExec(action -> {
formHandle.processFormSave(action);
final PageAction saveAction = formHandle.processFormSave(action);
if (ownAccount) {
// NOTE: in this case the user changed the password of the own account
// this should cause an logout with specified message that password change
@ -118,12 +119,15 @@ public class UserAccountChangePasswordForm implements TemplateComposer {
SWT.ERROR);
error.open(null);
}
return null;
return saveAction;
})
.ignoreMoveAwayFromEdit()
.publish()
.createAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
.withExec(PageAction::onEmptyEntityKeyGoToActivityHome)
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
.newAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
action,
ActionDefinition.USER_ACCOUNT_VIEW_LIST))
.publish();
}

View file

@ -31,15 +31,17 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.form.PageFormService;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
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.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;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.DeactivateUserAccount;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.NewUserAccount;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.SaveUserAccount;
@ -54,14 +56,14 @@ public class UserAccountForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(UserAccountForm.class);
private final PageFormService pageFormService;
private final PageService pageService;
private final ResourceService resourceService;
protected UserAccountForm(
final PageFormService pageFormService,
final PageService pageService,
final ResourceService resourceService) {
this.pageFormService = pageFormService;
this.pageService = pageService;
this.resourceService = resourceService;
}
@ -69,7 +71,7 @@ public class UserAccountForm implements TemplateComposer {
public void compose(final PageContext pageContext) {
final CurrentUser currentUser = this.resourceService.getCurrentUser();
final RestService restService = this.resourceService.getRestService();
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final UserInfo user = currentUser.get();
final EntityKey entityKey = pageContext.getEntityKey();
@ -127,7 +129,7 @@ public class UserAccountForm implements TemplateComposer {
titleKey);
// The UserAccount form
final FormHandle<UserInfo> formHandle = this.pageFormService.getBuilder(
final FormHandle<UserInfo> formHandle = this.pageService.formBuilder(
formContext.copyOf(content), 4)
.readonly(readonly)
.putStaticValueIf(isNotNew,
@ -187,46 +189,48 @@ public class UserAccountForm implements TemplateComposer {
: restService.getRestCall(SaveUserAccount.class));
// propagate content actions to action-pane
formContext.clearEntityKeys()
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
.createAction(ActionDefinition.USER_ACCOUNT_NEW)
.newAction(ActionDefinition.USER_ACCOUNT_NEW)
.publishIf(() -> writeGrant && readonly && institutionActive)
.createAction(ActionDefinition.USER_ACCOUNT_MODIFY)
.newAction(ActionDefinition.USER_ACCOUNT_MODIFY)
.withEntityKey(entityKey)
.publishIf(() -> modifyGrant && readonly && institutionActive)
.createAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSOWRD)
.newAction(ActionDefinition.USER_ACCOUNT_CHANGE_PASSOWRD)
.withEntityKey(entityKey)
.publishIf(() -> modifyGrant && readonly && institutionActive && userAccount.isActive())
.createAction(ActionDefinition.USER_ACCOUNT_DEACTIVATE)
.newAction(ActionDefinition.USER_ACCOUNT_DEACTIVATE)
.withEntityKey(entityKey)
.withExec(restService::activation)
.withSimpleRestCall(restService, DeactivateUserAccount.class)
.withConfirm(PageUtils.confirmDeactivation(userAccount, restService))
.publishIf(() -> writeGrant && readonly && institutionActive && userAccount.isActive())
.createAction(ActionDefinition.USER_ACCOUNT_ACTIVATE)
.newAction(ActionDefinition.USER_ACCOUNT_ACTIVATE)
.withEntityKey(entityKey)
.withExec(restService::activation)
.withSimpleRestCall(restService, ActivateUserAccount.class)
.publishIf(() -> writeGrant && readonly && institutionActive && !userAccount.isActive())
.createAction(ActionDefinition.USER_ACCOUNT_SAVE)
.newAction(ActionDefinition.USER_ACCOUNT_SAVE)
.withEntityKey(entityKey)
.withExec(action -> {
final PageAction postChanges = formHandle.processFormSave(action);
final PageAction saveAction = formHandle.processFormSave(action);
if (ownAccount) {
currentUser.refresh();
pageContext.forwardToMainPage();
}
return postChanges;
return saveAction;
})
.ignoreMoveAwayFromEdit()
.publishIf(() -> !readonly)
.createAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
.newAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
.withEntityKey(entityKey)
.withExec(PageAction::onEmptyEntityKeyGoToActivityHome)
.withConfirm("sebserver.overall.action.modify.cancel.confirm")
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
action,
ActionDefinition.USER_ACCOUNT_VIEW_LIST))
.publishIf(() -> !readonly);
}

View file

@ -26,9 +26,11 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.ResourceService;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
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.PageActionBuilder;
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.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccounts;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
@ -73,16 +75,16 @@ public class UserAccountList implements TemplateComposer {
private final TableFilterAttribute languageFilter;
// dependencies
private final WidgetFactory widgetFactory;
private final PageService pageService;
private final ResourceService resourceService;
private final int pageSize;
protected UserAccountList(
final WidgetFactory widgetFactory,
final PageService pageService,
final ResourceService resourceService,
@Value("${sebserver.gui.list.page.size}") final Integer pageSize) {
this.widgetFactory = widgetFactory;
this.pageService = pageService;
this.resourceService = resourceService;
this.pageSize = (pageSize != null) ? pageSize : 20;
@ -99,17 +101,19 @@ public class UserAccountList implements TemplateComposer {
@Override
public void compose(final PageContext pageContext) {
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final CurrentUser currentUser = this.resourceService.getCurrentUser();
final RestService restService = this.resourceService.getRestService();
// content page layout with title
final Composite content = this.widgetFactory.defaultPageLayout(
final Composite content = widgetFactory.defaultPageLayout(
pageContext.getParent(),
TITLE_TEXT_KEY);
final BooleanSupplier isSEBAdmin = () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
// table
final EntityTable<UserInfo> table = this.widgetFactory.entityTableBuilder(
final EntityTable<UserInfo> table = this.pageService.entityTableBuilder(
restService.getRestCall(GetUserAccounts.class))
.withEmptyMessage(new LocTextKey("sebserver.useraccount.list.empty"))
@ -150,30 +154,30 @@ public class UserAccountList implements TemplateComposer {
ACTIVE_TEXT_KEY,
entity -> entity.active,
true))
.withDefaultAction(pageContext
.clearEntityKeys()
.createAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST))
.withDefaultAction(actionBuilder
.newAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
.create())
.compose(content);
// propagate content actions to action-pane
final GrantCheck userGrant = currentUser.grantCheck(EntityType.USER);
pageContext.clearEntityKeys()
actionBuilder
.createAction(ActionDefinition.USER_ACCOUNT_NEW)
.newAction(ActionDefinition.USER_ACCOUNT_NEW)
.publishIf(userGrant::iw)
.createAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
.newAction(ActionDefinition.USER_ACCOUNT_VIEW_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> table.hasAnyContent())
.createAction(ActionDefinition.USER_ACCOUNT_MODIFY_FROM_LIST)
.newAction(ActionDefinition.USER_ACCOUNT_MODIFY_FROM_LIST)
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
.publishIf(() -> userGrant.im() && table.hasAnyContent());
}
private String getLocaleDisplayText(final UserInfo userInfo) {
return (userInfo.language != null)
? userInfo.language.getDisplayLanguage(this.widgetFactory.getI18nSupport().getCurrentLocale())
? userInfo.language.getDisplayLanguage(this.pageService.getI18nSupport().getCurrentLocale())
: Constants.EMPTY_NOTE;
}

View file

@ -8,471 +8,276 @@
package ch.ethz.seb.sebserver.gui.content.action;
import ch.ethz.seb.sebserver.gui.content.ExamForm;
import ch.ethz.seb.sebserver.gui.content.ExamList;
import ch.ethz.seb.sebserver.gui.content.IndicatorForm;
import ch.ethz.seb.sebserver.gui.content.InstitutionForm;
import ch.ethz.seb.sebserver.gui.content.InstitutionList;
import ch.ethz.seb.sebserver.gui.content.LmsSetupForm;
import ch.ethz.seb.sebserver.gui.content.LmsSetupList;
import ch.ethz.seb.sebserver.gui.content.QuizDiscoveryList;
import ch.ethz.seb.sebserver.gui.content.UserAccountChangePasswordForm;
import ch.ethz.seb.sebserver.gui.content.UserAccountForm;
import ch.ethz.seb.sebserver.gui.content.UserAccountList;
import ch.ethz.seb.sebserver.gui.content.activity.PageStateDefinition;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.ActivateExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.DeactivateExam;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.ActivateInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.DeactivateInstitution;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.ActivateLmsSetup;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.lmssetup.DeactivateLmsSetup;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.ActivateUserAccount;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.DeactivateUserAccount;
import ch.ethz.seb.sebserver.gui.service.page.PageState;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
/** Enumeration of static action data for each action within the SEB Server GUI */
// TODO add category to allow easy positioning of actions later
public enum ActionDefinition {
INSTITUTION_VIEW_LIST(
new LocTextKey("sebserver.institution.action.list"),
InstitutionList.class),
PageStateDefinition.INSTITUTION_LIST),
INSTITUTION_VIEW_FORM(
new LocTextKey("sebserver.institution.action.form"),
InstitutionForm.class,
INSTITUTION_VIEW_LIST),
PageStateDefinition.INSTITUTION_VIEW),
INSTITUTION_NEW(
new LocTextKey("sebserver.institution.action.new"),
ImageIcon.NEW,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
false),
PageStateDefinition.INSTITUTION_EDIT),
INSTITUTION_VIEW_FROM_LIST(
new LocTextKey("sebserver.institution.action.list.view"),
ImageIcon.SHOW,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
PageStateDefinition.INSTITUTION_VIEW,
ActionCategory.INSTITUTION_LIST),
INSTITUTION_MODIFY_FROM_LIST(
new LocTextKey("sebserver.institution.action.list.modify"),
ImageIcon.EDIT,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
ActionCategory.INSTITUTION_LIST,
false),
PageStateDefinition.INSTITUTION_EDIT,
ActionCategory.INSTITUTION_LIST),
INSTITUTION_MODIFY(
new LocTextKey("sebserver.institution.action.modify"),
ImageIcon.EDIT,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
ActionCategory.FORM,
false),
PageStateDefinition.INSTITUTION_EDIT,
ActionCategory.FORM),
INSTITUTION_CANCEL_MODIFY(
new LocTextKey("sebserver.overall.action.modify.cancel"),
ImageIcon.CANCEL,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
ActionCategory.FORM,
true),
PageStateDefinition.INSTITUTION_VIEW,
ActionCategory.FORM),
INSTITUTION_SAVE(
new LocTextKey("sebserver.institution.action.save"),
ImageIcon.SAVE,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
PageStateDefinition.INSTITUTION_VIEW,
ActionCategory.FORM),
INSTITUTION_ACTIVATE(
new LocTextKey("sebserver.institution.action.activate"),
ImageIcon.INACTIVE,
InstitutionForm.class,
ActivateInstitution.class,
INSTITUTION_VIEW_LIST,
PageStateDefinition.INSTITUTION_VIEW,
ActionCategory.FORM),
INSTITUTION_DEACTIVATE(
new LocTextKey("sebserver.institution.action.deactivate"),
ImageIcon.ACTIVE,
InstitutionForm.class,
DeactivateInstitution.class,
INSTITUTION_VIEW_LIST,
PageStateDefinition.INSTITUTION_VIEW,
ActionCategory.FORM),
INSTITUTION_DELETE(
new LocTextKey("sebserver.institution.action.modify"),
ImageIcon.DELETE,
InstitutionList.class,
INSTITUTION_VIEW_LIST),
INSTITUTION_EXPORT_SEB_CONFIG(
new LocTextKey("sebserver.institution.action.export.sebconfig"),
ImageIcon.SAVE,
InstitutionForm.class,
INSTITUTION_VIEW_LIST,
PageStateDefinition.INSTITUTION_VIEW,
ActionCategory.FORM),
USER_ACCOUNT_VIEW_LIST(
new LocTextKey("sebserver.useraccount.action.list"),
UserAccountList.class),
PageStateDefinition.USER_ACCOUNT_LIST),
USER_ACCOUNT_VIEW_FORM(
new LocTextKey("sebserver.useraccount.action.form"),
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST),
PageStateDefinition.USER_ACCOUNT_VIEW),
USER_ACCOUNT_NEW(
new LocTextKey("sebserver.useraccount.action.new"),
ImageIcon.NEW,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST, false),
PageStateDefinition.USER_ACCOUNT_EDIT),
USER_ACCOUNT_VIEW_FROM_LIST(
new LocTextKey("sebserver.useraccount.action.view"),
ImageIcon.SHOW,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST,
PageStateDefinition.USER_ACCOUNT_VIEW,
ActionCategory.USER_ACCOUNT_LIST),
USER_ACCOUNT_MODIFY_FROM_LIST(
new LocTextKey("sebserver.useraccount.action.list.modify"),
ImageIcon.EDIT,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST,
ActionCategory.USER_ACCOUNT_LIST,
false),
PageStateDefinition.USER_ACCOUNT_EDIT,
ActionCategory.USER_ACCOUNT_LIST),
USER_ACCOUNT_MODIFY(
new LocTextKey("sebserver.useraccount.action.modify"),
ImageIcon.EDIT,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST,
ActionCategory.FORM,
false),
PageStateDefinition.USER_ACCOUNT_EDIT,
ActionCategory.FORM),
USER_ACCOUNT_CANCEL_MODIFY(
new LocTextKey("sebserver.overall.action.modify.cancel"),
ImageIcon.CANCEL,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST,
ActionCategory.FORM,
true),
PageStateDefinition.USER_ACCOUNT_VIEW,
ActionCategory.FORM),
USER_ACCOUNT_SAVE(
new LocTextKey("sebserver.useraccount.action.save"),
ImageIcon.SAVE,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST,
PageStateDefinition.USER_ACCOUNT_VIEW,
ActionCategory.FORM),
USER_ACCOUNT_ACTIVATE(
new LocTextKey("sebserver.useraccount.action.activate"),
ImageIcon.INACTIVE,
UserAccountForm.class,
ActivateUserAccount.class,
USER_ACCOUNT_VIEW_LIST,
PageStateDefinition.USER_ACCOUNT_VIEW,
ActionCategory.FORM),
USER_ACCOUNT_DEACTIVATE(
new LocTextKey("sebserver.useraccount.action.deactivate"),
ImageIcon.ACTIVE,
UserAccountForm.class,
DeactivateUserAccount.class,
USER_ACCOUNT_VIEW_LIST,
PageStateDefinition.USER_ACCOUNT_VIEW,
ActionCategory.FORM),
USER_ACCOUNT_DELETE(
new LocTextKey("sebserver.useraccount.action.modify"),
ImageIcon.DELETE,
UserAccountList.class,
USER_ACCOUNT_VIEW_LIST),
USER_ACCOUNT_CHANGE_PASSOWRD(
new LocTextKey("sebserver.useraccount.action.change.password"),
ImageIcon.EDIT,
UserAccountChangePasswordForm.class,
USER_ACCOUNT_VIEW_LIST,
ActionCategory.FORM,
false),
PageStateDefinition.USER_ACCOUNT_PASSWORD_CHANGE,
ActionCategory.FORM),
USER_ACCOUNT_CHANGE_PASSOWRD_SAVE(
new LocTextKey("sebserver.useraccount.action.change.password.save"),
ImageIcon.SAVE,
UserAccountForm.class,
USER_ACCOUNT_VIEW_LIST,
PageStateDefinition.USER_ACCOUNT_VIEW,
ActionCategory.FORM),
LMS_SETUP_VIEW_LIST(
new LocTextKey("sebserver.lmssetup.action.list"),
LmsSetupList.class),
PageStateDefinition.LMS_SETUP_LIST),
LMS_SETUP_NEW(
new LocTextKey("sebserver.lmssetup.action.new"),
ImageIcon.NEW,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST, false),
PageStateDefinition.LMS_SETUP_EDIT),
LMS_SETUP_VIEW_FROM_LIST(
new LocTextKey("sebserver.lmssetup.action.list.view"),
ImageIcon.SHOW,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST,
PageStateDefinition.LMS_SETUP_VIEW,
ActionCategory.LMS_SETUP_LIST),
LMS_SETUP_MODIFY_FROM_LIST(
new LocTextKey("sebserver.lmssetup.action.list.modify"),
ImageIcon.EDIT,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST,
ActionCategory.LMS_SETUP_LIST,
false),
PageStateDefinition.LMS_SETUP_EDIT,
ActionCategory.LMS_SETUP_LIST),
LMS_SETUP_MODIFY(
new LocTextKey("sebserver.lmssetup.action.modify"),
ImageIcon.EDIT,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST,
ActionCategory.FORM,
false),
PageStateDefinition.LMS_SETUP_EDIT,
ActionCategory.FORM),
LMS_SETUP_TEST(
new LocTextKey("sebserver.lmssetup.action.test"),
ImageIcon.TEST,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST,
PageStateDefinition.LMS_SETUP_VIEW,
ActionCategory.FORM),
LMS_SETUP_CANCEL_MODIFY(
new LocTextKey("sebserver.overall.action.modify.cancel"),
ImageIcon.CANCEL,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST,
ActionCategory.FORM,
true),
PageStateDefinition.LMS_SETUP_VIEW,
ActionCategory.FORM),
LMS_SETUP_SAVE(
new LocTextKey("sebserver.lmssetup.action.save"),
ImageIcon.SAVE,
LmsSetupForm.class,
LMS_SETUP_VIEW_LIST,
PageStateDefinition.LMS_SETUP_VIEW,
ActionCategory.FORM),
LMS_SETUP_ACTIVATE(
new LocTextKey("sebserver.lmssetup.action.activate"),
ImageIcon.INACTIVE,
LmsSetupForm.class,
ActivateLmsSetup.class,
LMS_SETUP_VIEW_LIST,
PageStateDefinition.LMS_SETUP_VIEW,
ActionCategory.FORM),
LMS_SETUP_DEACTIVATE(
new LocTextKey("sebserver.lmssetup.action.deactivate"),
ImageIcon.ACTIVE,
LmsSetupForm.class,
DeactivateLmsSetup.class,
LMS_SETUP_VIEW_LIST,
PageStateDefinition.LMS_SETUP_VIEW,
ActionCategory.FORM),
QUIZ_DISCOVERY_VIEW_LIST(
new LocTextKey("sebserver.quizdiscovery.action.list"),
QuizDiscoveryList.class),
PageStateDefinition.QUIZ_LIST),
QUIZ_DISCOVERY_SHOW_DETAILS(
new LocTextKey("sebserver.quizdiscovery.action.details"),
ImageIcon.SHOW,
null,
ActionCategory.QUIZ_LIST),
QUIZ_DISCOVERY_EXAM_IMPORT(
new LocTextKey("sebserver.quizdiscovery.action.import"),
ImageIcon.IMPORT,
ExamForm.class,
QUIZ_DISCOVERY_VIEW_LIST,
ActionCategory.QUIZ_LIST,
false),
PageStateDefinition.EXAM_EDIT,
ActionCategory.QUIZ_LIST),
EXAM_VIEW_LIST(
new LocTextKey("sebserver.exam.action.list"),
ExamList.class),
PageStateDefinition.EXAM_LIST),
EXAM_IMPORT(
new LocTextKey("sebserver.exam.action.import"),
ImageIcon.IMPORT,
QuizDiscoveryList.class,
QUIZ_DISCOVERY_VIEW_LIST,
false),
PageStateDefinition.QUIZ_LIST),
EXAM_VIEW_FROM_LIST(
new LocTextKey("sebserver.exam.action.list.view"),
ImageIcon.SHOW,
ExamForm.class,
EXAM_VIEW_LIST,
PageStateDefinition.EXAM_VIEW,
ActionCategory.EXAM_LIST),
EXAM_MODIFY_FROM_LIST(
new LocTextKey("sebserver.exam.action.list.modify"),
ImageIcon.EDIT,
ExamForm.class,
EXAM_VIEW_LIST,
ActionCategory.EXAM_LIST,
false),
PageStateDefinition.EXAM_EDIT,
ActionCategory.EXAM_LIST),
EXAM_MODIFY(
new LocTextKey("sebserver.exam.action.modify"),
ImageIcon.EDIT,
ExamForm.class,
EXAM_VIEW_LIST,
ActionCategory.FORM,
false),
PageStateDefinition.EXAM_EDIT,
ActionCategory.FORM),
EXAM_CANCEL_MODIFY(
new LocTextKey("sebserver.overall.action.modify.cancel"),
ImageIcon.CANCEL,
ExamForm.class,
EXAM_VIEW_LIST,
ActionCategory.FORM,
true),
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_SAVE(
new LocTextKey("sebserver.exam.action.save"),
ImageIcon.SAVE,
ExamForm.class,
EXAM_VIEW_LIST,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_ACTIVATE(
new LocTextKey("sebserver.exam.action.activate"),
ImageIcon.INACTIVE,
ExamForm.class,
ActivateExam.class,
EXAM_VIEW_LIST,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_DEACTIVATE(
new LocTextKey("sebserver.exam.action.deactivate"),
ImageIcon.ACTIVE,
ExamForm.class,
DeactivateExam.class,
EXAM_VIEW_LIST,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_INDICATOR_NEW(
new LocTextKey("sebserver.exam.indicator.action.list.new"),
ImageIcon.NEW,
IndicatorForm.class,
EXAM_VIEW_FROM_LIST,
false),
PageStateDefinition.INDICATOR_EDIT),
EXAM_INDICATOR_MODIFY_FROM_LIST(
new LocTextKey("sebserver.exam.indicator.action.list.modify"),
ImageIcon.EDIT,
IndicatorForm.class,
EXAM_VIEW_FROM_LIST,
ActionCategory.INDICATOR_LIST,
false),
PageStateDefinition.INDICATOR_EDIT,
ActionCategory.INDICATOR_LIST),
EXAM_INDICATOR_DELETE_FROM_LIST(
new LocTextKey("sebserver.exam.indicator.action.list.delete"),
ImageIcon.DELETE,
ExamForm.class,
EXAM_VIEW_FROM_LIST,
ActionCategory.INDICATOR_LIST,
true),
PageStateDefinition.EXAM_VIEW,
ActionCategory.INDICATOR_LIST),
EXAM_INDICATOR_SAVE(
new LocTextKey("sebserver.exam.indicator.action.save"),
ImageIcon.SAVE,
ExamForm.class,
EXAM_VIEW_FROM_LIST,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
EXAM_INDICATOR_CANCEL_MODIFY(
new LocTextKey("sebserver.overall.action.modify.cancel"),
ImageIcon.CANCEL,
ExamForm.class,
EXAM_VIEW_FROM_LIST,
ActionCategory.FORM,
true),
TEST_ACTION(
new LocTextKey("TEST"),
ImageIcon.TEST,
ExamList.class,
EXAM_VIEW_LIST,
PageStateDefinition.EXAM_VIEW,
ActionCategory.FORM),
;
public final LocTextKey title;
public final ImageIcon icon;
public final Class<? extends TemplateComposer> contentPaneComposer;
public final Class<? extends TemplateComposer> actionPaneComposer;
public final Class<? extends RestCall<?>> restCallType;
public final ActionDefinition activityAlias;
public final PageState targetState;
public final ActionCategory category;
public final Boolean readonly;
private ActionDefinition(
final LocTextKey title,
final Class<? extends TemplateComposer> contentPaneComposer) {
this(title, null, contentPaneComposer, ActionPane.class, null, null, null, null);
private ActionDefinition(final LocTextKey title, final PageState targetState) {
this(title, null, targetState, ActionCategory.VARIA);
}
private ActionDefinition(
final LocTextKey title,
final Class<? extends TemplateComposer> contentPaneComposer,
final ActionDefinition activityAlias) {
this(title, null, contentPaneComposer, ActionPane.class, null, activityAlias, null, null);
private ActionDefinition(final LocTextKey title, final ImageIcon icon, final PageState targetState) {
this(title, icon, targetState, ActionCategory.VARIA);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final PageState targetState,
final ActionCategory category) {
this(title, icon, null, ActionPane.class, null, null, category, null);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final ActionDefinition activityAlias) {
this(title, icon, contentPaneComposer, ActionPane.class, null, activityAlias, null, null);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final ActionDefinition activityAlias,
final ActionCategory category) {
this(title, icon, contentPaneComposer, ActionPane.class, null, activityAlias, category, null);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final Class<? extends RestCall<?>> restCallType,
final ActionDefinition activityAlias) {
this(title, icon, contentPaneComposer, ActionPane.class, restCallType, activityAlias, null, null);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final Class<? extends RestCall<?>> restCallType,
final ActionDefinition activityAlias,
final ActionCategory category) {
this(title, icon, contentPaneComposer, ActionPane.class, restCallType, activityAlias, category, null);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final ActionDefinition activityAlias,
final boolean readonly) {
this(title, icon, contentPaneComposer, ActionPane.class, null, activityAlias, null, readonly);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final ActionDefinition activityAlias,
final ActionCategory category,
final boolean readonly) {
this(title, icon, contentPaneComposer, ActionPane.class, null, activityAlias, category, readonly);
}
private ActionDefinition(
final LocTextKey title,
final ImageIcon icon,
final Class<? extends TemplateComposer> contentPaneComposer,
final Class<? extends TemplateComposer> actionPaneComposer,
final Class<? extends RestCall<?>> restCallType,
final ActionDefinition activityAlias,
final ActionCategory category,
final Boolean readonly) {
this.title = title;
this.icon = icon;
this.contentPaneComposer = contentPaneComposer;
this.actionPaneComposer = actionPaneComposer;
this.restCallType = restCallType;
this.activityAlias = activityAlias;
this.category = (category != null) ? category : ActionCategory.VARIA;
this.readonly = readonly;
this.targetState = targetState;
this.category = category;
}
}

View file

@ -28,12 +28,13 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
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.event.ActionPublishEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
@ -43,13 +44,14 @@ public class ActionPane implements TemplateComposer {
private static final String ACTION_EVENT_CALL_KEY = "ACTION_EVENT_CALL";
private final PageService pageService;
private final WidgetFactory widgetFactory;
private final Map<String, Tree> actionTrees = new HashMap<>();
public ActionPane(final WidgetFactory widgetFactory) {
super();
this.widgetFactory = widgetFactory;
protected ActionPane(final PageService pageService) {
this.pageService = pageService;
this.widgetFactory = pageService.getWidgetFactory();
}
@Override
@ -161,7 +163,7 @@ public class ActionPane implements TemplateComposer {
final TreeItem treeItem = (TreeItem) event.item;
final PageAction action = (PageAction) treeItem.getData(ACTION_EVENT_CALL_KEY);
action.run();
this.pageService.executePageAction(action);
if (!treeItem.isDisposed()) {
treeItem.getParent().deselectAll();

View file

@ -24,14 +24,17 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.Activity;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.PageService;
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
import ch.ethz.seb.sebserver.gui.service.page.PageState;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEventListener;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEventListener;
import ch.ethz.seb.sebserver.gui.service.page.impl.MainPageState;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
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.CustomVariant;
@ -44,13 +47,15 @@ public class ActivitiesPane implements TemplateComposer {
private final WidgetFactory widgetFactory;
private final CurrentUser currentUser;
private final PageService pageService;
public ActivitiesPane(
final WidgetFactory widgetFactory,
final CurrentUser currentUser) {
final CurrentUser currentUser,
final PageService pageService) {
this.widgetFactory = widgetFactory;
this.widgetFactory = pageService.getWidgetFactory();
this.currentUser = currentUser;
this.pageService = pageService;
}
@Override
@ -73,27 +78,32 @@ public class ActivitiesPane implements TemplateComposer {
//navigationGridData.horizontalIndent = 10;
navigation.setLayoutData(navigationGridData);
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext);
// Institution
// If current user has SEB Server Admin role, show the Institution list
if (userInfo.hasRole(UserRole.SEB_SERVER_ADMIN)) {
// institutions (list) as root
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.INSTITUTION_VIEW_LIST.title);
ActivityDefinition.INSTITUTION.displayName);
injectActivitySelection(
institutions,
pageContext.createAction(ActionDefinition.INSTITUTION_VIEW_LIST));
actionBuilder
.newAction(ActionDefinition.INSTITUTION_VIEW_LIST)
.create());
} else {
// otherwise show the form of the institution for current user
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.INSTITUTION_VIEW_FORM.title);
ActivityDefinition.INSTITUTION.displayName);
injectActivitySelection(
institutions,
pageContext.createAction(ActionDefinition.INSTITUTION_VIEW_FORM)
actionBuilder.newAction(ActionDefinition.INSTITUTION_VIEW_FORM)
.withEntityKey(userInfo.institutionId, EntityType.INSTITUTION)
.withAttribute(AttributeKeys.READ_ONLY, "true"));
.withAttribute(AttributeKeys.READ_ONLY, "true")
.create());
}
// User Account
@ -101,30 +111,35 @@ public class ActivitiesPane implements TemplateComposer {
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, EntityType.USER)) {
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.USER_ACCOUNT_VIEW_LIST.title);
ActivityDefinition.USER_ACCOUNT.displayName);
injectActivitySelection(
userAccounts,
pageContext.createAction(ActionDefinition.USER_ACCOUNT_VIEW_LIST));
actionBuilder
.newAction(ActionDefinition.USER_ACCOUNT_VIEW_LIST)
.create());
} else {
// otherwise show the user account form for current user
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.USER_ACCOUNT_VIEW_FORM.title);
ActivityDefinition.USER_ACCOUNT.displayName);
injectActivitySelection(
userAccounts,
pageContext.createAction(ActionDefinition.USER_ACCOUNT_VIEW_FORM)
actionBuilder.newAction(ActionDefinition.USER_ACCOUNT_VIEW_FORM)
.withEntityKey(this.currentUser.get().getEntityKey())
.withAttribute(AttributeKeys.READ_ONLY, "true"));
.withAttribute(AttributeKeys.READ_ONLY, "true")
.create());
}
// LMS Setup
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, EntityType.LMS_SETUP)) {
final TreeItem lmsSetup = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.LMS_SETUP_VIEW_LIST.title);
ActivityDefinition.LMS_SETUP.displayName);
injectActivitySelection(
lmsSetup,
pageContext.createAction(ActionDefinition.LMS_SETUP_VIEW_LIST));
actionBuilder
.newAction(ActionDefinition.LMS_SETUP_VIEW_LIST)
.create());
}
// Exam (Quiz Discovery)
@ -134,18 +149,22 @@ public class ActivitiesPane implements TemplateComposer {
// TODO discussion if this should be visible on Activity Pane or just over the Exam activity and Import action
final TreeItem quizDiscovery = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST.title);
ActivityDefinition.QUIZ_DISCOVERY.displayName);
injectActivitySelection(
quizDiscovery,
pageContext.createAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST));
actionBuilder
.newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
.create());
// Exam
final TreeItem exam = this.widgetFactory.treeItemLocalized(
navigation,
ActionDefinition.EXAM_VIEW_LIST.title);
ActivityDefinition.EXAM.displayName);
injectActivitySelection(
exam,
pageContext.createAction(ActionDefinition.EXAM_VIEW_LIST));
actionBuilder
.newAction(ActionDefinition.EXAM_VIEW_LIST)
.create());
}
// TODO other activities
@ -157,34 +176,42 @@ public class ActivitiesPane implements TemplateComposer {
new ActivitiesActionEventListener(navigation));
// page-selection on (re)load
final MainPageState mainPageState = MainPageState.get();
if (mainPageState.action == null) {
mainPageState.action = getActivitySelection(navigation.getItem(0));
final PageState state = this.pageService.getCurrentState();
if (state == null) {
final TreeItem item = navigation.getItem(0);
final PageAction activityAction = getActivitySelection(item);
this.pageService.executePageAction(activityAction);
} else {
final TreeItem item = findItemByActionDefinition(navigation.getItems(), state);
if (item != null) {
navigation.select(item);
}
}
pageContext.firePageEvent(
new ActionEvent(mainPageState.action, false));
navigation.select(navigation.getItem(0));
}
private void handleSelection(final PageContext composerCtx, final Event event) {
final TreeItem treeItem = (TreeItem) event.item;
System.out.println("selected: " + treeItem);
final MainPageState mainPageState = MainPageState.get();
final PageAction action = getActivitySelection(treeItem);
if (mainPageState.action.definition != action.definition) {
mainPageState.action = action;
composerCtx.firePageEvent(
new ActionEvent(action, true));
}
this.pageService.executePageAction(
action,
result -> {
if (result.hasError()) {
final Tree tree = (Tree) event.widget;
tree.deselect(treeItem);
final PageState currentState = this.pageService.getCurrentState();
if (currentState != null) {
final TreeItem item = findItemByActionDefinition(tree.getItems(), currentState);
if (item != null) {
tree.select(item);
}
}
}
});
}
static final TreeItem findItemByActionDefinition(
private static final TreeItem findItemByActionDefinition(
final TreeItem[] items,
final ActionDefinition actionDefinition,
final Activity activity,
final String modelId) {
if (items == null) {
@ -197,13 +224,14 @@ public class ActivitiesPane implements TemplateComposer {
continue;
}
final Activity activityAnchor = action.definition.targetState.activityAnchor();
final EntityKey entityKey = action.getEntityKey();
if ((action.definition == actionDefinition || action.definition == actionDefinition.activityAlias) &&
if (activityAnchor.name().equals(activity.name()) &&
(entityKey == null || (modelId != null && modelId.equals(entityKey.modelId)))) {
return item;
}
final TreeItem _item = findItemByActionDefinition(item.getItems(), actionDefinition, modelId);
final TreeItem _item = findItemByActionDefinition(item.getItems(), activity, modelId);
if (_item != null) {
return _item;
}
@ -212,8 +240,8 @@ public class ActivitiesPane implements TemplateComposer {
return null;
}
static final TreeItem findItemByActionDefinition(final TreeItem[] items, final ActionDefinition actionDefinition) {
return findItemByActionDefinition(items, actionDefinition, null);
static final TreeItem findItemByActionDefinition(final TreeItem[] items, final PageState pageState) {
return findItemByActionDefinition(items, pageState.activityAnchor(), null);
}
static final void expand(final TreeItem item) {
@ -242,14 +270,15 @@ public class ActivitiesPane implements TemplateComposer {
@Override
public void notify(final ActionEvent event) {
final MainPageState mainPageState = MainPageState.get();
mainPageState.action = event.action;
// TODO
// final MainPageState mainPageState = MainPageState.get();
// mainPageState.action = event.action;
if (!event.activity) {
final EntityKey entityKey = event.action.getEntityKey();
final String modelId = (entityKey != null) ? entityKey.modelId : null;
final TreeItem item = findItemByActionDefinition(
this.navigation.getItems(),
event.action.definition,
event.action.definition.targetState.activityAnchor(),
modelId);
if (item != null) {
this.navigation.select(item);

View file

@ -0,0 +1,33 @@
/*
* 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.content.activity;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.Activity;
public enum ActivityDefinition implements Activity {
INSTITUTION(new LocTextKey("sebserver.institution.action.list")),
USER_ACCOUNT(new LocTextKey("sebserver.useraccount.action.list")),
LMS_SETUP(new LocTextKey("sebserver.lmssetup.action.list")),
QUIZ_DISCOVERY(new LocTextKey("sebserver.quizdiscovery.action.list")),
EXAM(new LocTextKey("sebserver.exam.action.list")),
;
public final LocTextKey displayName;
private ActivityDefinition(final LocTextKey displayName) {
this.displayName = displayName;
}
@Override
public LocTextKey displayName() {
return this.displayName;
}
}

View file

@ -0,0 +1,96 @@
/*
* 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.content.activity;
import ch.ethz.seb.sebserver.gui.content.ExamForm;
import ch.ethz.seb.sebserver.gui.content.ExamList;
import ch.ethz.seb.sebserver.gui.content.IndicatorForm;
import ch.ethz.seb.sebserver.gui.content.InstitutionForm;
import ch.ethz.seb.sebserver.gui.content.InstitutionList;
import ch.ethz.seb.sebserver.gui.content.LmsSetupForm;
import ch.ethz.seb.sebserver.gui.content.LmsSetupList;
import ch.ethz.seb.sebserver.gui.content.QuizDiscoveryList;
import ch.ethz.seb.sebserver.gui.content.UserAccountChangePasswordForm;
import ch.ethz.seb.sebserver.gui.content.UserAccountForm;
import ch.ethz.seb.sebserver.gui.content.UserAccountList;
import ch.ethz.seb.sebserver.gui.content.action.ActionPane;
import ch.ethz.seb.sebserver.gui.service.page.Activity;
import ch.ethz.seb.sebserver.gui.service.page.PageState;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
public enum PageStateDefinition implements PageState {
INSTITUTION_LIST(Type.LIST_VIEW, InstitutionList.class, ActivityDefinition.INSTITUTION),
INSTITUTION_VIEW(Type.FORM_VIEW, InstitutionForm.class, ActivityDefinition.INSTITUTION),
INSTITUTION_EDIT(Type.FORM_EDIT, InstitutionForm.class, ActivityDefinition.INSTITUTION),
USER_ACCOUNT_LIST(Type.LIST_VIEW, UserAccountList.class, ActivityDefinition.USER_ACCOUNT),
USER_ACCOUNT_VIEW(Type.FORM_VIEW, UserAccountForm.class, ActivityDefinition.USER_ACCOUNT),
USER_ACCOUNT_EDIT(Type.FORM_EDIT, UserAccountForm.class, ActivityDefinition.USER_ACCOUNT),
USER_ACCOUNT_PASSWORD_CHANGE(Type.FORM_EDIT, UserAccountChangePasswordForm.class, ActivityDefinition.USER_ACCOUNT),
LMS_SETUP_LIST(Type.LIST_VIEW, LmsSetupList.class, ActivityDefinition.LMS_SETUP),
LMS_SETUP_VIEW(Type.FORM_VIEW, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
LMS_SETUP_EDIT(Type.FORM_EDIT, LmsSetupForm.class, ActivityDefinition.LMS_SETUP),
QUIZ_LIST(Type.LIST_VIEW, QuizDiscoveryList.class, ActivityDefinition.QUIZ_DISCOVERY),
EXAM_LIST(Type.LIST_VIEW, ExamList.class, ActivityDefinition.EXAM),
EXAM_VIEW(Type.FORM_VIEW, ExamForm.class, ActivityDefinition.EXAM),
EXAM_EDIT(Type.FORM_EDIT, ExamForm.class, ActivityDefinition.EXAM),
INDICATOR_EDIT(Type.FORM_EDIT, IndicatorForm.class, ActivityDefinition.EXAM),
;
public final Type type;
public final Class<? extends TemplateComposer> contentPaneComposer;
public final Class<? extends TemplateComposer> actionPaneComposer;
public final Activity activityAnchor;
private PageStateDefinition(
final Type type,
final Class<? extends TemplateComposer> contentPaneComposer,
final Activity activityAnchor) {
this(type, contentPaneComposer, ActionPane.class, activityAnchor);
}
private PageStateDefinition(
final Type type,
final Class<? extends TemplateComposer> contentPaneComposer,
final Class<? extends TemplateComposer> actionPaneComposer,
final Activity activityAnchor) {
this.type = type;
this.contentPaneComposer = contentPaneComposer;
this.actionPaneComposer = actionPaneComposer;
this.activityAnchor = activityAnchor;
}
@Override
public Type type() {
return this.type;
}
@Override
public Class<? extends TemplateComposer> contentPaneComposer() {
return this.contentPaneComposer;
}
@Override
public Class<? extends TemplateComposer> actionPaneComposer() {
return this.actionPaneComposer;
}
@Override
public Activity activityAnchor() {
return this.activityAnchor;
}
}

View file

@ -25,12 +25,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
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.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.widget.Selection;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@ -40,9 +39,8 @@ public class FormBuilder {
private static final Logger log = LoggerFactory.getLogger(FormBuilder.class);
final PageService pageService;
final WidgetFactory widgetFactory;
final JSONMapper jsonMapper;
private final PolyglotPageService polyglotPageService;
public final PageContext pageContext;
public final Composite formParent;
public final Form form;
@ -53,18 +51,15 @@ public class FormBuilder {
private int defaultSpanEmptyCell = 1;
private boolean emptyCellSeparation = true;
FormBuilder(
final JSONMapper jsonMapper,
final WidgetFactory widgetFactory,
final PolyglotPageService polyglotPageService,
public FormBuilder(
final PageService pageService,
final PageContext pageContext,
final int rows) {
this.widgetFactory = widgetFactory;
this.jsonMapper = jsonMapper;
this.polyglotPageService = polyglotPageService;
this.pageService = pageService;
this.widgetFactory = pageService.getWidgetFactory();
this.pageContext = pageContext;
this.form = new Form(jsonMapper);
this.form = new Form(pageService.getJSONMapper());
this.formParent = new Composite(pageContext.getParent(), SWT.NONE);
final GridLayout layout = new GridLayout(rows, true);
@ -173,14 +168,12 @@ public class FormBuilder {
return buildFor(null);
}
public <T extends Entity> FormHandle<T> buildFor(
final RestCall<T> post) {
public <T extends Entity> FormHandle<T> buildFor(final RestCall<T> post) {
return new FormHandle<>(
this.pageService,
this.pageContext,
this.form,
post,
this.polyglotPageService.getI18nSupport());
post);
}
private void empty(final Composite parent, final int hspan, final int vspan) {

View file

@ -19,11 +19,10 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.form.Form.FormFieldAccessor;
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.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.FieldValidationError;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
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.api.RestCallError;
@ -33,21 +32,23 @@ public class FormHandle<T extends Entity> {
public static final String FIELD_VALIDATION_LOCTEXT_PREFIX = "sebserver.form.validation.fieldError.";
private final PageService pageService;
private final PageContext pageContext;
private final Form form;
private final RestCall<T> post;
private final I18nSupport i18nSupport;
FormHandle(
final PageService pageService,
final PageContext pageContext,
final Form form,
final RestCall<T> post,
final I18nSupport i18nSupport) {
final RestCall<T> post) {
this.pageService = pageService;
this.pageContext = pageContext;
this.form = form;
this.post = post;
this.i18nSupport = i18nSupport;
this.i18nSupport = pageService.getI18nSupport();
}
/** Process an API post request to send and save the form field values
@ -89,12 +90,14 @@ public class FormHandle<T extends Entity> {
public PageAction handleFormPost(final Result<T> postResult, final PageAction action) {
return postResult
.map(result -> {
PageAction resultAction = action.createNew()
.withAttribute(AttributeKeys.READ_ONLY, "true");
PageAction resultAction = this.pageService.pageActionBuilder(action.pageContext())
.newAction(action.definition)
.create();
if (resultAction.getEntityKey() == null) {
resultAction = resultAction.withEntityKey(result.getEntityKey());
}
action.pageContext().firePageEvent(new ActionEvent(resultAction, false));
return resultAction;
})
.onErrorDo(this::handleError)

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2018 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.form;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@Lazy
@Component
@GuiProfile
public class PageFormService {
private final JSONMapper jsonMapper;
private final WidgetFactory widgetFactory;
private final PolyglotPageService polyglotPageService;
public PageFormService(
final JSONMapper jsonMapper,
final WidgetFactory widgetFactory,
final PolyglotPageService polyglotPageService) {
this.jsonMapper = jsonMapper;
this.widgetFactory = widgetFactory;
this.polyglotPageService = polyglotPageService;
}
public FormBuilder getBuilder(
final PageContext pageContext,
final int rows) {
return new FormBuilder(
this.jsonMapper,
this.widgetFactory,
this.polyglotPageService,
pageContext,
rows);
}
public WidgetFactory getWidgetFactory() {
return this.widgetFactory;
}
public PolyglotPageService getPolyglotPageService() {
return this.polyglotPageService;
}
}

View file

@ -0,0 +1,19 @@
/*
* 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;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
public interface Activity {
String name();
LocTextKey displayName();
}

View file

@ -1,250 +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;
import java.util.Set;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionPublishEvent;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
public final class PageAction implements Runnable {
private static final Logger log = LoggerFactory.getLogger(PageAction.class);
public final ActionDefinition definition;
Supplier<LocTextKey> confirm;
LocTextKey successMessage;
Supplier<Set<EntityKey>> selectionSupplier;
LocTextKey noSelectionMessage;
private final PageContext originalPageContext;
private PageContext pageContext;
private Function<PageAction, PageAction> exec = Function.identity();
private boolean fireActionEvent = true;
public PageAction(
final ActionDefinition definition,
final PageContext pageContext) {
this.definition = definition;
this.originalPageContext = pageContext;
final String readonly = pageContext.getAttribute(AttributeKeys.READ_ONLY, "true");
this.pageContext = pageContext.withAttribute(
AttributeKeys.READ_ONLY,
definition.readonly != null
? String.valueOf(definition.readonly)
: readonly);
}
@Override
public void run() {
if (this.confirm != null) {
final LocTextKey confirmMessage = this.confirm.get();
if (confirmMessage != null) {
this.pageContext.applyConfirmDialog(confirmMessage, () -> exec());
}
} else {
exec();
}
}
private void exec() {
try {
final PageAction executedAction = this.exec.apply(this);
if (this.fireActionEvent) {
this.pageContext.firePageEvent(new ActionEvent(executedAction, false));
}
} catch (final PageMessageException pme) {
PageAction.this.pageContext.publishPageMessage(pme);
} catch (final RestCallError restCallError) {
if (restCallError.isFieldValidationError()) {
PageAction.this.pageContext.publishPageMessage(
new LocTextKey("sebserver.form.validation.error.title"),
new LocTextKey("sebserver.form.validation.error.message"));
} else {
log.error("Failed to execute action: {}", PageAction.this, restCallError);
PageAction.this.pageContext.notifyError("action.error.unexpected.message", restCallError);
}
} catch (final Throwable t) {
log.error("Failed to execute action: {}", PageAction.this, t);
PageAction.this.pageContext.notifyError("action.error.unexpected.message", t);
}
}
public PageAction createNew() {
return this.pageContext.createAction(this.definition);
}
public PageAction withExec(final Function<PageAction, PageAction> exec) {
this.exec = exec;
return this;
}
public PageAction withSelectionSupplier(final Supplier<Set<EntityKey>> selectionSupplier) {
this.selectionSupplier = selectionSupplier;
return this;
}
public PageAction withSelect(
final Supplier<Set<EntityKey>> selectionSupplier,
final Function<PageAction, PageAction> exec,
final LocTextKey noSelectionMessage) {
this.selectionSupplier = selectionSupplier;
this.exec = exec;
this.noSelectionMessage = noSelectionMessage;
return this;
}
public PageAction withConfirm(final String confirmationMessageKey) {
this.confirm = () -> new LocTextKey(confirmationMessageKey);
return this;
}
public PageAction withConfirm(final Supplier<LocTextKey> confirm) {
this.confirm = confirm;
return this;
}
public PageAction withSuccess(final String successMessageKey) {
this.successMessage = new LocTextKey(successMessageKey);
return this;
}
public PageAction resetEntityKey() {
this.pageContext = this.pageContext.withEntityKey(null);
return this;
}
public PageAction noEventPropagation() {
this.fireActionEvent = false;
return this;
}
public PageAction resetParentEntityKey() {
this.pageContext = this.pageContext.withParentEntityKey(null);
return this;
}
public EntityKey getEntityKey() {
return this.pageContext.getEntityKey();
}
public PageContext pageContext() {
return this.pageContext;
}
public PageAction withEntityKey(final EntityKey entityKey) {
this.pageContext = this.pageContext.withEntityKey(entityKey);
return this;
}
public PageAction withEntityKey(final Long modelId, final EntityType entityType) {
if (modelId != null) {
return withEntityKey(String.valueOf(modelId), entityType);
}
return this;
}
public PageAction withEntityKey(final String modelId, final EntityType entityType) {
if (modelId == null || entityType == null) {
return this;
}
this.pageContext = this.pageContext.withEntityKey(new EntityKey(modelId, entityType));
return this;
}
public PageAction withParentEntityKey(final EntityKey entityKey) {
this.pageContext = this.pageContext.withParentEntityKey(entityKey);
return this;
}
public PageAction withAttribute(final String name, final String value) {
this.pageContext = this.pageContext.withAttribute(name, value);
return this;
}
public PageContext publish() {
this.pageContext.firePageEvent(new ActionPublishEvent(this));
return this.originalPageContext;
}
public PageContext publishIf(final BooleanSupplier condition) {
if (condition.getAsBoolean()) {
publish();
}
return this.originalPageContext;
}
public EntityKey getSingleSelection() {
final Set<EntityKey> selection = getMultiSelection();
if (selection != null) {
return selection.iterator().next();
}
return null;
}
public Set<EntityKey> getMultiSelection() {
if (this.selectionSupplier != null) {
final Set<EntityKey> selection = this.selectionSupplier.get();
if (selection.isEmpty()) {
if (this.noSelectionMessage != null) {
throw new PageMessageException(this.noSelectionMessage);
}
return null;
}
return selection;
}
if (this.noSelectionMessage != null) {
throw new PageMessageException(this.noSelectionMessage);
}
return null;
}
public static PageAction applySingleSelection(final PageAction action) {
return action.withEntityKey(action.getSingleSelection());
}
public static PageAction onEmptyEntityKeyGoToActivityHome(final PageAction action) {
if (action.getEntityKey() == null) {
final PageContext pageContext = action.pageContext();
final PageAction activityHomeAction = pageContext.createAction(action.definition.activityAlias);
action.pageContext.firePageEvent(new ActionEvent(activityHomeAction, false));
return activityHomeAction;
}
return action;
}
}

View file

@ -8,15 +8,15 @@
package ch.ethz.seb.sebserver.gui.service.page;
import java.util.function.Consumer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEvent;
/** Holds a page-context and defines some convenient functionality for page handling */
public interface PageContext {
@ -149,21 +149,12 @@ public interface PageContext {
* @return a copy of this PageContext with the removed attribute */
PageContext removeAttribute(String name);
/** 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.
*
* @param event the concrete PageEvent instance */
<T extends PageEvent> void firePageEvent(T event);
PageAction createAction(ActionDefinition actionDefinition);
/** Apply a confirm dialog with a specified confirm message and a callback code
* block that will be executed on users OK selection.
*
* @param confirmMessage the localized confirm message key
* @param onOK callback code block that will be executed on users OK selection */
void applyConfirmDialog(LocTextKey confirmMessage, Runnable onOK);
* @param onOK callback code block that will be called on users selection */
void applyConfirmDialog(LocTextKey confirmMessage, final Consumer<Boolean> callback);
/** This can be used to forward to a defined page.
*

View file

@ -0,0 +1,259 @@
/*
* 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;
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 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.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
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.PolyglotPageService;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
import ch.ethz.seb.sebserver.gui.service.page.event.PageEvent;
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.RestService;
import ch.ethz.seb.sebserver.gui.table.TableBuilder;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
/** The main page service that provides functionality to build a page
* with forms and tables as well as dealing with page actions */
public interface PageService {
/** get the WidgetFactory service
*
* @return the WidgetFactory service */
WidgetFactory getWidgetFactory();
/** get the polyglotPageService service
*
* @return the polyglotPageService service */
PolyglotPageService getPolyglotPageService();
/** get the I18nSupport (internationalization support) service
*
* @return the I18nSupport (internationalization support) service */
I18nSupport getI18nSupport();
/** get the JSONMapper for parse, read and write JSON
*
* @return the JSONMapper for parse, read and write JSON */
JSONMapper getJSONMapper();
PageState initPageState(PageState initState);
PageState getCurrentState();
/** 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.
*
* @param event the concrete PageEvent instance */
<T extends PageEvent> void firePageEvent(T event, PageContext pageContext);
default void executePageAction(final PageAction pageAction) {
executePageAction(pageAction, result -> {
});
}
void executePageAction(PageAction pageAction, Consumer<Result<PageAction>> callback);
void publishAction(final PageAction pageAction);
FormBuilder formBuilder(final PageContext pageContext, final int rows);
<T extends Entity> TableBuilder<T> entityTableBuilder(final RestCall<Page<T>> apiCall);
void clear();
default PageActionBuilder pageActionBuilder(final PageContext pageContext) {
return new PageActionBuilder(this, pageContext);
}
default PageAction onEmptyEntityKeyGoTo(final PageAction action, final ActionDefinition gotoActionDef) {
if (action.getEntityKey() == null) {
final PageContext pageContext = action.pageContext();
final PageAction activityHomeAction = pageActionBuilder(pageContext)
.newAction(gotoActionDef)
.create();
firePageEvent(new ActionEvent(activityHomeAction), activityHomeAction.pageContext());
}
return action;
}
public class PageActionBuilder {
private final PageService pageService;
private final PageContext originalPageContext;
private PageContext pageContext;
private ActionDefinition definition;
private Supplier<LocTextKey> confirm;
private LocTextKey successMessage;
private Supplier<Set<EntityKey>> selectionSupplier;
private LocTextKey noSelectionMessage;
private Function<PageAction, PageAction> exec;
private boolean fireActionEvent = true;
private boolean ignoreMoveAwayFromEdit = false;
protected PageActionBuilder(final PageService pageService, final PageContext pageContext) {
this.pageService = pageService;
this.originalPageContext = pageContext;
}
public PageActionBuilder newAction(final ActionDefinition definition) {
pageContext = originalPageContext.copy();
this.definition = definition;
confirm = null;
successMessage = null;
selectionSupplier = null;
noSelectionMessage = null;
exec = null;
fireActionEvent = true;
ignoreMoveAwayFromEdit = false;
return this;
}
public PageAction create() {
return new PageAction(
definition,
confirm,
successMessage,
selectionSupplier,
noSelectionMessage,
pageContext,
exec,
fireActionEvent,
ignoreMoveAwayFromEdit);
}
public PageActionBuilder publish() {
pageService.publishAction(create());
return this;
}
public PageActionBuilder publishIf(final BooleanSupplier condition) {
if (!condition.getAsBoolean()) {
return this;
}
return this.publish();
}
public PageActionBuilder withExec(final Function<PageAction, PageAction> exec) {
this.exec = exec;
return this;
}
public PageActionBuilder withSelectionSupplier(final Supplier<Set<EntityKey>> selectionSupplier) {
this.selectionSupplier = selectionSupplier;
return this;
}
public PageActionBuilder withSelect(
final Supplier<Set<EntityKey>> selectionSupplier,
final Function<PageAction, PageAction> exec,
final LocTextKey noSelectionMessage) {
this.selectionSupplier = selectionSupplier;
this.exec = exec;
this.noSelectionMessage = noSelectionMessage;
return this;
}
public PageActionBuilder withSimpleRestCall(
final RestService restService,
final Class<? extends RestCall<?>> restCallType) {
this.exec = action -> {
restService.getBuilder(restCallType)
.withURIVariable(
API.PARAM_MODEL_ID,
action.pageContext().getAttribute(AttributeKeys.ENTITY_ID))
.call()
.onErrorDo(t -> action.pageContext().notifyError(t));
return action;
};
return this;
}
public PageActionBuilder withConfirm(final String confirmationMessageKey) {
this.confirm = () -> new LocTextKey(confirmationMessageKey);
return this;
}
public PageActionBuilder withConfirm(final Supplier<LocTextKey> confirm) {
this.confirm = confirm;
return this;
}
public PageActionBuilder withSuccess(final String successMessageKey) {
this.successMessage = new LocTextKey(successMessageKey);
return this;
}
public PageActionBuilder noEventPropagation() {
this.fireActionEvent = false;
return this;
}
public PageActionBuilder withEntityKey(final EntityKey entityKey) {
this.pageContext = this.pageContext.withEntityKey(entityKey);
return this;
}
public PageActionBuilder ignoreMoveAwayFromEdit() {
this.ignoreMoveAwayFromEdit = true;
return this;
}
public PageActionBuilder withEntityKey(final Long modelId, final EntityType entityType) {
if (modelId != null) {
return withEntityKey(String.valueOf(modelId), entityType);
}
return this;
}
public PageActionBuilder withEntityKey(final String modelId, final EntityType entityType) {
if (modelId == null || entityType == null) {
return this;
}
this.pageContext = this.pageContext.withEntityKey(new EntityKey(modelId, entityType));
return this;
}
public PageActionBuilder withParentEntityKey(final EntityKey entityKey) {
this.pageContext = this.pageContext.withParentEntityKey(entityKey);
return this;
}
public PageActionBuilder withAttribute(final String name, final String value) {
this.pageContext = this.pageContext.withAttribute(name, value);
return this;
}
}
}

View file

@ -0,0 +1,29 @@
/*
* 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;
public interface PageState {
enum Type {
UNDEFINED,
LIST_VIEW,
FORM_VIEW,
FORM_EDIT
}
String name();
Type type();
public Class<? extends TemplateComposer> contentPaneComposer();
public Class<? extends TemplateComposer> actionPaneComposer();
Activity activityAnchor();
}

View file

@ -8,15 +8,23 @@
package ch.ethz.seb.sebserver.gui.service.page.event;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
/** This Event is used to propagate a user-action to the GUI system.
* Potentially every component can listen to an Event and react on the user-action */
public final class ActionEvent implements PageEvent {
public final PageAction action;
@Deprecated // use the ActionDefinition
public final boolean activity;
public ActionEvent(final PageAction action) {
super();
this.action = action;
this.activity = false;
}
@Deprecated
public ActionEvent(final PageAction action, final boolean activity) {
super();
this.action = action;

View file

@ -8,7 +8,7 @@
package ch.ethz.seb.sebserver.gui.service.page.event;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
/** This action is used to publish an Action to the Action-Pane for a specified context.
* The ActionPane is listening to this events and render specified actions on notify */

View file

@ -24,7 +24,6 @@ import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
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.PageDefinition;
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;

View file

@ -30,10 +30,12 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
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.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
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.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
@ -50,6 +52,7 @@ public class DefaultPageLayout implements TemplateComposer {
private final WidgetFactory widgetFactory;
private final PolyglotPageService polyglotPageService;
private final AuthorizationContextHolder authorizationContextHolder;
private final PageService pageStateService;
private final String sebServerVersion;
private final boolean multilingual;
@ -57,12 +60,14 @@ public class DefaultPageLayout implements TemplateComposer {
final WidgetFactory widgetFactory,
final PolyglotPageService polyglotPageService,
final AuthorizationContextHolder authorizationContextHolder,
final PageService pageStateService,
final Environment environment) {
this.widgetFactory = widgetFactory;
this.polyglotPageService = polyglotPageService;
this.authorizationContextHolder = authorizationContextHolder;
this.sebServerVersion = environment.getProperty("sebserver.version", "--");
this.pageStateService = pageStateService;
this.sebServerVersion = environment.getProperty("sebserver.version", Constants.EMPTY_NOTE);
this.multilingual = BooleanUtils.toBoolean(environment.getProperty("sebserver.gui.multilingual", "false"));
}
@ -135,7 +140,7 @@ public class DefaultPageLayout implements TemplateComposer {
// TODO error handling
}
MainPageState.clear();
this.pageStateService.clear();
// forward to login page with success message
pageContext.forwardToLoginPage();

View file

@ -8,50 +8,52 @@
package ch.ethz.seb.sebserver.gui.service.page.impl;
import javax.servlet.http.HttpSession;
import org.eclipse.rap.rwt.RWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gui.content.MainPage;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
public final class MainPageState {
private static final Logger log = LoggerFactory.getLogger(MainPageState.class);
public PageAction action = null;
private MainPageState() {
}
public static MainPageState get() {
try {
final HttpSession httpSession = RWT
.getUISession()
.getHttpSession();
MainPageState mainPageState = (MainPageState) httpSession.getAttribute(MainPage.ATTR_MAIN_PAGE_STATE);
if (mainPageState == null) {
mainPageState = new MainPageState();
httpSession.setAttribute(MainPage.ATTR_MAIN_PAGE_STATE, mainPageState);
}
return mainPageState;
} catch (final RuntimeException re) {
throw re;
} catch (final Exception e) {
log.error("Unexpected error while trying to get MainPageState from user-session");
}
return null;
}
public static void clear() {
final MainPageState mainPageState = get();
mainPageState.action = null;
}
// private static final Logger log = LoggerFactory.getLogger(MainPageState.class);
//
// private PageAction action = null;
//
// private MainPageState() {
// }
//
// public action
//
// public boolean changeTo(final PageAction action) {
// if (this.action.definition != action.definition) {
// this.action = action;
// return true;
// }
//
// return false;
// }
//
// public static MainPageState get() {
// try {
//
// final HttpSession httpSession = RWT
// .getUISession()
// .getHttpSession();
//
// MainPageState mainPageState = (MainPageState) httpSession.getAttribute(MainPage.ATTR_MAIN_PAGE_STATE);
// if (mainPageState == null) {
// mainPageState = new MainPageState();
// httpSession.setAttribute(MainPage.ATTR_MAIN_PAGE_STATE, mainPageState);
// }
//
// return mainPageState;
//
// } catch (final RuntimeException re) {
// throw re;
// } catch (final Exception e) {
// log.error("Unexpected error while trying to get MainPageState from user-session");
// }
//
// return null;
// }
//
// public static void clear() {
// final MainPageState mainPageState = get();
// mainPageState.action = null;
// }
}

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.service.page;
package ch.ethz.seb.sebserver.gui.service.page.impl;
import java.util.function.Consumer;
import java.util.function.Supplier;
@ -22,6 +22,8 @@ import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Shell;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;

View file

@ -0,0 +1,170 @@
/*
* 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.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
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.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
import ch.ethz.seb.sebserver.gui.service.page.PageState.Type;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
public final class PageAction {
private static final Logger log = LoggerFactory.getLogger(PageAction.class);
public final ActionDefinition definition;
private final Supplier<LocTextKey> confirm;
final LocTextKey successMessage;
private final Supplier<Set<EntityKey>> selectionSupplier;
private final LocTextKey noSelectionMessage;
private PageContext pageContext;
private final Function<PageAction, PageAction> exec;
final boolean fireActionEvent;
final boolean ignoreMoveAwayFromEdit;
public PageAction(
final ActionDefinition definition,
final Supplier<LocTextKey> confirm,
final LocTextKey successMessage,
final Supplier<Set<EntityKey>> selectionSupplier,
final LocTextKey noSelectionMessage,
final PageContext pageContext,
final Function<PageAction, PageAction> exec,
final boolean fireActionEvent,
final boolean ignoreMoveAwayFromEdit) {
this.definition = definition;
this.confirm = confirm;
this.successMessage = successMessage;
this.selectionSupplier = selectionSupplier;
this.noSelectionMessage = noSelectionMessage;
this.pageContext = pageContext;
this.exec = (exec != null) ? exec : Function.identity();
this.fireActionEvent = fireActionEvent;
this.ignoreMoveAwayFromEdit = ignoreMoveAwayFromEdit;
this.pageContext = pageContext.withAttribute(AttributeKeys.READ_ONLY, Constants.TRUE_STRING);
if (definition.targetState != null) {
final Type type = definition.targetState.type();
if (type.name().equals(Type.FORM_EDIT.name())) {
this.pageContext = pageContext.withAttribute(AttributeKeys.READ_ONLY, Constants.FALSE_STRING);
}
}
}
public EntityKey getEntityKey() {
return this.pageContext.getEntityKey();
}
public PageContext pageContext() {
return this.pageContext;
}
public EntityKey getSingleSelection() {
final Set<EntityKey> selection = getMultiSelection();
if (selection != null) {
return selection.iterator().next();
}
return null;
}
public Set<EntityKey> getMultiSelection() {
if (this.selectionSupplier != null) {
final Set<EntityKey> selection = this.selectionSupplier.get();
if (selection.isEmpty()) {
if (this.noSelectionMessage != null) {
throw new PageMessageException(this.noSelectionMessage);
}
return null;
}
return selection;
}
if (this.noSelectionMessage != null) {
throw new PageMessageException(this.noSelectionMessage);
}
return null;
}
void applyAction(final Consumer<Result<PageAction>> callback) {
if (this.confirm != null) {
final LocTextKey confirmMessage = this.confirm.get();
if (confirmMessage != null) {
this.pageContext.applyConfirmDialog(confirmMessage,
confirm -> callback.accept((confirm)
? exec()
: Result.ofRuntimeError("Confirm denied")));
}
} else {
callback.accept(exec());
}
}
private Result<PageAction> exec() {
try {
return Result.of(this.exec.apply(this));
} catch (final PageMessageException pme) {
PageAction.this.pageContext.publishPageMessage(pme);
return Result.ofError(pme);
} catch (final RestCallError restCallError) {
if (restCallError.isFieldValidationError()) {
PageAction.this.pageContext.publishPageMessage(
new LocTextKey("sebserver.form.validation.error.title"),
new LocTextKey("sebserver.form.validation.error.message"));
} else {
log.error("Failed to execute action: {}", PageAction.this, restCallError);
PageAction.this.pageContext.notifyError("action.error.unexpected.message", restCallError);
}
return Result.ofError(restCallError);
} catch (final Throwable t) {
log.error("Failed to execute action: {}", PageAction.this, t);
PageAction.this.pageContext.notifyError("action.error.unexpected.message", t);
return Result.ofError(t);
}
}
public PageAction withEntityKey(final EntityKey entityKey) {
this.pageContext = this.pageContext.withEntityKey(entityKey);
return this;
}
public PageAction withParentEntityKey(final EntityKey parentEntityKey) {
this.pageContext = this.pageContext.withParentEntityKey(parentEntityKey);
return this;
}
public PageAction withAttribute(final String name, final String value) {
this.pageContext = this.pageContext.withAttribute(name, value);
return this;
}
public static PageAction applySingleSelection(final PageAction action) {
return action.withEntityKey(action.getSingleSelection());
}
}

View file

@ -8,12 +8,10 @@
package ch.ethz.seb.sebserver.gui.service.page.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.rap.rwt.widgets.DialogCallback;
@ -29,24 +27,18 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
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.PageAction;
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.PageDefinition;
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
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.widget.Message;
public class PageContextImpl implements PageContext {
private static final Logger log = LoggerFactory.getLogger(PageContextImpl.class);
private static final ListenerComparator LIST_COMPARATOR = new ListenerComparator();
private final I18nSupport i18nSupport;
private final ComposerService composerService;
private final Composite root;
@ -218,48 +210,14 @@ public class PageContextImpl implements PageContext {
}
@Override
@SuppressWarnings("unchecked")
public <T extends PageEvent> void firePageEvent(final T event) {
final Class<? extends PageEvent> typeClass = event.getClass();
final List<PageEventListener<T>> listeners = new ArrayList<>();
ComposerService.traversePageTree(
this.root,
c -> {
final PageEventListener<?> listener =
(PageEventListener<?>) c.getData(PageEventListener.LISTENER_ATTRIBUTE_KEY);
return listener != null && listener.match(typeClass);
},
c -> listeners.add(((PageEventListener<T>) c.getData(PageEventListener.LISTENER_ATTRIBUTE_KEY))));
if (listeners.isEmpty()) {
return;
}
listeners.stream()
.sorted(LIST_COMPARATOR)
.forEach(listener -> {
try {
listener.notify(event);
} catch (final Exception e) {
log.error("Unexpected error while notify PageEventListener: ", e);
}
});
}
@Override
public PageAction createAction(final ActionDefinition actionDefinition) {
return new PageAction(actionDefinition, this);
}
@Override
public void applyConfirmDialog(final LocTextKey confirmMessage, final Runnable onOK) {
public void applyConfirmDialog(final LocTextKey confirmMessage, final Consumer<Boolean> callback) {
final Message messageBox = new Message(
this.root.getShell(),
this.i18nSupport.getText("sebserver.dialog.confirm.title"),
this.i18nSupport.getText(confirmMessage),
SWT.OK | SWT.CANCEL);
messageBox.setMarkupEnabled(true);
messageBox.open(new ConfirmDialogCallback(onOK));
messageBox.open(new ConfirmDialogCallback(callback));
}
@Override
@ -341,7 +299,6 @@ public class PageContextImpl implements PageContext {
log.info("Cleanup logout failed: {}", e.getMessage());
}
MainPageState.clear();
forwardToLoginPage();
}
@ -353,9 +310,9 @@ public class PageContextImpl implements PageContext {
private static final class ConfirmDialogCallback implements DialogCallback {
private static final long serialVersionUID = 1491270214433492441L;
private final Runnable onOK;
private final Consumer<Boolean> onOK;
private ConfirmDialogCallback(final Runnable onOK) {
private ConfirmDialogCallback(final Consumer<Boolean> onOK) {
this.onOK = onOK;
}
@ -363,25 +320,15 @@ public class PageContextImpl implements PageContext {
public void dialogClosed(final int returnCode) {
if (returnCode == SWT.OK) {
try {
this.onOK.run();
this.onOK.accept(true);
} catch (final Throwable t) {
log.error(
"Unexpected on confirm callback execution. This should not happen, plase secure the given onOK Runnable",
t);
this.onOK.accept(false);
}
}
}
}
private static final class ListenerComparator implements Comparator<PageEventListener<?>>, Serializable {
private static final long serialVersionUID = 2571739214439340404L;
@Override
public int compare(final PageEventListener<?> o1, final PageEventListener<?> o2) {
final int x = o1.priority();
final int y = o2.priority();
return (x < y) ? -1 : ((x == y) ? 0 : 1);
this.onOK.accept(false);
}
}

View file

@ -0,0 +1,236 @@
/*
* 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.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import javax.servlet.http.HttpSession;
import org.eclipse.rap.rwt.RWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
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.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.PageService;
import ch.ethz.seb.sebserver.gui.service.page.PageState;
import ch.ethz.seb.sebserver.gui.service.page.PageState.Type;
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
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.table.TableBuilder;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@Lazy
@Service
@GuiProfile
public class PageServiceImpl implements PageService {
private static final Logger log = LoggerFactory.getLogger(PageServiceImpl.class);
private static final LocTextKey MSG_GO_AWAY_FROM_EDIT =
new LocTextKey("sebserver.overall.action.goAwayFromEditPageConfirm");
private static final String ATTR_PAGE_STATE = "PAGE_STATE";
private static final ListenerComparator LIST_COMPARATOR = new ListenerComparator();
private final JSONMapper jsonMapper;
private final WidgetFactory widgetFactory;
private final PolyglotPageService polyglotPageService;
public PageServiceImpl(
final JSONMapper jsonMapper,
final WidgetFactory widgetFactory,
final PolyglotPageService polyglotPageService) {
this.jsonMapper = jsonMapper;
this.widgetFactory = widgetFactory;
this.polyglotPageService = polyglotPageService;
}
@Override
public WidgetFactory getWidgetFactory() {
return this.widgetFactory;
}
@Override
public PolyglotPageService getPolyglotPageService() {
return this.polyglotPageService;
}
@Override
public I18nSupport getI18nSupport() {
return this.widgetFactory.getI18nSupport();
}
@Override
public JSONMapper getJSONMapper() {
return this.jsonMapper;
}
@Override
public PageState initPageState(final PageState initState) {
// TODO Auto-generated method stub
return null;
}
@Override
public PageState getCurrentState() {
try {
final HttpSession httpSession = RWT
.getUISession()
.getHttpSession();
return (PageState) httpSession.getAttribute(ATTR_PAGE_STATE);
} catch (final Exception e) {
log.error("Failed to get current PageState: ", e);
return null;
}
}
@Override
@SuppressWarnings("unchecked")
public <T extends PageEvent> void firePageEvent(final T event, final PageContext pageContext) {
final Class<? extends PageEvent> typeClass = event.getClass();
final List<PageEventListener<T>> listeners = new ArrayList<>();
ComposerService.traversePageTree(
pageContext.getRoot(),
c -> {
final PageEventListener<?> listener =
(PageEventListener<?>) c.getData(PageEventListener.LISTENER_ATTRIBUTE_KEY);
return listener != null && listener.match(typeClass);
},
c -> listeners.add(((PageEventListener<T>) c.getData(PageEventListener.LISTENER_ATTRIBUTE_KEY))));
if (listeners.isEmpty()) {
return;
}
listeners.stream()
.sorted(LIST_COMPARATOR)
.forEach(listener -> {
try {
listener.notify(event);
} catch (final Exception e) {
log.error("Unexpected error while notify PageEventListener: ", e);
}
});
}
@Override
public void executePageAction(final PageAction pageAction, final Consumer<Result<PageAction>> callback) {
final PageState currentState = getCurrentState();
// TODO should there be a check to reload or not to reload the page if the state is the same?
if (!pageAction.ignoreMoveAwayFromEdit && currentState != null && currentState.type() == Type.FORM_EDIT) {
pageAction.pageContext().applyConfirmDialog(
MSG_GO_AWAY_FROM_EDIT,
confirm -> {
if (confirm) {
exec(pageAction, callback);
} else {
callback.accept(Result.ofRuntimeError("Confirm denied"));
}
});
} else {
exec(pageAction, callback);
}
}
private void exec(final PageAction pageAction, final Consumer<Result<PageAction>> callback) {
pageAction.applyAction(result -> {
if (!result.hasError()) {
final PageAction action = result.get();
if (pageAction.fireActionEvent) {
firePageEvent(new ActionEvent(action), action.pageContext());
}
try {
final HttpSession httpSession = RWT
.getUISession()
.getHttpSession();
log.debug("SET session PageState: {} : {}", pageAction.definition.targetState, httpSession.getId());
httpSession.setAttribute(ATTR_PAGE_STATE, pageAction.definition.targetState);
} catch (final Exception e) {
log.error("Failed to set current PageState: ", e);
}
}
callback.accept(result);
});
}
@Override
public void publishAction(final PageAction pageAction) {
this.firePageEvent(new ActionPublishEvent(pageAction), pageAction.pageContext());
}
@Override
public FormBuilder formBuilder(final PageContext pageContext, final int rows) {
return new FormBuilder(this, pageContext, rows);
}
@Override
public <T extends Entity> TableBuilder<T> entityTableBuilder(final RestCall<Page<T>> apiCall) {
return new TableBuilder<>(this, apiCall);
}
@Override
public void clear() {
try {
final HttpSession httpSession = RWT
.getUISession()
.getHttpSession();
log.debug("Clear session PageState: {}", httpSession.getId());
httpSession.removeAttribute(ATTR_PAGE_STATE);
} catch (final Exception e) {
log.error("Failed to clear current PageState: ", e);
}
}
private static final class ListenerComparator implements Comparator<PageEventListener<?>>, Serializable {
private static final long serialVersionUID = 2571739214439340404L;
@Override
public int compare(final PageEventListener<?> o1, final PageEventListener<?> o2) {
final int x = o1.priority();
final int y = o2.priority();
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
}
}

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gui.service.page;
package ch.ethz.seb.sebserver.gui.service.page.impl;
import java.util.Set;
import java.util.function.Supplier;
@ -28,18 +28,6 @@ public final class PageUtils {
private static final Logger log = LoggerFactory.getLogger(PageUtils.class);
enum CommonTextKeys {
;
public LocTextKey textKey;
private CommonTextKeys(final LocTextKey textKey) {
this.textKey = textKey;
}
}
public static void clearComposite(final Composite parent) {
if (parent == null) {
return;

View file

@ -12,7 +12,6 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall.CallType;
/** Interface to SEB Server webservice API thought RestCall's
@ -72,11 +71,11 @@ public interface RestService {
EntityType entityType,
CallType callType);
/** Performs an activation Action on RestCall specified within the given Action.
* The RestCall must be of CallType.ACTIVATION_ACTIVATE or CallType.ACTIVATION_DEACTIVATE
*
* @param action the Action that defines an entity activation
* @return the successfully executed Action */
<T> PageAction activation(PageAction action);
// /** Performs an activation Action on RestCall specified within the given Action.
// * The RestCall must be of CallType.ACTIVATION_ACTIVATE or CallType.ACTIVATION_DEACTIVATE
// *
// * @param action the Action that defines an entity activation
// * @return the successfully executed Action */
// <T> PageAction activation(PageAction action);
}

View file

@ -17,12 +17,9 @@ import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
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.profile.GuiProfile;
import ch.ethz.seb.sebserver.gui.service.page.PageAction;
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall.CallType;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURIService;
@ -113,24 +110,24 @@ public class RestServiceImpl implements RestService {
return restCall.newBuilder();
}
@Override
public <T> PageAction activation(final PageAction action) {
if (action.definition.restCallType == null) {
throw new IllegalArgumentException("ActionDefinition needs to define a restCallType to use this action");
}
@SuppressWarnings("unchecked")
final Class<? extends RestCall<T>> restCallType =
(Class<? extends RestCall<T>>) action.definition.restCallType;
this.getBuilder(restCallType)
.withURIVariable(
API.PARAM_MODEL_ID,
action.pageContext().getAttribute(AttributeKeys.ENTITY_ID))
.call()
.onErrorDo(t -> action.pageContext().notifyError(t));
return action;
}
// @Override
// public <T> PageAction activation(final PageAction action) {
// if (action.restCallType() == null) {
// throw new IllegalArgumentException("ActionDefinition needs to define a restCallType to use this action");
// }
//
// @SuppressWarnings("unchecked")
// final Class<? extends RestCall<T>> restCallType =
// (Class<? extends RestCall<T>>) action.restCallType();
//
// this.getBuilder(restCallType)
// .withURIVariable(
// API.PARAM_MODEL_ID,
// action.pageContext().getAttribute(AttributeKeys.ENTITY_ID))
// .call()
// .onErrorDo(t -> action.pageContext().notifyError(t));
//
// return action;
// }
}

View file

@ -39,7 +39,8 @@ import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.util.Utils;
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.PageAction;
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.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
@ -52,6 +53,7 @@ public class EntityTable<ROW extends Entity> {
static final String COLUMN_DEFINITION = "COLUMN_DEFINITION";
static final String TABLE_ROW_DATA = "TABLE_ROW_DATA";
final PageService pageService;
final WidgetFactory widgetFactory;
final RestCall<Page<ROW>> restCall;
final I18nSupport i18nSupport;
@ -75,7 +77,7 @@ public class EntityTable<ROW extends Entity> {
final int type,
final Composite parent,
final RestCall<Page<ROW>> restCall,
final WidgetFactory widgetFactory,
final PageService pageService,
final List<ColumnDefinition<ROW>> columns,
final List<TableRowAction> actions,
final int pageSize,
@ -83,8 +85,9 @@ public class EntityTable<ROW extends Entity> {
final Function<EntityTable<ROW>, PageAction> defaultActionFunction) {
this.composite = new Composite(parent, type);
this.widgetFactory = widgetFactory;
this.i18nSupport = widgetFactory.getI18nSupport();
this.pageService = pageService;
this.i18nSupport = pageService.getI18nSupport();
this.widgetFactory = pageService.getWidgetFactory();
this.restCall = restCall;
this.columns = Utils.immutableListOf(columns);
this.actions = Utils.immutableListOf(actions);
@ -110,7 +113,7 @@ public class EntityTable<ROW extends Entity> {
.findFirst()
.isPresent() ? new TableFilter<>(this) : null;
this.table = widgetFactory.tableLocalized(this.composite);
this.table = this.widgetFactory.tableLocalized(this.composite);
final GridLayout gridLayout = new GridLayout(columns.size(), true);
this.table.setLayout(gridLayout);
gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
@ -133,9 +136,8 @@ public class EntityTable<ROW extends Entity> {
this.table.addListener(SWT.MouseDoubleClick, event -> {
final EntityKey selection = getSingleSelection();
if (selection != null) {
defaultAction
.withEntityKey(selection)
.run();
this.pageService.executePageAction(
defaultAction.withEntityKey(selection));
}
});
}

View file

@ -19,9 +19,9 @@ import org.eclipse.swt.widgets.Composite;
import ch.ethz.seb.sebserver.gbl.model.Entity;
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.PageAction;
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.widget.WidgetFactory;
/** <code>
* new TableBuilder<T>(RestCall)
@ -40,7 +40,7 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
* </code> */
public class TableBuilder<ROW extends Entity> {
private final WidgetFactory widgetFactory;
private final PageService pageService;
final RestCall<Page<ROW>> restCall;
final List<ColumnDefinition<ROW>> columns = new ArrayList<>();
final List<TableRowAction> actions = new ArrayList<>();
@ -50,10 +50,10 @@ public class TableBuilder<ROW extends Entity> {
private int type = SWT.NONE;
public TableBuilder(
final WidgetFactory widgetFactory,
final PageService pageService,
final RestCall<Page<ROW>> restCall) {
this.widgetFactory = widgetFactory;
this.pageService = pageService;
this.restCall = restCall;
}
@ -107,7 +107,7 @@ public class TableBuilder<ROW extends Entity> {
this.type,
parent,
this.restCall,
this.widgetFactory,
this.pageService,
this.columns,
this.actions,
this.pageSize,

View file

@ -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.PageUtils;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public class TableNavigator {

View file

@ -23,7 +23,7 @@ import org.eclipse.swt.widgets.Label;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
public class MultiSelection extends Composite implements Selection {

View file

@ -39,8 +39,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Tuple;
@ -50,8 +48,6 @@ 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.PageContext;
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
import ch.ethz.seb.sebserver.gui.table.TableBuilder;
@Lazy
@Service
@ -310,10 +306,6 @@ public class WidgetFactory {
return item;
}
public <T extends Entity> TableBuilder<T> entityTableBuilder(final RestCall<Page<T>> apiCall) {
return new TableBuilder<>(this, apiCall);
}
public Table tableLocalized(final Composite parent) {
final Table table = new Table(parent, SWT.SINGLE | SWT.NO_SCROLL);
this.injectI18n(table);

View file

@ -15,7 +15,7 @@ sebserver.overall.action.filter.clear=Clear Filter Criteria
sebserver.overall.action.ok=OK
sebserver.overall.action.cancel=Cancel
sebserver.overall.action.close=Close
sebserver.overall.action.goAwayFromEditPageConfirm=Are you sure to leave this page? Any unsaved data will be lost.
sebserver.overall.action.category.varia=Varia
################################