SEBSERV-324 finished maintenance
This commit is contained in:
parent
5aeb14ea8e
commit
d648bcb167
32 changed files with 781 additions and 200 deletions
|
@ -270,5 +270,4 @@ public class POSTMapper {
|
|||
this.params.putIfAbsent(name, Arrays.asList(value));
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.model.exam;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
|
@ -22,20 +25,12 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
|||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.CLIENT_GROUP;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ClientGroup implements ClientGroupData {
|
||||
|
||||
public static final String FILTER_ATTR_EXAM_ID = "examId";
|
||||
public static final String ATTR_IP_RANGE_START = "ipRangeStart";
|
||||
public static final String ATTR_IP_RANGE_END = "ipRangeEnd";
|
||||
public static final String ATTR_CLIENT_OS = "clientOS";
|
||||
|
||||
public enum ClientGroupType {
|
||||
NONE,
|
||||
IP_V4_RANGE,
|
||||
CLIENT_OS
|
||||
}
|
||||
|
||||
@JsonProperty(CLIENT_GROUP.ATTR_ID)
|
||||
public final Long id;
|
||||
|
@ -66,7 +61,7 @@ public class ClientGroup implements ClientGroupData {
|
|||
public final String ipRangeEnd;
|
||||
|
||||
@JsonProperty(ATTR_CLIENT_OS)
|
||||
public final String clientOS;
|
||||
public final ClientOS clientOS;
|
||||
|
||||
@JsonCreator
|
||||
public ClientGroup(
|
||||
|
@ -78,18 +73,18 @@ public class ClientGroup implements ClientGroupData {
|
|||
@JsonProperty(CLIENT_GROUP.ATTR_ICON) final String icon,
|
||||
@JsonProperty(ATTR_IP_RANGE_START) final String ipRangeStart,
|
||||
@JsonProperty(ATTR_IP_RANGE_END) final String ipRangeEnd,
|
||||
@JsonProperty(ATTR_CLIENT_OS) final String clientOS) {
|
||||
@JsonProperty(ATTR_CLIENT_OS) final ClientOS clientOS) {
|
||||
|
||||
super();
|
||||
this.id = id;
|
||||
this.examId = examId;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.type = type == null ? ClientGroupType.NONE : type;
|
||||
this.color = color;
|
||||
this.icon = icon;
|
||||
this.ipRangeStart = ipRangeStart;
|
||||
this.ipRangeEnd = ipRangeEnd;
|
||||
this.clientOS = clientOS;
|
||||
this.clientOS = clientOS == null ? ClientOS.NONE : clientOS;
|
||||
}
|
||||
|
||||
public ClientGroup(
|
||||
|
@ -105,7 +100,8 @@ public class ClientGroup implements ClientGroupData {
|
|||
this.id = id;
|
||||
this.examId = examId;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.type = type == null ? ClientGroupType.NONE : type;
|
||||
;
|
||||
this.color = color;
|
||||
this.icon = icon;
|
||||
|
||||
|
@ -114,19 +110,19 @@ public class ClientGroup implements ClientGroupData {
|
|||
final String[] split = StringUtils.split(data, Constants.EMBEDDED_LIST_SEPARATOR);
|
||||
this.ipRangeStart = split[0];
|
||||
this.ipRangeEnd = split[1];
|
||||
this.clientOS = null;
|
||||
this.clientOS = ClientOS.NONE;
|
||||
break;
|
||||
}
|
||||
case CLIENT_OS: {
|
||||
this.ipRangeStart = null;
|
||||
this.ipRangeEnd = null;
|
||||
this.clientOS = data;
|
||||
this.clientOS = Utils.enumFromString(data, ClientOS.class, ClientOS.NONE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
this.ipRangeStart = null;
|
||||
this.ipRangeEnd = null;
|
||||
this.clientOS = null;
|
||||
this.clientOS = ClientOS.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +136,15 @@ public class ClientGroup implements ClientGroupData {
|
|||
this.icon = postParams.getString(CLIENT_GROUP.ATTR_ICON);
|
||||
this.ipRangeStart = postParams.getString(ATTR_IP_RANGE_START);
|
||||
this.ipRangeEnd = postParams.getString(ATTR_IP_RANGE_END);
|
||||
this.clientOS = postParams.getString(ATTR_CLIENT_OS);
|
||||
this.clientOS = postParams.getEnum(ATTR_CLIENT_OS, ClientOS.class);
|
||||
}
|
||||
|
||||
public static ClientGroup createNew(final String examId) {
|
||||
try {
|
||||
return new ClientGroup(null, Long.parseLong(examId), null, null, null, null, null, null, null);
|
||||
} catch (final Exception e) {
|
||||
return new ClientGroup(null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -184,16 +188,32 @@ public class ClientGroup implements ClientGroupData {
|
|||
|
||||
@Override
|
||||
public String getIpRangeStart() {
|
||||
return this.ipRangeStart;
|
||||
if (StringUtils.isBlank(this.ipRangeStart)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return InetAddress.getByName(this.ipRangeStart).getHostAddress();
|
||||
} catch (final UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIpRangeEnd() {
|
||||
return this.ipRangeEnd;
|
||||
if (StringUtils.isBlank(this.ipRangeEnd)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return InetAddress.getByName(this.ipRangeEnd).getHostAddress();
|
||||
} catch (final UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientOS() {
|
||||
public ClientOS getClientOS() {
|
||||
return this.clientOS;
|
||||
}
|
||||
|
||||
|
@ -204,7 +224,7 @@ public class ClientGroup implements ClientGroupData {
|
|||
return this.ipRangeStart + Constants.EMBEDDED_LIST_SEPARATOR + this.ipRangeEnd;
|
||||
}
|
||||
case CLIENT_OS: {
|
||||
return this.clientOS;
|
||||
return this.clientOS.name();
|
||||
}
|
||||
default: {
|
||||
return StringUtils.EMPTY;
|
||||
|
|
|
@ -9,10 +9,33 @@
|
|||
package ch.ethz.seb.sebserver.gbl.model.exam;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
|
||||
public interface ClientGroupData extends Entity {
|
||||
|
||||
public static final String ATTR_IP_RANGE_START = "ipRangeStart";
|
||||
public static final String ATTR_IP_RANGE_END = "ipRangeEnd";
|
||||
public static final String ATTR_CLIENT_OS = "clientOS";
|
||||
|
||||
public enum ClientGroupType {
|
||||
NONE,
|
||||
IP_V4_RANGE,
|
||||
CLIENT_OS
|
||||
}
|
||||
|
||||
public enum ClientOS {
|
||||
NONE(null),
|
||||
WINDOWS("Windows"),
|
||||
MAC_OS("TODO"),
|
||||
I_OS("TODO");
|
||||
|
||||
final String queryString;
|
||||
|
||||
private ClientOS(final String queryString) {
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Long getId();
|
||||
|
||||
ClientGroupType getType();
|
||||
|
@ -25,5 +48,6 @@ public interface ClientGroupData extends Entity {
|
|||
|
||||
String getIpRangeEnd();
|
||||
|
||||
String getClientOS();
|
||||
ClientOS getClientOS();
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.model.exam;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
|
@ -22,7 +25,6 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
|||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.CLIENT_GROUP;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ClientGroupTemplate implements ClientGroupData {
|
||||
|
@ -57,7 +59,7 @@ public class ClientGroupTemplate implements ClientGroupData {
|
|||
public final String ipRangeEnd;
|
||||
|
||||
@JsonProperty(ClientGroup.ATTR_CLIENT_OS)
|
||||
public final String clientOS;
|
||||
public final ClientOS clientOS;
|
||||
|
||||
@JsonCreator
|
||||
public ClientGroupTemplate(
|
||||
|
@ -69,7 +71,7 @@ public class ClientGroupTemplate implements ClientGroupData {
|
|||
@JsonProperty(CLIENT_GROUP.ATTR_ICON) final String icon,
|
||||
@JsonProperty(ClientGroup.ATTR_IP_RANGE_START) final String ipRangeStart,
|
||||
@JsonProperty(ClientGroup.ATTR_IP_RANGE_END) final String ipRangeEnd,
|
||||
@JsonProperty(ClientGroup.ATTR_CLIENT_OS) final String clientOS) {
|
||||
@JsonProperty(ClientGroup.ATTR_CLIENT_OS) final ClientOS clientOS) {
|
||||
|
||||
super();
|
||||
this.id = id;
|
||||
|
@ -93,7 +95,7 @@ public class ClientGroupTemplate implements ClientGroupData {
|
|||
this.icon = postParams.getString(CLIENT_GROUP.ATTR_ICON);
|
||||
this.ipRangeStart = postParams.getString(ClientGroup.ATTR_IP_RANGE_START);
|
||||
this.ipRangeEnd = postParams.getString(ClientGroup.ATTR_IP_RANGE_END);
|
||||
this.clientOS = postParams.getString(ClientGroup.ATTR_CLIENT_OS);
|
||||
this.clientOS = postParams.getEnum(ClientGroup.ATTR_CLIENT_OS, ClientOS.class);
|
||||
}
|
||||
|
||||
public ClientGroupTemplate(final Long id, final ClientGroupTemplate other) {
|
||||
|
@ -150,16 +152,32 @@ public class ClientGroupTemplate implements ClientGroupData {
|
|||
|
||||
@Override
|
||||
public String getIpRangeStart() {
|
||||
return this.ipRangeStart;
|
||||
if (StringUtils.isBlank(this.ipRangeStart)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return InetAddress.getByName(this.ipRangeStart).getHostAddress();
|
||||
} catch (final UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIpRangeEnd() {
|
||||
return this.ipRangeEnd;
|
||||
if (StringUtils.isBlank(this.ipRangeEnd)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return InetAddress.getByName(this.ipRangeEnd).getHostAddress();
|
||||
} catch (final UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientOS() {
|
||||
public ClientOS getClientOS() {
|
||||
return this.clientOS;
|
||||
}
|
||||
|
||||
|
@ -170,7 +188,7 @@ public class ClientGroupTemplate implements ClientGroupData {
|
|||
return this.ipRangeStart + Constants.EMBEDDED_LIST_SEPARATOR + this.ipRangeEnd;
|
||||
}
|
||||
case CLIENT_OS: {
|
||||
return this.clientOS;
|
||||
return this.clientOS.name();
|
||||
}
|
||||
default: {
|
||||
return StringUtils.EMPTY;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
package ch.ethz.seb.sebserver.gbl.monitoring;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
|
||||
/** Defines a client connection to client group matcher for a specific client group type.
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
|
||||
@Lazy
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
|
|
|
@ -193,6 +193,18 @@ public final class Utils {
|
|||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> T enumFromString(
|
||||
final String string,
|
||||
final Class<T> enumClass,
|
||||
final T defaultValue) {
|
||||
|
||||
try {
|
||||
return Enum.valueOf(enumClass, string);
|
||||
} catch (final Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static Collection<String> getListOfLines(final String list) {
|
||||
if (list == null) {
|
||||
return Collections.emptyList();
|
||||
|
|
|
@ -23,6 +23,7 @@ public enum ActionCategory {
|
|||
CLIENT_GROUP_TEMPLATE_LIST(new LocTextKey("sebserver.examtemplate.clientgroup.list.actions"), 2),
|
||||
EXAM_CONFIG_MAPPING_LIST(new LocTextKey("sebserver.exam.configuration.list.actions"), 1),
|
||||
INDICATOR_LIST(new LocTextKey("sebserver.exam.indicator.list.actions"), 2),
|
||||
CLIENT_GROUP_LIST(new LocTextKey("sebserver.exam.clientgroup.list.actions"), 3),
|
||||
SEB_CLIENT_CONFIG_LIST(new LocTextKey("sebserver.clientconfig.list.actions"), 1),
|
||||
SEB_EXAM_CONFIG_LIST(new LocTextKey("sebserver.examconfig.list.actions"), 1),
|
||||
SEB_CONFIG_TEMPLATE_LIST(new LocTextKey("sebserver.configtemplate.list.actions"), 1),
|
||||
|
|
|
@ -388,6 +388,33 @@ public enum ActionDefinition {
|
|||
ImageIcon.CANCEL,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
||||
EXAM_CLIENT_GROUP_NEW(
|
||||
new LocTextKey("sebserver.exam.clientgroup.action.list.new"),
|
||||
ImageIcon.ADD_CLIENT_GROUP,
|
||||
PageStateDefinitionImpl.CLIENT_GROUP_EDIT,
|
||||
ActionCategory.CLIENT_GROUP_LIST),
|
||||
EXAM_CLIENT_GROUP_MODIFY_FROM_LIST(
|
||||
new LocTextKey("sebserver.exam.clientgroup.action.list.modify"),
|
||||
ImageIcon.EDIT,
|
||||
PageStateDefinitionImpl.CLIENT_GROUP_EDIT,
|
||||
ActionCategory.CLIENT_GROUP_LIST),
|
||||
EXAM_CLIENT_GROUP_DELETE_FROM_LIST(
|
||||
new LocTextKey("sebserver.exam.clientgroup.action.list.delete"),
|
||||
ImageIcon.DELETE,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.CLIENT_GROUP_LIST),
|
||||
EXAM_CLIENT_GROUP_SAVE(
|
||||
new LocTextKey("sebserver.exam.clientgroup.action.save"),
|
||||
ImageIcon.SAVE,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.FORM),
|
||||
EXAM_CLIENT_GROUP_CANCEL_MODIFY(
|
||||
new LocTextKey("sebserver.overall.action.modify.cancel"),
|
||||
ImageIcon.CANCEL,
|
||||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
||||
EXAM_SEB_CLIENT_CONFIG_EXPORT(
|
||||
new LocTextKey("sebserver.exam.action.createClientToStartExam"),
|
||||
ImageIcon.EXPORT,
|
||||
|
@ -471,7 +498,7 @@ public enum ActionDefinition {
|
|||
|
||||
CLIENT_GROUP_TEMPLATE_NEW(
|
||||
new LocTextKey("sebserver.examtemplate.clientgroup.action.list.new"),
|
||||
ImageIcon.CLIENT_GROUP,
|
||||
ImageIcon.ADD_CLIENT_GROUP,
|
||||
PageStateDefinitionImpl.CLIENT_GROUP_TEMPLATE_EDIT,
|
||||
ActionCategory.CLIENT_GROUP_TEMPLATE_LIST),
|
||||
CLIENT_GROUP_TEMPLATE_MODIFY_FROM_LIST(
|
||||
|
|
|
@ -254,14 +254,14 @@ public class ActionPane implements TemplateComposer {
|
|||
final Template template = new Template();
|
||||
final ImageCell imageCell = new ImageCell(template);
|
||||
imageCell.setLeft(0, -8)
|
||||
.setWidth(20)
|
||||
.setWidth(24)
|
||||
.setTop(0)
|
||||
.setBottom(0, 0)
|
||||
.setHorizontalAlignment(SWT.LEFT)
|
||||
.setBackground(null);
|
||||
imageCell.setBindingIndex(0);
|
||||
final TextCell textCell = new TextCell(template);
|
||||
textCell.setLeft(0, 20)
|
||||
textCell.setLeft(0, 24)
|
||||
.setWidth(SWT.DEFAULT)
|
||||
.setTop(7)
|
||||
.setBottom(0, 0)
|
||||
|
|
|
@ -24,6 +24,7 @@ import ch.ethz.seb.sebserver.gui.content.configs.SEBClientConfigList;
|
|||
import ch.ethz.seb.sebserver.gui.content.configs.SEBExamConfigForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.configs.SEBExamConfigList;
|
||||
import ch.ethz.seb.sebserver.gui.content.configs.SEBSettingsForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.exam.ClientGroupForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.exam.ClientGroupTemplateForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.exam.ExamForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.exam.ExamList;
|
||||
|
@ -66,6 +67,7 @@ public enum PageStateDefinitionImpl implements PageStateDefinition {
|
|||
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),
|
||||
CLIENT_GROUP_EDIT(Type.FORM_EDIT, ClientGroupForm.class, ActivityDefinition.EXAM),
|
||||
|
||||
EXAM_TEMPLATE_LIST(Type.LIST_VIEW, ExamTemplateList.class, ActivityDefinition.EXAM_TEMPLATE),
|
||||
EXAM_TEMPLATE_VIEW(Type.LIST_VIEW, ExamTemplateForm.class, ActivityDefinition.EXAM_TEMPLATE),
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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.exam;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupTemplate;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.Form;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.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.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;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.clientgroup.GetClientGroup;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.clientgroup.NewClientGroup;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.clientgroup.SaveClientGroup;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ClientGroupForm implements TemplateComposer {
|
||||
|
||||
private static final LocTextKey NEW_CLIENT_GROUP_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.title.new");
|
||||
private static final LocTextKey CLIENT_GROUP_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.title");
|
||||
private static final LocTextKey FORM_COLOR_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.color");
|
||||
private static final LocTextKey FORM_TYPE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.type");
|
||||
private static final LocTextKey FORM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.name");
|
||||
private static final LocTextKey FORM_EXAM_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.exam");
|
||||
private static final LocTextKey FORM_DESC_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.description");
|
||||
private static final LocTextKey FORM_IP_START_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.ipstart");
|
||||
private static final LocTextKey FORM_IP_END_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.ipend");
|
||||
private static final LocTextKey FORM_OS_TYPE_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.ostype");
|
||||
|
||||
private static final String CLIENT_GROUP_TYPE_DESC_PREFIX =
|
||||
"sebserver.exam.clientgroup.type.description.";
|
||||
private static final String TYPE_DESCRIPTION_FIELD_NAME =
|
||||
"typeDescription";
|
||||
|
||||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
private final I18nSupport i18nSupport;
|
||||
|
||||
protected ClientGroupForm(final PageService pageService) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.i18nSupport = pageService.getI18nSupport();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final RestService restService = this.resourceService.getRestService();
|
||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||
final boolean isNew = entityKey == null;
|
||||
final boolean isReadonly = pageContext.isReadonly();
|
||||
|
||||
final Exam exam = restService
|
||||
.getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error))
|
||||
.getOrThrow();
|
||||
|
||||
// get data or create new. Handle error if happen
|
||||
final ClientGroup clientGroup = (isNew)
|
||||
? ClientGroup.createNew(exam.getModelId())
|
||||
: restService
|
||||
.getBuilder(GetClientGroup.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.onError(error -> pageContext.notifyLoadError(EntityType.CLIENT_GROUP, error))
|
||||
.getOrThrow();
|
||||
|
||||
final boolean typeSet = clientGroup.type != null;
|
||||
final String typeDescription = (typeSet)
|
||||
? Utils.formatLineBreaks(
|
||||
this.i18nSupport.getText(CLIENT_GROUP_TYPE_DESC_PREFIX + clientGroup.type.name()))
|
||||
: Constants.EMPTY_NOTE;
|
||||
|
||||
// new PageContext with actual EntityKey
|
||||
final PageContext formContext = pageContext.withEntityKey(clientGroup.getEntityKey());
|
||||
|
||||
// the default page layout
|
||||
final LocTextKey titleKey = (isNew)
|
||||
? NEW_CLIENT_GROUP_TILE_TEXT_KEY
|
||||
: CLIENT_GROUP_TILE_TEXT_KEY;
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
titleKey);
|
||||
|
||||
final FormHandle<ClientGroup> formHandle = this.pageService.formBuilder(
|
||||
formContext.copyOf(content))
|
||||
.readonly(isReadonly)
|
||||
.putStaticValueIf(() -> !isNew,
|
||||
Domain.CLIENT_GROUP.ATTR_ID,
|
||||
clientGroup.getModelId())
|
||||
.putStaticValue(
|
||||
Domain.EXAM.ATTR_INSTITUTION_ID,
|
||||
String.valueOf(exam.getInstitutionId()))
|
||||
.putStaticValue(
|
||||
Domain.CLIENT_GROUP.ATTR_EXAM_ID,
|
||||
parentEntityKey.getModelId())
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_NAME,
|
||||
FORM_EXAM_TEXT_KEY,
|
||||
exam.name)
|
||||
.readonly(true))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_GROUP.ATTR_NAME,
|
||||
FORM_NAME_TEXT_KEY,
|
||||
clientGroup.name)
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.addField(FormBuilder.colorSelection(
|
||||
Domain.CLIENT_GROUP.ATTR_COLOR,
|
||||
FORM_COLOR_TEXT_KEY,
|
||||
clientGroup.color)
|
||||
.withEmptyCellSeparation(false))
|
||||
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.CLIENT_GROUP.ATTR_TYPE,
|
||||
FORM_TYPE_TEXT_KEY,
|
||||
clientGroup.type.name(),
|
||||
this.resourceService::clientGroupTypeResources)
|
||||
.withSelectionListener(form -> updateForm(form, this.i18nSupport))
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
TYPE_DESCRIPTION_FIELD_NAME,
|
||||
FORM_DESC_TEXT_KEY,
|
||||
typeDescription)
|
||||
.asArea()
|
||||
.readonly(true))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
ClientGroup.ATTR_IP_RANGE_START,
|
||||
FORM_IP_START_KEY,
|
||||
clientGroup::getIpRangeStart)
|
||||
.mandatory(!isReadonly)
|
||||
.visibleIf(clientGroup.type == ClientGroupType.IP_V4_RANGE))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
ClientGroup.ATTR_IP_RANGE_END,
|
||||
FORM_IP_END_KEY,
|
||||
clientGroup::getIpRangeEnd)
|
||||
.mandatory(!isReadonly)
|
||||
.visibleIf(clientGroup.type == ClientGroupType.IP_V4_RANGE))
|
||||
|
||||
.addField(FormBuilder.singleSelection(
|
||||
ClientGroupTemplate.ATTR_CLIENT_OS,
|
||||
FORM_OS_TYPE_KEY,
|
||||
clientGroup.clientOS.name(),
|
||||
this.resourceService::clientClientOSResources)
|
||||
.visibleIf(clientGroup.type == ClientGroupType.CLIENT_OS)
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.buildFor((isNew)
|
||||
? restService.getRestCall(NewClientGroup.class)
|
||||
: restService.getRestCall(SaveClientGroup.class));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_SAVE)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(formHandle::processFormSave)
|
||||
.ignoreMoveAwayFromEdit()
|
||||
.publishIf(() -> !isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_CANCEL_MODIFY)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.withExec(this.pageService.backToCurrentFunction())
|
||||
.publishIf(() -> !isReadonly);
|
||||
}
|
||||
|
||||
public static void updateForm(final Form form, final I18nSupport i18nSupport) {
|
||||
final String typeValue = form.getFieldValue(Domain.CLIENT_GROUP.ATTR_TYPE);
|
||||
if (StringUtils.isNotBlank(typeValue)) {
|
||||
final String text = i18nSupport.getText(CLIENT_GROUP_TYPE_DESC_PREFIX + typeValue);
|
||||
form.setFieldValue(
|
||||
TYPE_DESCRIPTION_FIELD_NAME,
|
||||
Utils.formatLineBreaks(text));
|
||||
final ClientGroupType type = ClientGroupType.valueOf(typeValue);
|
||||
form.setFieldVisible(false, ClientGroup.ATTR_IP_RANGE_START);
|
||||
form.setFieldVisible(false, ClientGroup.ATTR_IP_RANGE_END);
|
||||
form.setFieldVisible(false, ClientGroupTemplate.ATTR_CLIENT_OS);
|
||||
if (type == ClientGroupType.IP_V4_RANGE) {
|
||||
form.setFieldVisible(true, ClientGroup.ATTR_IP_RANGE_START);
|
||||
form.setFieldVisible(true, ClientGroup.ATTR_IP_RANGE_END);
|
||||
}
|
||||
if (type == ClientGroupType.CLIENT_OS) {
|
||||
form.setFieldVisible(true, ClientGroupTemplate.ATTR_CLIENT_OS);
|
||||
}
|
||||
|
||||
} else {
|
||||
form.setFieldValue(TYPE_DESCRIPTION_FIELD_NAME, Constants.EMPTY_NOTE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -19,14 +18,13 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupTemplate;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ExamTemplate;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.IndicatorTemplate;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.form.Form;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
|
@ -65,6 +63,8 @@ public class ClientGroupTemplateForm implements TemplateComposer {
|
|||
new LocTextKey("sebserver.exam.clientgroup.form.ipstart");
|
||||
private static final LocTextKey FORM_IP_END_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.ipend");
|
||||
private static final LocTextKey FORM_OS_TYPE_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.form.ostype");
|
||||
|
||||
private static final String CLIENT_GROUP_TYPE_DESC_PREFIX =
|
||||
"sebserver.exam.clientgroup.type.description.";
|
||||
|
@ -166,7 +166,7 @@ public class ClientGroupTemplateForm implements TemplateComposer {
|
|||
FORM_TYPE_TEXT_KEY,
|
||||
(clientGroupTemplate.type != null) ? clientGroupTemplate.type.name() : null,
|
||||
this.resourceService::clientGroupTypeResources)
|
||||
.withSelectionListener(this::updateForm)
|
||||
.withSelectionListener(form -> ClientGroupForm.updateForm(form, this.i18nSupport))
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
|
@ -174,13 +174,13 @@ public class ClientGroupTemplateForm implements TemplateComposer {
|
|||
FORM_DESC_TEXT_KEY,
|
||||
typeDescription)
|
||||
.asArea()
|
||||
//.asHTML(true)
|
||||
.readonly(true))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
ClientGroup.ATTR_IP_RANGE_START,
|
||||
FORM_IP_START_KEY,
|
||||
clientGroupTemplate::getIpRangeStart)
|
||||
.mandatory(!isReadonly)
|
||||
.visibleIf(clientGroupTemplate.type != null
|
||||
&& clientGroupTemplate.type == ClientGroupType.IP_V4_RANGE))
|
||||
|
||||
|
@ -188,9 +188,19 @@ public class ClientGroupTemplateForm implements TemplateComposer {
|
|||
ClientGroup.ATTR_IP_RANGE_END,
|
||||
FORM_IP_END_KEY,
|
||||
clientGroupTemplate::getIpRangeEnd)
|
||||
.mandatory(!isReadonly)
|
||||
.visibleIf(clientGroupTemplate.type != null
|
||||
&& clientGroupTemplate.type == ClientGroupType.IP_V4_RANGE))
|
||||
|
||||
.addField(FormBuilder.singleSelection(
|
||||
ClientGroupTemplate.ATTR_CLIENT_OS,
|
||||
FORM_OS_TYPE_KEY,
|
||||
(clientGroupTemplate.clientOS != null) ? clientGroupTemplate.clientOS.name() : null,
|
||||
this.resourceService::clientClientOSResources)
|
||||
.visibleIf(clientGroupTemplate.type != null
|
||||
&& clientGroupTemplate.type == ClientGroupType.CLIENT_OS)
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.buildFor((isNew)
|
||||
? restService.getRestCall(NewClientGroupTemplate.class)
|
||||
: restService.getRestCall(SaveClientGroupTemplate.class));
|
||||
|
@ -211,24 +221,4 @@ public class ClientGroupTemplateForm implements TemplateComposer {
|
|||
|
||||
}
|
||||
|
||||
private void updateForm(final Form form) {
|
||||
final String typeValue = form.getFieldValue(Domain.CLIENT_GROUP.ATTR_TYPE);
|
||||
if (StringUtils.isNotBlank(typeValue)) {
|
||||
final String text = this.i18nSupport.getText(CLIENT_GROUP_TYPE_DESC_PREFIX + typeValue);
|
||||
form.setFieldValue(
|
||||
TYPE_DESCRIPTION_FIELD_NAME,
|
||||
Utils.formatLineBreaks(text));
|
||||
final ClientGroupType type = ClientGroupType.valueOf(typeValue);
|
||||
form.setFieldVisible(false, ClientGroup.ATTR_IP_RANGE_START);
|
||||
form.setFieldVisible(false, ClientGroup.ATTR_IP_RANGE_END);
|
||||
if (type == ClientGroupType.IP_V4_RANGE) {
|
||||
form.setFieldVisible(true, ClientGroup.ATTR_IP_RANGE_START);
|
||||
form.setFieldVisible(true, ClientGroup.ATTR_IP_RANGE_END);
|
||||
}
|
||||
|
||||
} else {
|
||||
form.setFieldValue(TYPE_DESCRIPTION_FIELD_NAME, Constants.EMPTY_NOTE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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.exam;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
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.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.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.clientgroup.DeleteClientGroup;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.clientgroup.GetClientGroupPage;
|
||||
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
|
||||
@GuiProfile
|
||||
public class ExamClientGroupList implements TemplateComposer {
|
||||
|
||||
private final static LocTextKey CLIENT_GROUP_LIST_TITLE_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.title");
|
||||
private final static LocTextKey CLIENT_GROUP_LIST_TITLE_TOOLTIP_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.title" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private final static LocTextKey CLIENT_GROUP_TYPE_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.column.type");
|
||||
private final static LocTextKey CLIENT_GROUP_NAME_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.column.name");
|
||||
private final static LocTextKey CLIENT_GROUP_COLOR_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.column.color");
|
||||
private final static LocTextKey CLIENT_GROUP_DATA_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.column.data");
|
||||
private final static LocTextKey CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.pleaseSelect");
|
||||
private static final LocTextKey CLIENT_GROUP_EMPTY_LIST_MESSAGE =
|
||||
new LocTextKey("sebserver.exam.clientgroup.list.empty");
|
||||
|
||||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
|
||||
public ExamClientGroupList(final PageService pageService) {
|
||||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.widgetFactory = pageService.getWidgetFactory();
|
||||
this.restService = pageService.getRestService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final Composite content = pageContext.getParent();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
final boolean editable = BooleanUtils.toBoolean(
|
||||
pageContext.getAttribute(ExamForm.ATTR_EDITABLE));
|
||||
|
||||
// List of ClientGroups
|
||||
this.widgetFactory.addFormSubContextHeader(
|
||||
content,
|
||||
CLIENT_GROUP_LIST_TITLE_KEY,
|
||||
CLIENT_GROUP_LIST_TITLE_TOOLTIP_KEY);
|
||||
|
||||
final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext
|
||||
.clearEntityKeys()
|
||||
.removeAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA));
|
||||
|
||||
final EntityTable<ClientGroup> clientGroupTable =
|
||||
this.pageService
|
||||
.entityTableBuilder(this.restService.getRestCall(GetClientGroupPage.class))
|
||||
.withRestCallAdapter(builder -> builder.withURIVariable(
|
||||
API.PARAM_PARENT_MODEL_ID,
|
||||
entityKey.modelId))
|
||||
.withEmptyMessage(CLIENT_GROUP_EMPTY_LIST_MESSAGE)
|
||||
.withMarkup()
|
||||
.withPaging(100)
|
||||
.hideNavigation()
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CLIENT_GROUP.ATTR_NAME,
|
||||
CLIENT_GROUP_NAME_COLUMN_KEY,
|
||||
ClientGroup::getName)
|
||||
.widthProportion(2))
|
||||
|
||||
.withColumn(new ColumnDefinition<ClientGroup>(
|
||||
Domain.CLIENT_GROUP.ATTR_TYPE,
|
||||
CLIENT_GROUP_TYPE_COLUMN_KEY,
|
||||
cgt -> this.resourceService.clientGroupTypeName(cgt))
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<ClientGroup>(
|
||||
Domain.CLIENT_GROUP.ATTR_COLOR,
|
||||
CLIENT_GROUP_COLOR_COLUMN_KEY,
|
||||
cgt -> this.widgetFactory.getColorValueHTML(cgt))
|
||||
.asMarkup()
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<ClientGroup>(
|
||||
Domain.CLIENT_GROUP.ATTR_DATA,
|
||||
CLIENT_GROUP_DATA_COLUMN_KEY,
|
||||
cgt -> this.widgetFactory.clientGroupDataToHTML(cgt))
|
||||
.asMarkup()
|
||||
.widthProportion(3))
|
||||
|
||||
.withDefaultActionIf(
|
||||
() -> editable,
|
||||
() -> actionBuilder
|
||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_MODIFY_FROM_LIST)
|
||||
.withParentEntityKey(entityKey)
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.EXAM_CLIENT_GROUP_MODIFY_FROM_LIST,
|
||||
ActionDefinition.EXAM_CLIENT_GROUP_DELETE_FROM_LIST))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_MODIFY_FROM_LIST)
|
||||
.withParentEntityKey(entityKey)
|
||||
.withSelect(
|
||||
clientGroupTable::getMultiSelection,
|
||||
PageAction::applySingleSelectionAsEntityKey,
|
||||
CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> editable && clientGroupTable.hasAnyContent(), false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_DELETE_FROM_LIST)
|
||||
.withEntityKey(entityKey)
|
||||
.withSelect(
|
||||
clientGroupTable::getMultiSelection,
|
||||
this::deleteSelectedClientGroup,
|
||||
CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> editable && clientGroupTable.hasAnyContent(), false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CLIENT_GROUP_NEW)
|
||||
.withParentEntityKey(entityKey)
|
||||
.publishIf(() -> editable);
|
||||
}
|
||||
|
||||
private PageAction deleteSelectedClientGroup(final PageAction action) {
|
||||
final EntityKey clientGroupKey = action.getSingleSelection();
|
||||
this.resourceService.getRestService()
|
||||
.getBuilder(DeleteClientGroup.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, clientGroupKey.modelId)
|
||||
.call();
|
||||
return action;
|
||||
}
|
||||
|
||||
}
|
|
@ -151,7 +151,8 @@ public class ExamForm implements TemplateComposer {
|
|||
private final RestService restService;
|
||||
private final ExamDeletePopup examDeletePopup;
|
||||
private final ExamFormConfigs examFormConfigs;
|
||||
private final ExamFormIndicators examFormIndicators;
|
||||
private final ExamIndicatorsList examIndicatorsList;
|
||||
private final ExamClientGroupList examClientGroupList;
|
||||
private final ExamCreateClientConfigPopup examCreateClientConfigPopup;
|
||||
|
||||
protected ExamForm(
|
||||
|
@ -162,7 +163,8 @@ public class ExamForm implements TemplateComposer {
|
|||
final DownloadService downloadService,
|
||||
final ExamDeletePopup examDeletePopup,
|
||||
final ExamFormConfigs examFormConfigs,
|
||||
final ExamFormIndicators examFormIndicators,
|
||||
final ExamIndicatorsList examIndicatorsList,
|
||||
final ExamClientGroupList examClientGroupList,
|
||||
final ExamCreateClientConfigPopup examCreateClientConfigPopup) {
|
||||
|
||||
this.pageService = pageService;
|
||||
|
@ -173,7 +175,8 @@ public class ExamForm implements TemplateComposer {
|
|||
this.restService = this.resourceService.getRestService();
|
||||
this.examDeletePopup = examDeletePopup;
|
||||
this.examFormConfigs = examFormConfigs;
|
||||
this.examFormIndicators = examFormIndicators;
|
||||
this.examIndicatorsList = examIndicatorsList;
|
||||
this.examClientGroupList = examClientGroupList;
|
||||
this.examCreateClientConfigPopup = examCreateClientConfigPopup;
|
||||
|
||||
this.consistencyMessageMapping = new HashMap<>();
|
||||
|
@ -485,7 +488,15 @@ public class ExamForm implements TemplateComposer {
|
|||
.withAttribute(ATTR_EXAM_STATUS, examStatus.name()));
|
||||
|
||||
// Indicators
|
||||
this.examFormIndicators.compose(
|
||||
this.examIndicatorsList.compose(
|
||||
formContext
|
||||
.copyOf(content)
|
||||
.withAttribute(ATTR_READ_GRANT, String.valueOf(entityGrantCheck.r()))
|
||||
.withAttribute(ATTR_EDITABLE, String.valueOf(editable))
|
||||
.withAttribute(ATTR_EXAM_STATUS, examStatus.name()));
|
||||
|
||||
// Client Groups
|
||||
this.examClientGroupList.compose(
|
||||
formContext
|
||||
.copyOf(content)
|
||||
.withAttribute(ATTR_READ_GRANT, String.valueOf(entityGrantCheck.r()))
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content.exam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -20,10 +18,7 @@ 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.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
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.Utils;
|
||||
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;
|
||||
|
@ -38,12 +33,13 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.indicator.De
|
|||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.indicator.GetIndicatorPage;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.widget.ThresholdList;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class ExamFormIndicators implements TemplateComposer {
|
||||
public class ExamIndicatorsList implements TemplateComposer {
|
||||
|
||||
private final static LocTextKey INDICATOR_LIST_TITLE_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.list.title");
|
||||
|
@ -65,7 +61,7 @@ public class ExamFormIndicators implements TemplateComposer {
|
|||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
|
||||
public ExamFormIndicators(final PageService pageService) {
|
||||
public ExamIndicatorsList(final PageService pageService) {
|
||||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.widgetFactory = pageService.getWidgetFactory();
|
||||
|
@ -111,7 +107,7 @@ public class ExamFormIndicators implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<Indicator>(
|
||||
Domain.THRESHOLD.REFERENCE_NAME,
|
||||
INDICATOR_THRESHOLD_COLUMN_KEY,
|
||||
i -> thresholdsValue(i.thresholds, i.type))
|
||||
i -> ThresholdList.thresholdsToHTML(i.thresholds, i.type))
|
||||
.asMarkup()
|
||||
.widthProportion(4))
|
||||
.withDefaultActionIf(
|
||||
|
@ -170,34 +166,4 @@ public class ExamFormIndicators implements TemplateComposer {
|
|||
.getText(ResourceService.EXAM_INDICATOR_TYPE_PREFIX + indicator.type.name());
|
||||
}
|
||||
|
||||
static String thresholdsValue(
|
||||
final List<Threshold> thresholds,
|
||||
final IndicatorType indicatorType) {
|
||||
|
||||
if (thresholds.isEmpty()) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
final StringBuilder builder = thresholds
|
||||
.stream()
|
||||
.reduce(
|
||||
new StringBuilder(),
|
||||
(sb, threshold) -> sb
|
||||
.append("<span style='padding: 2px 5px 2px 5px; background-color: #")
|
||||
.append(threshold.color)
|
||||
.append("; ")
|
||||
.append((Utils.darkColorContrast(Utils.parseRGB(threshold.color)))
|
||||
? "color: #4a4a4a; "
|
||||
: "color: #FFFFFF;")
|
||||
.append("'>")
|
||||
.append(Indicator.getDisplayValue(indicatorType, threshold.value))
|
||||
.append(" (")
|
||||
.append(threshold.color)
|
||||
.append(")")
|
||||
.append("</span>")
|
||||
.append(" | "),
|
||||
StringBuilder::append);
|
||||
builder.delete(builder.length() - 3, builder.length() - 1);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -51,6 +51,7 @@ 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.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.widget.ThresholdList;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
|
@ -101,6 +102,8 @@ public class ExamTemplateForm implements TemplateComposer {
|
|||
new LocTextKey("sebserver.examtemplate.clientgroup.list.column.name");
|
||||
private final static LocTextKey CLIENT_GROUP_COLOR_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.examtemplate.clientgroup.list.column.color");
|
||||
private final static LocTextKey CLIENT_GROUP_DATA_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.examtemplate.clientgroup.list.column.data");
|
||||
private final static LocTextKey CLIENT_GROUP_EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.examtemplate.clientgroup.list.pleaseSelect");
|
||||
private static final LocTextKey CLIENT_GROUP_EMPTY_LIST_MESSAGE =
|
||||
|
@ -287,7 +290,7 @@ public class ExamTemplateForm implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<IndicatorTemplate>(
|
||||
Domain.THRESHOLD.REFERENCE_NAME,
|
||||
INDICATOR_THRESHOLD_COLUMN_KEY,
|
||||
it -> ExamFormIndicators.thresholdsValue(it.thresholds, it.type))
|
||||
it -> ThresholdList.thresholdsToHTML(it.thresholds, it.type))
|
||||
.asMarkup()
|
||||
.widthProportion(4))
|
||||
.withDefaultActionIf(
|
||||
|
@ -347,15 +350,21 @@ public class ExamTemplateForm implements TemplateComposer {
|
|||
CLIENT_GROUP_NAME_COLUMN_KEY,
|
||||
ClientGroupTemplate::getName)
|
||||
.widthProportion(2))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
.withColumn(new ColumnDefinition<ClientGroupTemplate>(
|
||||
Domain.CLIENT_GROUP.ATTR_TYPE,
|
||||
CLIENT_GROUP_TYPE_COLUMN_KEY,
|
||||
this::clientGroupTypeName)
|
||||
cgt -> this.resourceService.clientGroupTypeName(cgt))
|
||||
.widthProportion(1))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
.withColumn(new ColumnDefinition<ClientGroupTemplate>(
|
||||
Domain.CLIENT_GROUP.ATTR_COLOR,
|
||||
CLIENT_GROUP_COLOR_COLUMN_KEY,
|
||||
ClientGroupTemplate::getColor)
|
||||
cgt -> this.widgetFactory.getColorValueHTML(cgt))
|
||||
.asMarkup()
|
||||
.widthProportion(1))
|
||||
.withColumn(new ColumnDefinition<ClientGroupTemplate>(
|
||||
Domain.CLIENT_GROUP.ATTR_DATA,
|
||||
CLIENT_GROUP_DATA_COLUMN_KEY,
|
||||
cgt -> this.widgetFactory.clientGroupDataToHTML(cgt))
|
||||
.asMarkup()
|
||||
.widthProportion(4))
|
||||
.withDefaultActionIf(
|
||||
|
@ -430,18 +439,8 @@ public class ExamTemplateForm implements TemplateComposer {
|
|||
if (indicator.type == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return this.resourceService.getI18nSupport()
|
||||
.getText(ResourceService.EXAM_INDICATOR_TYPE_PREFIX + indicator.type.name());
|
||||
}
|
||||
|
||||
private String clientGroupTypeName(final ClientGroupTemplate clientGroup) {
|
||||
if (clientGroup.type == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return this.resourceService.getI18nSupport()
|
||||
.getText(ResourceService.EXAM_CLIENT_GROUP_TYPE_PREFIX + clientGroup.type.name());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -174,6 +174,15 @@ public final class Form implements FormBinding {
|
|||
return this;
|
||||
}
|
||||
|
||||
Form removeField(final String name) {
|
||||
if (this.formFields.containsKey(name)) {
|
||||
final List<FormFieldAccessor> list = this.formFields.remove(name);
|
||||
list.forEach(ffa -> ffa.dispose());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getFieldValue(final String attributeName) {
|
||||
final FormFieldAccessor fieldAccessor = this.formFields.getFirst(attributeName);
|
||||
if (fieldAccessor == null) {
|
||||
|
@ -464,6 +473,11 @@ public final class Form implements FormBinding {
|
|||
this(label, control, null, false, errorLabel);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
this.label.dispose();
|
||||
this.input.dispose();
|
||||
}
|
||||
|
||||
FormFieldAccessor(
|
||||
final Control label,
|
||||
final Control input,
|
||||
|
|
|
@ -36,7 +36,9 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Activatable;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientOS;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
|
||||
|
@ -125,6 +127,7 @@ public class ResourceService {
|
|||
public static final String USERACCOUNT_ROLE_PREFIX = "sebserver.useraccount.role.";
|
||||
public static final String EXAM_INDICATOR_TYPE_PREFIX = "sebserver.exam.indicator.type.";
|
||||
public static final String EXAM_CLIENT_GROUP_TYPE_PREFIX = "sebserver.exam.clientgroup.type.";
|
||||
public static final String CLIENT_OS_TYPE_PREFIX = "sebserver.overall.seb.os.type.";
|
||||
public static final String LMSSETUP_TYPE_PREFIX = "sebserver.lmssetup.type.";
|
||||
public static final String CONFIG_ATTRIBUTE_TYPE_PREFIX = "sebserver.configtemplate.attr.type.";
|
||||
public static final String SEB_RESTRICTION_WHITE_LIST_PREFIX = "sebserver.exam.form.sebrestriction.whiteListPaths.";
|
||||
|
@ -275,6 +278,19 @@ public class ResourceService {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Tuple<String>> clientClientOSResources() {
|
||||
return Arrays.stream(ClientOS.values())
|
||||
.filter(type -> type != ClientOS.NONE)
|
||||
.map(type -> new Tuple3<>(
|
||||
type.name(),
|
||||
this.i18nSupport.getText(CLIENT_OS_TYPE_PREFIX + type.name(), type.name()),
|
||||
Utils.formatLineBreaks(this.i18nSupport.getText(
|
||||
CLIENT_OS_TYPE_PREFIX + type.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
|
||||
StringUtils.EMPTY))))
|
||||
.sorted(RESOURCE_COMPARATOR_TUPLE_3)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Tuple<String>> examConfigurationSelectionResources() {
|
||||
return getExamConfigurationSelection()
|
||||
.getOr(Collections.emptyList())
|
||||
|
@ -905,4 +921,13 @@ public class ResourceService {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public String clientGroupTypeName(final ClientGroupData clientGroup) {
|
||||
if (clientGroup.getType() == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return this.getI18nSupport()
|
||||
.getText(ResourceService.EXAM_CLIENT_GROUP_TYPE_PREFIX + clientGroup.getType().name());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
|||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.widget.Selection.Type;
|
||||
|
@ -129,6 +130,37 @@ public final class ThresholdList extends Composite {
|
|||
return collect;
|
||||
}
|
||||
|
||||
public static String thresholdsToHTML(
|
||||
final List<Threshold> thresholds,
|
||||
final IndicatorType indicatorType) {
|
||||
|
||||
if (thresholds.isEmpty()) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
final StringBuilder builder = thresholds
|
||||
.stream()
|
||||
.reduce(
|
||||
new StringBuilder(),
|
||||
(sb, threshold) -> sb
|
||||
.append("<span style='padding: 2px 5px 2px 5px; background-color: #")
|
||||
.append(threshold.color)
|
||||
.append("; ")
|
||||
.append((Utils.darkColorContrast(Utils.parseRGB(threshold.color)))
|
||||
? "color: #4a4a4a; "
|
||||
: "color: #FFFFFF;")
|
||||
.append("'> ")
|
||||
.append(Indicator.getDisplayValue(indicatorType, threshold.value))
|
||||
.append(" (#")
|
||||
.append(threshold.color)
|
||||
.append(") ")
|
||||
.append("</span>")
|
||||
.append(" | "),
|
||||
StringBuilder::append);
|
||||
builder.delete(builder.length() - 3, builder.length() - 1);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void removeInvalidListEntries() {
|
||||
this.thresholds
|
||||
.stream()
|
||||
|
|
|
@ -49,11 +49,14 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
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;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
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.i18n.PolyglotPageService;
|
||||
|
@ -130,7 +133,8 @@ public class WidgetFactory {
|
|||
INSTITUTION("institution.png"),
|
||||
LMS_SETUP("lmssetup.png"),
|
||||
INDICATOR("indicator.png"),
|
||||
CLIENT_GROUP("indicator.png"),
|
||||
CLIENT_GROUP("clientgroup.png"),
|
||||
ADD_CLIENT_GROUP("add_clientgroup.png"),
|
||||
TEMPLATE("template.png"),
|
||||
DISABLE("disable.png"),
|
||||
SEND_QUIT("send-quit.png"),
|
||||
|
@ -1029,4 +1033,45 @@ public class WidgetFactory {
|
|||
executor.execute(builder.toString());
|
||||
}
|
||||
|
||||
public String clientGroupDataToHTML(final ClientGroupData data) {
|
||||
switch (data.getType()) {
|
||||
case IP_V4_RANGE: {
|
||||
final String ipRangeStart = StringUtils.isBlank(data.getIpRangeStart())
|
||||
? Constants.EMPTY_NOTE
|
||||
: data.getIpRangeStart();
|
||||
final String ipRangeEnd = StringUtils.isBlank(data.getIpRangeEnd())
|
||||
? Constants.EMPTY_NOTE
|
||||
: data.getIpRangeEnd();
|
||||
return ipRangeStart + " - " + ipRangeEnd;
|
||||
}
|
||||
case CLIENT_OS: {
|
||||
return this.i18nSupport.getText(ResourceService.CLIENT_OS_TYPE_PREFIX + data.getClientOS().name());
|
||||
}
|
||||
default: {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getColorValueHTML(final ClientGroupData data) {
|
||||
final String color = data.getColor();
|
||||
if (StringUtils.isBlank(color)) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return new StringBuilder().append("<span style='padding: 2px 5px 2px 5px; background-color: #")
|
||||
.append(color)
|
||||
.append("; ")
|
||||
.append((Utils.darkColorContrast(Utils.parseRGB(color)))
|
||||
? "color: #4a4a4a; "
|
||||
: "color: #FFFFFF;")
|
||||
.append("'> ")
|
||||
.append(" (#")
|
||||
.append(color)
|
||||
.append(") ")
|
||||
.append("</span>")
|
||||
.toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientGroupRecordDynamicSqlSupport;
|
||||
|
|
|
@ -601,11 +601,11 @@ public class ExamTemplateDAOImpl implements ExamTemplateDAO {
|
|||
|
||||
private void checkUniqueClientGroupName(
|
||||
final ClientGroupTemplate clientGroupTemplate,
|
||||
final Collection<ClientGroupTemplate> clinetGroups) {
|
||||
final Collection<ClientGroupTemplate> clietnGroups) {
|
||||
|
||||
// check unique name
|
||||
clinetGroups.stream()
|
||||
.filter(it -> !Objects.equals(it, clientGroupTemplate)
|
||||
clietnGroups.stream()
|
||||
.filter(it -> !Objects.equals(it.id, clientGroupTemplate.id)
|
||||
&& Objects.equals(it.name, clientGroupTemplate.name))
|
||||
.findAny()
|
||||
.ifPresent(it -> {
|
||||
|
|
|
@ -13,14 +13,16 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.validation.FieldError;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientOS;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||
|
@ -149,14 +151,14 @@ public interface ExamAdminService {
|
|||
* If a check fails, the methods throws a APIMessageException with a FieldError to notify the caller
|
||||
*
|
||||
* @param clientGroup ClientGroup instance to check */
|
||||
public static void checkClientGroupConsistency(final ClientGroupData clientGroup) {
|
||||
public static <T extends ClientGroupData> T checkClientGroupConsistency(final T clientGroup) {
|
||||
final ClientGroupType type = clientGroup.getType();
|
||||
if (type == null || type == ClientGroupType.NONE) {
|
||||
throw new APIMessageException(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
Domain.CLIENT_GROUP.TYPE_NAME,
|
||||
Domain.CLIENT_GROUP.ATTR_TYPE,
|
||||
"clientGroup:type:mandatory")));
|
||||
"clientGroup:type:notNull")));
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
@ -176,11 +178,13 @@ public interface ExamAdminService {
|
|||
"clientGroup:type:typeInvalid")));
|
||||
}
|
||||
}
|
||||
|
||||
return clientGroup;
|
||||
}
|
||||
|
||||
static void checkIPRange(final String ipRangeStart, final String ipRangeEnd) {
|
||||
final long startIP = Utils.ipToLong(ipRangeStart);
|
||||
if (startIP < 0) {
|
||||
if (StringUtils.isBlank(ipRangeStart) || startIP < 0) {
|
||||
throw new APIMessageException(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
Domain.CLIENT_GROUP.TYPE_NAME,
|
||||
|
@ -188,7 +192,7 @@ public interface ExamAdminService {
|
|||
"clientGroup:ipRangeStart:invalidIP")));
|
||||
}
|
||||
final long endIP = Utils.ipToLong(ipRangeEnd);
|
||||
if (endIP < 0) {
|
||||
if (StringUtils.isBlank(ipRangeEnd) || endIP < 0) {
|
||||
throw new APIMessageException(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
Domain.CLIENT_GROUP.TYPE_NAME,
|
||||
|
@ -211,8 +215,14 @@ public interface ExamAdminService {
|
|||
|
||||
}
|
||||
|
||||
static void checkClientOS(final String clientOS) {
|
||||
// TODO
|
||||
static void checkClientOS(final ClientOS clientOS) {
|
||||
if (clientOS == null) {
|
||||
throw new APIMessageException(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
Domain.CLIENT_GROUP.TYPE_NAME,
|
||||
ClientGroupData.ATTR_CLIENT_OS,
|
||||
"clientGroup:clientOS:notNull")));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientGroupDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||
|
||||
|
@ -88,15 +89,14 @@ public class ClientGroupController extends EntityController<ClientGroup, ClientG
|
|||
|
||||
@Override
|
||||
protected Result<ClientGroup> validForCreate(final ClientGroup entity) {
|
||||
// TODO check consistency!?
|
||||
return super.validForCreate(entity);
|
||||
|
||||
return super.validForCreate(entity)
|
||||
.map(ExamAdminService::checkClientGroupConsistency);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<ClientGroup> validForSave(final ClientGroup entity) {
|
||||
// TODO check consistency!?
|
||||
return super.validForSave(entity);
|
||||
return super.validForSave(entity)
|
||||
.map(ExamAdminService::checkClientGroupConsistency);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -118,57 +118,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
return ExamRecordDynamicSqlSupport.examRecord;
|
||||
}
|
||||
|
||||
// @RequestMapping(
|
||||
// method = RequestMethod.GET,
|
||||
// consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
// produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
// @Override
|
||||
// public Page<Exam> getPage(
|
||||
// @RequestParam(
|
||||
// name = API.PARAM_INSTITUTION_ID,
|
||||
// required = true,
|
||||
// defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
|
||||
// @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
|
||||
// @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
|
||||
// @RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
|
||||
// @RequestParam final MultiValueMap<String, String> allRequestParams,
|
||||
// final HttpServletRequest request) {
|
||||
//
|
||||
// checkReadPrivilege(institutionId);
|
||||
// this.authorization.check(
|
||||
// PrivilegeType.READ,
|
||||
// EntityType.EXAM,
|
||||
// institutionId);
|
||||
//
|
||||
// if (StringUtils.isBlank(sort) ||
|
||||
// (this.paginationService.isNativeSortingSupported(ExamRecordDynamicSqlSupport.examRecord, sort))) {
|
||||
//
|
||||
// System.out.println("*********************** sort, filter on DB");
|
||||
//
|
||||
// return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request);
|
||||
//
|
||||
// } else {
|
||||
//
|
||||
// System.out.println("*********************** sort, filter on List");
|
||||
//
|
||||
// return super.getPage(institutionId, pageNumber, pageSize, sort, allRequestParams, request);
|
||||
//
|
||||
//// final Collection<Exam> exams = this.examDAO
|
||||
//// .allMatching(new FilterMap(
|
||||
//// allRequestParams,
|
||||
//// request.getQueryString()),
|
||||
//// this::hasReadAccess)
|
||||
//// .getOrThrow();
|
||||
////
|
||||
//// return this.paginationService.buildPageFromList(
|
||||
//// pageNumber,
|
||||
//// pageSize,
|
||||
//// sort,
|
||||
//// exams,
|
||||
//// pageSort(sort));
|
||||
// }
|
||||
// }
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT
|
||||
+ API.EXAM_ADMINISTRATION_CHECK_IMPORTED_PATH_SEGMENT,
|
||||
|
|
|
@ -337,7 +337,7 @@ public class ExamTemplateController extends EntityController<ExamTemplate, ExamT
|
|||
null,
|
||||
postMap.getLong(ClientGroupTemplate.ATTR_EXAM_TEMPLATE_ID),
|
||||
postMap))
|
||||
.map(this::checkClientGroupConsistency)
|
||||
.map(ExamAdminService::checkClientGroupConsistency)
|
||||
.flatMap(this.examTemplateDAO::createNewClientGroupTemplate)
|
||||
.flatMap(this.userActivityLogDAO::logCreate)
|
||||
.getOrThrow();
|
||||
|
@ -359,7 +359,7 @@ public class ExamTemplateController extends EntityController<ExamTemplate, ExamT
|
|||
this.checkModifyPrivilege(institutionId);
|
||||
return this.beanValidationService
|
||||
.validateBean(modifyData)
|
||||
.map(this::checkClientGroupConsistency)
|
||||
.map(ExamAdminService::checkClientGroupConsistency)
|
||||
.flatMap(this.examTemplateDAO::saveClientGroupTemplate)
|
||||
.flatMap(this.userActivityLogDAO::logModify)
|
||||
.getOrThrow();
|
||||
|
@ -494,11 +494,6 @@ public class ExamTemplateController extends EntityController<ExamTemplate, ExamT
|
|||
};
|
||||
}
|
||||
|
||||
private ClientGroupTemplate checkClientGroupConsistency(final ClientGroupTemplate clientGroupTemplate) {
|
||||
ExamAdminService.checkClientGroupConsistency(clientGroupTemplate);
|
||||
return clientGroupTemplate;
|
||||
}
|
||||
|
||||
private IndicatorTemplate checkIndicatorConsistency(final IndicatorTemplate indicatorTemplate) {
|
||||
ExamAdminService.checkThresholdConsistency(indicatorTemplate.thresholds);
|
||||
return indicatorTemplate;
|
||||
|
|
|
@ -80,6 +80,11 @@ sebserver.overall.activity.title.monitoring=Monitoring
|
|||
|
||||
sebserver.overall.batchaction.selected=Selected
|
||||
|
||||
sebserver.overall.seb.os.type.NONE=Undefined
|
||||
sebserver.overall.seb.os.type.WINDOWS=Windows
|
||||
sebserver.overall.seb.os.type.MAC_OS=MacOS
|
||||
sebserver.overall.seb.os.type.I_OS=iOS
|
||||
|
||||
################################
|
||||
# Form validation and messages
|
||||
################################
|
||||
|
@ -595,7 +600,7 @@ sebserver.exam.status.ARCHIVED=Archived
|
|||
sebserver.exam.status.CORRUPT_NO_LMS_CONNECTION=Corrupt (No LMS Connection)
|
||||
sebserver.exam.status.CORRUPT_INVALID_ID=Corrupt (Invalid Identifier)
|
||||
|
||||
sebserver.exam.configuration.list.actions=
|
||||
sebserver.exam.configuration.list.actions=
|
||||
sebserver.exam.configuration.list.title=Exam Configuration
|
||||
sebserver.exam.configuration.list.title.tooltip=A list of all attached exam configuration for this exam
|
||||
sebserver.exam.configuration.list.column.name=Name
|
||||
|
@ -628,7 +633,7 @@ sebserver.exam.configuration.form.status.tooltip=The current status of the selec
|
|||
sebserver.exam.configuration.form.encryptSecret.confirm=Confirm Password
|
||||
sebserver.exam.configuration.form.encryptSecret.confirm.tooltip=Please confirm the encryption password if there is one
|
||||
|
||||
sebserver.exam.indicator.list.actions=
|
||||
sebserver.exam.indicator.list.actions=
|
||||
sebserver.exam.indicator.list.title=Indicators
|
||||
sebserver.exam.indicator.list.title.tooltip=A list of indicators that are shown on the exam monitoring view
|
||||
sebserver.exam.indicator.list.column.type=Type
|
||||
|
@ -640,6 +645,20 @@ sebserver.exam.indicator.list.column.thresholds.tooltip=The thresholds of the in
|
|||
sebserver.exam.indicator.list.empty=There is currently no indicator defined for this exam. Please create a new one
|
||||
sebserver.exam.indicator.list.pleaseSelect=At first please select an indicator from the list
|
||||
|
||||
sebserver.exam.clientgroup.list.actions=
|
||||
sebserver.exam.clientgroup.list.title=Client Groups
|
||||
sebserver.exam.clientgroup.list.title.tooltip=A list of client groups that are shown on the exam monitoring view for the client connections that matches the specific group(s)
|
||||
sebserver.exam.clientgroup.list.column.type=Type
|
||||
sebserver.exam.clientgroup.list.column.type.tooltip=The type of the client group
|
||||
sebserver.exam.clientgroup.list.column.name=Name
|
||||
sebserver.exam.clientgroup.list.column.name.tooltip=The name of the client group
|
||||
sebserver.exam.clientgroup.list.column.color=Color
|
||||
sebserver.exam.clientgroup.list.column.color.tooltip=The color of the client group
|
||||
sebserver.exam.clientgroup.list.column.data=Data
|
||||
sebserver.exam.clientgroup.list.column.data.tooltip=The data of the client group that is specific to the type of the client group
|
||||
sebserver.exam.clientgroup.list.empty=There is currently no client group defined for this exam.
|
||||
sebserver.exam.clientgroup.list.pleaseSelect=At first please select a client group from the list
|
||||
|
||||
sebserver.exam.indicator.type.LAST_PING=Last Ping Time
|
||||
sebserver.exam.indicator.type.ERROR_COUNT=Error-Log Counter
|
||||
sebserver.exam.indicator.type.WARN_COUNT=Warning-Log Counter
|
||||
|
@ -655,6 +674,7 @@ sebserver.exam.indicator.type.description.WLAN_STATUS=This indicator shows the p
|
|||
|
||||
sebserver.exam.clientgroup.type.IP_V4_RANGE=IP v4 Range
|
||||
sebserver.exam.clientgroup.type.CLIENT_OS=SEB Client OS
|
||||
sebserver.exam.clientgroup.type.description.NONE=No Client Group type is selected.<br/>Please select one.
|
||||
sebserver.exam.clientgroup.type.description.IP_V4_RANGE=IP v4 Range TODO
|
||||
sebserver.exam.clientgroup.type.description.CLIENT_OS=SEB Client OS TODO
|
||||
|
||||
|
@ -665,6 +685,11 @@ sebserver.exam.indicator.action.list.modify=Edit Selected Indicator
|
|||
sebserver.exam.indicator.action.list.delete=Delete Selected Indicator
|
||||
sebserver.exam.indicator.action.save=Save
|
||||
|
||||
sebserver.exam.clientgroup.action.list.new=Add Client Group
|
||||
sebserver.exam.clientgroup.action.list.modify=Edit Selected Client Group
|
||||
sebserver.exam.clientgroup.action.list.delete=Delete Selected Client Group
|
||||
sebserver.exam.clientgroup.action.save=Save
|
||||
|
||||
sebserver.exam.indicator.form.title=Indicator
|
||||
sebserver.exam.indicator.form.title.subtitle=
|
||||
sebserver.exam.indicator.form.title.new=Add Indicator
|
||||
|
@ -703,6 +728,8 @@ sebserver.exam.clientgroup.form.ipstart=Start of IP range
|
|||
sebserver.exam.clientgroup.form.ipstart.tooltip=An IP v4 formatted PI address like 111.111.111.111 that defines the start of the range
|
||||
sebserver.exam.clientgroup.form.ipend=End of IP range
|
||||
sebserver.exam.clientgroup.form.ipend.tooltip=An IP v4 formatted PI address like 111.111.111.111 that defines the end of the range
|
||||
sebserver.exam.clientgroup.form.ostype=Client OS Type
|
||||
sebserver.exam.clientgroup.form.ostype.tooltip=The operating system type of the machine where SEB is running on
|
||||
|
||||
|
||||
sebserver.exam.indicator.thresholds.list.title=Thresholds
|
||||
|
@ -1797,6 +1824,8 @@ sebserver.examtemplate.clientgroup.list.column.name=Name
|
|||
sebserver.examtemplate.clientgroup.list.column.name.tooltip=The name of the client group
|
||||
sebserver.examtemplate.clientgroup.list.column.color=Color
|
||||
sebserver.examtemplate.clientgroup.list.column.color.tooltip=The color of the client group
|
||||
sebserver.examtemplate.clientgroup.list.column.data=Data
|
||||
sebserver.examtemplate.clientgroup.list.column.data.tooltip=The data of the client group that is specific to the type of the client group
|
||||
sebserver.examtemplate.clientgroup.list.empty=There is currently no client group defined for this exam template. Please create a new one
|
||||
sebserver.examtemplate.clientgroup.list.pleaseSelect=At first please select an client group from the list
|
||||
|
||||
|
|
BIN
src/main/resources/static/images/add_clientgroup.png
Normal file
BIN
src/main/resources/static/images/add_clientgroup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 232 B |
BIN
src/main/resources/static/images/clientgroup.png
Normal file
BIN
src/main/resources/static/images/clientgroup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 224 B |
|
@ -66,7 +66,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroup.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ClientGroupData.ClientGroupType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
|
||||
|
|
Loading…
Reference in a new issue