fixed notification changes in GUI
This commit is contained in:
parent
dffb0e61f8
commit
7d647cc9c2
8 changed files with 63 additions and 35 deletions
|
@ -28,6 +28,7 @@ public class GuiServiceInfo {
|
|||
private final String contextPath;
|
||||
private final UriComponentsBuilder internalServerURIBuilder;
|
||||
private final UriComponentsBuilder externalServerURIBuilder;
|
||||
private final boolean distributedSetup;
|
||||
|
||||
public GuiServiceInfo(
|
||||
@Value("${server.address}") final String internalServer,
|
||||
|
@ -36,7 +37,8 @@ public class GuiServiceInfo {
|
|||
@Value("${sebserver.gui.http.external.servername}") final String externalServer,
|
||||
@Value("${sebserver.gui.http.external.port}") final String externalPort,
|
||||
@Value("${sebserver.gui.entrypoint:/gui}") final String entryPoint,
|
||||
@Value("${server.servlet.context-path:/}") final String contextPath) {
|
||||
@Value("${server.servlet.context-path:/}") final String contextPath,
|
||||
@Value("${sebserver.webservice.distributed:false}") final boolean distributedSetup) {
|
||||
|
||||
if (StringUtils.isBlank(externalScheme)) {
|
||||
throw new RuntimeException("Missing mandatory inital parameter sebserver.gui.http.external.servername");
|
||||
|
@ -69,6 +71,8 @@ public class GuiServiceInfo {
|
|||
if (StringUtils.isNotBlank(contextPath) && !contextPath.equals("/")) {
|
||||
this.externalServerURIBuilder.path(contextPath);
|
||||
}
|
||||
|
||||
this.distributedSetup = distributedSetup;
|
||||
}
|
||||
|
||||
public String getExternalScheme() {
|
||||
|
@ -107,4 +111,8 @@ public class GuiServiceInfo {
|
|||
return this.externalServerURIBuilder.cloneBuilder();
|
||||
}
|
||||
|
||||
public boolean isDistributedSetup() {
|
||||
return this.distributedSetup;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.gui.content;
|
|||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -195,10 +194,9 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
indicators);
|
||||
|
||||
// NOTIFICATIONS
|
||||
final boolean hasNotifications = BooleanUtils.isTrue(connectionData.pendingNotification());
|
||||
Supplier<EntityTable<ClientNotification>> _notificationTableSupplier = () -> null;
|
||||
if (hasNotifications) {
|
||||
final PageService.PageActionBuilder actionBuilder = this.pageService
|
||||
if (connectionData.clientConnection.status.clientActiveStatus) {
|
||||
final PageService.PageActionBuilder notificationActionBuilder = this.pageService
|
||||
.pageActionBuilder(
|
||||
pageContext
|
||||
.clearAttributes()
|
||||
|
@ -240,7 +238,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
this::getServerTime)
|
||||
.sortable()
|
||||
.widthProportion(1))
|
||||
.withDefaultAction(t -> actionBuilder
|
||||
.withDefaultAction(t -> notificationActionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)
|
||||
.withParentEntityKey(parentEntityKey)
|
||||
.withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
|
||||
|
@ -252,7 +250,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION))
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
notificationActionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION_CONFIRM_NOTIFICATION)
|
||||
.withParentEntityKey(parentEntityKey)
|
||||
.withConfirm(() -> NOTIFICATION_LIST_CONFIRM_TEXT_KEY)
|
||||
|
|
|
@ -41,6 +41,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
|||
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.GuiServiceInfo;
|
||||
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;
|
||||
|
@ -92,6 +93,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
private final InstructionProcessor instructionProcessor;
|
||||
private final MonitoringExamSearchPopup monitoringExamSearchPopup;
|
||||
private final MonitoringProctoringService monitoringProctoringService;
|
||||
private final boolean distributedSetup;
|
||||
private final long pollInterval;
|
||||
private final long proctoringRoomUpdateInterval;
|
||||
|
||||
|
@ -102,6 +104,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
final InstructionProcessor instructionProcessor,
|
||||
final MonitoringExamSearchPopup monitoringExamSearchPopup,
|
||||
final MonitoringProctoringService monitoringProctoringService,
|
||||
final GuiServiceInfo guiServiceInfo,
|
||||
@Value("${sebserver.gui.webservice.poll-interval:1000}") final long pollInterval,
|
||||
@Value("${sebserver.gui.remote.proctoring.rooms.update.poll-interval:5000}") final long proctoringRoomUpdateInterval) {
|
||||
|
||||
|
@ -113,6 +116,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
this.instructionProcessor = instructionProcessor;
|
||||
this.monitoringProctoringService = monitoringProctoringService;
|
||||
this.pollInterval = pollInterval;
|
||||
this.distributedSetup = guiServiceInfo.isDistributedSetup();
|
||||
this.monitoringExamSearchPopup = monitoringExamSearchPopup;
|
||||
this.proctoringRoomUpdateInterval = proctoringRoomUpdateInterval;
|
||||
}
|
||||
|
@ -164,7 +168,8 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
exam,
|
||||
indicators,
|
||||
restCall,
|
||||
pushContext);
|
||||
pushContext,
|
||||
this.distributedSetup);
|
||||
|
||||
clientTable
|
||||
.withDefaultAction(
|
||||
|
|
|
@ -83,8 +83,8 @@ public class ServerPushService {
|
|||
});
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Stop Server Push Session on: {}", Thread.currentThread().getName());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Stop Server Push Session on: {}", Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -100,7 +100,9 @@ public class ServerPushService {
|
|||
|
||||
});
|
||||
|
||||
log.info("Start new Server Push Session on: {}", bgThread.getName());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Start new Server Push Session on: {}", bgThread.getName());
|
||||
}
|
||||
|
||||
bgThread.setDaemon(true);
|
||||
bgThread.start();
|
||||
|
|
|
@ -25,7 +25,6 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
|
|||
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.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
|
||||
|
@ -69,6 +68,7 @@ public class ClientConnectionDetails {
|
|||
|
||||
private ClientConnectionData connectionData = null;
|
||||
private boolean statusChanged = true;
|
||||
private long startTime = -1;
|
||||
private Consumer<ClientConnectionData> statusChangeListener = null;
|
||||
|
||||
public ClientConnectionDetails(
|
||||
|
@ -147,13 +147,22 @@ public class ClientConnectionDetails {
|
|||
.toBoolean(connectionData.missingPing);
|
||||
}
|
||||
this.connectionData = connectionData;
|
||||
|
||||
if (this.startTime < 0) {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGUI(
|
||||
final Supplier<EntityTable<ClientNotification>> notificationTableSupplier,
|
||||
final PageContext pageContext) {
|
||||
|
||||
// Note: This is to update the whole page (by reload) only when the status has changed
|
||||
// while this page was open. This prevent constant page reloads.
|
||||
if (this.statusChanged && System.currentTimeMillis() - this.startTime > Constants.SECOND_IN_MILLIS) {
|
||||
reloadPage(pageContext);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.connectionData == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -214,16 +223,8 @@ public class ClientConnectionDetails {
|
|||
|
||||
// update notifications
|
||||
final EntityTable<ClientNotification> notificationTable = notificationTableSupplier.get();
|
||||
if (notificationTable != null && this.connectionData.clientConnection.status == ConnectionStatus.CLOSED) {
|
||||
reloadPage(pageContext);
|
||||
} else {
|
||||
if (BooleanUtils.isTrue(this.connectionData.pendingNotification())) {
|
||||
if (notificationTable == null) {
|
||||
reloadPage(pageContext);
|
||||
} else {
|
||||
notificationTable.refreshPageSize();
|
||||
}
|
||||
}
|
||||
if (notificationTable != null) {
|
||||
notificationTable.refreshPageSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ public final class ClientConnectionTable {
|
|||
private final Exam exam;
|
||||
private final RestCall<Collection<ClientConnectionData>>.RestCallBuilder restCallBuilder;
|
||||
private final ServerPushContext pushConext;
|
||||
private final boolean distributedSetup;
|
||||
|
||||
private final Map<Long, IndicatorData> indicatorMapping;
|
||||
private final Table table;
|
||||
|
@ -119,8 +120,6 @@ public final class ClientConnectionTable {
|
|||
private boolean forceUpdateAll = false;
|
||||
private boolean updateInProgress = false;
|
||||
|
||||
//private int updateErrors = 0;
|
||||
|
||||
public ClientConnectionTable(
|
||||
final PageService pageService,
|
||||
final Composite tableRoot,
|
||||
|
@ -128,13 +127,15 @@ public final class ClientConnectionTable {
|
|||
final Exam exam,
|
||||
final Collection<Indicator> indicators,
|
||||
final RestCall<Collection<ClientConnectionData>>.RestCallBuilder restCallBuilder,
|
||||
final ServerPushContext pushConext) {
|
||||
final ServerPushContext pushConext,
|
||||
final boolean distributedSetup) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.asyncRunner = asyncRunner;
|
||||
this.exam = exam;
|
||||
this.restCallBuilder = restCallBuilder;
|
||||
this.pushConext = pushConext;
|
||||
this.distributedSetup = distributedSetup;
|
||||
|
||||
final WidgetFactory widgetFactory = pageService.getWidgetFactory();
|
||||
final ResourceService resourceService = pageService.getResourceService();
|
||||
|
@ -332,9 +333,8 @@ public final class ClientConnectionTable {
|
|||
private void updateValuesAsync(final boolean needsSync) {
|
||||
|
||||
try {
|
||||
|
||||
// TODO forceUpdateAll doeasn't work on distributed
|
||||
if (this.statusFilterChanged || this.forceUpdateAll || needsSync) {
|
||||
final boolean sync = this.statusFilterChanged || this.forceUpdateAll || needsSync || this.distributedSetup;
|
||||
if (sync) {
|
||||
this.toDelete.clear();
|
||||
this.toDelete.addAll(this.tableMapping.keySet());
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ public final class ClientConnectionTable {
|
|||
data.getConnectionId(),
|
||||
UpdatableTableItem::new);
|
||||
tableItem.push(data);
|
||||
if (this.statusFilterChanged || this.forceUpdateAll || needsSync) {
|
||||
if (sync) {
|
||||
this.toDelete.remove(data.getConnectionId());
|
||||
}
|
||||
});
|
||||
|
@ -680,8 +680,11 @@ public final class ClientConnectionTable {
|
|||
!this.connectionData.dataEquals(connectionData);
|
||||
final boolean statusChanged = this.connectionData == null ||
|
||||
this.connectionData.clientConnection.status != connectionData.clientConnection.status;
|
||||
final boolean notificationChanged = this.connectionData == null ||
|
||||
BooleanUtils.toBoolean(this.connectionData.pendingNotification) != BooleanUtils
|
||||
.toBoolean(connectionData.pendingNotification);
|
||||
|
||||
if (statusChanged) {
|
||||
if (statusChanged || notificationChanged) {
|
||||
ClientConnectionTable.this.needsSort = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
||||
|
@ -51,20 +51,25 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
|
|||
private final Set<Long> examUpdate = new HashSet<>();
|
||||
|
||||
private long lastUpdate = 0;
|
||||
private long updateInterval = 5 * Constants.SECOND_IN_MILLIS;
|
||||
|
||||
public SEBClientNotificationServiceImpl(
|
||||
final ClientEventDAO clientEventDAO,
|
||||
final ClientConnectionDAO clientConnectionDAO,
|
||||
final SEBClientInstructionService sebClientInstructionService) {
|
||||
final SEBClientInstructionService sebClientInstructionService,
|
||||
final WebserviceInfo webserviceInfo) {
|
||||
|
||||
this.clientEventDAO = clientEventDAO;
|
||||
this.clientConnectionDAO = clientConnectionDAO;
|
||||
this.sebClientInstructionService = sebClientInstructionService;
|
||||
if (webserviceInfo.isDistributed()) {
|
||||
this.updateInterval = Constants.SECOND_IN_MILLIS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hasAnyPendingNotification(final ClientConnection clientConnection) {
|
||||
if (clientConnection.status != ConnectionStatus.ACTIVE) {
|
||||
if (!clientConnection.status.clientActiveStatus) {
|
||||
return false;
|
||||
}
|
||||
updateCache(clientConnection.examId);
|
||||
|
@ -141,7 +146,7 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
|
|||
}
|
||||
|
||||
private final void updateCache(final Long examId) {
|
||||
if (System.currentTimeMillis() - this.lastUpdate > 5 * Constants.SECOND_IN_MILLIS) {
|
||||
if (System.currentTimeMillis() - this.lastUpdate > this.updateInterval) {
|
||||
this.examUpdate.clear();
|
||||
this.pendingNotifications.clear();
|
||||
this.lastUpdate = System.currentTimeMillis();
|
||||
|
|
|
@ -42,4 +42,10 @@ public class ReplTest {
|
|||
// assertEquals(Constants.DAY_IN_MIN, interv.toDurationMillis() / Constants.MINUTE_IN_MILLIS);
|
||||
// }
|
||||
|
||||
// @Test
|
||||
// public void testBooleanMatch() {
|
||||
// assertTrue(Boolean.valueOf(false) == Boolean.valueOf(false));
|
||||
// assertTrue(new Boolean(false) == new Boolean(false));
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue