SEBSERV-45 Exam Configuration list and form
This commit is contained in:
parent
c0f68c1340
commit
5c7bbdb3a3
20 changed files with 731 additions and 19 deletions
|
@ -156,4 +156,28 @@ public final class ConfigurationNode implements GrantEntity, Activatable {
|
|||
+ ", active=" + this.active + "]";
|
||||
}
|
||||
|
||||
public static ConfigurationNode createNewExamConfig(final Long institutionId) {
|
||||
return new ConfigurationNode(
|
||||
null,
|
||||
institutionId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
ConfigurationType.EXAM_CONFIG,
|
||||
null,
|
||||
false);
|
||||
}
|
||||
|
||||
public static ConfigurationNode createNewTemplate(final Long institutionId) {
|
||||
return new ConfigurationNode(
|
||||
null,
|
||||
institutionId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
ConfigurationType.TEMPLATE,
|
||||
null,
|
||||
false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ public class ExamList implements TemplateComposer {
|
|||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.EXAM_IMPORT)
|
||||
.publishIf(userGrant::im)
|
||||
.publishIf(userGrant::im) // TODO iw instead of im?
|
||||
|
||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, emptySelectionTextKey)
|
||||
|
|
|
@ -97,7 +97,6 @@ public class SebClientConfigList implements TemplateComposer {
|
|||
public void compose(final PageContext pageContext) {
|
||||
|
||||
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
|
||||
|
||||
final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
TITLE_TEXT_KEY);
|
||||
|
@ -150,7 +149,7 @@ public class SebClientConfigList implements TemplateComposer {
|
|||
pageActionBuilder
|
||||
|
||||
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_NEW)
|
||||
.publishIf(clientConfigGrant::w)
|
||||
.publishIf(clientConfigGrant::iw)
|
||||
|
||||
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_VIEW_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
|
@ -158,7 +157,7 @@ public class SebClientConfigList implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_MODIFY_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> clientConfigGrant.m() && table.hasAnyContent());
|
||||
.publishIf(() -> clientConfigGrant.im() && table.hasAnyContent());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageUtils;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ActivateExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.DeactivateExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.NewExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfig;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SebExamConfigForm implements TemplateComposer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SebExamConfigForm.class);
|
||||
|
||||
private static final LocTextKey FORM_TITLE_NEW =
|
||||
new LocTextKey("sebserver.examconfig.form.title.new");
|
||||
private static final LocTextKey FORM_TITLE =
|
||||
new LocTextKey("sebserver.examconfig.form.title");
|
||||
private static final LocTextKey FORM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.form.name");
|
||||
private static final LocTextKey FORM_DESCRIPTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.form.description");
|
||||
|
||||
private final PageService pageService;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
|
||||
protected SebExamConfigForm(
|
||||
final PageService pageService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||
|
||||
final UserInfo user = this.currentUser.get();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||
|
||||
final boolean isNew = entityKey == null;
|
||||
|
||||
// get data or create new. Handle error if happen
|
||||
final ConfigurationNode examConfig = (isNew)
|
||||
? ConfigurationNode.createNewExamConfig((parentEntityKey != null)
|
||||
? Long.valueOf(parentEntityKey.modelId)
|
||||
: user.institutionId)
|
||||
: this.restService
|
||||
.getBuilder(GetExamConfigNode.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
|
||||
if (examConfig == null) {
|
||||
log.error("Failed to get ConfigurationNode. "
|
||||
+ "Error was notified to the User. "
|
||||
+ "See previous logs for more infomation");
|
||||
return;
|
||||
}
|
||||
|
||||
final EntityGrantCheck entityGrant = this.currentUser.entityGrantCheck(examConfig);
|
||||
final boolean writeGrant = entityGrant.w();
|
||||
final boolean modifyGrant = entityGrant.m();
|
||||
final boolean isReadonly = pageContext.isReadonly();
|
||||
|
||||
// new PageContext with actual EntityKey
|
||||
final PageContext formContext = pageContext.withEntityKey(examConfig.getEntityKey());
|
||||
|
||||
// the default page layout with interactive title
|
||||
final LocTextKey titleKey = (isNew)
|
||||
? FORM_TITLE_NEW
|
||||
: FORM_TITLE;
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
titleKey);
|
||||
|
||||
// The SebClientConfig form
|
||||
final FormHandle<ConfigurationNode> formHandle = this.pageService.formBuilder(
|
||||
formContext.copyOf(content), 4)
|
||||
.readonly(isReadonly)
|
||||
.putStaticValueIf(() -> !isNew,
|
||||
Domain.CONFIGURATION_NODE.ATTR_ID,
|
||||
examConfig.getModelId())
|
||||
.putStaticValue(
|
||||
Domain.CONFIGURATION_NODE.ATTR_INSTITUTION_ID,
|
||||
String.valueOf(examConfig.getInstitutionId()))
|
||||
.putStaticValue(
|
||||
Domain.CONFIGURATION_NODE.ATTR_TYPE,
|
||||
ConfigurationType.EXAM_CONFIG.name())
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CONFIGURATION_NODE.ATTR_NAME,
|
||||
FORM_NAME_TEXT_KEY,
|
||||
examConfig.name))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||
FORM_DESCRIPTION_TEXT_KEY,
|
||||
examConfig.description).asArea())
|
||||
.buildFor((isNew)
|
||||
? this.restService.getRestCall(NewExamConfig.class)
|
||||
: this.restService.getRestCall(SaveExamConfig.class));
|
||||
|
||||
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
||||
.publishIf(() -> writeGrant && isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY)
|
||||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_DEACTIVATE)
|
||||
.withEntityKey(entityKey)
|
||||
.withSimpleRestCall(this.restService, DeactivateExamConfig.class)
|
||||
.withConfirm(PageUtils.confirmDeactivation(examConfig, this.restService))
|
||||
.publishIf(() -> writeGrant && isReadonly && examConfig.isActive())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_ACTIVATE)
|
||||
.withEntityKey(entityKey)
|
||||
.withSimpleRestCall(this.restService, ActivateExamConfig.class)
|
||||
.publishIf(() -> writeGrant && isReadonly && !examConfig.isActive())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_SAVE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(formHandle::processFormSave)
|
||||
.ignoreMoveAwayFromEdit()
|
||||
.publishIf(() -> !isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_CANCEL_MODIFY)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> this.pageService.onEmptyEntityKeyGoTo(
|
||||
action,
|
||||
ActionDefinition.SEB_EXAM_CONFIG_LIST))
|
||||
.publishIf(() -> !isReadonly);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -8,26 +8,155 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
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.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.seb.examconfig.GetExamConfigNodes;
|
||||
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.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SebExamConfigList implements TemplateComposer {
|
||||
|
||||
public SebExamConfigList() {
|
||||
// TODO Auto-generated constructor stub
|
||||
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.empty");
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.title");
|
||||
private static final LocTextKey INSTITUTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.institution");
|
||||
private static final LocTextKey NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.name");
|
||||
private static final LocTextKey DESCRIPTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.description");
|
||||
private static final LocTextKey ACTIVE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.list.column.active");
|
||||
private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examconfig.info.pleaseSelect");
|
||||
|
||||
private final TableFilterAttribute institutionFilter;
|
||||
private final TableFilterAttribute nameFilter =
|
||||
new TableFilterAttribute(CriteriaType.TEXT, Entity.FILTER_ATTR_NAME);
|
||||
|
||||
private final PageService pageService;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
private final ResourceService resourceService;
|
||||
private final int pageSize;
|
||||
|
||||
protected SebExamConfigList(
|
||||
final PageService pageService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser,
|
||||
@Value("${sebserver.gui.list.page.size}") final Integer pageSize) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.institutionFilter = new TableFilterAttribute(
|
||||
CriteriaType.SINGLE_SELECTION,
|
||||
Entity.FILTER_ATTR_INSTITUTION,
|
||||
this.resourceService::institutionResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
TITLE_TEXT_KEY);
|
||||
|
||||
final boolean isSEBAdmin = this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||
final PageActionBuilder pageActionBuilder =
|
||||
this.pageService.pageActionBuilder(pageContext.clearEntityKeys());
|
||||
|
||||
// table
|
||||
final EntityTable<ConfigurationNode> table =
|
||||
this.pageService.entityTableBuilder(this.restService.getRestCall(GetExamConfigNodes.class))
|
||||
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
|
||||
.withPaging(this.pageSize)
|
||||
.withColumnIf(
|
||||
() -> isSEBAdmin,
|
||||
() -> new ColumnDefinition<>(
|
||||
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
||||
INSTITUTION_TEXT_KEY,
|
||||
examConfigInstitutionNameFunction(this.resourceService),
|
||||
this.institutionFilter,
|
||||
false))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_NAME,
|
||||
NAME_TEXT_KEY,
|
||||
entity -> entity.name,
|
||||
this.nameFilter,
|
||||
true))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||
DESCRIPTION_TEXT_KEY,
|
||||
entity -> entity.description,
|
||||
this.nameFilter,
|
||||
true))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CONFIGURATION_NODE.ATTR_ACTIVE,
|
||||
ACTIVE_TEXT_KEY,
|
||||
entity -> entity.active,
|
||||
true))
|
||||
.withDefaultAction(pageActionBuilder
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_FROM_LIST)
|
||||
.create())
|
||||
.compose(content);
|
||||
|
||||
final GrantCheck examConfigGrant = this.currentUser.grantCheck(EntityType.CONFIGURATION_NODE);
|
||||
|
||||
pageActionBuilder
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_NEW)
|
||||
.publishIf(examConfigGrant::iw)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> table.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && table.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_PROPERTIES_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelection, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && table.hasAnyContent());
|
||||
}
|
||||
|
||||
private static Function<ConfigurationNode, String> examConfigInstitutionNameFunction(
|
||||
final ResourceService resourceService) {
|
||||
|
||||
return config -> resourceService.getInstitutionNameFunction()
|
||||
.apply(String.valueOf(config.institutionId));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SebExamConfigPropertiesForm implements TemplateComposer {
|
||||
|
||||
public SebExamConfigPropertiesForm() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -304,6 +304,51 @@ public enum ActionDefinition {
|
|||
SEB_EXAM_CONFIG_LIST(
|
||||
new LocTextKey("sebserver.examconfig.action.list"),
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_LIST),
|
||||
SEB_EXAM_CONFIG_NEW(
|
||||
new LocTextKey("sebserver.examconfig.action.list.new"),
|
||||
ImageIcon.NEW,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT),
|
||||
SEB_EXAM_CONFIG_VIEW_FROM_LIST(
|
||||
new LocTextKey("sebserver.examconfig.action.list.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_VIEW,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
SEB_EXAM_CONFIG_MODIFY_FROM_LIST(
|
||||
new LocTextKey("sebserver.examconfig.action.list.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
SEB_EXAM_CONFIG_MODIFY(
|
||||
new LocTextKey("sebserver.examconfig.action.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_CANCEL_MODIFY(
|
||||
new LocTextKey("sebserver.overall.action.modify.cancel"),
|
||||
ImageIcon.CANCEL,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_VIEW,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_SAVE(
|
||||
new LocTextKey("sebserver.examconfig.action.save"),
|
||||
ImageIcon.SAVE,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_VIEW,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_ACTIVATE(
|
||||
new LocTextKey("sebserver.examconfig.action.activate"),
|
||||
ImageIcon.INACTIVE,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_VIEW,
|
||||
ActionCategory.FORM),
|
||||
SEB_EXAM_CONFIG_DEACTIVATE(
|
||||
new LocTextKey("sebserver.examconfig.action.deactivate"),
|
||||
ImageIcon.ACTIVE,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
||||
SEB_EXAM_CONFIG_MODIFY_PROPERTIES_FROM_LIST(
|
||||
new LocTextKey("sebserver.examconfig.properties.action.list.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinition.SEB_EXAM_CONFIG_EDIT,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ import ch.ethz.seb.sebserver.gui.content.LmsSetupList;
|
|||
import ch.ethz.seb.sebserver.gui.content.QuizDiscoveryList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebClientConfigForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebClientConfigList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebExamConfigForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebExamConfigList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SebExamConfigPropertiesForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.UserAccountChangePasswordForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.UserAccountForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.UserAccountList;
|
||||
|
@ -53,7 +55,12 @@ public enum PageStateDefinition implements PageState {
|
|||
SEB_CLIENT_CONFIG_VIEW(Type.FORM_VIEW, SebClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG),
|
||||
SEB_CLIENT_CONFIG_EDIT(Type.FORM_EDIT, SebClientConfigForm.class, ActivityDefinition.SEB_CLIENT_CONFIG),
|
||||
|
||||
SEB_EXAM_CONFIG_LIST(Type.LIST_VIEW, SebExamConfigList.class, ActivityDefinition.SEB_EXAM_CONFIG)
|
||||
SEB_EXAM_CONFIG_LIST(Type.LIST_VIEW, SebExamConfigList.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
SEB_EXAM_CONFIG_VIEW(Type.FORM_VIEW, SebExamConfigForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
SEB_EXAM_CONFIG_EDIT(Type.FORM_EDIT, SebExamConfigForm.class, ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
|
||||
SEB_EXAM_CONFIG_PROPERTIES_EDIT(Type.FORM_VIEW, SebExamConfigPropertiesForm.class,
|
||||
ActivityDefinition.SEB_EXAM_CONFIG),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ActivateExamConfig extends RestCall<EntityProcessingReport> {
|
||||
|
||||
protected ActivateExamConfig() {
|
||||
super(new TypeKey<>(
|
||||
CallType.ACTIVATION_ACTIVATE,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
}),
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT + API.PATH_VAR_ACTIVE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class DeactivateExamConfig extends RestCall<EntityProcessingReport> {
|
||||
|
||||
protected DeactivateExamConfig() {
|
||||
super(new TypeKey<>(
|
||||
CallType.ACTIVATION_DEACTIVATE,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
}),
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT + API.PATH_VAR_INACTIVE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetExamConfigNode extends RestCall<ConfigurationNode> {
|
||||
|
||||
protected GetExamConfigNode() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_SINGLE,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<ConfigurationNode>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetExamConfigNodes extends RestCall<Page<ConfigurationNode>> {
|
||||
|
||||
protected GetExamConfigNodes() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_PAGE,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<Page<ConfigurationNode>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class NewExamConfig extends RestCall<ConfigurationNode> {
|
||||
|
||||
protected NewExamConfig() {
|
||||
super(new TypeKey<>(
|
||||
CallType.NEW,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<ConfigurationNode>() {
|
||||
}),
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.CONFIGURATION_NODE_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.remote.webservice.api.seb.examconfig;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SaveExamConfig extends RestCall<ConfigurationNode> {
|
||||
|
||||
protected SaveExamConfig() {
|
||||
super(new TypeKey<>(
|
||||
CallType.SAVE,
|
||||
EntityType.CONFIGURATION_NODE,
|
||||
new TypeReference<ConfigurationNode>() {
|
||||
}),
|
||||
HttpMethod.PUT,
|
||||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.CONFIGURATION_NODE_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,8 @@ import java.net.UnknownHostException;
|
|||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.cryptonode.jncryptor.AES256JNCryptor;
|
||||
import org.cryptonode.jncryptor.JNCryptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -68,4 +70,10 @@ public class WebServiceInit implements ApplicationListener<ApplicationReadyEvent
|
|||
public TokenStore tokenStore(final DataSource dataSource) {
|
||||
return new JdbcTokenStore(dataSource);
|
||||
}
|
||||
|
||||
@Lazy
|
||||
@Bean
|
||||
public JNCryptor jnCryptor() {
|
||||
return new AES256JNCryptor();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,20 +111,25 @@ public class ClientCredentialServiceImpl implements ClientCredentialService {
|
|||
|
||||
final CharSequence secret = this.environment
|
||||
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
|
||||
|
||||
return this.decrypt(credentials.accessToken, secret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence encrypt(final CharSequence text) {
|
||||
|
||||
final CharSequence secret = this.environment
|
||||
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
|
||||
|
||||
return encrypt(text, secret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence decrypt(final CharSequence text) {
|
||||
|
||||
final CharSequence secret = this.environment
|
||||
.getRequiredProperty(SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY);
|
||||
|
||||
return decrypt(text, secret);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import java.nio.CharBuffer;
|
|||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.cryptonode.jncryptor.AES256JNCryptor;
|
||||
import org.cryptonode.jncryptor.CryptorException;
|
||||
import org.cryptonode.jncryptor.JNCryptor;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -45,17 +44,17 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
|
|||
private final InstitutionDAO institutionDAO;
|
||||
private final SebClientConfigDAO sebClientConfigDAO;
|
||||
private final ClientCredentialService clientCredentialService;
|
||||
private final JNCryptor jnCryptor;
|
||||
private final String httpScheme;
|
||||
private final String serverAddress;
|
||||
private final String serverPort;
|
||||
private final String sebClientAPIEndpoint;
|
||||
|
||||
private final JNCryptor cryptor = new AES256JNCryptor();
|
||||
|
||||
protected SebClientConfigServiceImpl(
|
||||
final InstitutionDAO institutionDAO,
|
||||
final SebClientConfigDAO sebClientConfigDAO,
|
||||
final ClientCredentialService clientCredentialService,
|
||||
final JNCryptor jnCryptor,
|
||||
@Value("${sebserver.webservice.http.scheme}") final String httpScheme,
|
||||
@Value("${server.address}") final String serverAddress,
|
||||
@Value("${server.port}") final String serverPort,
|
||||
|
@ -64,6 +63,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
|
|||
this.institutionDAO = institutionDAO;
|
||||
this.sebClientConfigDAO = sebClientConfigDAO;
|
||||
this.clientCredentialService = clientCredentialService;
|
||||
this.jnCryptor = jnCryptor;
|
||||
this.httpScheme = httpScheme;
|
||||
this.serverAddress = serverAddress;
|
||||
this.serverPort = serverPort;
|
||||
|
@ -166,11 +166,28 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
|
|||
|
||||
private byte[] encode(final byte[] plainTextConfig, final CharSequence secret) {
|
||||
|
||||
// TODO format the plainTextConfig for SEB Client encoding format
|
||||
|
||||
try {
|
||||
// TODO do we need salt
|
||||
return this.cryptor.encryptData(plainTextConfig, CharBuffer.wrap(secret).array());
|
||||
|
||||
char[] secretChars;
|
||||
final CharBuffer secretBuffer = CharBuffer.wrap(secret);
|
||||
if (secretBuffer.hasArray()) {
|
||||
secretChars = secretBuffer.array();
|
||||
} else {
|
||||
secretChars = new char[secretBuffer.length()];
|
||||
secretBuffer.get(secretChars);
|
||||
}
|
||||
// TODO format the plainTextConfig for SEB Client encoding format
|
||||
// jnCryptor.encryptData(
|
||||
// plainTextConfig,
|
||||
// secret,
|
||||
// encryptionSalt,
|
||||
// hmacSalt,
|
||||
// iv);
|
||||
|
||||
return this.jnCryptor.encryptData(
|
||||
plainTextConfig,
|
||||
secretChars);
|
||||
|
||||
} catch (final CryptorException e) {
|
||||
log.error("Unexpected error while trying to encrypt SEB Client configuration: ", e);
|
||||
return plainTextConfig;
|
||||
|
|
|
@ -14,11 +14,13 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationNodeRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
|
@ -48,6 +50,8 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
|
|||
@Override
|
||||
protected ConfigurationNode createNew(final POSTMapper postParams) {
|
||||
final Long institutionId = postParams.getLong(API.PARAM_INSTITUTION_ID);
|
||||
final SEBServerUser currentUser = this.authorization.getUserService().getCurrentUser();
|
||||
postParams.putIfAbsent(EXAM.ATTR_OWNER, currentUser.uuid());
|
||||
return new ConfigurationNode(institutionId, postParams);
|
||||
}
|
||||
|
||||
|
|
|
@ -313,16 +313,16 @@ sebserver.sebconfig.activity.name=SEB Configuration
|
|||
sebserver.clientconfig.action.list=Client Configuration
|
||||
sebserver.clientconfig.action.export=Export
|
||||
|
||||
sebserver.clientconfig.list.empty=There is currently no SEB Client configuration available. Please create a new one
|
||||
sebserver.clientconfig.list.empty=There is currently no SEB-Client configuration available. Please create a new one
|
||||
sebserver.clientconfig.list.title=SEB Client Configurations
|
||||
sebserver.clientconfig.list.actions=Selected Configuration
|
||||
sebserver.clientconfig.list.column.institution=Institution
|
||||
sebserver.clientconfig.list.column.name=Name
|
||||
sebserver.clientconfig.list.column.date=Date
|
||||
sebserver.clientconfig.list.column.date=Creation Date
|
||||
sebserver.clientconfig.list.column.active=Active
|
||||
sebserver.clientconfig.info.pleaseSelect=Please Select a client configuration first
|
||||
|
||||
sebserver.clientconfig.form.title.new=New SEB Client Configuration
|
||||
sebserver.clientconfig.form.title.new=New Client Configuration
|
||||
sebserver.clientconfig.form.title=SEB Client Configuration
|
||||
sebserver.clientconfig.form.name=Name
|
||||
sebserver.clientconfig.form.date=Creation Date
|
||||
|
@ -341,7 +341,29 @@ sebserver.clientconfig.action.deactivate=Deactivate
|
|||
# SEB Exam Configuration
|
||||
################################
|
||||
|
||||
|
||||
sebserver.examconfig.action.list=Exam Configuration
|
||||
sebserver.examconfig.list.title=Exam Configurations
|
||||
sebserver.examconfig.list.column.institution=Institution
|
||||
sebserver.examconfig.list.column.name=Name
|
||||
sebserver.examconfig.list.column.description=Description
|
||||
sebserver.examconfig.list.column.active=Active
|
||||
|
||||
sebserver.examconfig.list.actions=Selected Configuration
|
||||
|
||||
sebserver.examconfig.list.empty=There is currently no SEB-Exam configuration available. Please create a new one
|
||||
sebserver.examconfig.info.pleaseSelect=Please Select an exam configuration first
|
||||
|
||||
sebserver.examconfig.action.list.new=New Exam Configuration
|
||||
sebserver.examconfig.action.list.view=View Configuration
|
||||
sebserver.examconfig.action.list.modify=Edit Configuration
|
||||
sebserver.examconfig.action.modify=Edit
|
||||
sebserver.examconfig.action.save=Save
|
||||
sebserver.examconfig.action.activate=Activate
|
||||
sebserver.examconfig.action.deactivate=Deactivate
|
||||
|
||||
sebserver.examconfig.form.title.new=New Exam Configuration
|
||||
sebserver.examconfig.form.title=Exam Configuration
|
||||
sebserver.examconfig.form.name=Name
|
||||
sebserver.examconfig.form.description=Description
|
||||
|
||||
sebserver.examconfig.properties.action.list.modify=Edit Properties
|
||||
|
|
|
@ -203,6 +203,7 @@ Text.error {
|
|||
|
||||
Text[MULTI] {
|
||||
padding: 5px 10px 5px 10px;
|
||||
height=50px;
|
||||
}
|
||||
|
||||
Text[BORDER], Text[MULTI][BORDER] {
|
||||
|
@ -221,6 +222,7 @@ Text[BORDER]:disabled, Text[MULTI][BORDER]:disabled, Text[BORDER]:read-only,
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/* Combo default theme */
|
||||
Combo, Combo[BORDER] {
|
||||
font: 12px Verdana, "Lucida Sans", Arial, Helvetica, sans-serif;
|
||||
|
|
Loading…
Reference in a new issue