fix quit instruction, added default indicator, connection status filter

This commit is contained in:
anhefti 2020-02-10 15:04:40 +01:00
parent 92663c18e8
commit b94e445257
8 changed files with 305 additions and 80 deletions

View file

@ -41,6 +41,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import ch.ethz.seb.sebserver.gbl.Constants; 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.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
@ -85,10 +86,13 @@ public final class ClientConnectionTable {
private final Table table; private final Table table;
private final ColorData colorData; private final ColorData colorData;
private final EnumSet<ConnectionStatus> statusFilter; private final EnumSet<ConnectionStatus> statusFilter;
private String statusFilterParam = "";
private boolean statusFilterChanged = false;
private int tableWidth; private int tableWidth;
private boolean needsSort = false; private boolean needsSort = false;
private LinkedHashMap<Long, UpdatableTableItem> tableMapping; private LinkedHashMap<Long, UpdatableTableItem> tableMapping;
private final Set<Long> toDelete = new HashSet<>();
private final MultiValueMap<String, Long> sessionIds; private final MultiValueMap<String, Long> sessionIds;
private final Color darkFontColor; private final Color darkFontColor;
@ -180,39 +184,6 @@ public final class ClientConnectionTable {
saveStatusFilter(); saveStatusFilter();
} }
private void saveStatusFilter() {
try {
this.resourceService
.getCurrentUser()
.putAttribute(
USER_SESSION_STATUS_FILTER_ATTRIBUTE,
StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR));
} catch (final Exception e) {
log.warn("Failed to save status filter to user session");
}
}
private void loadStatusFilter() {
try {
final String attribute = this.resourceService
.getCurrentUser()
.getAttribute(USER_SESSION_STATUS_FILTER_ATTRIBUTE);
if (attribute != null) {
this.statusFilter.clear();
Arrays.asList(StringUtils.split(attribute, Constants.LIST_SEPARATOR))
.forEach(name -> this.statusFilter.add(ConnectionStatus.valueOf(name)));
} else {
this.statusFilter.clear();
this.statusFilter.add(ConnectionStatus.DISABLED);
}
} catch (final Exception e) {
log.warn("Failed to load status filter to user session");
this.statusFilter.clear();
this.statusFilter.add(ConnectionStatus.DISABLED);
}
}
public void withDefaultAction(final PageAction pageAction, final PageService pageService) { public void withDefaultAction(final PageAction pageAction, final PageService pageService) {
this.table.addListener(SWT.MouseDoubleClick, event -> { this.table.addListener(SWT.MouseDoubleClick, event -> {
final Tuple<String> selection = getSingleSelection(); final Tuple<String> selection = getSingleSelection();
@ -300,7 +271,12 @@ public final class ClientConnectionTable {
} }
public void updateValues() { public void updateValues() {
if (this.statusFilterChanged) {
this.toDelete.clear();
this.toDelete.addAll(this.tableMapping.keySet());
}
this.restCallBuilder this.restCallBuilder
.withHeader(API.EXAM_MONITORING_STATE_FILTER, this.statusFilterParam)
.call() .call()
.get(error -> { .get(error -> {
log.error("Error poll connection data: ", error); log.error("Error poll connection data: ", error);
@ -312,7 +288,21 @@ public final class ClientConnectionTable {
data.getConnectionId(), data.getConnectionId(),
connectionId -> new UpdatableTableItem(connectionId)); connectionId -> new UpdatableTableItem(connectionId));
tableItem.push(data); tableItem.push(data);
if (this.statusFilterChanged) {
this.toDelete.remove(data.getConnectionId());
}
}); });
if (this.statusFilterChanged && !this.toDelete.isEmpty()) {
this.toDelete.stream().forEach(id -> {
final UpdatableTableItem item = this.tableMapping.remove(id);
final List<Long> list = this.sessionIds.get(item.connectionData.clientConnection.userSessionId);
if (list != null) {
list.remove(id);
}
});
this.statusFilterChanged = false;
}
} }
public void updateGUI() { public void updateGUI() {
@ -370,6 +360,45 @@ public final class ClientConnectionTable {
(e1, e2) -> e1, LinkedHashMap::new)); (e1, e2) -> e1, LinkedHashMap::new));
} }
private void saveStatusFilter() {
try {
this.resourceService
.getCurrentUser()
.putAttribute(
USER_SESSION_STATUS_FILTER_ATTRIBUTE,
StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR));
} catch (final Exception e) {
log.warn("Failed to save status filter to user session");
} finally {
this.statusFilterParam = StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR);
this.statusFilterChanged = true;
}
}
private void loadStatusFilter() {
try {
final String attribute = this.resourceService
.getCurrentUser()
.getAttribute(USER_SESSION_STATUS_FILTER_ATTRIBUTE);
if (attribute != null) {
this.statusFilter.clear();
Arrays.asList(StringUtils.split(attribute, Constants.LIST_SEPARATOR))
.forEach(name -> this.statusFilter.add(ConnectionStatus.valueOf(name)));
} else {
this.statusFilter.clear();
this.statusFilter.add(ConnectionStatus.DISABLED);
}
} catch (final Exception e) {
log.warn("Failed to load status filter to user session");
this.statusFilter.clear();
this.statusFilter.add(ConnectionStatus.DISABLED);
} finally {
this.statusFilterParam = StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR);
this.statusFilterChanged = true;
}
}
private final class UpdatableTableItem implements Comparable<UpdatableTableItem> { private final class UpdatableTableItem implements Comparable<UpdatableTableItem> {
final Long connectionId; final Long connectionId;
@ -567,8 +596,12 @@ public final class ClientConnectionTable {
this.connectionData = connectionData; this.connectionData = connectionData;
if (!this.duplicateChecked && StringUtils.isNotBlank(connectionData.clientConnection.userSessionId)) { if (!this.duplicateChecked &&
ClientConnectionTable.this.sessionIds.add(connectionData.clientConnection.userSessionId, this.connectionData.clientConnection.status != ConnectionStatus.DISABLED &&
StringUtils.isNotBlank(connectionData.clientConnection.userSessionId)) {
ClientConnectionTable.this.sessionIds.add(
connectionData.clientConnection.userSessionId,
this.connectionId); this.connectionId);
this.duplicateChecked = true; this.duplicateChecked = true;
} }

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.util.Result;
public interface ExamAdminService {
/** Adds a default indicator that is defined by configuration to a given exam.
*
* @param exam The Exam to add the default indicator
* @return the Exam with added default indicator */
Result<Exam> addDefaultIndicator(final Exam exam);
/** Applies all additional SEB restriction attributes that are defined by the
* type of the LMS of a given Exam to this given Exam.
*
* @param exam the Exam to apply all additional SEB restriction attributes
* @return the Exam */
Result<Exam> applyAdditionalSEBRestrictions(final Exam exam);
}

View file

@ -0,0 +1,130 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
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.OpenEdxSebRestriction;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SebRestrictionService;
@Lazy
@Service
@WebServiceProfile
public class ExamAdminServiceImpl implements ExamAdminService {
private final ExamDAO examDAO;
private final IndicatorDAO indicatorDAO;
private final AdditionalAttributesDAO additionalAttributesDAO;
private final LmsAPIService lmsAPIService;
private final JSONMapper jsonMapper;
private final String defaultIndicatorName;
private final String defaultIndicatorType;
private final String defaultIndicatorColor;
private final String defaultIndicatorThresholds;
protected ExamAdminServiceImpl(
final ExamDAO examDAO,
final IndicatorDAO indicatorDAO,
final AdditionalAttributesDAO additionalAttributesDAO,
final LmsAPIService lmsAPIService,
final JSONMapper jsonMapper,
@Value("${sebserver.webservice.api.exam.indicator.name:Ping}") final String defaultIndicatorName,
@Value("${sebserver.webservice.api.exam.indicator.type:LAST_PING}") final String defaultIndicatorType,
@Value("${sebserver.webservice.api.exam.indicator.color:b4b4b4}") final String defaultIndicatorColor,
@Value("${sebserver.webservice.api.exam.indicator.thresholds:[{\"value\":2000.0,\"color\":\"22b14c\"},{\"value\":5000.0,\"color\":\"ff7e00\"},{\"value\":10000.0,\"color\":\"ed1c24\"}]}") final String defaultIndicatorThresholds) {
this.examDAO = examDAO;
this.indicatorDAO = indicatorDAO;
this.additionalAttributesDAO = additionalAttributesDAO;
this.lmsAPIService = lmsAPIService;
this.jsonMapper = jsonMapper;
this.defaultIndicatorName = defaultIndicatorName;
this.defaultIndicatorType = defaultIndicatorType;
this.defaultIndicatorColor = defaultIndicatorColor;
this.defaultIndicatorThresholds = defaultIndicatorThresholds;
}
@Override
public Result<Exam> addDefaultIndicator(final Exam exam) {
return Result.tryCatch(() -> {
final Collection<Indicator.Threshold> thresholds = this.jsonMapper.readValue(
this.defaultIndicatorThresholds,
new TypeReference<Collection<Indicator.Threshold>>() {
});
final Indicator indicator = new Indicator(
null,
exam.id,
this.defaultIndicatorName,
IndicatorType.valueOf(this.defaultIndicatorType),
this.defaultIndicatorColor,
thresholds);
this.indicatorDAO.createNew(indicator)
.getOrThrow();
return this.examDAO
.byPK(exam.id)
.getOrThrow();
});
}
@Override
public Result<Exam> applyAdditionalSEBRestrictions(final Exam exam) {
return Result.tryCatch(() -> {
final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(exam.lmsSetupId)
.getOrThrow();
if (lmsSetup.lmsType == LmsType.OPEN_EDX) {
final List<String> permissions = Arrays.asList(
OpenEdxSebRestriction.PermissionComponent.ALWAYS_ALLOW_STUFF.key,
OpenEdxSebRestriction.PermissionComponent.CHECK_CONFIG_KEY.key);
this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM,
exam.id,
SebRestrictionService.SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX +
OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS,
StringUtils.join(permissions, Constants.LIST_SEPARATOR_CHAR))
.getOrThrow();
}
return this.examDAO
.byPK(exam.id)
.getOrThrow();
});
}
}

View file

@ -28,6 +28,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
@ -180,7 +181,7 @@ final class MoodleRestTemplateFactory {
private CharSequence accessToken = null; private CharSequence accessToken = null;
private final Map<String, String> tokenReqURIVars; private final Map<String, String> tokenReqURIVars;
private final HttpEntity<?> tokenReqEntity = new HttpEntity<>(null); private final HttpEntity<?> tokenReqEntity = new HttpEntity<>(new LinkedMultiValueMap<>());
protected MoodleAPIRestTemplate( protected MoodleAPIRestTemplate(
@ -272,7 +273,7 @@ final class MoodleRestTemplateFactory {
functionReqEntity = new HttpEntity<>(body, headers); functionReqEntity = new HttpEntity<>(body, headers);
} else { } else {
functionReqEntity = new HttpEntity<>(null); functionReqEntity = new HttpEntity<>(new LinkedMultiValueMap<>());
} }
final ResponseEntity<String> response = super.exchange( final ResponseEntity<String> response = super.exchange(

View file

@ -15,6 +15,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -133,20 +134,19 @@ public class SebInstructionServiceImpl implements SebInstructionService {
.append(Constants.COLON) .append(Constants.COLON)
.append(Constants.DOUBLE_QUOTE) .append(Constants.DOUBLE_QUOTE)
.append(clientInstruction.getType()) .append(clientInstruction.getType())
.append(Constants.DOUBLE_QUOTE) .append(Constants.DOUBLE_QUOTE);
.append(Constants.COMMA)
if (StringUtils.isNotBlank(attributes)) {
sBuilder.append(Constants.COMMA)
.append(Constants.DOUBLE_QUOTE) .append(Constants.DOUBLE_QUOTE)
.append(JSON_ATTR) .append(JSON_ATTR)
.append(Constants.DOUBLE_QUOTE) .append(Constants.DOUBLE_QUOTE)
.append(Constants.COLON); .append(Constants.COLON)
if (attributes == null || attributes.isEmpty()) { .append(Constants.CURLY_BRACE_OPEN)
sBuilder.append(Constants.NULL);
} else {
sBuilder.append(Constants.CURLY_BRACE_OPEN)
.append(attributes) .append(attributes)
.append(Constants.CURLY_BRACE_CLOSE); .append(Constants.CURLY_BRACE_CLOSE);
} }
return sBuilder return sBuilder
.append(Constants.CURLY_BRACE_CLOSE) .append(Constants.CURLY_BRACE_CLOSE)
.toString(); .toString();

View file

@ -10,7 +10,6 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -37,7 +36,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException; import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
@ -49,12 +47,10 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction; import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
@ -64,11 +60,11 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.Authorization
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService; import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SebRestrictionService; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SebRestrictionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService;
@ -84,7 +80,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
private final ExamDAO examDAO; private final ExamDAO examDAO;
private final UserDAO userDAO; private final UserDAO userDAO;
private final AdditionalAttributesDAO additionalAttributesDAO; private final ExamAdminService examAdminService;
private final LmsAPIService lmsAPIService; private final LmsAPIService lmsAPIService;
private final ExamConfigService sebExamConfigService; private final ExamConfigService sebExamConfigService;
private final ExamSessionService examSessionService; private final ExamSessionService examSessionService;
@ -99,10 +95,10 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
final BeanValidationService beanValidationService, final BeanValidationService beanValidationService,
final LmsAPIService lmsAPIService, final LmsAPIService lmsAPIService,
final UserDAO userDAO, final UserDAO userDAO,
final ExamAdminService examAdminService,
final ExamConfigService sebExamConfigService, final ExamConfigService sebExamConfigService,
final ExamSessionService examSessionService, final ExamSessionService examSessionService,
final SebRestrictionService sebRestrictionService, final SebRestrictionService sebRestrictionService) {
final AdditionalAttributesDAO additionalAttributesDAO) {
super(authorization, super(authorization,
bulkActionService, bulkActionService,
@ -113,7 +109,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
this.examDAO = examDAO; this.examDAO = examDAO;
this.userDAO = userDAO; this.userDAO = userDAO;
this.additionalAttributesDAO = additionalAttributesDAO; this.examAdminService = examAdminService;
this.lmsAPIService = lmsAPIService; this.lmsAPIService = lmsAPIService;
this.sebExamConfigService = sebExamConfigService; this.sebExamConfigService = sebExamConfigService;
this.examSessionService = examSessionService; this.examSessionService = examSessionService;
@ -337,29 +333,9 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
@Override @Override
protected Result<Exam> notifyCreated(final Exam entity) { protected Result<Exam> notifyCreated(final Exam entity) {
return Result.tryCatch(() -> { return this.examAdminService
.addDefaultIndicator(entity)
final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(entity.lmsSetupId) .flatMap(this.examAdminService::applyAdditionalSEBRestrictions);
.getOrThrow();
// if we have an Open edX LMS involved, add additional initial SEB restriction attributes
if (lmsSetup.lmsType == LmsType.OPEN_EDX) {
final List<String> permissions = Arrays.asList(
OpenEdxSebRestriction.PermissionComponent.ALWAYS_ALLOW_STUFF.key,
OpenEdxSebRestriction.PermissionComponent.CHECK_CONFIG_KEY.key);
this.additionalAttributesDAO.saveAdditionalAttribute(
EntityType.EXAM,
entity.id,
SebRestrictionService.SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX +
OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS,
StringUtils.join(permissions, Constants.LIST_SEPARATOR_CHAR))
.getOrThrow();
}
return entity;
});
} }
@Override @Override

View file

@ -187,7 +187,7 @@ public class ExamMonitoringController {
examId, examId,
filterStates.isEmpty() filterStates.isEmpty()
? Objects::nonNull ? Objects::nonNull
: conn -> conn != null && filterStates.contains(conn.clientConnection.status)) : conn -> conn != null && !filterStates.contains(conn.clientConnection.status))
.getOrThrow(); .getOrThrow();
} }

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.gbl.model.exam;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
public class IndicatorTest {
@Test
public void testDefault() throws IOException {
final Indicator indicator = new Indicator(
null,
1L,
"Ping",
IndicatorType.LAST_PING,
"b4b4b4",
Arrays.asList(
new Indicator.Threshold(2000d, "22b14c"),
new Indicator.Threshold(5000d, "ff7e00"),
new Indicator.Threshold(10000d, "ed1c24")));
final JSONMapper mapper = new JSONMapper();
final String jsonString = mapper.writeValueAsString(indicator);
assertEquals(
"{\"examId\":1,\"name\":\"Ping\",\"type\":\"LAST_PING\",\"color\":\"b4b4b4\",\"thresholds\":[{\"value\":2000.0,\"color\":\"22b14c\"},{\"value\":5000.0,\"color\":\"ff7e00\"}",
jsonString);
final String threholds =
"[{\"value\":2000.0,\"color\":\"22b14c\"},{\"value\":5000.0,\"color\":\"ff7e00\"},{\"value\":10000.0,\"color\":\"ed1c24\"}]";
final Collection<Threshold> values = mapper.readValue(threholds, new TypeReference<Collection<Threshold>>() {
});
assertEquals(
"[Threshold [value=2000.0, color=22b14c], Threshold [value=5000.0, color=ff7e00], Threshold [value=10000.0, color=ed1c24]]",
values.toString());
}
}