SEBSERV-240 implementation
This commit is contained in:
parent
ebbbf56314
commit
5b3648bcee
12 changed files with 389 additions and 44 deletions
|
@ -32,7 +32,7 @@ public interface IndicatorValue extends IndicatorValueHolder {
|
|||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
if (type.integerValue) {
|
||||
return String.valueOf((int) indicatorValue.getValue());
|
||||
return String.valueOf((long) indicatorValue.getValue());
|
||||
} else {
|
||||
return String.valueOf(indicatorValue.getValue());
|
||||
}
|
||||
|
|
|
@ -835,11 +835,21 @@ public enum ActionDefinition {
|
|||
FINISHED_EXAM_VIEW_LIST(
|
||||
new LocTextKey("sebserver.finished.action.list"),
|
||||
PageStateDefinitionImpl.FINISHED_EXAM_LIST),
|
||||
VIEW_EXAM_FROM_FINISHED_LIST(
|
||||
VIEW_FINISHED_EXAM_FROM_LIST(
|
||||
new LocTextKey("sebserver.finished.exam.action.list.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.FINISHED_EXAM,
|
||||
ActionCategory.FINISHED_EXAM_LIST),
|
||||
VIEW_FINISHED_EXAM_CLIENT_CONNECTION(
|
||||
new LocTextKey("sebserver.finished.exam.connection.action.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.FINISHED_CLIENT_CONNECTION,
|
||||
ActionCategory.CLIENT_EVENT_LIST),
|
||||
FINISHED_EXAM_BACK_TO_OVERVIEW(
|
||||
new LocTextKey("sebserver.finished.exam.action.detail.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.FINISHED_EXAM,
|
||||
ActionCategory.FORM),
|
||||
|
||||
LOGS_USER_ACTIVITY_LIST(
|
||||
new LocTextKey("sebserver.logs.activity.userlogs"),
|
||||
|
|
|
@ -34,6 +34,7 @@ import ch.ethz.seb.sebserver.gui.content.exam.LmsSetupForm;
|
|||
import ch.ethz.seb.sebserver.gui.content.exam.LmsSetupList;
|
||||
import ch.ethz.seb.sebserver.gui.content.exam.QuizLookupList;
|
||||
import ch.ethz.seb.sebserver.gui.content.monitoring.FinishedExam;
|
||||
import ch.ethz.seb.sebserver.gui.content.monitoring.FinishedExamClientConnection;
|
||||
import ch.ethz.seb.sebserver.gui.content.monitoring.FinishedExamList;
|
||||
import ch.ethz.seb.sebserver.gui.content.monitoring.MonitoringClientConnection;
|
||||
import ch.ethz.seb.sebserver.gui.content.monitoring.MonitoringRunningExam;
|
||||
|
@ -100,7 +101,7 @@ public enum PageStateDefinitionImpl implements PageStateDefinition {
|
|||
|
||||
FINISHED_EXAM_LIST(Type.LIST_VIEW, FinishedExamList.class, ActivityDefinition.FINISHED_EXAMS),
|
||||
FINISHED_EXAM(Type.FORM_VIEW, FinishedExam.class, ActivityDefinition.FINISHED_EXAMS),
|
||||
FINISHED_CLIENT_CONNECTION(Type.FORM_VIEW, MonitoringClientConnection.class, ActivityDefinition.FINISHED_EXAMS),
|
||||
FINISHED_CLIENT_CONNECTION(Type.FORM_VIEW, FinishedExamClientConnection.class, ActivityDefinition.FINISHED_EXAMS),
|
||||
|
||||
USER_ACTIVITY_LOGS(Type.LIST_VIEW, UserActivityLogs.class, ActivityDefinition.USER_ACTIVITY_LOGS),
|
||||
SEB_CLIENT_LOGS(Type.LIST_VIEW, SEBClientEvents.class, ActivityDefinition.SEB_CLIENT_LOGS)
|
||||
|
|
|
@ -244,10 +244,9 @@ public class ExamForm implements TemplateComposer {
|
|||
final boolean modifyGrant = userGrantCheck.m();
|
||||
final boolean writeGrant = userGrantCheck.w();
|
||||
final ExamStatus examStatus = exam.getStatus();
|
||||
final boolean editable = modifyGrant && (examStatus == ExamStatus.UP_COMING ||
|
||||
examStatus == ExamStatus.RUNNING);
|
||||
final boolean editable = modifyGrant &&
|
||||
(examStatus == ExamStatus.UP_COMING || examStatus == ExamStatus.RUNNING);
|
||||
|
||||
// TODO this is not performat try to improve by doing one check with the CheckExamConsistency above
|
||||
final boolean sebRestrictionAvailable = testSEBRestrictionAPI(exam);
|
||||
final boolean isRestricted = readonly && sebRestrictionAvailable && this.restService
|
||||
.getBuilder(CheckSEBRestriction.class)
|
||||
|
@ -408,6 +407,11 @@ public class ExamForm implements TemplateComposer {
|
|||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && readonly && editable)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_DELETE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examDeletePopup.deleteWizardFunction(pageContext))
|
||||
.publishIf(() -> writeGrant && readonly)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_SAVE)
|
||||
.withExec(action -> (importFromQuizData)
|
||||
? importExam(action, formHandle, sebRestrictionAvailable && exam.status == ExamStatus.RUNNING)
|
||||
|
@ -451,20 +455,15 @@ public class ExamForm implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.EXAM_PROCTORING_ON)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examProctoringSettings.settingsFunction(this.pageService, modifyGrant))
|
||||
.withExec(this.examProctoringSettings.settingsFunction(this.pageService, modifyGrant && editable))
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> editable && proctoringEnabled && readonly)
|
||||
.publishIf(() -> proctoringEnabled && readonly)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_PROCTORING_OFF)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examProctoringSettings.settingsFunction(this.pageService, modifyGrant))
|
||||
.withExec(this.examProctoringSettings.settingsFunction(this.pageService, modifyGrant && editable))
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> editable && !proctoringEnabled && readonly)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_DELETE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.examDeletePopup.deleteWizardFunction(pageContext))
|
||||
.publishIf(() -> writeGrant && readonly);
|
||||
.publishIf(() -> !proctoringEnabled && readonly);
|
||||
|
||||
// additional data in read-only view
|
||||
if (readonly && !importFromQuizData) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package ch.ethz.seb.sebserver.gui.content.monitoring;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
@ -17,26 +18,34 @@ 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.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.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
|
||||
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.GetIndicators;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetFinishedExamClientConnectionPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
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.TableBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||
|
||||
|
@ -45,6 +54,8 @@ import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
|||
@GuiProfile
|
||||
public class FinishedExam implements TemplateComposer {
|
||||
|
||||
private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.emptySelection");
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connections.title");
|
||||
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
|
@ -64,7 +75,6 @@ public class FinishedExam implements TemplateComposer {
|
|||
|
||||
private final PageService pageService;
|
||||
private final RestService restService;
|
||||
private final ResourceService resourceService;
|
||||
private final int pageSize;
|
||||
|
||||
public FinishedExam(
|
||||
|
@ -74,7 +84,6 @@ public class FinishedExam implements TemplateComposer {
|
|||
|
||||
this.pageService = pageService;
|
||||
this.restService = pageService.getRestService();
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.statusFilter = new TableFilterAttribute(
|
||||
|
@ -86,19 +95,29 @@ public class FinishedExam implements TemplateComposer {
|
|||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final EntityKey examKey = pageContext.getEntityKey();
|
||||
final CurrentUser currentUser = this.pageService.getResourceService().getCurrentUser();
|
||||
final UserInfo user = currentUser.get();
|
||||
|
||||
final RestService restService = this.pageService.getRestService();
|
||||
final RestService restService = this.pageService
|
||||
.getRestService();
|
||||
final PageActionBuilder actionBuilder = this.pageService
|
||||
.pageActionBuilder(pageContext.clearEntityKeys());
|
||||
|
||||
final Collection<Indicator> indicators = restService.getBuilder(GetIndicators.class)
|
||||
final Collection<Indicator> indicators = restService
|
||||
.getBuilder(GetIndicators.class)
|
||||
.withQueryParam(Indicator.FILTER_ATTR_EXAM_ID, examKey.modelId)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
final Exam exam = this.restService.getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, examKey.modelId)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
final boolean supporting = user.hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||
exam.supporter.contains(user.uuid);
|
||||
final BooleanSupplier isExamSupporter = () -> supporting || user.hasRole(UserRole.EXAM_ADMIN);
|
||||
|
||||
final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
TITLE_TEXT_KEY);
|
||||
new LocTextKey(TITLE_TEXT_KEY.name, exam.getName()));
|
||||
|
||||
final TableBuilder<ClientConnectionData> tableBuilder =
|
||||
this.pageService.entityTableBuilder(restService.getRestCall(GetFinishedExamClientConnectionPage.class))
|
||||
|
@ -126,21 +145,30 @@ public class FinishedExam implements TemplateComposer {
|
|||
.withFilter(this.statusFilter))
|
||||
|
||||
.withDefaultAction(t -> actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
||||
.newAction(ActionDefinition.VIEW_FINISHED_EXAM_CLIENT_CONNECTION)
|
||||
.withParentEntityKey(examKey)
|
||||
.create());
|
||||
|
||||
indicators.stream().forEach(indicator -> {
|
||||
tableBuilder.withColumn(new ColumnDefinition<>(
|
||||
indicator.name,
|
||||
new LocTextKey(indicator.name),
|
||||
indicatorValueFunction(indicator)));
|
||||
if (indicator.type != IndicatorType.LAST_PING) {
|
||||
tableBuilder.withColumn(new ColumnDefinition<>(
|
||||
indicator.name,
|
||||
new LocTextKey(indicator.name),
|
||||
indicatorValueFunction(indicator)));
|
||||
}
|
||||
});
|
||||
|
||||
tableBuilder.compose(pageContext.copyOf(content));
|
||||
final EntityTable<ClientConnectionData> table = tableBuilder.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.VIEW_FINISHED_EXAM_CLIENT_CONNECTION)
|
||||
.withParentEntityKey(examKey)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(isExamSupporter, false);
|
||||
}
|
||||
|
||||
private Function<ClientConnectionData, String> indicatorValueFunction(final Indicator indicator) {
|
||||
public Function<ClientConnectionData, String> indicatorValueFunction(final Indicator indicator) {
|
||||
return clientConnectionData -> {
|
||||
return clientConnectionData.indicatorValues
|
||||
.stream()
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* 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.monitoring;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.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.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
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.FormBuilder;
|
||||
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.GetIndicators;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetExtendedClientEventPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetFinishedExamClientConnection;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.table.TableFilter.CriteriaType;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class FinishedExamClientConnection implements TemplateComposer {
|
||||
|
||||
private static final LocTextKey PAGE_TITLE_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.title");
|
||||
|
||||
private final static LocTextKey EXAM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.connection.form.exam");
|
||||
private final static LocTextKey CONNECTION_ID_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.connection.form.id");
|
||||
private final static LocTextKey CONNECTION_INFO_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.connection.form.info");
|
||||
private final static LocTextKey CONNECTION_STATUS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.connection.form.status");
|
||||
|
||||
private static final LocTextKey EVENT_LIST_TITLE_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.title");
|
||||
private static final LocTextKey EVENT_LIST_TITLE_TOOLTIP_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.title.tooltip");
|
||||
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.empty");
|
||||
private static final LocTextKey LIST_COLUMN_TYPE_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.type");
|
||||
|
||||
private static final LocTextKey LIST_COLUMN_CLIENT_TIME_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.clienttime");
|
||||
private static final LocTextKey LIST_COLUMN_SERVER_TIME_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.servertime");
|
||||
private static final LocTextKey LIST_COLUMN_VALUE_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.value");
|
||||
private static final LocTextKey LIST_COLUMN_TEXT_KEY =
|
||||
new LocTextKey("sebserver.finished.exam.connection.eventlist.text");
|
||||
|
||||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
private final I18nSupport i18nSupport;
|
||||
private final SEBClientEventDetailsPopup sebClientLogDetailsPopup;
|
||||
private final int pageSize;
|
||||
|
||||
private final TableFilterAttribute typeFilter;
|
||||
private final TableFilterAttribute textFilter =
|
||||
new TableFilterAttribute(CriteriaType.TEXT, ClientEvent.FILTER_ATTR_TEXT);
|
||||
|
||||
protected FinishedExamClientConnection(
|
||||
final PageService pageService,
|
||||
final SEBClientEventDetailsPopup sebClientLogDetailsPopup,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.i18nSupport = this.resourceService.getI18nSupport();
|
||||
this.sebClientLogDetailsPopup = sebClientLogDetailsPopup;
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.typeFilter = new TableFilterAttribute(
|
||||
CriteriaType.SINGLE_SELECTION,
|
||||
Domain.CLIENT_EVENT.ATTR_TYPE,
|
||||
this.resourceService::clientEventTypeResources);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final RestService restService = this.resourceService.getRestService();
|
||||
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
|
||||
final CurrentUser currentUser = this.resourceService.getCurrentUser();
|
||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
|
||||
// content page layout with title
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
PAGE_TITLE_KEY);
|
||||
final Exam exam = restService
|
||||
.getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error))
|
||||
.getOrThrow();
|
||||
final UserInfo user = currentUser.get();
|
||||
final boolean supporting = user.hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||
exam.supporter.contains(user.uuid);
|
||||
final BooleanSupplier isExamSupporter = () -> supporting || user.hasRole(UserRole.EXAM_ADMIN);
|
||||
final Collection<Indicator> indicators = restService
|
||||
.getBuilder(GetIndicators.class)
|
||||
.withQueryParam(Indicator.FILTER_ATTR_EXAM_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
final ClientConnectionData connectionData = restService
|
||||
.getBuilder(GetFinishedExamClientConnection.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.getOrThrow();
|
||||
|
||||
final FormBuilder formBuilder = this.pageService.formBuilder(pageContext.copyOf(content))
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_NAME,
|
||||
EXAM_NAME_TEXT_KEY,
|
||||
exam.getName()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
|
||||
CONNECTION_ID_TEXT_KEY,
|
||||
connectionData.clientConnection.userSessionId))
|
||||
.addField(FormBuilder.text(
|
||||
ClientConnection.ATTR_INFO,
|
||||
CONNECTION_INFO_TEXT_KEY,
|
||||
connectionData.clientConnection.info))
|
||||
.withDefaultSpanInput(3)
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_STATUS,
|
||||
CONNECTION_STATUS_TEXT_KEY,
|
||||
this.resourceService.localizedClientConnectionStatusName(
|
||||
connectionData.clientConnection.status))
|
||||
.asColorBox())
|
||||
.addEmptyCell();
|
||||
|
||||
indicators.forEach(indicator -> formBuilder.addField(FormBuilder.text(
|
||||
indicator.name,
|
||||
new LocTextKey(indicator.name),
|
||||
connectionData.indicatorValues
|
||||
.stream()
|
||||
.filter(indicatorValue -> indicatorValue.getIndicatorId().equals(indicator.id))
|
||||
.findFirst()
|
||||
.map(iv -> IndicatorValue.getDisplayValue(iv, indicator.type))
|
||||
.orElse(Constants.EMPTY_NOTE))
|
||||
.asColorBox()
|
||||
.withDefaultLabel(indicator.name))
|
||||
.addEmptyCell());
|
||||
|
||||
formBuilder.build();
|
||||
|
||||
// CLIENT EVENTS
|
||||
final PageService.PageActionBuilder actionBuilder = this.pageService
|
||||
.pageActionBuilder(
|
||||
pageContext
|
||||
.clearAttributes()
|
||||
.clearEntityKeys());
|
||||
|
||||
widgetFactory.addFormSubContextHeader(
|
||||
content,
|
||||
EVENT_LIST_TITLE_KEY,
|
||||
EVENT_LIST_TITLE_TOOLTIP_KEY);
|
||||
|
||||
// client event table for this connection
|
||||
this.pageService
|
||||
.entityTableBuilder(
|
||||
"seb-client-" + connectionData.getModelId(),
|
||||
restService.getRestCall(GetExtendedClientEventPage.class))
|
||||
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
|
||||
.withPaging(this.pageSize)
|
||||
.withRestCallAdapter(restCallBuilder -> restCallBuilder.withQueryParam(
|
||||
ClientEvent.FILTER_ATTR_CONNECTION_ID,
|
||||
entityKey.modelId))
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_TYPE,
|
||||
LIST_COLUMN_TYPE_KEY,
|
||||
this.resourceService::getEventTypeName)
|
||||
.withFilter(this.typeFilter)
|
||||
.sortable()
|
||||
.widthProportion(2))
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_TEXT,
|
||||
LIST_COLUMN_TEXT_KEY,
|
||||
ClientEvent::getText)
|
||||
.withFilter(this.textFilter)
|
||||
.sortable()
|
||||
.withCellTooltip()
|
||||
.widthProportion(4))
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_NUMERIC_VALUE,
|
||||
LIST_COLUMN_VALUE_KEY,
|
||||
ClientEvent::getValue)
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_CLIENT_TIME,
|
||||
new LocTextKey(LIST_COLUMN_CLIENT_TIME_KEY.name,
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()),
|
||||
this::getClientTime)
|
||||
.sortable()
|
||||
.widthProportion(1))
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_SERVER_TIME,
|
||||
new LocTextKey(LIST_COLUMN_SERVER_TIME_KEY.name,
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()),
|
||||
this::getServerTime)
|
||||
.sortable()
|
||||
.widthProportion(1))
|
||||
|
||||
.withDefaultAction(t -> actionBuilder
|
||||
.newAction(ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS)
|
||||
.withExec(action -> this.sebClientLogDetailsPopup.showDetails(action,
|
||||
t.getSingleSelectedROWData()))
|
||||
.noEventPropagation()
|
||||
.create())
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.FINISHED_EXAM_BACK_TO_OVERVIEW)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.publishIf(isExamSupporter);
|
||||
}
|
||||
|
||||
private String getClientTime(final ClientEvent event) {
|
||||
if (event == null || event.getClientTime() == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return this.i18nSupport
|
||||
.formatDisplayTime(Utils.toDateTimeUTC(event.getClientTime()));
|
||||
}
|
||||
|
||||
private String getServerTime(final ClientEvent event) {
|
||||
if (event == null || event.getServerTime() == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
return this.i18nSupport
|
||||
.formatDisplayTime(Utils.toDateTimeUTC(event.getServerTime()));
|
||||
}
|
||||
|
||||
}
|
|
@ -129,18 +129,18 @@ public class FinishedExamList implements TemplateComposer {
|
|||
.sortable())
|
||||
|
||||
.withDefaultAction(actionBuilder
|
||||
.newAction(ActionDefinition.VIEW_EXAM_FROM_FINISHED_LIST)
|
||||
.newAction(ActionDefinition.VIEW_FINISHED_EXAM_FROM_LIST)
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.VIEW_EXAM_FROM_FINISHED_LIST))
|
||||
ActionDefinition.VIEW_FINISHED_EXAM_FROM_LIST))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.VIEW_EXAM_FROM_FINISHED_LIST)
|
||||
.newAction(ActionDefinition.VIEW_FINISHED_EXAM_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER), false);
|
||||
|
||||
|
|
|
@ -90,6 +90,11 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
private static final LocTextKey NOTIFICATION_LIST_COLUMN_TYPE_KEY =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.notificationlist.type");
|
||||
|
||||
private static final LocTextKey CONFIRM_QUIT =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.confirm");
|
||||
private static final LocTextKey CONFIRM_OPEN_SINGLE_ROOM =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.action.singleroom.confirm");
|
||||
|
||||
private static final LocTextKey EVENT_LIST_TITLE_KEY =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.eventlist.title");
|
||||
private static final LocTextKey EVENT_LIST_TITLE_TOOLTIP_KEY =
|
||||
|
@ -107,10 +112,6 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
new LocTextKey("sebserver.monitoring.exam.connection.eventlist.value");
|
||||
private static final LocTextKey LIST_COLUMN_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.eventlist.text");
|
||||
private static final LocTextKey CONFIRM_QUIT =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.confirm");
|
||||
private static final LocTextKey CONFIRM_OPEN_SINGLE_ROOM =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.action.singleroom.confirm");
|
||||
|
||||
private final ServerPushService serverPushService;
|
||||
private final PageService pageService;
|
||||
|
|
|
@ -70,8 +70,6 @@ import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService
|
|||
@GuiProfile
|
||||
public class MonitoringRunningExam implements TemplateComposer {
|
||||
|
||||
//private static final Logger log = LoggerFactory.getLogger(MonitoringRunningExam.class);
|
||||
|
||||
private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.emptySelection");
|
||||
private static final LocTextKey EMPTY_ACTIVE_SELECTION_TEXT_KEY =
|
||||
|
|
|
@ -55,8 +55,8 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato
|
|||
@Override
|
||||
public double computeValueAt(final long timestamp) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("computeValueAt: {}", timestamp);
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("computeValueAt: {}", timestamp);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -73,8 +73,8 @@ public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator {
|
|||
@Override
|
||||
public double computeValueAt(final long timestamp) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("computeValueAt: {}", timestamp);
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("computeValueAt: {}", timestamp);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -1831,7 +1831,6 @@ sebserver.monitoring.exam.connection.notificationlist.pleaseSelect=At first plea
|
|||
sebserver.monitoring.exam.connection.notificationlist.title=Pending Notification
|
||||
sebserver.monitoring.exam.connection.notificationlist.title.tooltip=All pending notifications sent by the SEB Client
|
||||
|
||||
|
||||
sebserver.monitoring.exam.connection.eventlist.title=Events
|
||||
sebserver.monitoring.exam.connection.eventlist.title.tooltip=All events and logs sent by the SEB Client
|
||||
sebserver.monitoring.exam.connection.eventlist.empty=No event found
|
||||
|
@ -1888,12 +1887,38 @@ sebserver.finished.exam.list.column.endTime=End Time {0}
|
|||
sebserver.finished.exam.list.column.endTime.tooltip=The end date and time of the exam<br/><br/>{0}
|
||||
sebserver.finished.exam.action.list.view=View Finished Exam
|
||||
|
||||
sebserver.finished.exam.connections.title=Search Connections
|
||||
sebserver.finished.exam.connections.title=Finished Exam ({0})
|
||||
sebserver.finished.exam.connections.action=Search
|
||||
sebserver.finished.exam.connections.empty=No Client Connections available
|
||||
sebserver.finished.exam.connections.name=Session or User Name
|
||||
sebserver.finished.exam.connections.info=Connection Info
|
||||
sebserver.finished.exam.connections.status=Status
|
||||
sebserver.finished.exam.connection.emptySelection=At first please select a Connection from the list
|
||||
|
||||
sebserver.finished.exam.connection.title=SEB Client Connection
|
||||
sebserver.finished.connection.form.id=User Name or Session
|
||||
sebserver.finished.connection.form.id.tooltip=The user session identifier or username sent by the SEB client after LMS login
|
||||
sebserver.finished.connection.form.info=Connection Info
|
||||
sebserver.finished.connection.form.info.tooltip=Format: IP Address,SEB Version, OSName
|
||||
sebserver.finished.connection.form.status=Status
|
||||
sebserver.finished.connection.form.status.tooltip=The current connection status
|
||||
sebserver.finished.connection.form.exam=Exam
|
||||
sebserver.finished.connection.form.exam.tooltip=The exam name
|
||||
|
||||
sebserver.finished.exam.connection.eventlist.title=Events
|
||||
sebserver.finished.exam.connection.eventlist.title.tooltip=All events and logs sent by the SEB Client
|
||||
sebserver.finished.exam.connection.eventlist.empty=No event found
|
||||
sebserver.finished.exam.connection.eventlist.type=Event Type
|
||||
sebserver.finished.exam.connection.eventlist.type.tooltip=The type of the log event<br/><br/>Use the filter above to set a specific event type<br/>{0}
|
||||
sebserver.finished.exam.connection.eventlist.clienttime=Client Time {0}
|
||||
sebserver.finished.exam.connection.eventlist.clienttime.tooltip=The time the SEB client has sent within the log event<br/><br/>{0}
|
||||
sebserver.finished.exam.connection.eventlist.servertime=Server Time {0}
|
||||
sebserver.finished.exam.connection.eventlist.servertime.tooltip=The exact time (UTC) the SEB Server has received the log event<br/><br/>{0}
|
||||
sebserver.finished.exam.connection.eventlist.value=Value
|
||||
sebserver.finished.exam.connection.eventlist.value.tooltip=The value of the log event<br/><br/>{0}
|
||||
sebserver.finished.exam.connection.eventlist.text=Text
|
||||
sebserver.finished.exam.connection.eventlist.text.tooltip=The text of the log event<br/><br/>{0}
|
||||
sebserver.finished.exam.action.detail.view=Back To Exam
|
||||
|
||||
################################
|
||||
# Logs
|
||||
|
|
Loading…
Reference in a new issue