From 0c2c592d7930348422a4cdf1c834fac500b39cae Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 22 Aug 2019 13:00:14 +0200 Subject: [PATCH] added institution column to quiz-, exam- and log-list pages --- .../ch/ethz/seb/sebserver/gbl/util/Tuple.java | 8 +++ .../seb/sebserver/gui/content/ExamList.java | 36 +++++++++- .../gui/content/QuizDiscoveryList.java | 66 +++++++++++++++++-- .../sebserver/gui/content/SebClientLogs.java | 29 ++++++++ .../gui/content/UserActivityLogs.java | 34 ++++++++++ .../weblayer/api/QuizController.java | 8 ++- src/main/resources/messages.properties | 2 + 7 files changed, 173 insertions(+), 10 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java index ed8b4fa9..61dab764 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Tuple.java @@ -22,6 +22,14 @@ public class Tuple { this._2 = _2; } + public T get_1() { + return this._1; + } + + public T get_2() { + return this._2; + } + @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java index 9db4bdd1..52526901 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamList.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.gui.content; +import java.util.function.BooleanSupplier; import java.util.function.Function; import org.eclipse.swt.widgets.Composite; @@ -19,9 +20,11 @@ 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.Entity; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; +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; @@ -55,7 +58,9 @@ public class ExamList implements TemplateComposer { new LocTextKey("sebserver.exam.list.action.no.modify.privilege"); private final static LocTextKey EMPTY_SELECTION_TEXT_KEY = new LocTextKey("sebserver.exam.info.pleaseSelect"); - private final static LocTextKey COLUMN_TITLE_KEY = + private final static LocTextKey COLUMN_TITLE_INSTITUTION_KEY = + new LocTextKey("sebserver.exam.list.column.institution"); + private final static LocTextKey COLUMN_TITLE_LMS_KEY = new LocTextKey("sebserver.exam.list.column.lmssetup"); private final static LocTextKey COLUMN_TITLE_NAME_KEY = new LocTextKey("sebserver.exam.list.column.name"); @@ -66,6 +71,7 @@ public class ExamList implements TemplateComposer { private final static LocTextKey EMPTY_LIST_TEXT_KEY = new LocTextKey("sebserver.exam.list.empty"); + private final TableFilterAttribute institutionFilter; private final TableFilterAttribute lmsFilter; private final TableFilterAttribute nameFilter = new TableFilterAttribute(CriteriaType.TEXT, QuizData.FILTER_ATTR_NAME); @@ -84,6 +90,11 @@ public class ExamList implements TemplateComposer { this.resourceService = resourceService; this.pageSize = pageSize; + this.institutionFilter = new TableFilterAttribute( + CriteriaType.SINGLE_SELECTION, + Entity.FILTER_ATTR_INSTITUTION, + this.resourceService::institutionResource); + this.lmsFilter = new TableFilterAttribute( CriteriaType.SINGLE_SELECTION, LmsSetup.FILTER_ATTR_LMS_SETUP, @@ -111,23 +122,41 @@ public class ExamList implements TemplateComposer { final PageActionBuilder actionBuilder = this.pageService .pageActionBuilder(pageContext.clearEntityKeys()); + final BooleanSupplier isSebAdmin = + () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN); + + final Function institutionNameFunction = + this.resourceService.getInstitutionNameFunction(); + // table final EntityTable table = this.pageService.entityTableBuilder(restService.getRestCall(GetExamPage.class)) .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) + + .withColumnIf( + isSebAdmin, + () -> new ColumnDefinition( + Domain.EXAM.ATTR_INSTITUTION_ID, + COLUMN_TITLE_INSTITUTION_KEY, + exam -> institutionNameFunction + .apply(String.valueOf(exam.getInstitutionId()))) + .withFilter(this.institutionFilter)) + .withColumn(new ColumnDefinition<>( Domain.EXAM.ATTR_LMS_SETUP_ID, - COLUMN_TITLE_KEY, + COLUMN_TITLE_LMS_KEY, examLmsSetupNameFunction(this.resourceService)) .withFilter(this.lmsFilter) .sortable()) + .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_NAME, COLUMN_TITLE_NAME_KEY, Exam::getName) .withFilter(this.nameFilter) .sortable()) + .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_START_TIME, new LocTextKey( @@ -141,15 +170,18 @@ public class ExamList implements TemplateComposer { .minusYears(1) .toString())) .sortable()) + .withColumn(new ColumnDefinition<>( Domain.EXAM.ATTR_TYPE, COLUMN_TITLE_TYPE_KEY, this.resourceService::localizedExamTypeName) .withFilter(this.typeFilter) .sortable()) + .withDefaultAction(actionBuilder .newAction(ActionDefinition.EXAM_VIEW_FROM_LIST) .create()) + .compose(pageContext.copyOf(content)); // propagate content actions to action-pane diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java index e4ecaa67..8042e990 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/QuizDiscoveryList.java @@ -8,6 +8,7 @@ package ch.ethz.seb.sebserver.gui.content; +import java.util.function.BooleanSupplier; import java.util.function.Function; import org.eclipse.swt.widgets.Composite; @@ -18,9 +19,11 @@ 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.Entity; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; +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.form.FormBuilder; @@ -61,6 +64,8 @@ public class QuizDiscoveryList implements TemplateComposer { new LocTextKey("sebserver.quizdiscovery.quiz.details.description"); private static final LocTextKey QUIZ_DETAILS_NAME_TEXT_KEY = new LocTextKey("sebserver.quizdiscovery.quiz.details.name"); + private static final LocTextKey QUIZ_DETAILS_INSTITUION_TEXT_KEY = + new LocTextKey("sebserver.quizdiscovery.quiz.details.institution"); private static final LocTextKey QUIZ_DETAILS_LMS_TEXT_KEY = new LocTextKey("sebserver.quizdiscovery.quiz.details.lms"); private static final LocTextKey TITLE_TEXT_KEY = @@ -69,6 +74,8 @@ public class QuizDiscoveryList implements TemplateComposer { new LocTextKey("sebserver.quizdiscovery.list.empty"); private final static LocTextKey EMPTY_SELECTION_TEXT = new LocTextKey("sebserver.quizdiscovery.info.pleaseSelect"); + private final static LocTextKey INSTITUION_TEXT_KEY = + new LocTextKey("sebserver.quizdiscovery.list.column.institution"); private final static LocTextKey LMS_TEXT_KEY = new LocTextKey("sebserver.quizdiscovery.list.column.lmssetup"); private final static LocTextKey NAME_TEXT_KEY = @@ -79,6 +86,7 @@ public class QuizDiscoveryList implements TemplateComposer { new LocTextKey("sebserver.quizdiscovery.quiz.import.out.dated"); // filter attribute models + private final TableFilterAttribute institutionFilter; private final TableFilterAttribute lmsFilter; private final TableFilterAttribute nameFilter = new TableFilterAttribute(CriteriaType.TEXT, QuizData.FILTER_ATTR_NAME); @@ -101,6 +109,11 @@ public class QuizDiscoveryList implements TemplateComposer { this.resourceService = resourceService; this.pageSize = pageSize; + this.institutionFilter = new TableFilterAttribute( + CriteriaType.SINGLE_SELECTION, + Entity.FILTER_ATTR_INSTITUTION, + this.resourceService::institutionResource); + this.lmsFilter = new TableFilterAttribute( CriteriaType.SINGLE_SELECTION, LmsSetup.FILTER_ATTR_LMS_SETUP, @@ -118,25 +131,44 @@ public class QuizDiscoveryList implements TemplateComposer { pageContext.getParent(), TITLE_TEXT_KEY); - final PageActionBuilder actionBuilder = this.pageService.pageActionBuilder(pageContext.clearEntityKeys()); + final PageActionBuilder actionBuilder = + this.pageService.pageActionBuilder(pageContext.clearEntityKeys()); + + final BooleanSupplier isSebAdmin = + () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN); + + final Function institutionNameFunction = + this.resourceService.getInstitutionNameFunction(); // table final EntityTable table = this.pageService.entityTableBuilder(restService.getRestCall(GetQuizPage.class)) .withEmptyMessage(EMPTY_LIST_TEXT_KEY) .withPaging(this.pageSize) + + .withColumnIf( + isSebAdmin, + () -> new ColumnDefinition( + QuizData.QUIZ_ATTR_INSTITUION_ID, + INSTITUION_TEXT_KEY, + quiz -> institutionNameFunction + .apply(String.valueOf(quiz.institutionId))) + .withFilter(this.institutionFilter)) + .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_LMS_SETUP_ID, LMS_TEXT_KEY, quizDataLmsSetupNameFunction(this.resourceService)) .withFilter(this.lmsFilter) .sortable()) + .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_NAME, NAME_TEXT_KEY, QuizData::getName) .withFilter(this.nameFilter) .sortable()) + .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_START_TIME, new LocTextKey( @@ -145,6 +177,7 @@ public class QuizDiscoveryList implements TemplateComposer { QuizData::getStartTime) .withFilter(this.startTimeFilter) .sortable()) + .withColumn(new ColumnDefinition<>( QuizData.QUIZ_ATTR_END_TIME, new LocTextKey( @@ -152,11 +185,16 @@ public class QuizDiscoveryList implements TemplateComposer { i18nSupport.getUsersTimeZoneTitleSuffix()), QuizData::getEndTime) .sortable()) + .withDefaultAction(t -> actionBuilder .newAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS) - .withExec(action -> this.showDetails(action, t.getSelectedROWData())) + .withExec(action -> this.showDetails( + action, + t.getSelectedROWData(), + institutionNameFunction)) .noEventPropagation() .create()) + .compose(pageContext.copyOf(content)); // propagate content actions to action-pane @@ -170,7 +208,10 @@ public class QuizDiscoveryList implements TemplateComposer { .newAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS) .withSelect( table::getSelection, - action -> this.showDetails(action, table.getSelectedROWData()), + action -> this.showDetails( + action, + table.getSelectedROWData(), + institutionNameFunction), EMPTY_SELECTION_TEXT) .noEventPropagation() .publishIf(table::hasAnyContent) @@ -205,7 +246,11 @@ public class QuizDiscoveryList implements TemplateComposer { .withAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA, "true"); } - private PageAction showDetails(final PageAction action, final QuizData quizData) { + private PageAction showDetails( + final PageAction action, + final QuizData quizData, + final Function institutionNameFunction) { + action.getSingleSelection(); final ModalInputDialog dialog = new ModalInputDialog<>( @@ -215,12 +260,15 @@ public class QuizDiscoveryList implements TemplateComposer { dialog.open( DETAILS_TITLE_TEXT_KEY, action.pageContext(), - pc -> createDetailsForm(quizData, pc)); + pc -> createDetailsForm(quizData, pc, institutionNameFunction)); return action; } - private void createDetailsForm(final QuizData quizData, final PageContext pc) { + private void createDetailsForm( + final QuizData quizData, + final PageContext pc, + final Function institutionNameFunction) { final Composite parent = pc.getParent(); final Composite grid = this.widgetFactory.createPopupScrollComposite(parent); @@ -228,6 +276,12 @@ public class QuizDiscoveryList implements TemplateComposer { this.pageService.formBuilder(pc.copyOf(grid), 3) .withEmptyCellSeparation(false) .readonly(true) + .addFieldIf( + () -> this.resourceService.getCurrentUser().get().hasRole(UserRole.SEB_SERVER_ADMIN), + () -> FormBuilder.text( + QuizData.QUIZ_ATTR_INSTITUION_ID, + QUIZ_DETAILS_INSTITUION_TEXT_KEY, + institutionNameFunction.apply(quizData.getModelId()))) .addField(FormBuilder.singleSelection( QuizData.QUIZ_ATTR_LMS_SETUP_ID, QUIZ_DETAILS_LMS_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java index 781ecebb..e95f8fd6 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebClientLogs.java @@ -9,6 +9,7 @@ package ch.ethz.seb.sebserver.gui.content; import java.util.Map; +import java.util.function.BooleanSupplier; import java.util.function.Function; import org.eclipse.swt.widgets.Composite; @@ -26,6 +27,7 @@ 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.ClientEvent; import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent; +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; @@ -43,6 +45,7 @@ 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.logs.GetExtendedClientEventPage; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnection; +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; @@ -64,6 +67,8 @@ public class SebClientLogs implements TemplateComposer { private static final LocTextKey EMPTY_TEXT_KEY = new LocTextKey("sebserver.seblogs.list.empty"); + private static final LocTextKey INSTITUTION_TEXT_KEY = + new LocTextKey("sebserver.seblogs.list.column.institution"); private static final LocTextKey EXAM_TEXT_KEY = new LocTextKey("sebserver.seblogs.list.column.exam"); private static final LocTextKey CLIENT_SESSION_TEXT_KEY = @@ -155,6 +160,7 @@ public class SebClientLogs implements TemplateComposer { @Override public void compose(final PageContext pageContext) { + final CurrentUser currentUser = this.resourceService.getCurrentUser(); final WidgetFactory widgetFactory = this.pageService.getWidgetFactory(); final RestService restService = this.resourceService.getRestService(); // content page layout with title @@ -167,12 +173,35 @@ public class SebClientLogs implements TemplateComposer { .clearEntityKeys() .clearAttributes()); + final BooleanSupplier isSebAdmin = + () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN); + + final Function institutionNameFunction = + this.resourceService.getInstitutionNameFunction() + .compose(log -> { + try { + final ClientConnection connection = restService.getBuilder(GetClientConnection.class) + .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(log.getConnectionId())) + .call().getOrThrow(); + return String.valueOf(connection.getInstitutionId()); + } catch (final Exception e) { + return Constants.EMPTY_NOTE; + } + }); // table final EntityTable table = this.pageService.entityTableBuilder( restService.getRestCall(GetExtendedClientEventPage.class)) .withEmptyMessage(EMPTY_TEXT_KEY) .withPaging(this.pageSize) + .withColumnIf( + isSebAdmin, + () -> new ColumnDefinition<>( + Domain.INSTITUTION.ATTR_NAME, + INSTITUTION_TEXT_KEY, + institutionNameFunction) + .widthProportion(2)) + .withColumn(new ColumnDefinition<>( Domain.CLIENT_CONNECTION.ATTR_EXAM_ID, EXAM_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java index 0f3264d7..a225b2f5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/UserActivityLogs.java @@ -8,14 +8,20 @@ package ch.ethz.seb.sebserver.gui.content; +import java.util.function.BooleanSupplier; +import java.util.function.Function; + 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.model.Domain; import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog; +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; @@ -31,6 +37,8 @@ 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.logs.GetUserLogPage; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount; +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; @@ -48,6 +56,8 @@ public class UserActivityLogs implements TemplateComposer { new LocTextKey("sebserver.userlogs.list.title"); private static final LocTextKey EMPTY_TEXT_KEY = new LocTextKey("sebserver.userlogs.list.empty"); + private static final LocTextKey INSTITUTION_TEXT_KEY = + new LocTextKey("sebserver.userlogs.list.column.institution"); private static final LocTextKey USER_TEXT_KEY = new LocTextKey("sebserver.userlogs.list.column.user"); private static final LocTextKey DATE_TEXT_KEY = @@ -101,6 +111,7 @@ public class UserActivityLogs implements TemplateComposer { @Override public void compose(final PageContext pageContext) { + final CurrentUser currentUser = this.resourceService.getCurrentUser(); final WidgetFactory widgetFactory = this.pageService.getWidgetFactory(); final RestService restService = this.resourceService.getRestService(); // content page layout with title @@ -113,12 +124,35 @@ public class UserActivityLogs implements TemplateComposer { .clearEntityKeys() .clearAttributes()); + final BooleanSupplier isSebAdmin = + () -> currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN); + + final Function institutionNameFunction = + this.resourceService.getInstitutionNameFunction() + .compose(log -> { + try { + final UserInfo user = restService.getBuilder(GetUserAccount.class) + .withURIVariable(API.PARAM_MODEL_ID, log.getUserUuid()) + .call().getOrThrow(); + return String.valueOf(user.getInstitutionId()); + } catch (final Exception e) { + return Constants.EMPTY_NOTE; + } + }); + // table final EntityTable table = this.pageService.entityTableBuilder( restService.getRestCall(GetUserLogPage.class)) .withEmptyMessage(EMPTY_TEXT_KEY) .withPaging(this.pageSize) + .withColumnIf( + isSebAdmin, + () -> new ColumnDefinition<>( + UserActivityLog.FILTER_ATTR_INSTITUTION, + INSTITUTION_TEXT_KEY, + institutionNameFunction)) + .withColumn(new ColumnDefinition<>( UserActivityLog.ATTR_USER_NAME, USER_TEXT_KEY, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java index 5d432f6a..24f65f1f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/QuizController.java @@ -85,8 +85,12 @@ public class QuizController { EntityType.EXAM, institutionId); - final FilterMap filterMap = new FilterMap(allRequestParams) - .putIfAbsent(Entity.FILTER_ATTR_INSTITUTION, String.valueOf(institutionId)); + final FilterMap filterMap = new FilterMap(allRequestParams); + // if current user has no read access for specified entity type within other institution + // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance + if (!this.authorization.hasGrant(PrivilegeType.READ, EntityType.EXAM)) { + filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + } return this.lmsAPIService.requestQuizDataPage( (pageNumber != null) diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index b00c6467..507eb2af 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -254,6 +254,7 @@ sebserver.quizdiscovery.action.details=Show Details sebserver.quizdiscovery.quiz.details.title=Quiz Details sebserver.quizdiscovery.quiz.details.lms=LMS +sebserver.quizdiscovery.quiz.details.institution=Institution sebserver.quizdiscovery.quiz.details.name=Name sebserver.quizdiscovery.quiz.details.description=Description sebserver.quizdiscovery.quiz.details.starttime=Start Time @@ -980,6 +981,7 @@ sebserver.seblogs.list.actions=Selected Log sebserver.seblogs.list.empty=No SEB client logs has been found. Please adapt or clear the filter sebserver.seblogs.info.pleaseSelect=Please select a log from the list +sebserver.seblogs.list.column.institution=Institution sebserver.seblogs.list.column.exam=Exam sebserver.seblogs.list.column.client-session=User Session-ID sebserver.seblogs.list.column.type=Event Type