fixed various issues
This commit is contained in:
parent
873391394a
commit
4c002b4ac2
19 changed files with 270 additions and 35 deletions
|
@ -46,7 +46,7 @@ public final class LmsSetup implements GrantEntity, Activatable {
|
|||
public enum LmsType {
|
||||
MOCKUP(Features.COURSE_API),
|
||||
OPEN_EDX(Features.COURSE_API, Features.SEB_RESTRICTION),
|
||||
MOODLE(Features.COURSE_API, Features.SEB_RESTRICTION);
|
||||
MOODLE(Features.COURSE_API /* , Features.SEB_RESTRICTION */);
|
||||
|
||||
public final EnumSet<Features> features;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ public final class LmsSetupTestResult {
|
|||
public static final String ATTR_MISSING_ATTRIBUTE = "missingLMSSetupAttribute";
|
||||
|
||||
public enum ErrorType {
|
||||
FEATURE_NOT_AVAILABLE,
|
||||
MISSING_ATTRIBUTE,
|
||||
TOKEN_REQUEST,
|
||||
QUIZ_ACCESS_API_REQUEST,
|
||||
|
@ -118,6 +119,10 @@ public final class LmsSetupTestResult {
|
|||
return new LmsSetupTestResult(new Error(ErrorType.QUIZ_RESTRICTION_API_REQUEST, message));
|
||||
}
|
||||
|
||||
public static LmsSetupTestResult ofQuizRestrictionNotAvailable() {
|
||||
return new LmsSetupTestResult(new Error(ErrorType.FEATURE_NOT_AVAILABLE, "Restriction Feature Not Available"));
|
||||
}
|
||||
|
||||
public final static class Error {
|
||||
|
||||
@JsonProperty(ATTR_ERROR_TYPE)
|
||||
|
|
|
@ -55,6 +55,7 @@ public final class ClientConnection implements GrantEntity {
|
|||
public static final String FILTER_ATTR_EXAM_ID = Domain.CLIENT_CONNECTION.ATTR_EXAM_ID;
|
||||
public static final String FILTER_ATTR_STATUS = Domain.CLIENT_CONNECTION.ATTR_STATUS;
|
||||
public static final String FILTER_ATTR_SESSION_ID = Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID;
|
||||
public static final String FILTER_ATTR_IP_STRING = Domain.CLIENT_CONNECTION.ATTR_CLIENT_ADDRESS;
|
||||
|
||||
@JsonProperty(Domain.CLIENT_CONNECTION.ATTR_ID)
|
||||
public final Long id;
|
||||
|
|
|
@ -474,7 +474,8 @@ public class ExamForm implements TemplateComposer {
|
|||
}
|
||||
|
||||
final LmsSetupTestResult lmsSetupTestResult = result.get();
|
||||
return !lmsSetupTestResult.hasError(ErrorType.QUIZ_RESTRICTION_API_REQUEST);
|
||||
return !lmsSetupTestResult.hasError(ErrorType.QUIZ_RESTRICTION_API_REQUEST)
|
||||
&& !lmsSetupTestResult.hasError(ErrorType.FEATURE_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
private void showConsistencyChecks(final Collection<APIMessage> result, final Composite parent) {
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.gui.content;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionPage;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class MonitoringExamSearchPopup {
|
||||
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.search.title");
|
||||
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.search.list.empty");
|
||||
private static final LocTextKey TABLE_COLUMN_NAME =
|
||||
new LocTextKey("sebserver.monitoring.search.list.name");
|
||||
|
||||
private final PageService pageService;
|
||||
|
||||
private final TableFilterAttribute nameFilter =
|
||||
new TableFilterAttribute(CriteriaType.TEXT, ClientConnection.FILTER_ATTR_SESSION_ID);
|
||||
|
||||
protected MonitoringExamSearchPopup(final PageService pageService) {
|
||||
this.pageService = pageService;
|
||||
}
|
||||
|
||||
public void show(final PageContext pageContext) {
|
||||
final ModalInputDialog<Void> dialog = new ModalInputDialog<>(
|
||||
pageContext.getParent().getShell(),
|
||||
this.pageService.getWidgetFactory());
|
||||
dialog.setLargeDialogWidth();
|
||||
dialog.open(
|
||||
TITLE_TEXT_KEY,
|
||||
pageContext,
|
||||
pc -> this.compose(pc, dialog));
|
||||
}
|
||||
|
||||
private void compose(final PageContext pageContext, final ModalInputDialog<Void> dialog) {
|
||||
final EntityKey examKey = pageContext.getEntityKey();
|
||||
|
||||
final RestService restService = this.pageService.getRestService();
|
||||
final PageActionBuilder actionBuilder = this.pageService
|
||||
.pageActionBuilder(pageContext.clearEntityKeys());
|
||||
|
||||
final EntityTable<ClientConnection> table =
|
||||
this.pageService.entityTableBuilder(restService.getRestCall(GetClientConnectionPage.class))
|
||||
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
|
||||
.withPaging(10)
|
||||
.withStaticFilter(ClientConnection.FILTER_ATTR_EXAM_ID, examKey.modelId)
|
||||
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
|
||||
TABLE_COLUMN_NAME,
|
||||
ClientConnection::getUserSessionId)
|
||||
.withFilter(this.nameFilter))
|
||||
.withDefaultAction(t -> actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
||||
.withParentEntityKey(examKey)
|
||||
.withExec(action -> showClientConnection(action, dialog, t))
|
||||
.create())
|
||||
|
||||
.compose(pageContext);
|
||||
}
|
||||
|
||||
private PageAction showClientConnection(
|
||||
final PageAction pageAction,
|
||||
final ModalInputDialog<Void> dialog,
|
||||
final EntityTable<ClientConnection> table) {
|
||||
|
||||
final ClientConnection singleSelectedROWData = table.getSingleSelectedROWData();
|
||||
dialog.close();
|
||||
return pageAction
|
||||
.withEntityKey(new EntityKey(
|
||||
singleSelectedROWData.id,
|
||||
EntityType.CLIENT_CONNECTION))
|
||||
.withAttribute(
|
||||
Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN,
|
||||
singleSelectedROWData.getConnectionToken());
|
||||
}
|
||||
|
||||
}
|
|
@ -125,16 +125,18 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
private final ResourceService resourceService;
|
||||
private final InstructionProcessor instructionProcessor;
|
||||
private final GuiServiceInfo guiServiceInfo;
|
||||
private final MonitoringExamSearchPopup monitoringExamSearchPopup;
|
||||
private final ProctorRoomConnectionsPopup proctorRoomConnectionsPopup;
|
||||
private final long pollInterval;
|
||||
private final long proctoringRoomUpdateInterval;
|
||||
private final String remoteProctoringEndpoint;
|
||||
private final ProctorRoomConnectionsPopup proctorRoomConnectionsPopup;
|
||||
|
||||
protected MonitoringRunningExam(
|
||||
final ServerPushService serverPushService,
|
||||
final PageService pageService,
|
||||
final InstructionProcessor instructionProcessor,
|
||||
final GuiServiceInfo guiServiceInfo,
|
||||
final MonitoringExamSearchPopup monitoringExamSearchPopup,
|
||||
final ProctorRoomConnectionsPopup proctorRoomConnectionsPopup,
|
||||
@Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval,
|
||||
@Value("${sebserver.gui.remote.proctoring.entrypoint:/remote-proctoring}") final String remoteProctoringEndpoint,
|
||||
|
@ -146,6 +148,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
this.instructionProcessor = instructionProcessor;
|
||||
this.guiServiceInfo = guiServiceInfo;
|
||||
this.pollInterval = pollInterval;
|
||||
this.monitoringExamSearchPopup = monitoringExamSearchPopup;
|
||||
this.remoteProctoringEndpoint = remoteProctoringEndpoint;
|
||||
this.proctorRoomConnectionsPopup = proctorRoomConnectionsPopup;
|
||||
this.proctoringRoomUpdateInterval = proctoringRoomUpdateInterval;
|
||||
|
@ -243,6 +246,12 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
.noEventPropagation()
|
||||
.publishIf(privilege)
|
||||
|
||||
.newAction(ActionDefinition.MONITORING_EXAM_SEARCH_CONNECTIONS)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this::openSearchPopup)
|
||||
.noEventPropagation()
|
||||
.publishIf(privilege)
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_QUIT_SELECTED)
|
||||
.withEntityKey(entityKey)
|
||||
.withConfirm(() -> CONFIRM_QUIT_SELECTED)
|
||||
|
@ -391,6 +400,11 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
return townhall != null && townhall.id != null;
|
||||
}
|
||||
|
||||
private PageAction openSearchPopup(final PageAction action) {
|
||||
this.monitoringExamSearchPopup.show(action.pageContext());
|
||||
return action;
|
||||
}
|
||||
|
||||
private PageAction toggleTownhallRoom(final PageAction action) {
|
||||
if (isTownhallRoomActive(action.getEntityKey().modelId)) {
|
||||
closeTownhallRoom(action);
|
||||
|
|
|
@ -699,6 +699,17 @@ public enum ActionDefinition {
|
|||
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
|
||||
ActionCategory.FILTER),
|
||||
|
||||
MONITORING_EXAM_SEARCH_CONNECTIONS(
|
||||
new LocTextKey("sebserver.monitoring.search.action"),
|
||||
ImageIcon.SEARCH,
|
||||
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
|
||||
ActionCategory.FORM),
|
||||
MONITORING_EXAM_SEARCH_VIEW_CONNECTION(
|
||||
new LocTextKey("sebserver.monitoring.search.action.view"),
|
||||
ImageIcon.SEARCH,
|
||||
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
|
||||
ActionCategory.CLIENT_EVENT_LIST),
|
||||
|
||||
MONITOR_EXAM_NEW_PROCTOR_ROOM(
|
||||
new LocTextKey("sebserver.monitoring.exam.action.newroom"),
|
||||
ImageIcon.VISIBILITY,
|
||||
|
|
|
@ -170,16 +170,16 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
final Consumer<PageContext> contentComposer) {
|
||||
|
||||
// Create the info dialog window
|
||||
final Shell shell = new Shell(getParent(), getStyle());
|
||||
shell.setText(getText());
|
||||
shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||
shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||
shell.setLayout(new GridLayout());
|
||||
this.shell = new Shell(getParent(), getStyle());
|
||||
this.shell.setText(getText());
|
||||
this.shell.setData(RWT.CUSTOM_VARIANT, CustomVariant.MESSAGE.key);
|
||||
this.shell.setText(this.widgetFactory.getI18nSupport().getText(title));
|
||||
this.shell.setLayout(new GridLayout());
|
||||
final GridData gridData2 = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||
|
||||
shell.setLayoutData(gridData2);
|
||||
this.shell.setLayoutData(gridData2);
|
||||
|
||||
final Composite main = new Composite(shell, SWT.NONE);
|
||||
final Composite main = new Composite(this.shell, SWT.NONE);
|
||||
main.setLayout(new GridLayout());
|
||||
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||
gridData.widthHint = this.dialogWidth;
|
||||
|
@ -188,13 +188,19 @@ public class ModalInputDialog<T> extends Dialog {
|
|||
contentComposer.accept(pageContext.copyOf(main));
|
||||
gridData.heightHint = calcDialogHeight(main);
|
||||
|
||||
final Button close = this.widgetFactory.buttonLocalized(shell, CLOSE_TEXT_KEY);
|
||||
final Button close = this.widgetFactory.buttonLocalized(this.shell, CLOSE_TEXT_KEY);
|
||||
final GridData data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
|
||||
data.widthHint = this.buttonWidth;
|
||||
close.setLayoutData(data);
|
||||
close.addListener(SWT.Selection, event -> shell.close());
|
||||
close.addListener(SWT.Selection, event -> this.shell.close());
|
||||
|
||||
finishUp(shell);
|
||||
finishUp(this.shell);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (this.shell != null) {
|
||||
this.shell.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void finishUp(final Shell shell) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.gui.service.remote.webservice.api.session;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetClientConnectionPage extends RestCall<Page<ClientConnection>> {
|
||||
|
||||
public GetClientConnectionPage() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_PAGE,
|
||||
EntityType.CLIENT_CONNECTION,
|
||||
new TypeReference<Page<ClientConnection>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.SEB_CLIENT_CONNECTION_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -205,6 +205,14 @@ public class FilterMap extends POSTMapper {
|
|||
return getString(ClientConnection.FILTER_ATTR_STATUS);
|
||||
}
|
||||
|
||||
public String getClientConnectionUserId() {
|
||||
return getSQLWildcard(ClientConnection.FILTER_ATTR_SESSION_ID);
|
||||
}
|
||||
|
||||
public String getClientConnectionIPAddress() {
|
||||
return getSQLWildcard(ClientConnection.FILTER_ATTR_IP_STRING);
|
||||
}
|
||||
|
||||
public Long getClientEventConnectionId() {
|
||||
return getLong(ClientEvent.FILTER_ATTR_CONNECTION_ID);
|
||||
}
|
||||
|
|
|
@ -99,6 +99,12 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.status,
|
||||
isEqualToWhenPresent(filterMap.getClientConnectionStatus()))
|
||||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.examUserSessionId,
|
||||
isLikeWhenPresent(filterMap.getClientConnectionUserId()))
|
||||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.clientAddress,
|
||||
isLikeWhenPresent(filterMap.getClientConnectionIPAddress()))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
|
|
|
@ -118,7 +118,11 @@ public class LmsAPIServiceImpl implements LmsAPIService {
|
|||
return testCourseAccessAPI;
|
||||
}
|
||||
|
||||
return template.testCourseRestrictionAPI();
|
||||
if (template.lmsSetup().getLmsType().features.contains(LmsSetup.Features.SEB_RESTRICTION)) {
|
||||
return template.testCourseRestrictionAPI();
|
||||
} else {
|
||||
return LmsSetupTestResult.ofQuizRestrictionNotAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -149,7 +149,7 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
if (restTemplateRequest.hasError()) {
|
||||
final String message = "Failed to gain access token from Moodle Rest API:\n tried token endpoints: " +
|
||||
this.moodleRestTemplateFactory.knownTokenAccessPaths;
|
||||
log.error(message, restTemplateRequest.getError().getMessage());
|
||||
log.error(message + " cause: ", restTemplateRequest.getError());
|
||||
return LmsSetupTestResult.ofTokenRequestError(message);
|
||||
}
|
||||
|
||||
|
@ -254,13 +254,15 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
CourseQuizData.class);
|
||||
|
||||
final Map<String, CourseData> finalCourseDataRef = courseData;
|
||||
courseQuizData.quizzes
|
||||
.forEach(quiz -> {
|
||||
final CourseData course = finalCourseDataRef.get(quiz.course);
|
||||
if (course != null) {
|
||||
course.quizzes.add(quiz);
|
||||
}
|
||||
});
|
||||
if (courseQuizData.quizzes != null) {
|
||||
courseQuizData.quizzes
|
||||
.forEach(quiz -> {
|
||||
final CourseData course = finalCourseDataRef.get(quiz.course);
|
||||
if (course != null) {
|
||||
course.quizzes.add(quiz);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return courseData.values()
|
||||
.stream()
|
||||
|
@ -273,12 +275,17 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
}
|
||||
|
||||
private Predicate<CourseData> getCourseFilter(final long from) {
|
||||
final long now = DateTime.now(DateTimeZone.UTC).getMillis();
|
||||
return course -> course.time_created == null
|
||||
|| course.time_created.longValue() > from
|
||||
|| (course.end_date == null
|
||||
|| (course.end_date <= 0
|
||||
|| course.end_date > now));
|
||||
final long now = DateTime.now(DateTimeZone.UTC).getMillis() / 1000;
|
||||
return course -> {
|
||||
if (course.end_date != null && course.end_date > 0 && course.end_date < now) {
|
||||
return false;
|
||||
}
|
||||
if (course.time_created != null && course.time_created.longValue() < from) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
private Collection<CourseData> getCoursesPage(
|
||||
|
@ -287,7 +294,7 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
final int size) throws JsonParseException, JsonMappingException, IOException {
|
||||
|
||||
try {
|
||||
final long aYearAgo = DateTime.now(DateTimeZone.UTC).minusYears(1).getMillis();
|
||||
final long aYearAgo = DateTime.now(DateTimeZone.UTC).minusYears(1).getMillis() / 1000;
|
||||
// get course ids per page
|
||||
final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>();
|
||||
attributes.add(MOODLE_COURSE_API_SEARCH_CRITERIA_NAME, "search");
|
||||
|
|
|
@ -64,7 +64,6 @@ public class MoodleCourseRestriction {
|
|||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION_CREATE = "seb_restriction_create";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION_UPDATE = "seb_restriction_update";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_WS_FUNCTION_DELETE = "seb_restriction_delete";
|
||||
//private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_COURSE_ID = "courseId";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_SHORT_NAME = "shortname";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_ID_NUMBER = "idnumber";
|
||||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_QUIZ_ID = "quizId";
|
||||
|
|
|
@ -29,6 +29,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails;
|
|||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException;
|
||||
|
||||
public class MoodleLmsAPITemplate implements LmsAPITemplate {
|
||||
|
||||
|
@ -60,7 +61,8 @@ public class MoodleLmsAPITemplate implements LmsAPITemplate {
|
|||
|
||||
@Override
|
||||
public LmsSetupTestResult testCourseRestrictionAPI() {
|
||||
return this.moodleCourseRestriction.initAPIAccess();
|
||||
throw new NoSEBRestrictionException();
|
||||
//return this.moodleCourseRestriction.initAPIAccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,8 @@ import java.util.function.Function;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
@ -50,6 +52,8 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
|
|||
|
||||
class MoodleRestTemplateFactory {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MoodleRestTemplateFactory.class);
|
||||
|
||||
final JSONMapper jsonMapper;
|
||||
final LmsSetup lmsSetup;
|
||||
final ClientCredentials credentials;
|
||||
|
@ -113,6 +117,12 @@ class MoodleRestTemplateFactory {
|
|||
return this.knownTokenAccessPaths
|
||||
.stream()
|
||||
.map(this::createRestTemplate)
|
||||
.map(result -> {
|
||||
if (result.hasError()) {
|
||||
log.error("Failed to get access token: ", result.getError());
|
||||
}
|
||||
return result;
|
||||
})
|
||||
.filter(Result::hasValue)
|
||||
.findFirst()
|
||||
.orElse(Result.ofRuntimeError(
|
||||
|
|
|
@ -61,7 +61,7 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato
|
|||
return errors.doubleValue();
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to get indicator count from persistent storage: ", e);
|
||||
return this.currentValue;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
|
|||
|
||||
import static org.mybatis.dynamic.sql.SqlBuilder.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||
|
@ -64,12 +65,17 @@ public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator {
|
|||
.execute();
|
||||
|
||||
if (execute == null || execute.isEmpty()) {
|
||||
return this.currentValue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return execute.get(execute.size() - 1).getNumericValue().doubleValue();
|
||||
final BigDecimal numericValue = execute.get(execute.size() - 1).getNumericValue();
|
||||
if (numericValue != null) {
|
||||
return numericValue.doubleValue();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to get indicator number from persistent storage: ", e);
|
||||
log.error("Failed to get indicator number from persistent storage: {}", e.getMessage());
|
||||
return this.currentValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1498,6 +1498,12 @@ sebserver.monitoring.connection.form.status.tooltip=The current connection statu
|
|||
sebserver.monitoring.connection.form.exam=Exam
|
||||
sebserver.monitoring.connection.form.exam.tooltip=The exam name
|
||||
|
||||
sebserver.monitoring.search.title=Search Connections
|
||||
sebserver.monitoring.search.action=Search
|
||||
sebserver.monitoring.search.list.empty=No Client Connections available
|
||||
sebserver.monitoring.search.list.name=Session or User Name
|
||||
|
||||
|
||||
sebserver.monitoring.exam.connection.emptySelection=At first please select a Connection from the list
|
||||
sebserver.monitoring.exam.connection.emptySelection.active=At first please select an active Connection from the list
|
||||
sebserver.monitoring.exam.connection.title=SEB Client Connection
|
||||
|
|
Loading…
Add table
Reference in a new issue