finished GUI refactoring
This commit is contained in:
parent
000e8c3c7d
commit
26561288c9
31 changed files with 7533 additions and 7178 deletions
|
@ -34,7 +34,7 @@ public final class QuizData implements GrantEntity {
|
|||
public static final String ATTR_ADDITIONAL_ATTRIBUTES = "ADDITIONAL_ATTRIBUTES";
|
||||
|
||||
public static final String QUIZ_ATTR_ID = "quiz_id";
|
||||
public static final String QUIZ_ATTR_INSTITUION_ID = Domain.EXAM.ATTR_INSTITUTION_ID;
|
||||
public static final String QUIZ_ATTR_INSTITUTION_ID = Domain.EXAM.ATTR_INSTITUTION_ID;
|
||||
public static final String QUIZ_ATTR_LMS_SETUP_ID = "lms_setup_id";
|
||||
public static final String QUIZ_ATTR_LMS_TYPE = "lms_setup_type";
|
||||
public static final String QUIZ_ATTR_NAME = "quiz_name";
|
||||
|
@ -43,10 +43,17 @@ public final class QuizData implements GrantEntity {
|
|||
public static final String QUIZ_ATTR_END_TIME = "quiz_end_time";
|
||||
public static final String QUIZ_ATTR_START_URL = "quiz_start_url";
|
||||
|
||||
public static final String ATTR_ADDITIONAL_CREATION_TIME = "time_created";
|
||||
public static final String ATTR_ADDITIONAL_SHORT_NAME = "course_short_name";
|
||||
public static final String ATTR_ADDITIONAL_FULL_NAME = "course_full_name";
|
||||
public static final String ATTR_ADDITIONAL_DISPLAY_NAME = "course_display_name";
|
||||
public static final String ATTR_ADDITIONAL_SUMMARY = "course_summary";
|
||||
public static final String ATTR_ADDITIONAL_TIME_LIMIT = "time_limit";
|
||||
|
||||
@JsonProperty(QUIZ_ATTR_ID)
|
||||
public final String id;
|
||||
|
||||
@JsonProperty(QUIZ_ATTR_INSTITUION_ID)
|
||||
@JsonProperty(QUIZ_ATTR_INSTITUTION_ID)
|
||||
public final Long institutionId;
|
||||
|
||||
@JsonProperty(QUIZ_ATTR_LMS_SETUP_ID)
|
||||
|
@ -76,7 +83,7 @@ public final class QuizData implements GrantEntity {
|
|||
@JsonCreator
|
||||
public QuizData(
|
||||
@JsonProperty(QUIZ_ATTR_ID) final String id,
|
||||
@JsonProperty(QUIZ_ATTR_INSTITUION_ID) final Long institutionId,
|
||||
@JsonProperty(QUIZ_ATTR_INSTITUTION_ID) final Long institutionId,
|
||||
@JsonProperty(QUIZ_ATTR_LMS_SETUP_ID) final Long lmsSetupId,
|
||||
@JsonProperty(QUIZ_ATTR_LMS_TYPE) final LmsType lmsType,
|
||||
@JsonProperty(QUIZ_ATTR_NAME) final String name,
|
||||
|
|
|
@ -332,7 +332,9 @@ public final class Utils {
|
|||
return null;
|
||||
}
|
||||
|
||||
return text.replace("</br>", "\n");
|
||||
return text
|
||||
.replace("<br/>", "\n")
|
||||
.replace("<br></br>", "\n");
|
||||
}
|
||||
|
||||
public static String encodeFormURL_UTF_8(final String value) {
|
||||
|
|
|
@ -141,7 +141,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
|
|||
final String requestURI = request.getRequestURI();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Trying to verify insitution from requested entrypoint url: {}", requestURI);
|
||||
log.debug("Trying to verify institution from requested entrypoint url: {}", requestURI);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -149,7 +149,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
|
|||
requestURI.lastIndexOf(Constants.SLASH) + 1,
|
||||
requestURI.length());
|
||||
} catch (final Exception e) {
|
||||
log.error("Fauled to extract institutional URL suffix: {}", e.getMessage());
|
||||
log.error("Failed to extract institutional URL suffix: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
@ -117,6 +118,8 @@ public class ExamForm implements TemplateComposer {
|
|||
|
||||
private final static LocTextKey CONFIG_LIST_TITLE_KEY =
|
||||
new LocTextKey("sebserver.exam.configuration.list.title");
|
||||
private final static LocTextKey CONFIG_LIST_TITLE_TOOLTIP_KEY =
|
||||
new LocTextKey("sebserver.exam.configuration.list.title" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private final static LocTextKey CONFIG_NAME_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.exam.configuration.list.column.name");
|
||||
private final static LocTextKey CONFIG_DESCRIPTION_COLUMN_KEY =
|
||||
|
@ -128,6 +131,8 @@ public class ExamForm implements TemplateComposer {
|
|||
|
||||
private final static LocTextKey INDICATOR_LIST_TITLE_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.list.title");
|
||||
private final static LocTextKey INDICATOR_LIST_TITLE_TOOLTIP_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.list.title" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private final static LocTextKey INDICATOR_TYPE_COLUMN_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.list.column.type");
|
||||
private final static LocTextKey INDICATOR_NAME_COLUMN_KEY =
|
||||
|
@ -326,11 +331,12 @@ public class ExamForm implements TemplateComposer {
|
|||
.addField(FormBuilder.singleSelection(
|
||||
Domain.EXAM.ATTR_TYPE,
|
||||
FORM_TYPE_TEXT_KEY,
|
||||
String.valueOf(exam.type),
|
||||
(exam.type != null) ? String.valueOf(exam.type) : Exam.ExamType.UNDEFINED.name(),
|
||||
this.resourceService::examTypeResources)
|
||||
.withLabelSpan(2)
|
||||
.withInputSpan(4)
|
||||
.withEmptyCellSpan(2))
|
||||
.withEmptyCellSpan(2)
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addField(FormBuilder.multiComboSelection(
|
||||
Domain.EXAM.ATTR_SUPPORTER,
|
||||
|
@ -339,7 +345,8 @@ public class ExamForm implements TemplateComposer {
|
|||
this.resourceService::examSupporterResources)
|
||||
.withLabelSpan(2)
|
||||
.withInputSpan(4)
|
||||
.withEmptyCellSpan(2))
|
||||
.withEmptyCellSpan(2)
|
||||
.mandatory(!readonly))
|
||||
|
||||
.buildFor(importFromQuizData
|
||||
? this.restService.getRestCall(ImportAsExam.class)
|
||||
|
@ -398,7 +405,8 @@ public class ExamForm implements TemplateComposer {
|
|||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
CONFIG_LIST_TITLE_KEY);
|
||||
CONFIG_LIST_TITLE_KEY,
|
||||
CONFIG_LIST_TITLE_TOOLTIP_KEY);
|
||||
this.widgetFactory.labelSeparator(content);
|
||||
|
||||
final EntityTable<ExamConfigurationMap> configurationTable =
|
||||
|
@ -428,6 +436,13 @@ public class ExamForm implements TemplateComposer {
|
|||
() -> modifyGrant,
|
||||
this::viewExamConfigPageAction)
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP,
|
||||
ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST,
|
||||
ActionDefinition.EXAM_CONFIGURATION_EXPORT,
|
||||
ActionDefinition.EXAM_CONFIGURATION_GET_CONFIG_KEY))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
final EntityKey configMapKey = (configurationTable.hasAnyContent())
|
||||
|
@ -447,7 +462,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
|
||||
.withParentEntityKey(entityKey)
|
||||
.withEntityKey(configMapKey)
|
||||
.publishIf(() -> modifyGrant && configurationTable.hasAnyContent())
|
||||
.publishIf(() -> modifyGrant && configurationTable.hasAnyContent(), false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
|
||||
.withEntityKey(entityKey)
|
||||
|
@ -461,7 +476,7 @@ public class ExamForm implements TemplateComposer {
|
|||
}
|
||||
return null;
|
||||
})
|
||||
.publishIf(() -> modifyGrant && configurationTable.hasAnyContent() && editable)
|
||||
.publishIf(() -> modifyGrant && configurationTable.hasAnyContent() && editable, false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_EXPORT)
|
||||
.withParentEntityKey(entityKey)
|
||||
|
@ -470,7 +485,7 @@ public class ExamForm implements TemplateComposer {
|
|||
this::downloadExamConfigAction,
|
||||
CONFIG_EMPTY_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent())
|
||||
.publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent(), false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_GET_CONFIG_KEY)
|
||||
.withSelect(
|
||||
|
@ -478,14 +493,15 @@ public class ExamForm implements TemplateComposer {
|
|||
this::getExamConfigKey,
|
||||
CONFIG_EMPTY_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent());
|
||||
.publishIf(() -> userGrantCheck.r() && configurationTable.hasAnyContent(), false);
|
||||
|
||||
// List of Indicators
|
||||
this.widgetFactory.label(content, "");
|
||||
this.widgetFactory.label(content, StringUtils.EMPTY);
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
INDICATOR_LIST_TITLE_KEY);
|
||||
INDICATOR_LIST_TITLE_KEY,
|
||||
INDICATOR_LIST_TITLE_TOOLTIP_KEY);
|
||||
this.widgetFactory.labelSeparator(content);
|
||||
|
||||
final EntityTable<Indicator> indicatorTable =
|
||||
|
@ -520,6 +536,11 @@ public class ExamForm implements TemplateComposer {
|
|||
.withParentEntityKey(entityKey)
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST,
|
||||
ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
|
@ -534,7 +555,7 @@ public class ExamForm implements TemplateComposer {
|
|||
indicatorTable::getSelection,
|
||||
PageAction::applySingleSelectionAsEntityKey,
|
||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent())
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent(), false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
|
||||
.withEntityKey(entityKey)
|
||||
|
@ -542,7 +563,7 @@ public class ExamForm implements TemplateComposer {
|
|||
indicatorTable::getSelection,
|
||||
this::deleteSelectedIndicator,
|
||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent());
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -560,7 +581,7 @@ public class ExamForm implements TemplateComposer {
|
|||
processFormSave,
|
||||
true,
|
||||
this.restService,
|
||||
t -> log.error("Failed to intially restrict the course for SEB on LMS: {}", t.getMessage()));
|
||||
t -> log.error("Failed to initially restrict the course for SEB on LMS: {}", t.getMessage()));
|
||||
}
|
||||
|
||||
return processFormSave;
|
||||
|
@ -589,7 +610,7 @@ public class ExamForm implements TemplateComposer {
|
|||
result
|
||||
.stream()
|
||||
.map(message -> this.consistencyMessageMapping.get(message.messageCode))
|
||||
.filter(message -> message != null)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(message -> this.widgetFactory.labelLocalized(
|
||||
warningPanel,
|
||||
CustomVariant.MESSAGE,
|
||||
|
@ -699,7 +720,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.withQueryParam(QuizData.QUIZ_ATTR_LMS_SETUP_ID, parentEntityKey.modelId)
|
||||
.call()
|
||||
.map(quizzData -> new Exam(quizzData))
|
||||
.map(Exam::new)
|
||||
.onError(error -> pageContext.notifyLoadError(EntityType.EXAM, error));
|
||||
}
|
||||
|
||||
|
@ -735,7 +756,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.append(")")
|
||||
.append("</span>")
|
||||
.append(" | "),
|
||||
(sb1, sb2) -> sb1.append(sb2));
|
||||
StringBuilder::append);
|
||||
builder.delete(builder.length() - 3, builder.length() - 1);
|
||||
return builder.toString();
|
||||
}
|
||||
|
|
|
@ -197,30 +197,30 @@ public class ExamList implements TemplateComposer {
|
|||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.EXAM_VIEW_FROM_LIST,
|
||||
ActionDefinition.EXAM_MODIFY_FROM_LIST))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
final GrantCheck userGrant = currentUser.grantCheck(EntityType.EXAM);
|
||||
actionBuilder
|
||||
|
||||
// Removed as discussed in SEBSERV-52
|
||||
// .newAction(ActionDefinition.EXAM_IMPORT)
|
||||
// .publishIf(userGrant::im)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_VIEW_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(table::hasAnyContent)
|
||||
.publishIf(table::hasAnyContent, false)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_MODIFY_FROM_LIST)
|
||||
.withSelect(
|
||||
table.getGrantedSelection(currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
action -> modifyExam(action, table),
|
||||
EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> userGrant.im() && table.hasAnyContent());
|
||||
.publishIf(() -> userGrant.im() && table.hasAnyContent(), false);
|
||||
|
||||
}
|
||||
|
||||
static final PageAction modifyExam(final PageAction action, final EntityTable<Exam> table) {
|
||||
static PageAction modifyExam(final PageAction action, final EntityTable<Exam> table) {
|
||||
final Exam exam = table.getSingleSelectedROWData();
|
||||
|
||||
if (exam == null) {
|
||||
|
@ -237,22 +237,20 @@ public class ExamList implements TemplateComposer {
|
|||
return action.withEntityKey(action.getSingleSelection());
|
||||
}
|
||||
|
||||
static final BiConsumer<TableItem, ExamConfigurationMap> decorateOnExamMapConsistency(
|
||||
static BiConsumer<TableItem, ExamConfigurationMap> decorateOnExamMapConsistency(
|
||||
final PageService pageService) {
|
||||
|
||||
return (item, examMap) -> {
|
||||
pageService.getRestService().getBuilder(GetExam.class)
|
||||
return (item, examMap) -> pageService.getRestService().getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examMap.examId))
|
||||
.call()
|
||||
.ifPresent(exam -> decorateOnExamConsistency(item, exam, pageService));
|
||||
};
|
||||
}
|
||||
|
||||
static final BiConsumer<TableItem, Exam> decorateOnExamConsistency(final PageService pageService) {
|
||||
static BiConsumer<TableItem, Exam> decorateOnExamConsistency(final PageService pageService) {
|
||||
return (item, exam) -> decorateOnExamConsistency(item, exam, pageService);
|
||||
}
|
||||
|
||||
static final void decorateOnExamConsistency(
|
||||
static void decorateOnExamConsistency(
|
||||
final TableItem item,
|
||||
final Exam exam,
|
||||
final PageService pageService) {
|
||||
|
|
|
@ -49,6 +49,10 @@ public class ExamSebRestrictionSettings {
|
|||
private final static LocTextKey SEB_RESTRICTION_FORM_TITLE =
|
||||
new LocTextKey("sebserver.exam.action.sebrestriction.details");
|
||||
|
||||
private final static LocTextKey SEB_RESTRICTION_FORM_INFO =
|
||||
new LocTextKey("sebserver.exam.form.sebrestriction.info");
|
||||
private final static LocTextKey SEB_RESTRICTION_FORM_INFO_TEXT =
|
||||
new LocTextKey("sebserver.exam.form.sebrestriction.info-text");
|
||||
private final static LocTextKey SEB_RESTRICTION_FORM_CONFIG_KEYS =
|
||||
new LocTextKey("sebserver.exam.form.sebrestriction.configKeys");
|
||||
private final static LocTextKey SEB_RESTRICTION_FORM_BROWSER_KEYS =
|
||||
|
@ -95,7 +99,7 @@ public class ExamSebRestrictionSettings {
|
|||
};
|
||||
}
|
||||
|
||||
private static final boolean doCreate(
|
||||
private static boolean doCreate(
|
||||
final PageService pageService,
|
||||
final PageContext pageContext,
|
||||
final FormHandle<?> formHandle) {
|
||||
|
@ -187,6 +191,14 @@ public class ExamSebRestrictionSettings {
|
|||
.withEmptyCellSeparation(false)
|
||||
.readonly(false)
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
"Info",
|
||||
SEB_RESTRICTION_FORM_INFO,
|
||||
pageService.getI18nSupport().getText(SEB_RESTRICTION_FORM_INFO_TEXT))
|
||||
.asArea(50)
|
||||
.asHTML()
|
||||
.readonly(true))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
SebRestriction.ATTR_CONFIG_KEYS,
|
||||
SEB_RESTRICTION_FORM_CONFIG_KEYS,
|
||||
|
@ -207,7 +219,7 @@ public class ExamSebRestrictionSettings {
|
|||
SEB_RESTRICTION_FORM_EDX_WHITE_LIST_PATHS,
|
||||
sebRestriction.getAdditionalProperties()
|
||||
.get(OpenEdxSebRestriction.ATTR_WHITELIST_PATHS),
|
||||
() -> resourceService.sebRestrictionWhiteListResources()))
|
||||
resourceService::sebRestrictionWhiteListResources))
|
||||
|
||||
.addFieldIf(
|
||||
() -> lmsType == LmsType.OPEN_EDX,
|
||||
|
@ -216,7 +228,7 @@ public class ExamSebRestrictionSettings {
|
|||
SEB_RESTRICTION_FORM_EDX_PERMISSIONS,
|
||||
sebRestriction.getAdditionalProperties()
|
||||
.get(OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS),
|
||||
() -> resourceService.sebRestrictionPermissionResources()))
|
||||
resourceService::sebRestrictionPermissionResources))
|
||||
|
||||
.addFieldIf(
|
||||
() -> lmsType == LmsType.OPEN_EDX,
|
||||
|
|
|
@ -114,7 +114,7 @@ final class ExamToConfigBindingForm {
|
|||
};
|
||||
}
|
||||
|
||||
private static final boolean doCreate(
|
||||
private static boolean doCreate(
|
||||
final PageService pageService,
|
||||
final PageContext pageContext,
|
||||
final FormHandle<ExamConfigurationMap> formHandle) {
|
||||
|
@ -212,7 +212,8 @@ final class ExamToConfigBindingForm {
|
|||
CONFIG_MAPPING_NAME_TEXT_KEY,
|
||||
String.valueOf(examConfigurationMap.configurationNodeId),
|
||||
resourceService::examConfigurationSelectionResources)
|
||||
.withSelectionListener(form -> updateFormValuesFromConfigSelection(form, resourceService)))
|
||||
.withSelectionListener(form -> updateFormValuesFromConfigSelection(form, resourceService))
|
||||
.mandatory())
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CONFIGURATION_NODE.ATTR_DESCRIPTION,
|
||||
|
|
|
@ -142,20 +142,23 @@ public class IndicatorForm implements TemplateComposer {
|
|||
.addField(FormBuilder.text(
|
||||
Domain.INDICATOR.ATTR_NAME,
|
||||
FORM_NAME_TEXT_KEY,
|
||||
indicator.name))
|
||||
indicator.name)
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.INDICATOR.ATTR_TYPE,
|
||||
FORM_TYPE_TEXT_KEY,
|
||||
(indicator.type != null) ? indicator.type.name() : null,
|
||||
this.resourceService::indicatorTypeResources)
|
||||
.withSelectionListener(this::updateForm))
|
||||
.withSelectionListener(this::updateForm)
|
||||
.mandatory(!isReadonly))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
TYPE_DESCRIPTION_FIELD_NAME,
|
||||
FORM_DESC_TEXT_KEY,
|
||||
typeDescription)
|
||||
.asArea()
|
||||
.asHTML(true)
|
||||
.readonly(true)
|
||||
.withInputSpan(6))
|
||||
|
||||
|
@ -189,7 +192,7 @@ public class IndicatorForm implements TemplateComposer {
|
|||
|
||||
}
|
||||
|
||||
private final void updateForm(final Form form) {
|
||||
private void updateForm(final Form form) {
|
||||
final String typeValue = form.getFieldValue(Domain.INDICATOR.ATTR_TYPE);
|
||||
if (StringUtils.isNotBlank(typeValue)) {
|
||||
form.setFieldValue(
|
||||
|
|
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.content;
|
|||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gui.form.Form;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -84,6 +85,8 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
new LocTextKey("sebserver.lmssetup.form.proxy.port");
|
||||
private static final LocTextKey FORM_PROXY_AUTH_CREDENTIALS_KEY =
|
||||
new LocTextKey("sebserver.lmssetup.form.proxy.auth-credentials");
|
||||
public static final LocTextKey LMS_SETUP_TEST_OK =
|
||||
new LocTextKey("sebserver.lmssetup.action.test.ok");
|
||||
|
||||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
|
@ -160,38 +163,49 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
.putStaticValueIf(isNotNew,
|
||||
Domain.LMS_SETUP.ATTR_LMS_TYPE,
|
||||
String.valueOf(lmsSetup.getLmsType()))
|
||||
|
||||
.addFieldIf(
|
||||
isSEBAdmin,
|
||||
() -> FormBuilder.singleSelection(
|
||||
Domain.LMS_SETUP.ATTR_INSTITUTION_ID,
|
||||
FORM_INSTITUTION_TEXT_KEY,
|
||||
String.valueOf(lmsSetup.getInstitutionId()),
|
||||
() -> this.resourceService.institutionResource())
|
||||
this.resourceService::institutionResource)
|
||||
.readonly(true))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_NAME,
|
||||
FORM_NAME_TEXT_KEY,
|
||||
lmsSetup.getName()))
|
||||
lmsSetup.getName())
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addField(FormBuilder.singleSelection(
|
||||
Domain.LMS_SETUP.ATTR_LMS_TYPE,
|
||||
FORM_TYPE_TEXT_KEY,
|
||||
(lmsType != null) ? lmsType.name() : LmsType.MOCKUP.name(),
|
||||
this.resourceService::lmsTypeResources)
|
||||
.readonlyIf(isNotNew))
|
||||
.readonlyIf(isNotNew)
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_LMS_URL,
|
||||
FORM_URL_TEXT_KEY,
|
||||
lmsSetup.getLmsApiUrl()))
|
||||
lmsSetup.getLmsApiUrl())
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addField(FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_LMS_CLIENTNAME,
|
||||
FORM_CLIENTNAME_LMS_TEXT_KEY,
|
||||
(lmsSetup.getLmsAuthName() != null) ? lmsSetup.getLmsAuthName() : null))
|
||||
lmsSetup.getLmsAuthName())
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addFieldIf(
|
||||
isEdit,
|
||||
() -> FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_LMS_CLIENTSECRET,
|
||||
FORM_SECRET_LMS_TEXT_KEY)
|
||||
.asPasswordField())
|
||||
.asPasswordField()
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addFieldIf(
|
||||
() -> readonly,
|
||||
|
@ -230,7 +244,7 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
() -> FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_LMS_PROXY_AUTH_USERNAME,
|
||||
FORM_PROXY_AUTH_CREDENTIALS_KEY,
|
||||
(lmsSetup.getProxyAuthUsername() != null) ? lmsSetup.getProxyAuthUsername() : null)
|
||||
lmsSetup.getProxyAuthUsername())
|
||||
.withInputSpan(3)
|
||||
.withEmptyCellSpan(0))
|
||||
.addFieldIf(
|
||||
|
@ -256,12 +270,6 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && readonly && institutionActive)
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_TEST_AND_SAVE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> this.testAdHoc(action, formHandle))
|
||||
.ignoreMoveAwayFromEdit()
|
||||
.publishIf(() -> modifyGrant && !readonly)
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_DEACTIVATE)
|
||||
.withEntityKey(entityKey)
|
||||
.withSimpleRestCall(restService, DeactivateLmsSetup.class)
|
||||
|
@ -270,7 +278,7 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.LMS_SETUP_ACTIVATE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> activate(action, formHandle))
|
||||
.withExec(action -> activate(action, formHandle, restService))
|
||||
.publishIf(() -> writeGrant && readonly && institutionActive && !lmsSetup.isActive())
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_SAVE)
|
||||
|
@ -279,6 +287,17 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
.ignoreMoveAwayFromEdit()
|
||||
.publishIf(() -> !readonly)
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_SAVE_AND_ACTIVATE)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> {
|
||||
this.testAdHoc(action, formHandle);
|
||||
PageAction newAction = formHandle.saveAndActivate(action);
|
||||
pageContext.publishInfo(LMS_SETUP_TEST_OK);
|
||||
return newAction;
|
||||
})
|
||||
.ignoreMoveAwayFromEdit()
|
||||
.publishIf(() -> !readonly && !lmsSetup.isActive())
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_CANCEL_MODIFY)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(this.pageService.backToCurrentFunction())
|
||||
|
@ -286,11 +305,15 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
}
|
||||
|
||||
/** Save and test connection before activation */
|
||||
private PageAction activate(final PageAction action, final FormHandle<LmsSetup> formHandle) {
|
||||
public static PageAction activate(
|
||||
final PageAction action,
|
||||
final FormHandle<LmsSetup> formHandle,
|
||||
final RestService restService) {
|
||||
|
||||
// first test the LMS Setup. If this fails the action execution will stops
|
||||
final PageAction testLmsSetup = this.testLmsSetup(action, formHandle, false);
|
||||
final PageAction testLmsSetup = testLmsSetup(action, formHandle, restService);
|
||||
// if LMS Setup test was successful, the activation action applies
|
||||
this.resourceService.getRestService().getBuilder(ActivateLmsSetup.class)
|
||||
restService.getBuilder(ActivateLmsSetup.class)
|
||||
.withURIVariable(
|
||||
API.PARAM_MODEL_ID,
|
||||
action.pageContext().getAttribute(AttributeKeys.ENTITY_ID))
|
||||
|
@ -306,7 +329,7 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
// reset previous errors
|
||||
formHandle.process(
|
||||
Utils.truePredicate(),
|
||||
fieldAccessor -> fieldAccessor.resetError());
|
||||
Form.FormFieldAccessor::resetError);
|
||||
|
||||
// first test the connection on ad hoc object
|
||||
final Result<LmsSetupTestResult> result = this.resourceService.getRestService()
|
||||
|
@ -326,44 +349,29 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
}
|
||||
}
|
||||
|
||||
return handleTestResult(
|
||||
action,
|
||||
a -> {
|
||||
// try to save the LmsSetup
|
||||
final PageAction processFormSave = formHandle.processFormSave(a);
|
||||
processFormSave.pageContext().publishInfo(
|
||||
new LocTextKey("sebserver.lmssetup.action.test.ok"));
|
||||
return processFormSave;
|
||||
},
|
||||
result.getOrThrow());
|
||||
return action;
|
||||
}
|
||||
|
||||
/** LmsSetup test action implementation */
|
||||
private PageAction testLmsSetup(
|
||||
public static PageAction testLmsSetup(
|
||||
final PageAction action,
|
||||
final FormHandle<LmsSetup> formHandle, final boolean saveFirst) {
|
||||
|
||||
if (saveFirst) {
|
||||
final Result<LmsSetup> postResult = formHandle.doAPIPost();
|
||||
if (postResult.hasError()) {
|
||||
formHandle.handleError(postResult.getError());
|
||||
postResult.getOrThrow();
|
||||
}
|
||||
}
|
||||
final FormHandle<LmsSetup> formHandle,
|
||||
final RestService restService) {
|
||||
|
||||
// Call the testing endpoint with the specified data to test
|
||||
final EntityKey entityKey = action.getEntityKey();
|
||||
final RestService restService = this.resourceService.getRestService();
|
||||
final Result<LmsSetupTestResult> result = restService.getBuilder(TestLmsSetup.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.getModelId())
|
||||
.call();
|
||||
|
||||
// ... and handle the response
|
||||
if (result.hasError()) {
|
||||
if (formHandle.handleError(result.getError())) {
|
||||
if (formHandle != null && formHandle.handleError(result.getError())) {
|
||||
throw new PageMessageException(
|
||||
new LocTextKey("sebserver.lmssetup.action.test.missingParameter"));
|
||||
}
|
||||
|
||||
result.getOrThrow();
|
||||
}
|
||||
|
||||
return handleTestResult(
|
||||
|
@ -377,7 +385,7 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
result.getOrThrow());
|
||||
}
|
||||
|
||||
private PageAction handleTestResult(
|
||||
private static PageAction handleTestResult(
|
||||
final PageAction action,
|
||||
final Function<PageAction, PageAction> onOK,
|
||||
final LmsSetupTestResult testResult) {
|
||||
|
|
|
@ -144,9 +144,20 @@ public class LmsSetupList implements TemplateComposer {
|
|||
this.pageService.getResourceService().<LmsSetup> localizedActivityFunction())
|
||||
.withFilter(this.activityFilter)
|
||||
.sortable())
|
||||
|
||||
.withDefaultAction(actionBuilder
|
||||
.newAction(ActionDefinition.LMS_SETUP_VIEW_FROM_LIST)
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
ActionDefinition.LMS_SETUP_TOGGLE_ACTIVITY,
|
||||
ActionDefinition.LMS_SETUP_ACTIVATE,
|
||||
ActionDefinition.LMS_SETUP_DEACTIVATE,
|
||||
pageContext,
|
||||
ActionDefinition.LMS_SETUP_VIEW_FROM_LIST,
|
||||
ActionDefinition.LMS_SETUP_MODIFY_FROM_LIST,
|
||||
ActionDefinition.LMS_SETUP_TOGGLE_ACTIVITY))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
|
@ -158,13 +169,21 @@ public class LmsSetupList implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.LMS_SETUP_VIEW_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> table.hasAnyContent())
|
||||
.publishIf(table::hasAnyContent, false)
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_MODIFY_FROM_LIST)
|
||||
.withSelect(
|
||||
table.getGrantedSelection(currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> userGrant.im() && table.hasAnyContent());
|
||||
.publishIf(() -> userGrant.im() && table.hasAnyContent(), false)
|
||||
|
||||
.newAction(ActionDefinition.LMS_SETUP_TOGGLE_ACTIVITY)
|
||||
.withExec(this.pageService.activationToggleActionFunction(
|
||||
table,
|
||||
EMPTY_SELECTION_TEXT_KEY,
|
||||
action -> LmsSetupForm.testLmsSetup(action, null, restService)))
|
||||
.withConfirm(this.pageService.confirmDeactivation(table))
|
||||
.publishIf(() -> userGrant.im() && table.hasAnyContent(), false);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ package ch.ethz.seb.sebserver.gui.content;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetExtendedClientEventPage;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
@ -82,6 +84,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
private final ResourceService resourceService;
|
||||
private final I18nSupport i18nSupport;
|
||||
private final InstructionProcessor instructionProcessor;
|
||||
private final SebClientLogDetailsPopup sebClientLogDetailsPopup;
|
||||
private final long pollInterval;
|
||||
private final int pageSize;
|
||||
|
||||
|
@ -94,6 +97,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
final PageService pageService,
|
||||
final ResourceService resourceService,
|
||||
final InstructionProcessor instructionProcessor,
|
||||
final SebClientLogDetailsPopup sebClientLogDetailsPopup,
|
||||
@Value("${sebserver.gui.webservice.poll-interval:500}") final long pollInterval,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
|
||||
|
@ -103,6 +107,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
this.i18nSupport = resourceService.getI18nSupport();
|
||||
this.instructionProcessor = instructionProcessor;
|
||||
this.pollInterval = pollInterval;
|
||||
this.sebClientLogDetailsPopup = sebClientLogDetailsPopup;
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.typeFilter = new TableFilterAttribute(
|
||||
|
@ -160,29 +165,38 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
this.serverPushService.runServerPush(
|
||||
new ServerPushContext(content, Utils.truePredicate()),
|
||||
this.pollInterval,
|
||||
clientConnectionDetails::updateData,
|
||||
clientConnectionDetails::updateGUI);
|
||||
context1 -> clientConnectionDetails.updateData(),
|
||||
context -> clientConnectionDetails.updateGUI());
|
||||
|
||||
widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
EVENT_LIST_TITLE_KEY);
|
||||
|
||||
PageService.PageActionBuilder actionBuilder = this.pageService
|
||||
.pageActionBuilder(
|
||||
pageContext
|
||||
.clearAttributes()
|
||||
.clearEntityKeys());
|
||||
|
||||
|
||||
// client event table for this connection
|
||||
this.pageService.entityTableBuilder(restService.getRestCall(GetClientEventPage.class))
|
||||
this.pageService.entityTableBuilder(restService.getRestCall(GetExtendedClientEventPage.class))
|
||||
.withEmptyMessage(EMPTY_LIST_TEXT_KEY)
|
||||
.withPaging(this.pageSize)
|
||||
.withRestCallAdapter(restCallBuilder -> restCallBuilder.withQueryParam(
|
||||
ClientEvent.FILTER_ATTR_CONECTION_ID,
|
||||
entityKey.modelId))
|
||||
.withColumn(new ColumnDefinition<ClientEvent>(
|
||||
|
||||
.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<>(
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_TEXT,
|
||||
LIST_COLUMN_TEXT_KEY,
|
||||
ClientEvent::getText)
|
||||
|
@ -190,19 +204,22 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
.sortable()
|
||||
.withCellTooltip()
|
||||
.widthProportion(4))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_NUMERIC_VALUE,
|
||||
LIST_COLUMN_VALUE_KEY,
|
||||
ClientEvent::getValue)
|
||||
.widthProportion(1))
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
|
||||
.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<>(
|
||||
|
||||
.withColumn(new ColumnDefinition<ExtendedClientEvent>(
|
||||
Domain.CLIENT_EVENT.ATTR_SERVER_TIME,
|
||||
new LocTextKey(LIST_COLUMN_SERVER_TIME_KEY.name,
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()),
|
||||
|
@ -210,15 +227,17 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
.sortable()
|
||||
.widthProportion(1))
|
||||
|
||||
.withDefaultAction(t -> actionBuilder
|
||||
.newAction(ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS)
|
||||
.withExec(action -> sebClientLogDetailsPopup.showDetails(action, t.getSingleSelectedROWData()))
|
||||
.noEventPropagation()
|
||||
.create())
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
this.pageService
|
||||
.pageActionBuilder(
|
||||
pageContext
|
||||
.clearAttributes()
|
||||
.clearEntityKeys())
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_FROM_DETAILS)
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_BACK_TO_OVERVIEW)
|
||||
.withEntityKey(parentEntityKey)
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER))
|
||||
|
||||
|
@ -237,7 +256,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
|
||||
}
|
||||
|
||||
private final String getClientTime(final ClientEvent event) {
|
||||
private String getClientTime(final ClientEvent event) {
|
||||
if (event == null || event.getClientTime() == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
@ -246,7 +265,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
.formatDisplayTime(Utils.toDateTimeUTC(event.getClientTime()));
|
||||
}
|
||||
|
||||
private final String getServerTime(final ClientEvent event) {
|
||||
private String getServerTime(final ClientEvent event) {
|
||||
if (event == null || event.getServerTime() == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
|
|
@ -135,12 +135,18 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
indicators,
|
||||
restCall);
|
||||
|
||||
clientTable.withDefaultAction(
|
||||
clientTable
|
||||
.withDefaultAction(
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION)
|
||||
.withParentEntityKey(entityKey)
|
||||
.create(),
|
||||
this.pageService);
|
||||
this.pageService)
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.MONITOR_EXAM_CLIENT_CONNECTION,
|
||||
ActionDefinition.MONITOR_EXAM_QUIT_SELECTED,
|
||||
ActionDefinition.MONITOR_EXAM_DISABLE_SELECTED_CONNECTION));
|
||||
|
||||
this.serverPushService.runServerPush(
|
||||
new ServerPushContext(content, Utils.truePredicate()),
|
||||
|
@ -170,7 +176,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
|
||||
return copyOfPageAction;
|
||||
})
|
||||
.publishIf(privilege)
|
||||
.publishIf(privilege, false)
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_QUIT_ALL)
|
||||
.withEntityKey(entityKey)
|
||||
|
@ -187,7 +193,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
action -> this.quitSebClients(action, clientTable, false),
|
||||
EMPTY_ACTIVE_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(privilege)
|
||||
.publishIf(privilege, false)
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_DISABLE_SELECTED_CONNECTION)
|
||||
.withEntityKey(entityKey)
|
||||
|
@ -197,7 +203,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
action -> this.disableSebClients(action, clientTable, false),
|
||||
EMPTY_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(privilege);
|
||||
.publishIf(privilege, false);
|
||||
|
||||
if (privilege.getAsBoolean()) {
|
||||
|
||||
|
@ -272,7 +278,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
}
|
||||
}
|
||||
|
||||
private static final Function<PageAction, PageAction> showStateViewAction(
|
||||
private static Function<PageAction, PageAction> showStateViewAction(
|
||||
final ClientConnectionTable clientTable,
|
||||
final ConnectionStatus status) {
|
||||
|
||||
|
@ -283,7 +289,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
};
|
||||
}
|
||||
|
||||
private static final Function<PageAction, PageAction> hideStateViewAction(
|
||||
private static Function<PageAction, PageAction> hideStateViewAction(
|
||||
final ClientConnectionTable clientTable,
|
||||
final ConnectionStatus status) {
|
||||
|
||||
|
@ -337,7 +343,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
return action;
|
||||
}
|
||||
|
||||
private final Consumer<ServerPushContext> updateTableGUI(final ClientConnectionTable clientTable) {
|
||||
private Consumer<ServerPushContext> updateTableGUI(final ClientConnectionTable clientTable) {
|
||||
return context -> {
|
||||
if (!context.isDisposed()) {
|
||||
try {
|
||||
|
|
|
@ -131,13 +131,17 @@ public class MonitoringRunningExamList implements TemplateComposer {
|
|||
.newAction(ActionDefinition.MONITOR_EXAM_FROM_LIST)
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.MONITOR_EXAM_FROM_LIST))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
|
||||
.newAction(ActionDefinition.MONITOR_EXAM_FROM_LIST)
|
||||
.withSelect(table::getSelection, PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER));
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER), false);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Collection;
|
|||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
@ -57,21 +58,14 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
|||
public class QuizDiscoveryList implements TemplateComposer {
|
||||
|
||||
// localized text keys
|
||||
private static final LocTextKey QUIZ_DETAILS_URL_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.url");
|
||||
private static final LocTextKey QUIZ_DETAILS_DESCRIPTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.description");
|
||||
private static final LocTextKey QUIZ_DETAILS_START_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.starttime");
|
||||
private static final LocTextKey QUIZ_DETAILS_END_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.endtime");
|
||||
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.list.title");
|
||||
private static final LocTextKey EMPTY_LIST_TEXT_KEY =
|
||||
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 =
|
||||
private final static LocTextKey INSTITUTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.list.column.institution");
|
||||
private final static LocTextKey LMS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.list.column.lmssetup");
|
||||
|
@ -83,6 +77,20 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
new LocTextKey("sebserver.quizdiscovery.list.column.endtime");
|
||||
private final static LocTextKey DETAILS_TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.title");
|
||||
private static final LocTextKey QUIZ_DETAILS_URL_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.url");
|
||||
private static final LocTextKey QUIZ_DETAILS_INSTITUTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.institution");
|
||||
private static final LocTextKey QUIZ_DETAILS_LMS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.lmssetup");
|
||||
private static final LocTextKey QUIZ_DETAILS_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.name");
|
||||
private static final LocTextKey QUIZ_DETAILS_DESCRIPTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.description");
|
||||
private static final LocTextKey QUIZ_DETAILS_START_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.starttime");
|
||||
private static final LocTextKey QUIZ_DETAILS_END_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.details.endtime");
|
||||
private final static LocTextKey NO_IMPORT_OF_OUT_DATED_QUIZ =
|
||||
new LocTextKey("sebserver.quizdiscovery.quiz.import.out.dated");
|
||||
|
||||
|
@ -151,8 +159,8 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
.withColumnIf(
|
||||
isSebAdmin,
|
||||
() -> new ColumnDefinition<QuizData>(
|
||||
QuizData.QUIZ_ATTR_INSTITUION_ID,
|
||||
INSTITUION_TEXT_KEY,
|
||||
QuizData.QUIZ_ATTR_INSTITUTION_ID,
|
||||
INSTITUTION_TEXT_KEY,
|
||||
quiz -> institutionNameFunction
|
||||
.apply(String.valueOf(quiz.institutionId)))
|
||||
.withFilter(this.institutionFilter))
|
||||
|
@ -202,16 +210,16 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
.noEventPropagation()
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS,
|
||||
ActionDefinition.QUIZ_DISCOVERY_EXAM_IMPORT))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
final GrantCheck examGrant = currentUser.grantCheck(EntityType.EXAM);
|
||||
actionBuilder
|
||||
|
||||
// Removed as discussed in SEBSERV-52
|
||||
// .newAction(ActionDefinition.LMS_SETUP_NEW)
|
||||
// .publishIf(lmsSetupGrant::iw)
|
||||
|
||||
.newAction(ActionDefinition.QUIZ_DISCOVERY_SHOW_DETAILS)
|
||||
.withSelect(
|
||||
table::getSelection,
|
||||
|
@ -221,14 +229,14 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
institutionNameFunction),
|
||||
EMPTY_SELECTION_TEXT)
|
||||
.noEventPropagation()
|
||||
.publishIf(table::hasAnyContent)
|
||||
.publishIf(table::hasAnyContent, false)
|
||||
|
||||
.newAction(ActionDefinition.QUIZ_DISCOVERY_EXAM_IMPORT)
|
||||
.withSelect(
|
||||
table::getSelection,
|
||||
action -> this.importQuizData(action, table),
|
||||
EMPTY_SELECTION_TEXT)
|
||||
.publishIf(() -> examGrant.im() && table.hasAnyContent());
|
||||
.publishIf(() -> examGrant.im() && table.hasAnyContent(), false);
|
||||
}
|
||||
|
||||
private static Function<QuizData, String> quizDataLmsSetupNameFunction(final ResourceService resourceService) {
|
||||
|
@ -250,7 +258,7 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
return action
|
||||
.withEntityKey(action.getSingleSelection())
|
||||
.withParentEntityKey(new EntityKey(selectedROWData.lmsSetupId, EntityType.LMS_SETUP))
|
||||
.withAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA, "true");
|
||||
.withAttribute(AttributeKeys.IMPORT_FROM_QUIZ_DATA, Constants.TRUE_STRING);
|
||||
}
|
||||
|
||||
private PageAction showDetails(
|
||||
|
@ -291,17 +299,17 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
.addFieldIf(
|
||||
() -> this.resourceService.getCurrentUser().get().hasRole(UserRole.SEB_SERVER_ADMIN),
|
||||
() -> FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_INSTITUION_ID,
|
||||
INSTITUION_TEXT_KEY,
|
||||
QuizData.QUIZ_ATTR_INSTITUTION_ID,
|
||||
QUIZ_DETAILS_INSTITUTION_TEXT_KEY,
|
||||
institutionNameFunction.apply(quizData.getModelId())))
|
||||
.addField(FormBuilder.singleSelection(
|
||||
QuizData.QUIZ_ATTR_LMS_SETUP_ID,
|
||||
LMS_TEXT_KEY,
|
||||
QUIZ_DETAILS_LMS_TEXT_KEY,
|
||||
String.valueOf(quizData.lmsSetupId),
|
||||
() -> this.resourceService.lmsSetupResource()))
|
||||
this.resourceService::lmsSetupResource))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_NAME,
|
||||
NAME_TEXT_KEY,
|
||||
QUIZ_DETAILS_NAME_TEXT_KEY,
|
||||
quizData.name))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_DESCRIPTION,
|
||||
|
@ -323,19 +331,17 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
|
||||
if (!quizData.additionalAttributes.isEmpty()) {
|
||||
quizData.additionalAttributes
|
||||
.entrySet()
|
||||
.stream()
|
||||
.forEach(entry -> {
|
||||
LocTextKey titleKey = new LocTextKey(TEXT_KEY_ADDITIONAL_ATTR_PREFIX + entry.getKey());
|
||||
.forEach((key, value) -> {
|
||||
LocTextKey titleKey = new LocTextKey(TEXT_KEY_ADDITIONAL_ATTR_PREFIX + key);
|
||||
if (!this.pageService.getI18nSupport().hasText(titleKey)) {
|
||||
titleKey = new LocTextKey(entry.getKey());
|
||||
titleKey = new LocTextKey(key);
|
||||
}
|
||||
formbuilder
|
||||
.addField(FormBuilder.text(
|
||||
entry.getKey(),
|
||||
key,
|
||||
titleKey,
|
||||
toAdditionalValue(entry.getKey(), entry.getValue()))
|
||||
.asHTML(ADDITIONAL_HTML_ATTRIBUTES.contains(entry.getKey())));
|
||||
toAdditionalValue(key, value))
|
||||
.asHTML(ADDITIONAL_HTML_ATTRIBUTES.contains(key)));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -343,7 +349,7 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
}
|
||||
|
||||
private String toAdditionalValue(final String name, final String value) {
|
||||
if ("timecreated".equals(name)) {
|
||||
if (QuizData.ATTR_ADDITIONAL_CREATION_TIME.equals(name)) {
|
||||
try {
|
||||
return this.pageService
|
||||
.getI18nSupport()
|
||||
|
@ -351,7 +357,7 @@ public class QuizDiscoveryList implements TemplateComposer {
|
|||
} catch (final Exception e) {
|
||||
return value;
|
||||
}
|
||||
} else if ("timelimit".equals(name)) {
|
||||
} else if (QuizData.ATTR_ADDITIONAL_TIME_LIMIT.equals(name)) {
|
||||
try {
|
||||
return this.pageService
|
||||
.getI18nSupport()
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* 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 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.exam.Exam;
|
||||
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.ExtendedClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
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.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.exam.GetExam;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnection;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SebClientLogDetailsPopup {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SebClientLogDetailsPopup.class);
|
||||
|
||||
private static final LocTextKey DETAILS_TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.title");
|
||||
private static final LocTextKey DETAILS_EVENT_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.event.title");
|
||||
private static final LocTextKey DETAILS_CONNECTION_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.connection.title");
|
||||
private static final LocTextKey DETAILS_EXAM_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.exam.title");
|
||||
|
||||
private static final LocTextKey FORM_TYPE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.type");
|
||||
private static final LocTextKey FORM_SERVERTIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.server-time");
|
||||
private static final LocTextKey FORM_CLIENTTIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.client-time");
|
||||
private static final LocTextKey FORM_VALUE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.value");
|
||||
private static final LocTextKey FORM_MESSAGE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.message");
|
||||
|
||||
private static final LocTextKey FORM_SESSION_ID_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.session-id");
|
||||
private static final LocTextKey FORM_ADDRESS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.address");
|
||||
private static final LocTextKey FORM_TOKEN_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.token");
|
||||
private static final LocTextKey FORM_STATUS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.status");
|
||||
private static final LocTextKey FORM_EXAM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.name");
|
||||
private static final LocTextKey FORM_DESC_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.description");
|
||||
private static final LocTextKey FORM_EXAM_TYPE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.type");
|
||||
private static final LocTextKey FORM_START_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.startTime");
|
||||
private static final LocTextKey FORM_END_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.endTime");
|
||||
|
||||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
private final RestService restService;
|
||||
private final I18nSupport i18nSupport;
|
||||
private final WidgetFactory widgetFactory;
|
||||
|
||||
public SebClientLogDetailsPopup(
|
||||
final PageService pageService,
|
||||
final WidgetFactory widgetFactory) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.restService = pageService.getRestService();
|
||||
this.i18nSupport = pageService.getI18nSupport();
|
||||
}
|
||||
|
||||
PageAction showDetails(final PageAction action, final ExtendedClientEvent clientEvent) {
|
||||
action.getSingleSelection();
|
||||
|
||||
final ModalInputDialog<Void> dialog = new ModalInputDialog<>(
|
||||
action.pageContext().getParent().getShell(),
|
||||
this.widgetFactory);
|
||||
dialog.setDialogWidth(600);
|
||||
|
||||
dialog.open(
|
||||
DETAILS_TITLE_TEXT_KEY,
|
||||
action.pageContext(),
|
||||
pc -> createDetailsForm(clientEvent, pc));
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
private void createDetailsForm(final ExtendedClientEvent clientEvent, final PageContext pc) {
|
||||
|
||||
final Composite parent = pc.getParent();
|
||||
final Composite content = this.widgetFactory.createPopupScrollComposite(parent);
|
||||
|
||||
// Event Details Title
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
WidgetFactory.CustomVariant.TEXT_H3,
|
||||
DETAILS_EVENT_TILE_TEXT_KEY);
|
||||
|
||||
PageContext formContext = pc.copyOf(content);
|
||||
|
||||
this.pageService.formBuilder(formContext)
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.TYPE_NAME,
|
||||
FORM_TYPE_TEXT_KEY,
|
||||
this.resourceService.getEventTypeName(clientEvent)))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_CLIENT_TIME,
|
||||
FORM_CLIENTTIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateTime(clientEvent.clientTime) + " " +
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_SERVER_TIME,
|
||||
FORM_SERVERTIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateTime(clientEvent.serverTime) + " " +
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_NUMERIC_VALUE,
|
||||
FORM_VALUE_TEXT_KEY,
|
||||
(clientEvent.numValue != null)
|
||||
? String.valueOf(clientEvent.numValue)
|
||||
: Constants.EMPTY_NOTE))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_TEXT,
|
||||
FORM_MESSAGE_TEXT_KEY,
|
||||
clientEvent.text)
|
||||
.asArea())
|
||||
.build();
|
||||
|
||||
// SEB Client Connection Title
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
WidgetFactory.CustomVariant.TEXT_H3,
|
||||
DETAILS_CONNECTION_TILE_TEXT_KEY);
|
||||
|
||||
final ClientConnection connection = this.restService.getBuilder(GetClientConnection.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(clientEvent.connectionId))
|
||||
.call()
|
||||
.get(
|
||||
error -> log.error("Failed to get ClientConnection for id {}", clientEvent.connectionId, error),
|
||||
() -> ClientConnection.EMPTY_CLIENT_CONNECTION);
|
||||
|
||||
this.pageService.formBuilder(formContext)
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
|
||||
FORM_SESSION_ID_TEXT_KEY,
|
||||
connection.userSessionId))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_CLIENT_ADDRESS,
|
||||
FORM_ADDRESS_TEXT_KEY,
|
||||
connection.clientAddress))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN,
|
||||
FORM_TOKEN_TEXT_KEY,
|
||||
connection.connectionToken))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_STATUS,
|
||||
FORM_STATUS_TEXT_KEY,
|
||||
this.resourceService.localizedClientConnectionStatusName(connection.status)))
|
||||
.build();
|
||||
|
||||
// Exam Details Title
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
WidgetFactory.CustomVariant.TEXT_H3,
|
||||
DETAILS_EXAM_TILE_TEXT_KEY);
|
||||
|
||||
final Exam exam = this.restService.getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(clientEvent.examId))
|
||||
.call()
|
||||
.get(
|
||||
error -> log.error("Failed to get Exam for id {}", clientEvent.examId, error),
|
||||
() -> Exam.EMPTY_EXAM);
|
||||
|
||||
this.pageService.formBuilder(formContext)
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_NAME,
|
||||
FORM_EXAM_NAME_TEXT_KEY,
|
||||
exam.name))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_DESCRIPTION,
|
||||
FORM_DESC_TEXT_KEY,
|
||||
exam.description))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.EXAM.ATTR_TYPE,
|
||||
FORM_EXAM_TYPE_TEXT_KEY,
|
||||
this.resourceService.localizedExamTypeName(exam)))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_START_TIME,
|
||||
FORM_START_TIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateWithTimeZone(exam.startTime)))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_END_TIME,
|
||||
FORM_END_TIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateWithTimeZone(exam.endTime)))
|
||||
.build();
|
||||
|
||||
}
|
||||
}
|
|
@ -8,28 +8,14 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.exam.Exam;
|
||||
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.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;
|
||||
|
@ -37,28 +23,26 @@ 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.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.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.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;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
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 java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SebClientLogs implements TemplateComposer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SebClientLogs.class);
|
||||
|
||||
private static final LocTextKey DETAILS_TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.title");
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.list.title");
|
||||
private static final LocTextKey EMPTY_TEXT_KEY =
|
||||
|
@ -74,45 +58,6 @@ public class SebClientLogs implements TemplateComposer {
|
|||
new LocTextKey("sebserver.seblogs.list.column.time");
|
||||
private static final LocTextKey VALUE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.list.column.value");
|
||||
|
||||
private static final LocTextKey DETAILS_EVENT_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.event.title");
|
||||
private static final LocTextKey DETAILS_CONNECTION_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.connection.title");
|
||||
private static final LocTextKey DETAILS_EXAM_TILE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.details.exam.title");
|
||||
|
||||
private static final LocTextKey FORM_TYPE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.type");
|
||||
private static final LocTextKey FORM_SERVERTIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.server-time");
|
||||
private static final LocTextKey FORM_CLIENTTIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.client-time");
|
||||
private static final LocTextKey FORM_VALUE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.value");
|
||||
private static final LocTextKey FORM_MESSAGE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.message");
|
||||
|
||||
private static final LocTextKey FORM_SESSION_ID_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.session-id");
|
||||
private static final LocTextKey FORM_ADDRESS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.address");
|
||||
private static final LocTextKey FORM_TOKEN_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.token");
|
||||
private static final LocTextKey FORM_STATUS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.connection.status");
|
||||
|
||||
private static final LocTextKey FORM_EXAM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.name");
|
||||
private static final LocTextKey FORM_DESC_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.description");
|
||||
private static final LocTextKey FORM_EXAM_TYPE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.type");
|
||||
private static final LocTextKey FORM_START_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.startTime");
|
||||
private static final LocTextKey FORM_END_TIME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.form.column.exam.endTime");
|
||||
|
||||
private final static LocTextKey EMPTY_SELECTION_TEXT =
|
||||
new LocTextKey("sebserver.seblogs.info.pleaseSelect");
|
||||
|
||||
|
@ -124,18 +69,19 @@ public class SebClientLogs implements TemplateComposer {
|
|||
private final ResourceService resourceService;
|
||||
private final RestService restService;
|
||||
private final I18nSupport i18nSupport;
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final SebClientLogDetailsPopup sebClientLogDetailsPopup;
|
||||
private final int pageSize;
|
||||
|
||||
public SebClientLogs(
|
||||
final PageService pageService,
|
||||
final SebClientLogDetailsPopup sebClientLogDetailsPopup,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
|
||||
this.pageService = pageService;
|
||||
this.resourceService = pageService.getResourceService();
|
||||
this.restService = this.resourceService.getRestService();
|
||||
this.i18nSupport = this.resourceService.getI18nSupport();
|
||||
this.widgetFactory = pageService.getWidgetFactory();
|
||||
this.sebClientLogDetailsPopup = sebClientLogDetailsPopup;
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.examFilter = new TableFilterAttribute(
|
||||
|
@ -220,162 +166,34 @@ public class SebClientLogs implements TemplateComposer {
|
|||
|
||||
.withDefaultAction(t -> actionBuilder
|
||||
.newAction(ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS)
|
||||
.withExec(action -> this.showDetails(action, t.getSingleSelectedROWData()))
|
||||
.withExec(action -> sebClientLogDetailsPopup.showDetails(action, t.getSingleSelectedROWData()))
|
||||
.noEventPropagation()
|
||||
.create())
|
||||
|
||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||
pageContext,
|
||||
ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS))
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.LOGS_SEB_CLIENT_SHOW_DETAILS)
|
||||
.withSelect(
|
||||
table::getSelection,
|
||||
action -> this.showDetails(action, table.getSingleSelectedROWData()),
|
||||
action -> sebClientLogDetailsPopup.showDetails(action, table.getSingleSelectedROWData()),
|
||||
EMPTY_SELECTION_TEXT)
|
||||
.noEventPropagation()
|
||||
.publishIf(table::hasAnyContent);
|
||||
.publishIf(table::hasAnyContent, false);
|
||||
}
|
||||
|
||||
private PageAction showDetails(final PageAction action, final ExtendedClientEvent clientEvent) {
|
||||
action.getSingleSelection();
|
||||
|
||||
final ModalInputDialog<Void> dialog = new ModalInputDialog<>(
|
||||
action.pageContext().getParent().getShell(),
|
||||
this.widgetFactory);
|
||||
dialog.setDialogWidth(600);
|
||||
|
||||
dialog.open(
|
||||
DETAILS_TITLE_TEXT_KEY,
|
||||
action.pageContext(),
|
||||
pc -> createDetailsForm(clientEvent, pc));
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
private void createDetailsForm(final ExtendedClientEvent clientEvent, final PageContext pc) {
|
||||
|
||||
final Composite parent = pc.getParent();
|
||||
final Composite content = this.widgetFactory.createPopupScrollComposite(parent);
|
||||
|
||||
// Event Details Title
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
DETAILS_EVENT_TILE_TEXT_KEY);
|
||||
|
||||
this.pageService.formBuilder(pc.copyOf(content))
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.TYPE_NAME,
|
||||
FORM_TYPE_TEXT_KEY,
|
||||
this.resourceService.getEventTypeName(clientEvent)))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_CLIENT_TIME,
|
||||
FORM_CLIENTTIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateTime(clientEvent.clientTime) + " " +
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_SERVER_TIME,
|
||||
FORM_SERVERTIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateTime(clientEvent.serverTime) + " " +
|
||||
this.i18nSupport.getUsersTimeZoneTitleSuffix()))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_NUMERIC_VALUE,
|
||||
FORM_VALUE_TEXT_KEY,
|
||||
(clientEvent.numValue != null)
|
||||
? String.valueOf(clientEvent.numValue)
|
||||
: Constants.EMPTY_NOTE))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_EVENT.ATTR_TEXT,
|
||||
FORM_MESSAGE_TEXT_KEY,
|
||||
clientEvent.text)
|
||||
.asArea())
|
||||
.build();
|
||||
|
||||
// SEB Client Connection Title
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
DETAILS_CONNECTION_TILE_TEXT_KEY);
|
||||
|
||||
final ClientConnection connection = this.restService.getBuilder(GetClientConnection.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(clientEvent.connectionId))
|
||||
.call()
|
||||
.get(
|
||||
error -> log.error("Failed to get ClientConnection for id {}", clientEvent.connectionId, error),
|
||||
() -> ClientConnection.EMPTY_CLIENT_CONNECTION);
|
||||
|
||||
this.pageService.formBuilder(pc.copyOf(content))
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
|
||||
FORM_SESSION_ID_TEXT_KEY,
|
||||
connection.userSessionId))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_CLIENT_ADDRESS,
|
||||
FORM_ADDRESS_TEXT_KEY,
|
||||
connection.clientAddress))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN,
|
||||
FORM_TOKEN_TEXT_KEY,
|
||||
connection.connectionToken))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.CLIENT_CONNECTION.ATTR_STATUS,
|
||||
FORM_STATUS_TEXT_KEY,
|
||||
this.resourceService.localizedClientConnectionStatusName(connection.status)))
|
||||
.build();
|
||||
|
||||
// Exam Details Title
|
||||
this.widgetFactory.labelLocalized(
|
||||
content,
|
||||
CustomVariant.TEXT_H3,
|
||||
DETAILS_EXAM_TILE_TEXT_KEY);
|
||||
|
||||
final Exam exam = this.restService.getBuilder(GetExam.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, String.valueOf(clientEvent.examId))
|
||||
.call()
|
||||
.get(
|
||||
error -> log.error("Failed to get Exam for id {}", clientEvent.examId, error),
|
||||
() -> Exam.EMPTY_EXAM);
|
||||
|
||||
this.pageService.formBuilder(pc.copyOf(content))
|
||||
.withDefaultSpanInput(6)
|
||||
.withEmptyCellSeparation(false)
|
||||
.readonly(true)
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_NAME,
|
||||
FORM_EXAM_NAME_TEXT_KEY,
|
||||
exam.name))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_DESCRIPTION,
|
||||
FORM_DESC_TEXT_KEY,
|
||||
exam.description))
|
||||
.addField(FormBuilder.text(
|
||||
Domain.EXAM.ATTR_TYPE,
|
||||
FORM_EXAM_TYPE_TEXT_KEY,
|
||||
this.resourceService.localizedExamTypeName(exam)))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_START_TIME,
|
||||
FORM_START_TIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateWithTimeZone(exam.startTime)))
|
||||
.addField(FormBuilder.text(
|
||||
QuizData.QUIZ_ATTR_END_TIME,
|
||||
FORM_END_TIME_TEXT_KEY,
|
||||
this.i18nSupport.formatDisplayDateWithTimeZone(exam.endTime)))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
private Function<ExtendedClientEvent, String> examNameFunction() {
|
||||
final Map<Long, String> examNameMapping = this.resourceService.getExamNameMapping();
|
||||
return event -> examNameMapping.get(event.examId);
|
||||
}
|
||||
|
||||
private final String getEventTime(final ExtendedClientEvent event) {
|
||||
private String getEventTime(final ExtendedClientEvent event) {
|
||||
if (event == null || event.serverTime == null) {
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ final class SebExamConfigCreationPopup {
|
|||
};
|
||||
}
|
||||
|
||||
private static final boolean doCreate(
|
||||
private static boolean doCreate(
|
||||
final PageService pageService,
|
||||
final PageContext pageContext,
|
||||
final boolean copyAsTemplate,
|
||||
|
|
|
@ -183,6 +183,11 @@ public enum ActionDefinition {
|
|||
ImageIcon.SAVE,
|
||||
PageStateDefinitionImpl.LMS_SETUP_VIEW,
|
||||
ActionCategory.FORM),
|
||||
LMS_SETUP_SAVE_AND_ACTIVATE(
|
||||
new LocTextKey("sebserver.form.action.save.activate"),
|
||||
ImageIcon.ACTIVE,
|
||||
PageStateDefinitionImpl.LMS_SETUP_VIEW,
|
||||
ActionCategory.FORM),
|
||||
LMS_SETUP_ACTIVATE(
|
||||
new LocTextKey("sebserver.lmssetup.action.activate"),
|
||||
ImageIcon.TOGGLE_OFF,
|
||||
|
@ -193,6 +198,11 @@ public enum ActionDefinition {
|
|||
ImageIcon.TOGGLE_ON,
|
||||
PageStateDefinitionImpl.LMS_SETUP_VIEW,
|
||||
ActionCategory.FORM),
|
||||
LMS_SETUP_TOGGLE_ACTIVITY(
|
||||
new LocTextKey("sebserver.overall.action.toggle-activity"),
|
||||
ImageIcon.SWITCH,
|
||||
PageStateDefinitionImpl.LMS_SETUP_LIST,
|
||||
ActionCategory.LMS_SETUP_LIST),
|
||||
|
||||
QUIZ_DISCOVERY_VIEW_LIST(
|
||||
new LocTextKey("sebserver.quizdiscovery.action.list"),
|
||||
|
@ -593,7 +603,7 @@ public enum ActionDefinition {
|
|||
ImageIcon.SEND_QUIT,
|
||||
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
|
||||
ActionCategory.FORM),
|
||||
MONITOR_EXAM_FROM_DETAILS(
|
||||
MONITOR_EXAM_BACK_TO_OVERVIEW(
|
||||
new LocTextKey("sebserver.monitoring.exam.action.detail.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.MONITORING_RUNNING_EXAM,
|
||||
|
|
|
@ -132,7 +132,7 @@ public class FormHandle<T extends Entity> {
|
|||
return resultAction;
|
||||
})
|
||||
.onError(this::handleError)
|
||||
.getOrThrow(error -> new FormPostException(error));
|
||||
.getOrThrow(FormPostException::new);
|
||||
}
|
||||
|
||||
public boolean handleError(final Exception error) {
|
||||
|
|
|
@ -36,7 +36,7 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
|||
Consumer<String> numberCheck = null;
|
||||
boolean isArea = false;
|
||||
int areaMinHeight = WidgetFactory.TEXT_AREA_INPUT_MIN_HEIGHT;
|
||||
boolean isColorbox = false;
|
||||
boolean isColorBox = false;
|
||||
boolean isHTML = false;
|
||||
|
||||
TextFieldBuilder(final String name, final LocTextKey label, final String value) {
|
||||
|
@ -80,8 +80,8 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TextFieldBuilder asColorbox() {
|
||||
this.isColorbox = true;
|
||||
public TextFieldBuilder asColorBox() {
|
||||
this.isColorBox = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
|||
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||
if (this.isArea) {
|
||||
gridData.minimumHeight = this.areaMinHeight;
|
||||
} else if (this.isColorbox) {
|
||||
} else if (this.isColorBox) {
|
||||
gridData.minimumHeight = WidgetFactory.TEXT_INPUT_MIN_HEIGHT;
|
||||
textInput.setData(RWT.CUSTOM_VARIANT, "colorbox");
|
||||
}
|
||||
|
|
|
@ -164,8 +164,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> lmsTypeResources() {
|
||||
return Arrays.asList(LmsType.values())
|
||||
.stream()
|
||||
return Arrays.stream(LmsType.values())
|
||||
.filter(lmsType -> lmsType != LmsType.MOCKUP || this.mock_lms_enabled)
|
||||
.map(lmsType -> new Tuple<>(
|
||||
lmsType.name(),
|
||||
|
@ -175,8 +174,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> clientEventTypeResources() {
|
||||
return Arrays.asList(EventType.values())
|
||||
.stream()
|
||||
return Arrays.stream(EventType.values())
|
||||
.filter(eventType -> !CLIENT_EVENT_TYPE_EXCLUDE_MAP.contains(eventType))
|
||||
.map(eventType -> new Tuple<>(
|
||||
eventType.name(),
|
||||
|
@ -200,8 +198,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> indicatorTypeResources() {
|
||||
return Arrays.asList(IndicatorType.values())
|
||||
.stream()
|
||||
return Arrays.stream(IndicatorType.values())
|
||||
.map(type -> new Tuple3<>(
|
||||
type.name(),
|
||||
this.i18nSupport.getText(EXAM_INDICATOR_TYPE_PREFIX + type.name(), type.name()),
|
||||
|
@ -295,8 +292,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> entityTypeResources() {
|
||||
return Arrays.asList(EntityType.values())
|
||||
.stream()
|
||||
return Arrays.stream(EntityType.values())
|
||||
.filter(type -> !ENTITY_TYPE_EXCLUDE_MAP.contains(type))
|
||||
.map(type -> new Tuple<>(type.name(), getEntityTypeName(type)))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
|
@ -319,8 +315,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> userActivityTypeResources() {
|
||||
return Arrays.asList(UserLogActivityType.values())
|
||||
.stream()
|
||||
return Arrays.stream(UserLogActivityType.values())
|
||||
.map(type -> new Tuple<>(type.name(), getUserActivityTypeName(type)))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
|
@ -363,16 +358,13 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> examTypeResources() {
|
||||
return Arrays.asList(ExamType.values())
|
||||
.stream()
|
||||
.filter(type -> type != ExamType.UNDEFINED)
|
||||
return Arrays.stream(ExamType.values())
|
||||
.map(type -> new Tuple3<>(
|
||||
type.name(),
|
||||
this.i18nSupport.getText(EXAM_TYPE_PREFIX + type.name()),
|
||||
Utils.formatLineBreaks(this.i18nSupport.getText(
|
||||
this.i18nSupport.getText(EXAM_TYPE_PREFIX + type.name()) + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
|
||||
StringUtils.EMPTY))
|
||||
))
|
||||
EXAM_INDICATOR_TYPE_PREFIX + type.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
|
||||
StringUtils.EMPTY))))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
@ -382,8 +374,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> examConfigStatusResources(final boolean isAttachedToExam) {
|
||||
return Arrays.asList(ConfigurationStatus.values())
|
||||
.stream()
|
||||
return Arrays.stream(ConfigurationStatus.values())
|
||||
.filter(status -> {
|
||||
if (isAttachedToExam) {
|
||||
return status != ConfigurationStatus.READY_TO_USE;
|
||||
|
@ -579,8 +570,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> getAttributeTypeResources() {
|
||||
return Arrays.asList(AttributeType.values())
|
||||
.stream()
|
||||
return Arrays.stream(AttributeType.values())
|
||||
.filter(type -> !ATTRIBUTE_TYPES_NOT_DISPLAYED.contains(type))
|
||||
.map(type -> new Tuple<>(getAttributeTypeFilterName(type), getAttributeTypeName(type)))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
|
@ -629,21 +619,25 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
public List<Tuple<String>> sebRestrictionWhiteListResources() {
|
||||
return Arrays.asList(WhiteListPath.values())
|
||||
.stream()
|
||||
.map(type -> new Tuple<>(
|
||||
return Arrays.stream(WhiteListPath.values())
|
||||
.map(type -> new Tuple3<>(
|
||||
type.key,
|
||||
this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key)))
|
||||
this.i18nSupport.getText(SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name(), type.key),
|
||||
Utils.formatLineBreaks(this.i18nSupport.getText(
|
||||
SEB_RESTRICTION_WHITE_LIST_PREFIX + type.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
|
||||
StringUtils.EMPTY))))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Tuple<String>> sebRestrictionPermissionResources() {
|
||||
return Arrays.asList(PermissionComponent.values())
|
||||
.stream()
|
||||
.map(type -> new Tuple<>(
|
||||
return Arrays.stream(PermissionComponent.values())
|
||||
.map(type -> new Tuple3<>(
|
||||
type.key,
|
||||
this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key)))
|
||||
this.i18nSupport.getText(SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name(), type.key),
|
||||
Utils.formatLineBreaks(this.i18nSupport.getText(
|
||||
SEB_RESTRICTION_PERMISSIONS_PREFIX + type.name() + Constants.TOOLTIP_TEXT_KEY_SUFFIX,
|
||||
StringUtils.EMPTY))))
|
||||
.sorted(RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
|
|
@ -118,10 +118,25 @@ public interface PageService {
|
|||
*
|
||||
* @param table the entity table
|
||||
* @param noSelectionText LocTextKey for missing selection message
|
||||
* @param testBeforeActivation a function to test before activation. This function shall throw an error if test fails.
|
||||
* My be null if no specific test is needed before activation
|
||||
* @return page action execution function for switching the activity */
|
||||
<T extends Entity & Activatable> Function<PageAction, PageAction> activationToggleActionFunction(
|
||||
EntityTable<T> table,
|
||||
LocTextKey noSelectionText);
|
||||
LocTextKey noSelectionText,
|
||||
Function<PageAction, PageAction> testBeforeActivation);
|
||||
|
||||
/** Get a page action execution function for switching the activity of currently selected
|
||||
* entities from a given entity-table.
|
||||
*
|
||||
* @param table the entity table
|
||||
* @param noSelectionText LocTextKey for missing selection message
|
||||
* @return page action execution function for switching the activity */
|
||||
default <T extends Entity & Activatable> Function<PageAction, PageAction> activationToggleActionFunction(
|
||||
EntityTable<T> table,
|
||||
LocTextKey noSelectionText) {
|
||||
return this.activationToggleActionFunction(table, noSelectionText, null);
|
||||
}
|
||||
|
||||
/** Get a message supplier to notify deactivation dependencies to the user for all given entities
|
||||
*
|
||||
|
@ -142,14 +157,12 @@ public interface PageService {
|
|||
* @param table the entity table
|
||||
* @return a message supplier to notify deactivation dependencies to the user */
|
||||
default <T extends Entity & Activatable> Supplier<LocTextKey> confirmDeactivation(final EntityTable<T> table) {
|
||||
return () -> {
|
||||
return confirmDeactivation(table
|
||||
return () -> confirmDeactivation(table
|
||||
.getSelectedROWData()
|
||||
.stream()
|
||||
.filter(e -> e.isActive()) // NOTE: Activatable::isActive leads to an error here!?
|
||||
.filter(Activatable::isActive) // NOTE: Activatable::isActive leads to an error here!?
|
||||
.collect(Collectors.toSet()))
|
||||
.get();
|
||||
};
|
||||
}
|
||||
|
||||
/** Use this to get an table selection action publisher that processes the action
|
||||
|
@ -158,15 +171,13 @@ public interface PageService {
|
|||
* @param pageContext the current PageContext
|
||||
* @param actionDefinitions list of action definitions that activity should be toggled on table selection
|
||||
* @return the selection publisher that handles this defines action activation on table selection */
|
||||
default <T extends Entity> Consumer<Set<T>> getSelectionPublisher(
|
||||
default <T> Consumer<Set<T>> getSelectionPublisher(
|
||||
final PageContext pageContext,
|
||||
final ActionDefinition... actionDefinitions) {
|
||||
|
||||
return rows -> {
|
||||
firePageEvent(
|
||||
return rows -> firePageEvent(
|
||||
new ActionActivationEvent(!rows.isEmpty(), actionDefinitions),
|
||||
pageContext);
|
||||
};
|
||||
}
|
||||
|
||||
/** Use this to get an table selection action publisher that processes the action
|
||||
|
@ -268,7 +279,7 @@ public interface PageService {
|
|||
|
||||
/** Get an new TableBuilder for specified page based RestCall.
|
||||
*
|
||||
* @param The name of the table to build
|
||||
* @param name The name of the table to build
|
||||
* @param apiCall the SEB Server API RestCall that feeds the table with data
|
||||
* @param <T> the type of the Entity of the table
|
||||
* @return TableBuilder of specified type */
|
||||
|
@ -298,7 +309,7 @@ public interface PageService {
|
|||
void clearState();
|
||||
|
||||
/** Key to store the ScrolledComposite update function within Control data map */
|
||||
static String SCROLLED_COMPOSITE_UPDATE = "SCROLLED_COMPOSITE_UPDATE";
|
||||
String SCROLLED_COMPOSITE_UPDATE = "SCROLLED_COMPOSITE_UPDATE";
|
||||
|
||||
/** Creates a ScrolledComposite with content supplied the given content creation function.
|
||||
* The content creation function is used to create the content Composite as a child of the
|
||||
|
@ -371,7 +382,7 @@ public interface PageService {
|
|||
}
|
||||
}
|
||||
|
||||
public class PageActionBuilder {
|
||||
class PageActionBuilder {
|
||||
private final PageService pageService;
|
||||
private final PageContext originalPageContext;
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.util.Set;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
@ -215,10 +214,10 @@ public class PageServiceImpl implements PageService {
|
|||
}
|
||||
|
||||
try {
|
||||
final int dependencies = entities.stream()
|
||||
final int dependencies = (int) entities.stream()
|
||||
.flatMap(entity -> {
|
||||
final RestCall<Set<EntityKey>>.RestCallBuilder builder =
|
||||
restService.<Set<EntityKey>> getBuilder(
|
||||
restService.<Set<EntityKey>>getBuilder(
|
||||
entity.entityType(),
|
||||
CallType.GET_DEPENDENCIES);
|
||||
|
||||
|
@ -227,9 +226,7 @@ public class PageServiceImpl implements PageService {
|
|||
.withQueryParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.DEACTIVATE.name())
|
||||
.call()
|
||||
.getOrThrow().stream();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
.size();
|
||||
}).count();
|
||||
if (dependencies > 0) {
|
||||
return new LocTextKey(CONFIRM_DEACTIVATION_KEY, String.valueOf(dependencies));
|
||||
} else {
|
||||
|
@ -237,7 +234,7 @@ public class PageServiceImpl implements PageService {
|
|||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.warn("Failed to get dependencyies. Error: {}", e.getMessage());
|
||||
log.warn("Failed to get dependencies. Error: {}", e.getMessage());
|
||||
return new LocTextKey(CONFIRM_DEACTIVATION_KEY, "");
|
||||
}
|
||||
};
|
||||
|
@ -246,7 +243,8 @@ public class PageServiceImpl implements PageService {
|
|||
@Override
|
||||
public <T extends Entity & Activatable> Function<PageAction, PageAction> activationToggleActionFunction(
|
||||
final EntityTable<T> table,
|
||||
final LocTextKey noSelectionText) {
|
||||
final LocTextKey noSelectionText,
|
||||
Function<PageAction, PageAction> testBeforeActivation) {
|
||||
|
||||
return action -> {
|
||||
final Set<T> selectedROWData = table.getSelectedROWData();
|
||||
|
@ -259,13 +257,29 @@ public class PageServiceImpl implements PageService {
|
|||
|
||||
final Collection<Exception> errors = new ArrayList<>();
|
||||
for (final T entity : selectedROWData) {
|
||||
if (entity.isActive()) {
|
||||
restService.getBuilder(entityType, CallType.ACTIVATION_DEACTIVATE)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entity.getModelId())
|
||||
|
||||
if (!entity.isActive()) {
|
||||
RestCall<T>.RestCallBuilder restCallBuilder = restService.<T>getBuilder(
|
||||
entityType,
|
||||
CallType.ACTIVATION_ACTIVATE)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entity.getModelId());
|
||||
if (testBeforeActivation != null) {
|
||||
try {
|
||||
action.withEntityKey(entity.getEntityKey());
|
||||
testBeforeActivation.apply(action);
|
||||
restCallBuilder
|
||||
.call()
|
||||
.onError(errors::add);
|
||||
} catch (Exception e) {
|
||||
errors.add(e);
|
||||
}
|
||||
} else {
|
||||
restService.getBuilder(entityType, CallType.ACTIVATION_ACTIVATE)
|
||||
restCallBuilder
|
||||
.call()
|
||||
.onError(errors::add);
|
||||
}
|
||||
} else {
|
||||
restService.<T>getBuilder(entityType, CallType.ACTIVATION_DEACTIVATE)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entity.getModelId())
|
||||
.call()
|
||||
.onError(errors::add);
|
||||
|
@ -375,9 +389,7 @@ public class PageServiceImpl implements PageService {
|
|||
|
||||
@Override
|
||||
public int compare(final PageEventListener<?> o1, final PageEventListener<?> o2) {
|
||||
final int x = o1.priority();
|
||||
final int y = o2.priority();
|
||||
return (x < y) ? -1 : ((x == y) ? 0 : 1);
|
||||
return Integer.compare(o1.priority(), o2.priority());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,13 +40,13 @@ public class ClientConnectionDetails {
|
|||
private static final Logger log = LoggerFactory.getLogger(ClientConnectionDetails.class);
|
||||
|
||||
private final static LocTextKey EXAM_NAME_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.examname");
|
||||
new LocTextKey("sebserver.monitoring.connection.form.exam");
|
||||
private final static LocTextKey CONNECTION_ID_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.id");
|
||||
new LocTextKey("sebserver.monitoring.connection.form.id");
|
||||
private final static LocTextKey CONNECTION_ADDRESS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.address");
|
||||
new LocTextKey("sebserver.monitoring.connection.form.address");
|
||||
private final static LocTextKey CONNECTION_STATUS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.status");
|
||||
new LocTextKey("sebserver.monitoring.connection.form.status");
|
||||
|
||||
private static final int NUMBER_OF_NONE_INDICATOR_ROWS = 3;
|
||||
|
||||
|
@ -100,26 +100,23 @@ public class ClientConnectionDetails {
|
|||
Domain.CLIENT_CONNECTION.ATTR_STATUS,
|
||||
CONNECTION_STATUS_TEXT_KEY,
|
||||
Constants.EMPTY_NOTE)
|
||||
.asColorbox())
|
||||
.asColorBox())
|
||||
.addEmptyCell();
|
||||
|
||||
this.indicatorMapping
|
||||
.values()
|
||||
.stream()
|
||||
.forEach(indData -> {
|
||||
formBuilder.addField(FormBuilder.text(
|
||||
.forEach(indData -> formBuilder.addField(FormBuilder.text(
|
||||
indData.indicator.name,
|
||||
new LocTextKey(indData.indicator.name),
|
||||
Constants.EMPTY_NOTE)
|
||||
.asColorbox()
|
||||
.asColorBox()
|
||||
.withDefaultLabel(indData.indicator.name))
|
||||
.addEmptyCell();
|
||||
});
|
||||
.addEmptyCell());
|
||||
|
||||
this.formhandle = formBuilder.build();
|
||||
}
|
||||
|
||||
public void updateData(final ServerPushContext context) {
|
||||
public void updateData() {
|
||||
final ClientConnectionData connectionData = this.restCallBuilder
|
||||
.call()
|
||||
.get(error -> {
|
||||
|
@ -135,7 +132,7 @@ public class ClientConnectionDetails {
|
|||
this.connectionData = connectionData;
|
||||
}
|
||||
|
||||
public void updateGUI(final ServerPushContext context) {
|
||||
public void updateGUI() {
|
||||
if (this.connectionData == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -162,7 +159,6 @@ public class ClientConnectionDetails {
|
|||
|
||||
// update indicators
|
||||
this.connectionData.getIndicatorValues()
|
||||
.stream()
|
||||
.forEach(indValue -> {
|
||||
final IndicatorData indData = this.indicatorMapping.get(indValue.getType());
|
||||
final double value = indValue.getValue();
|
||||
|
|
|
@ -21,10 +21,12 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.tomcat.util.bcel.Const;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
@ -70,13 +72,19 @@ public final class ClientConnectionTable {
|
|||
private static final String USER_SESSION_STATUS_FILTER_ATTRIBUTE = "USER_SESSION_STATUS_FILTER_ATTRIBUTE";
|
||||
|
||||
private static final String INDICATOR_NAME_TEXT_KEY_PREFIX =
|
||||
"sebserver.monitoring.connection.list.column.indicator.";
|
||||
"sebserver.exam.indicator.type.description.";
|
||||
private final static LocTextKey CONNECTION_ID_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.id");
|
||||
private final static LocTextKey CONNECTION_ID_TOOLTIP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.id" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private final static LocTextKey CONNECTION_ADDRESS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.address");
|
||||
private final static LocTextKey CONNECTION_ADDRESS_TOOLTIP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.address" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private final static LocTextKey CONNECTION_STATUS_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.status");
|
||||
private final static LocTextKey CONNECTION_STATUS_TOOLTIP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.connection.list.column.status" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final ResourceService resourceService;
|
||||
|
@ -88,6 +96,7 @@ public final class ClientConnectionTable {
|
|||
private final EnumSet<ConnectionStatus> statusFilter;
|
||||
private String statusFilterParam = "";
|
||||
private boolean statusFilterChanged = false;
|
||||
private Consumer<Set<EntityKey>> selectionListener;
|
||||
|
||||
private int tableWidth;
|
||||
private boolean needsSort = false;
|
||||
|
@ -136,21 +145,27 @@ public final class ClientConnectionTable {
|
|||
this.table.setHeaderVisible(true);
|
||||
this.table.setLinesVisible(true);
|
||||
|
||||
this.table.addListener(SWT.Selection, event -> this.notifySelectionChange());
|
||||
|
||||
this.widgetFactory.tableColumnLocalized(
|
||||
this.table,
|
||||
CONNECTION_ID_TEXT_KEY);
|
||||
CONNECTION_ID_TEXT_KEY,
|
||||
CONNECTION_ID_TOOLTIP_TEXT_KEY);
|
||||
this.widgetFactory.tableColumnLocalized(
|
||||
this.table,
|
||||
CONNECTION_ADDRESS_TEXT_KEY);
|
||||
CONNECTION_ADDRESS_TEXT_KEY,
|
||||
CONNECTION_ADDRESS_TOOLTIP_TEXT_KEY);
|
||||
this.widgetFactory.tableColumnLocalized(
|
||||
this.table,
|
||||
CONNECTION_STATUS_TEXT_KEY);
|
||||
CONNECTION_STATUS_TEXT_KEY,
|
||||
CONNECTION_STATUS_TOOLTIP_TEXT_KEY);
|
||||
for (final Indicator indDef : indicators) {
|
||||
final TableColumn tc = new TableColumn(this.table, SWT.NONE);
|
||||
final String indicatorName = this.widgetFactory.getI18nSupport().getText(
|
||||
INDICATOR_NAME_TEXT_KEY_PREFIX + indDef.name,
|
||||
indDef.name);
|
||||
tc.setText(indicatorName);
|
||||
TableColumn tableColumn = widgetFactory.tableColumnLocalized(
|
||||
this.table,
|
||||
new LocTextKey(INDICATOR_NAME_TEXT_KEY_PREFIX + indDef.name),
|
||||
new LocTextKey(INDICATOR_NAME_TEXT_KEY_PREFIX + indDef.type.name)
|
||||
);
|
||||
tableColumn.setText(indDef.name);
|
||||
}
|
||||
|
||||
this.tableMapping = new LinkedHashMap<>();
|
||||
|
@ -184,7 +199,7 @@ public final class ClientConnectionTable {
|
|||
saveStatusFilter();
|
||||
}
|
||||
|
||||
public void withDefaultAction(final PageAction pageAction, final PageService pageService) {
|
||||
public ClientConnectionTable withDefaultAction(final PageAction pageAction, final PageService pageService) {
|
||||
this.table.addListener(SWT.MouseDoubleClick, event -> {
|
||||
final Tuple<String> selection = getSingleSelection();
|
||||
if (selection == null) {
|
||||
|
@ -200,7 +215,7 @@ public final class ClientConnectionTable {
|
|||
selection._2);
|
||||
pageService.executePageAction(copyOfPageAction);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Set<String> getConnectionTokens(
|
||||
|
@ -237,9 +252,15 @@ public final class ClientConnectionTable {
|
|||
public void removeSelection() {
|
||||
if (this.table != null) {
|
||||
this.table.deselectAll();
|
||||
this.notifySelectionChange();
|
||||
}
|
||||
}
|
||||
|
||||
public ClientConnectionTable withSelectionListener(Consumer<Set<EntityKey>> selectionListener) {
|
||||
this.selectionListener = selectionListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Set<EntityKey> getSelection() {
|
||||
final int[] selectionIndices = this.table.getSelectionIndices();
|
||||
if (selectionIndices == null || selectionIndices.length < 1) {
|
||||
|
@ -282,11 +303,10 @@ public final class ClientConnectionTable {
|
|||
log.error("Error poll connection data: ", error);
|
||||
return Collections.emptyList();
|
||||
})
|
||||
.stream()
|
||||
.forEach(data -> {
|
||||
final UpdatableTableItem tableItem = this.tableMapping.computeIfAbsent(
|
||||
data.getConnectionId(),
|
||||
connectionId -> new UpdatableTableItem(connectionId));
|
||||
UpdatableTableItem::new);
|
||||
tableItem.push(data);
|
||||
if (this.statusFilterChanged) {
|
||||
this.toDelete.remove(data.getConnectionId());
|
||||
|
@ -294,7 +314,7 @@ public final class ClientConnectionTable {
|
|||
});
|
||||
|
||||
if (this.statusFilterChanged && !this.toDelete.isEmpty()) {
|
||||
this.toDelete.stream().forEach(id -> {
|
||||
this.toDelete.forEach(id -> {
|
||||
final UpdatableTableItem item = this.tableMapping.remove(id);
|
||||
final List<Long> list = this.sessionIds.get(item.connectionData.clientConnection.userSessionId);
|
||||
if (list != null) {
|
||||
|
@ -399,6 +419,14 @@ public final class ClientConnectionTable {
|
|||
}
|
||||
}
|
||||
|
||||
private void notifySelectionChange() {
|
||||
if (this.selectionListener == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectionListener.accept(this.getSelection());
|
||||
}
|
||||
|
||||
private final class UpdatableTableItem implements Comparable<UpdatableTableItem> {
|
||||
|
||||
final Long connectionId;
|
||||
|
|
|
@ -104,7 +104,6 @@ public final class MultiSelectionCheckbox extends Composite implements Selection
|
|||
}
|
||||
|
||||
Arrays.asList(StringUtils.split(keys, Constants.LIST_SEPARATOR))
|
||||
.stream()
|
||||
.forEach(key -> {
|
||||
final Button button = this.checkboxes.get(key);
|
||||
if (button != null) {
|
||||
|
@ -120,7 +119,7 @@ public final class MultiSelectionCheckbox extends Composite implements Selection
|
|||
this.checkboxes
|
||||
.values()
|
||||
.stream()
|
||||
.filter(button -> button.getSelection())
|
||||
.filter(Button::getSelection)
|
||||
.map(button -> (String) button.getData(OPTION_VALUE))
|
||||
.collect(Collectors.toList()).toArray());
|
||||
}
|
||||
|
@ -129,7 +128,6 @@ public final class MultiSelectionCheckbox extends Composite implements Selection
|
|||
public void clear() {
|
||||
this.checkboxes
|
||||
.values()
|
||||
.stream()
|
||||
.forEach(button -> button.setSelection(false));
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.List;
|
|||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
|
@ -41,10 +42,18 @@ public final class ThresholdList extends Composite {
|
|||
private static final int ACTION_COLUMN_WIDTH = 20;
|
||||
|
||||
private static final String COLOR_SELECTION_TEXT_KEY = "sebserver.exam.indicator.thresholds.select.color";
|
||||
private static final LocTextKey VALUE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.value");
|
||||
private static final LocTextKey COLOR_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.color");
|
||||
private static final LocTextKey ADD_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.add");
|
||||
private static final LocTextKey REMOVE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.remove");
|
||||
private static final LocTextKey VALUE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.thresholds.list.value");
|
||||
private static final LocTextKey VALUE_TOOLTIP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.thresholds.list.value" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private static final LocTextKey COLOR_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.thresholds.list.color");
|
||||
private static final LocTextKey COLOR_TOOLTIP_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.thresholds.list.color" + Constants.TOOLTIP_TEXT_KEY_SUFFIX);
|
||||
private static final LocTextKey ADD_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.thresholds.list.add");
|
||||
private static final LocTextKey REMOVE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.exam.indicator.thresholds.list.remove");
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final Supplier<IndicatorType> indicatorTypeSupplier;
|
||||
|
@ -80,14 +89,16 @@ public final class ThresholdList extends Composite {
|
|||
final Label valueTitle = widgetFactory.labelLocalized(
|
||||
this,
|
||||
CustomVariant.TITLE_LABEL,
|
||||
VALUE_TEXT_KEY);
|
||||
VALUE_TEXT_KEY,
|
||||
VALUE_TOOLTIP_TEXT_KEY);
|
||||
this.valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
|
||||
valueTitle.setLayoutData(this.valueCell);
|
||||
|
||||
final Label colorTitle = widgetFactory.labelLocalized(
|
||||
this,
|
||||
CustomVariant.TITLE_LABEL,
|
||||
COLOR_TEXT_KEY);
|
||||
COLOR_TEXT_KEY,
|
||||
COLOR_TOOLTIP_TEXT_KEY);
|
||||
this.colorCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
|
||||
colorTitle.setLayoutData(this.colorCell);
|
||||
|
||||
|
@ -103,9 +114,7 @@ public final class ThresholdList extends Composite {
|
|||
public void setThresholds(final Collection<Threshold> thresholds) {
|
||||
clearList();
|
||||
if (thresholds != null) {
|
||||
thresholds
|
||||
.stream()
|
||||
.forEach(this::addThreshold);
|
||||
thresholds.forEach(this::addThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,13 +131,11 @@ public final class ThresholdList extends Composite {
|
|||
.stream()
|
||||
.filter(entry -> entry.getValue() == null || StringUtils.isBlank(entry.getColor()))
|
||||
.collect(Collectors.toList())
|
||||
.stream()
|
||||
.forEach(entry -> removeThreshold(entry));
|
||||
.forEach(this::removeThreshold);
|
||||
}
|
||||
|
||||
private void clearList() {
|
||||
this.thresholds.stream()
|
||||
.forEach(e -> e.dispose());
|
||||
this.thresholds.forEach(Entry::dispose);
|
||||
this.thresholds.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,10 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(MoodleCourseAccess.class);
|
||||
|
||||
private static final String MOOLDE_QUIZ_START_URL_PATH = "/mod/quiz/view.php?id=";
|
||||
private static final String MOODLE_QUIZ_START_URL_PATH = "/mod/quiz/view.php?id=";
|
||||
private static final String MOODLE_COURSE_API_FUNCTION_NAME = "core_course_get_courses";
|
||||
private static final String MOODLE_QUIZ_API_FUNCTION_NAME = "mod_quiz_get_quizzes_by_courses";
|
||||
private static final String MOODLE_COURSE_API_COURSE_IDS = "courseids";
|
||||
|
||||
private final JSONMapper jsonMapper;
|
||||
private final LmsSetup lmsSetup;
|
||||
|
@ -96,20 +97,18 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
|
||||
@Override
|
||||
protected Supplier<List<QuizData>> allQuizzesSupplier() {
|
||||
return () -> {
|
||||
return getRestTemplate()
|
||||
return () -> getRestTemplate()
|
||||
.map(this::collectAllQuizzes)
|
||||
.getOrThrow();
|
||||
};
|
||||
}
|
||||
|
||||
private ArrayList<QuizData> collectAllQuizzes(final MoodleAPIRestTemplate restTemplate) {
|
||||
final String urlPrefix = this.lmsSetup.lmsApiUrl + MOOLDE_QUIZ_START_URL_PATH;
|
||||
final String urlPrefix = this.lmsSetup.lmsApiUrl + MOODLE_QUIZ_START_URL_PATH;
|
||||
return collectAllCourses(
|
||||
restTemplate)
|
||||
.stream()
|
||||
.reduce(
|
||||
new ArrayList<QuizData>(),
|
||||
new ArrayList<>(),
|
||||
(list, courseData) -> {
|
||||
list.addAll(quizDataOf(
|
||||
this.lmsSetup,
|
||||
|
@ -138,7 +137,7 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
|
||||
// then get all quizzes of courses and filter
|
||||
final LinkedMultiValueMap<String, String> attributes = new LinkedMultiValueMap<>();
|
||||
attributes.put("courseids", new ArrayList<>(courseData.keySet()));
|
||||
attributes.put(MOODLE_COURSE_API_COURSE_IDS, new ArrayList<>(courseData.keySet()));
|
||||
|
||||
final String quizzesJSON = restTemplate.callMoodleAPIFunction(
|
||||
MOODLE_QUIZ_API_FUNCTION_NAME,
|
||||
|
@ -149,7 +148,6 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
CourseQuizData.class);
|
||||
|
||||
courseQuizData.quizzes
|
||||
.stream()
|
||||
.forEach(quiz -> {
|
||||
final CourseData course = courseData.get(quiz.course);
|
||||
if (course != null) {
|
||||
|
@ -166,24 +164,24 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
}
|
||||
}
|
||||
|
||||
static Map<String, String> additionalAttrs = new HashMap<>();
|
||||
private static List<QuizData> quizDataOf(
|
||||
final LmsSetup lmsSetup,
|
||||
final CourseData courseData,
|
||||
final String uriPrefix) {
|
||||
|
||||
final Map<String, String> additionalAttrs = new HashMap<>();
|
||||
additionalAttrs.clear();
|
||||
additionalAttrs.put("timecreated", String.valueOf(courseData.timecreated));
|
||||
additionalAttrs.put("course_shortname", courseData.shortname);
|
||||
additionalAttrs.put("course_fullname", courseData.fullname);
|
||||
additionalAttrs.put("course_displayname", courseData.displayname);
|
||||
additionalAttrs.put("course_summary", courseData.summary);
|
||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_CREATION_TIME, String.valueOf(courseData.time_created));
|
||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_SHORT_NAME, courseData.short_name);
|
||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_FULL_NAME, courseData.full_name);
|
||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_DISPLAY_NAME, courseData.display_name);
|
||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_SUMMARY, courseData.summary);
|
||||
|
||||
return courseData.quizzes
|
||||
.stream()
|
||||
.map(courseQuizData -> {
|
||||
final String startURI = uriPrefix + courseData.id;
|
||||
additionalAttrs.put("timelimit", String.valueOf(courseQuizData.timelimit));
|
||||
additionalAttrs.put(QuizData.ATTR_ADDITIONAL_TIME_LIMIT, String.valueOf(courseQuizData.time_limit));
|
||||
return new QuizData(
|
||||
courseQuizData.id,
|
||||
lmsSetup.getInstitutionId(),
|
||||
|
@ -191,13 +189,12 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
lmsSetup.getLmsType(),
|
||||
courseQuizData.name,
|
||||
courseQuizData.intro,
|
||||
Utils.toDateTimeUTCUnix(courseData.startdate),
|
||||
Utils.toDateTimeUTCUnix(courseData.enddate),
|
||||
Utils.toDateTimeUTCUnix(courseData.start_date),
|
||||
Utils.toDateTimeUTCUnix(courseData.end_date),
|
||||
startURI,
|
||||
additionalAttrs);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
private Result<MoodleAPIRestTemplate> getRestTemplate() {
|
||||
|
@ -218,34 +215,34 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
static final class CourseData {
|
||||
final String id;
|
||||
final String shortname;
|
||||
final String fullname;
|
||||
final String displayname;
|
||||
final String short_name;
|
||||
final String full_name;
|
||||
final String display_name;
|
||||
final String summary;
|
||||
final Long startdate; // unixtime milliseconds UTC
|
||||
final Long enddate; // unixtime milliseconds UTC
|
||||
final Long timecreated; // unixtime milliseconds UTC
|
||||
final Long start_date; // unix-time milliseconds UTC
|
||||
final Long end_date; // unix-time milliseconds UTC
|
||||
final Long time_created; // unix-time milliseconds UTC
|
||||
final Collection<CourseQuiz> quizzes = new ArrayList<>();
|
||||
|
||||
@JsonCreator
|
||||
protected CourseData(
|
||||
@JsonProperty(value = "id") final String id,
|
||||
@JsonProperty(value = "shortname") final String shortname,
|
||||
@JsonProperty(value = "fullname") final String fullname,
|
||||
@JsonProperty(value = "displayname") final String displayname,
|
||||
@JsonProperty(value = "shortname") final String short_name,
|
||||
@JsonProperty(value = "fullname") final String full_name,
|
||||
@JsonProperty(value = "displayname") final String display_name,
|
||||
@JsonProperty(value = "summary") final String summary,
|
||||
@JsonProperty(value = "startdate") final Long startdate,
|
||||
@JsonProperty(value = "enddate") final Long enddate,
|
||||
@JsonProperty(value = "timecreated") final Long timecreated) {
|
||||
@JsonProperty(value = "startdate") final Long start_date,
|
||||
@JsonProperty(value = "enddate") final Long end_date,
|
||||
@JsonProperty(value = "timecreated") final Long time_created) {
|
||||
|
||||
this.id = id;
|
||||
this.shortname = shortname;
|
||||
this.fullname = fullname;
|
||||
this.displayname = displayname;
|
||||
this.short_name = short_name;
|
||||
this.full_name = full_name;
|
||||
this.display_name = display_name;
|
||||
this.summary = summary;
|
||||
this.startdate = startdate;
|
||||
this.enddate = enddate;
|
||||
this.timecreated = timecreated;
|
||||
this.start_date = start_date;
|
||||
this.end_date = end_date;
|
||||
this.time_created = time_created;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -266,26 +263,26 @@ public class MoodleCourseAccess extends CourseAccess {
|
|||
static final class CourseQuiz {
|
||||
final String id;
|
||||
final String course;
|
||||
final String coursemodule;
|
||||
final String course_module;
|
||||
final String name;
|
||||
final String intro; // HTML
|
||||
final Long timelimit; // unixtime milliseconds UTC
|
||||
final Long time_limit; // unix-time milliseconds UTC
|
||||
|
||||
@JsonCreator
|
||||
protected CourseQuiz(
|
||||
@JsonProperty(value = "id") final String id,
|
||||
@JsonProperty(value = "course") final String course,
|
||||
@JsonProperty(value = "coursemodule") final String coursemodule,
|
||||
@JsonProperty(value = "coursemodule") final String course_module,
|
||||
@JsonProperty(value = "name") final String name,
|
||||
@JsonProperty(value = "intro") final String intro,
|
||||
@JsonProperty(value = "timelimit") final Long timelimit) {
|
||||
@JsonProperty(value = "timelimit") final Long time_limit) {
|
||||
|
||||
this.id = id;
|
||||
this.course = course;
|
||||
this.coursemodule = coursemodule;
|
||||
this.course_module = course_module;
|
||||
this.name = name;
|
||||
this.intro = intro;
|
||||
this.timelimit = timelimit;
|
||||
this.time_limit = time_limit;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
|||
// this processing returns immediately with the error
|
||||
final T result = changeAction
|
||||
.apply(mapping)
|
||||
.onError(t -> log.error("Fauled to save exam configuration: {}",
|
||||
.onError(t -> log.error("Failed to save exam configuration: {}",
|
||||
mapping.configurationNodeId))
|
||||
.getOrThrow();
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
|
||||
final ExamConfigurationMap requestModel = this.createNew(postMap);
|
||||
return this.checkCreateAccess(requestModel)
|
||||
.flatMap(this::validForCreate)
|
||||
.map(this::checkPasswordMatch)
|
||||
.flatMap(entity -> this.examConfigUpdateService.processExamConfigurationMappingChange(
|
||||
entity,
|
||||
|
|
|
@ -9,7 +9,7 @@ sebserver.overall.about.markup=<span style='font-family: Arial, Helvetica,sans-s
|
|||
sebserver.overall.help=Documentation
|
||||
sebserver.overall.help.link=https://www.safeexambrowser.org/news_en.html
|
||||
|
||||
sebserver.overall.message.leave.without.save=You have unsaved changes!</br>Are you sure you want to leave the page? The changes will be lost.
|
||||
sebserver.overall.message.leave.without.save=You have unsaved changes!<br/>Are you sure you want to leave the page? The changes will be lost.
|
||||
sebserver.overall.upload=Please select a file
|
||||
sebserver.overall.upload.unsupported.file=This file type is not supported. Supported files are: {0}
|
||||
sebserver.overall.action.modify.cancel=Cancel
|
||||
|
@ -77,6 +77,7 @@ sebserver.form.validation.fieldError.size=The size must be between {3} and {4}
|
|||
sebserver.form.validation.fieldError.name=The Name is mandatory and must have a size between {3} and {4} character
|
||||
sebserver.form.validation.fieldError.urlSuffix=The URL Suffix must have a size between {3} and {4} character
|
||||
sebserver.form.validation.fieldError.notNull=This field is mandatory
|
||||
sebserver.form.validation.fieldError.name.notunique=This name is already in use. Please choose another one.
|
||||
sebserver.form.validation.fieldError.username.notunique=This Username is already in use. Please choose another one.
|
||||
sebserver.form.validation.fieldError.password.wrong=The old password is wrong
|
||||
sebserver.form.validation.fieldError.password.mismatch=The re-typed password doesn't match the new password
|
||||
|
@ -112,7 +113,7 @@ sebserver.login.failed.title=Login failed
|
|||
sebserver.login.failed.message=Access denied: wrong username or password
|
||||
sebserver.logout=Sign out
|
||||
sebserver.logout.success.message=You have been successfully signed out.
|
||||
sebserver.logout.invalid-session.message=You have been signed out because of a user session invalidation.</br>Please sign in again
|
||||
sebserver.logout.invalid-session.message=You have been signed out because of a user session invalidation.<br/>Please sign in again
|
||||
sebserver.login.password.change=Information
|
||||
sebserver.login.password.change.success=The password was successfully changed. Please sign in with your new password
|
||||
|
||||
|
@ -139,11 +140,11 @@ sebserver.institution.list.actions=
|
|||
sebserver.institution.list.empty=No institution has been found. Please adapt the filter or create a new institution
|
||||
sebserver.institution.list.title=Institutions
|
||||
sebserver.institution.list.column.name=Name
|
||||
sebserver.institution.list.column.name.tooltip=The name of the institution.</br></br>Use the filter above to narrow down a specific name.</br>{0}
|
||||
sebserver.institution.list.column.name.tooltip=The name of the institution.<br/><br/>Use the filter above to narrow down a specific name.<br/>{0}
|
||||
sebserver.institution.list.column.urlSuffix=URL Suffix
|
||||
sebserver.institution.list.column.urlSuffix.tooltip=The URL suffix to the institutional login page.</br></br>Use the filter above to narrow down a specific URL suffix.</br>{0}
|
||||
sebserver.institution.list.column.urlSuffix.tooltip=The URL suffix to the institutional login page.<br/><br/>Use the filter above to narrow down a specific URL suffix.<br/>{0}
|
||||
sebserver.institution.list.column.active=Status
|
||||
sebserver.institution.list.column.active.tooltip=The activity of the institution.</br></br>Use the filter above to specify the activity.</br>{0}
|
||||
sebserver.institution.list.column.active.tooltip=The activity of the institution.<br/><br/>Use the filter above to specify the activity.<br/>{0}
|
||||
|
||||
sebserver.institution.action.list=Institution
|
||||
sebserver.institution.action.form=Institution
|
||||
|
@ -164,9 +165,9 @@ sebserver.institution.form.title=Institution
|
|||
sebserver.institution.form.name=Name
|
||||
sebserver.institution.form.name.tooltip=The name of the institution
|
||||
sebserver.institution.form.urlSuffix=URL Suffix
|
||||
sebserver.institution.form.urlSuffix.tooltip=The URL suffix to the institutional login page.</br> Institutional URL is: http(s)://<seb-server-name>/<suffix>
|
||||
sebserver.institution.form.urlSuffix.tooltip=The URL suffix to the institutional login page.<br/> Institutional URL is: http(s)://<seb-server-name>/<suffix>
|
||||
sebserver.institution.form.logoImage=Logo Image
|
||||
sebserver.institution.form.logoImage.tooltip=The Image that is shown as a logo in the specified institutional login page.</br>In edit mode, use the arrow sign to open a upload dialog.
|
||||
sebserver.institution.form.logoImage.tooltip=The Image that is shown as a logo in the specified institutional login page.<br/>In edit mode, use the arrow sign to open a upload dialog.
|
||||
sebserver.institution.form.logoImage.unsupportedFileType=The selected file is not supported. Supported are: PNG and JPG
|
||||
|
||||
|
||||
|
@ -176,27 +177,27 @@ sebserver.institution.form.logoImage.unsupportedFileType=The selected file is no
|
|||
|
||||
sebserver.useraccount.list.actions=
|
||||
sebserver.useraccount.role.SEB_SERVER_ADMIN=SEB Server Administrator
|
||||
sebserver.useraccount.role.SEB_SERVER_ADMIN.tooltip=A SEB server administrator has overall read privileges</br>and is able to create new institutions and user accounts
|
||||
sebserver.useraccount.role.SEB_SERVER_ADMIN.tooltip=A SEB server administrator has overall read privileges<br/>and is able to create new institutions and user accounts
|
||||
sebserver.useraccount.role.INSTITUTIONAL_ADMIN=Institutional Administrator
|
||||
sebserver.useraccount.role.INSTITUTIONAL_ADMIN.tooltip=An institutional administrator has overall read privileges on the assigned institution</br>and is able to edit the institution and create new user accounts for the institution.</br>Furthermore an institutional administrator is able to create new LMS bindings and SEB client configurations for the institution.
|
||||
sebserver.useraccount.role.INSTITUTIONAL_ADMIN.tooltip=An institutional administrator has overall read privileges on the assigned institution<br/>and is able to edit the institution and create new user accounts for the institution.<br/>Furthermore an institutional administrator is able to create new LMS bindings and SEB client configurations for the institution.
|
||||
sebserver.useraccount.role.EXAM_ADMIN=Exam Administrator
|
||||
sebserver.useraccount.role.EXAM_ADMIN.tooltip=An exam administrator has overall read privileges for the institution but cannot see or manage other user accounts.</br>An exam administrator is able to create new SEB configurations and import and setup exams.
|
||||
sebserver.useraccount.role.EXAM_ADMIN.tooltip=An exam administrator has overall read privileges for the institution but cannot see or manage other user accounts.<br/>An exam administrator is able to create new SEB configurations and import and setup exams.
|
||||
sebserver.useraccount.role.EXAM_SUPPORTER=Exam Supporter
|
||||
sebserver.useraccount.role.EXAM_SUPPORTER.tooltip=An exam supporter can only see and edit the own user account</br> and monitor exams for that he/she was attached by an exam administrator.
|
||||
sebserver.useraccount.role.EXAM_SUPPORTER.tooltip=An exam supporter can only see and edit the own user account<br/> and monitor exams for that he/she was attached by an exam administrator.
|
||||
|
||||
sebserver.useraccount.list.empty=No user account has been found. Please adapt the filter or create a new user account
|
||||
sebserver.useraccount.list.title=User Accounts
|
||||
sebserver.useraccount.list.column.institution=Institution
|
||||
sebserver.useraccount.list.column.institution.tooltip=The institution of the user account.</br></br>Use the filter above to specify the institution.</br>{0}
|
||||
sebserver.useraccount.list.column.institution.tooltip=The institution of the user account.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.useraccount.list.column.name=First Name
|
||||
sebserver.useraccount.list.column.name.tooltip=The first name of the user.</br></br>Use the filter above to narrow down a specific first name.</br>{0}
|
||||
sebserver.useraccount.list.column.name.tooltip=The first name of the user.<br/><br/>Use the filter above to narrow down a specific first name.<br/>{0}
|
||||
sebserver.useraccount.list.column.username=User Name
|
||||
sebserver.useraccount.list.column.username.tooltip=The internal user name of the user.</br></br>Use the filter above to narrow down a specific user name.</br>{0}
|
||||
sebserver.useraccount.list.column.username.tooltip=The internal user name of the user.<br/><br/>Use the filter above to narrow down a specific user name.<br/>{0}
|
||||
sebserver.useraccount.list.column.email=Mail
|
||||
sebserver.useraccount.list.column.email.tooltip=The e-mail address of the user.</br></br>Use the filter above to narrow down a specific e-mail address.</br>{0}
|
||||
sebserver.useraccount.list.column.email.tooltip=The e-mail address of the user.<br/><br/>Use the filter above to narrow down a specific e-mail address.<br/>{0}
|
||||
sebserver.useraccount.list.column.language=Language
|
||||
sebserver.useraccount.list.column.active=Active
|
||||
sebserver.useraccount.list.column.active.tooltip=The activity of the user.</br></br>Use the filter above to specify the activity.</br>{0}
|
||||
sebserver.useraccount.list.column.active.tooltip=The activity of the user.<br/><br/>Use the filter above to specify the activity.<br/>{0}
|
||||
|
||||
sebserver.useraccount.action.list=User Account
|
||||
sebserver.useraccount.action.form=User Account of {0}
|
||||
|
@ -231,9 +232,9 @@ sebserver.useraccount.form.mail.tooltip=The e-mail address of the user.
|
|||
sebserver.useraccount.form.language=Language
|
||||
sebserver.useraccount.form.language.tooltip=The users language.
|
||||
sebserver.useraccount.form.timezone=Time Zone
|
||||
sebserver.useraccount.form.timezone.tooltip=The time-zone of the user.</br></br>Note that this also defines the exact time and date that is displayed to the user.
|
||||
sebserver.useraccount.form.timezone.tooltip=The time-zone of the user.<br/><br/>Note that this also defines the exact time and date that is displayed to the user.
|
||||
sebserver.useraccount.form.roles=User Roles
|
||||
sebserver.useraccount.form.roles.tooltip=Select the roles for the user.</br>A user can have more then one role but must have at least one.</br></br>Please use the tooltip on the role name for more information about a specific role.
|
||||
sebserver.useraccount.form.roles.tooltip=Select the roles for the user.<br/>A user can have more then one role but must have at least one.<br/><br/>Please use the tooltip on the role name for more information about a specific role.
|
||||
sebserver.useraccount.form.password=Password
|
||||
sebserver.useraccount.form.password.tooltip=The password of the user account
|
||||
sebserver.useraccount.form.password.confirm=Confirm Password
|
||||
|
@ -257,9 +258,13 @@ sebserver.lmssetup.list.action.no.modify.privilege=No Access: A LMS Setup from o
|
|||
sebserver.lmssetup.list.empty=No LMS Setup has been found. Please adapt the filter or create a new LMS Setup
|
||||
sebserver.lmssetup.list.title=Learning Management System Setups
|
||||
sebserver.lmssetup.list.column.institution=Institution
|
||||
sebserver.lmssetup.list.column.institution.tooltip=The institution of the LMS setup.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.lmssetup.list.column.name=Name
|
||||
sebserver.lmssetup.list.column.name.tooltip=The name of the LMS setup.<br/><br/>Use the filter above to narrow down a specific LMS by name.<br/>{0}
|
||||
sebserver.lmssetup.list.column.type=LMS Type
|
||||
sebserver.lmssetup.list.column.type.tooltip=The type of the LMS.<br/><br/>Use the filter above to specify the LMS type.<br/>{0}
|
||||
sebserver.lmssetup.list.column.active=Active
|
||||
sebserver.lmssetup.list.column.active.tooltip=The activity of the LMS Setup.<br/><br/>Use the filter above to specify the activity.<br/>{0}
|
||||
|
||||
sebserver.lmssetup.action.list=LMS Connection Settings
|
||||
sebserver.lmssetup.action.form=LMS Setup
|
||||
|
@ -270,7 +275,7 @@ sebserver.lmssetup.action.modify=Edit
|
|||
sebserver.lmssetup.action.savetest=Test And Save
|
||||
sebserver.lmssetup.action.testsave=Test And Save
|
||||
sebserver.lmssetup.action.test.ok=Successfully connected to the course API
|
||||
sebserver.lmssetup.action.test.tokenRequestError=The API access was denied: {0}
|
||||
sebserver.lmssetup.action.test.tokenRequestError=The API access was denied: {0}<br/>Please check the LMS connection details.
|
||||
sebserver.lmssetup.action.test.quizRequestError=Unable to request courses or quizzes from the course API of the LMS. {0}
|
||||
sebserver.lmssetup.action.test.quizRestrictionError=Unable to access course restriction API of the LMS. {0}
|
||||
sebserver.lmssetup.action.test.missingParameter=There is one or more missing connection parameter.<br/>Please check the connection parameter for this LMS Setup
|
||||
|
@ -285,17 +290,25 @@ sebserver.lmssetup.info.pleaseSelect=Please select first a LMS Setup from the li
|
|||
sebserver.lmssetup.form.title=Learning Management System Setup
|
||||
sebserver.lmssetup.form.title.new=Add Learning Management System Setup
|
||||
sebserver.lmssetup.form.institution=Institution
|
||||
sebserver.lmssetup.form.institution.tooltip=The institution where the LMS setup belongs to
|
||||
sebserver.lmssetup.form.name=Name
|
||||
sebserver.lmssetup.form.name.tooltip=The name of the LMS setup
|
||||
sebserver.lmssetup.form.type=Type
|
||||
sebserver.lmssetup.form.clientname.seb=SEB Auth. Name
|
||||
sebserver.lmssetup.form.secret.seb=SEB Auth. Password
|
||||
sebserver.lmssetup.form.type.tooltip=The type of the LMS Setup.
|
||||
sebserver.lmssetup.form.url=LMS Server Address
|
||||
sebserver.lmssetup.form.url.tooltip=The server URL to the specific LMS server.<br/><br/>This should point to the main- or root-address of the LMS server
|
||||
sebserver.lmssetup.form.clientname.lms=LMS Server Username
|
||||
sebserver.lmssetup.form.clientname.lms.tooltip=The client name of the API client access to the LMS.<br/><br/>This is usually provided by an LMS administrator that has created a API access account for SEB Server binding within the LMS server.
|
||||
sebserver.lmssetup.form.secret.lms=LMS Server Password
|
||||
sebserver.lmssetup.form.secret.lms.tooltip=The secret or password of the API client access to the LMS.<br/><br/>This is usually provided by an LMS administrator that has created a API access account for SEB Server binding within the LMS server.
|
||||
sebserver.lmssetup.form.proxy=Proxy
|
||||
sebserver.lmssetup.form.proxy.tooltip=The proxy details of a proxy is needed to connect to a LMS server
|
||||
sebserver.lmssetup.form.proxy.host=Proxy Host
|
||||
sebserver.lmssetup.form.proxy.host.tooltip=The server name of the proxy host to connect to
|
||||
sebserver.lmssetup.form.proxy.port=Proxy Port
|
||||
sebserver.lmssetup.form.proxy.port.tooltip=The proxy server port to connect to
|
||||
sebserver.lmssetup.form.proxy.auth-credentials=Proxy Name/Password
|
||||
sebserver.lmssetup.form.proxy.auth-credentials.tooltip=The proxy authentication credentials (name and password)<br/>to authenticate the connection within the proxy server
|
||||
|
||||
################################
|
||||
# Quiz Discovery
|
||||
|
@ -306,10 +319,15 @@ sebserver.quizdiscovery.list.actions=
|
|||
sebserver.quizdiscovery.list.title=Quizzes
|
||||
sebserver.quizdiscovery.list.empty=No Quiz has been found. Please adapt the filter or create a new LMS Setup
|
||||
sebserver.quizdiscovery.list.column.institution=Institution
|
||||
sebserver.quizdiscovery.list.column.institution.tooltip=The institution of the LMS setup that defines LMS of the quiz.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.quizdiscovery.list.column.lmssetup=LMS
|
||||
sebserver.quizdiscovery.list.column.lmssetup.tooltip=The LMS setup that defines the LMS of the quiz<br/><br/>Use the filter above to specify the LMS setup.<br/>{0}
|
||||
sebserver.quizdiscovery.list.column.name=Name
|
||||
sebserver.quizdiscovery.list.column.name.tooltip=The name of the quiz.<br/><br/>Use the filter above to narrow down a specific quiz name.<br/>{0}
|
||||
sebserver.quizdiscovery.list.column.starttime=Start Time {0}
|
||||
sebserver.quizdiscovery.list.column.starttime.tooltip=The start time of the quiz.<br/><br/>Use the filter above to set a specific from date.<br/>{0}
|
||||
sebserver.quizdiscovery.list.column.endtime=End Time {0}
|
||||
sebserver.quizdiscovery.list.column.endtime.tooltip=The end time of the quiz.<br/><br/>{0}
|
||||
sebserver.quizdiscovery.info.pleaseSelect=Please select first a Quiz from the list
|
||||
|
||||
sebserver.quizdiscovery.action.list=LMS Exam Discovery
|
||||
|
@ -318,16 +336,32 @@ sebserver.quizdiscovery.quiz.import.out.dated=The Selected Quiz is is already fi
|
|||
sebserver.quizdiscovery.action.details=Show Details
|
||||
|
||||
sebserver.quizdiscovery.quiz.details.title=Quiz Details
|
||||
sebserver.quizdiscovery.quiz.details.institution=Institution
|
||||
sebserver.quizdiscovery.quiz.details.institution.tooltip=The institution of the LMS setup that defines the LMS of the quiz.
|
||||
sebserver.quizdiscovery.quiz.details.lmssetup=LMS Setup
|
||||
sebserver.quizdiscovery.quiz.details.lmssetup.tooltip=The LMS setup that defines the LMS of the quiz.
|
||||
sebserver.quizdiscovery.quiz.details.name=Name
|
||||
sebserver.quizdiscovery.quiz.details.name.tooltip=The name of the quiz.<br/><br/>This name is defined on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.description=Description
|
||||
sebserver.quizdiscovery.quiz.details.description.tooltip=The description of the quiz.<br/><br/>This description is defined on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.starttime=Start Time
|
||||
sebserver.quizdiscovery.quiz.details.starttime.tooltip=The start time of the quiz.<br/><br/>This time is set on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.endtime=End Time
|
||||
sebserver.quizdiscovery.quiz.details.endtime.tooltip=The end time of the quiz.<br/><br/>This time is set on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.url=Start URL
|
||||
sebserver.quizdiscovery.quiz.details.url.tooltip=The start URL on the LMS for the quiz.<br/><br/>This is defined by the LMS setup and the quiz URL
|
||||
sebserver.quizdiscovery.quiz.details.additional.timecreated=Creation Time
|
||||
sebserver.quizdiscovery.quiz.details.additional.timecreated.tooltip=The time when the quiz was first created<br/><br/>This time is defined by the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_shortname=Short Name
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_shortname.tooltip=The short name of the quiz<br/><br/>This is defined on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_fullname=Full Name
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_fullname.tooltip=The full name of the quiz<br/><br/>This is defined on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_displayname=Display Name
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_displayname.tooltip=The display name of the quiz<br/><br/>This is defined on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_summary=Summary
|
||||
sebserver.quizdiscovery.quiz.details.additional.course_summary.tooltip=The summary of the quiz<br/><br/>This is defined on the corresponding LMS
|
||||
sebserver.quizdiscovery.quiz.details.additional.timelimit=Time Limit
|
||||
sebserver.quizdiscovery.quiz.details.additional.timelimit.toolitp=The time limit of the quiz<br/><br/>This is defined on the corresponding LMS
|
||||
|
||||
################################
|
||||
# Exam
|
||||
|
@ -336,10 +370,15 @@ sebserver.quizdiscovery.quiz.details.additional.timelimit=Time Limit
|
|||
sebserver.exam.list.actions=
|
||||
sebserver.exam.list.title=Exams
|
||||
sebserver.exam.list.column.institution=Institution
|
||||
sebserver.exam.list.column.institution.tooltip=The institution of the LMS setup that defines LMS of the exam.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.exam.list.column.lmssetup=LMS
|
||||
sebserver.exam.list.column.lmssetup.tooltip=The LMS setup that defines the LMS of the exam<br/><br/>Use the filter above to specify the LMS setup.<br/>{0}
|
||||
sebserver.exam.list.column.name=Name
|
||||
sebserver.exam.list.column.name.tooltip=The name of the exam.<br/><br/>Use the filter above to narrow down a specific exam name.<br/>{0}
|
||||
sebserver.exam.list.column.starttime=Start Time {0}
|
||||
sebserver.exam.list.column.starttime.tooltip=The start time of the exam.<br/><br/>Use the filter above to set a specific from date.<br/>{0}
|
||||
sebserver.exam.list.column.type=Type
|
||||
sebserver.exam.list.column.type.tooltip=The type of the exam.<br/><br/>Use the filter above to set a specific exam type.<br/>{0}
|
||||
|
||||
sebserver.exam.list.empty=No Exam has been found. Please adapt the filter or import one from Quiz
|
||||
sebserver.exam.list.modify.out.dated=Finished exams cannot be modified.
|
||||
|
@ -369,43 +408,73 @@ sebserver.exam.info.pleaseSelect=Please select first an Exam from the list
|
|||
sebserver.exam.form.title.import=Import Exam
|
||||
sebserver.exam.form.title=Exam
|
||||
sebserver.exam.form.lmssetup=LMS Setup
|
||||
sebserver.exam.form.lmssetup.tooltip=The LMS setup that defines the LMS of the exam.
|
||||
sebserver.exam.form.quizid=Quiz Identifier
|
||||
sebserver.exam.form.quizid.tooltip=The identifier that identifies the quiz of the exam on the corresponding LMS
|
||||
sebserver.exam.form.quizurl=Quiz URL
|
||||
sebserver.exam.form.quizurl.tooltip=The direct URL link to the quiz/exam on the LMS
|
||||
sebserver.exam.form.name=Name
|
||||
sebserver.exam.form.name.tooltip=The name of the exam.<br/><br/>This name is defined on the corresponding LMS
|
||||
sebserver.exam.form.description=Description
|
||||
sebserver.exam.form.description.tooltip=The description of the exam.<br/><br/>This description is defined on the corresponding LMS
|
||||
sebserver.exam.form.starttime=Start Time
|
||||
sebserver.exam.form.starttime.tooltip=The start time of the exam.<br/><br/>This time is set on the corresponding LMS
|
||||
sebserver.exam.form.endtime=End Time
|
||||
sebserver.exam.form.endtime.tooltip=The end time of the exam.<br/><br/>This time is set on the corresponding LMS
|
||||
sebserver.exam.form.status=Status
|
||||
sebserver.exam.form.status.tooltip=The current status for the exam.<br/><br/>Either "Up Coming" for an exam that has not yet been started,<br/>"Running" for an exam that is currently running<br/>or "Finished" for an exam that has already been finished yet
|
||||
sebserver.exam.form.type=Exam Type
|
||||
sebserver.exam.form.type.tooltip=The type of the exam.<br/><br/>This has only descriptive character for now and can be used to categorise exams within a type
|
||||
sebserver.exam.form.supporter=Exam Supporter
|
||||
sebserver.exam.form.supporter.action.add=Add as supporter for this exam
|
||||
sebserver.exam.form.supporter.action.remove=Remove supporter
|
||||
sebserver.exam.form.supporter.tooltip=A list of users that are allowed to support this exam.<br/><br/>To add a user in edit mode click into the field on right-hand and start typing the first letters of the username.<br/>A filtered choice will drop down. Click on a specific username on the drop-down to add the user to the list.<br/>To remove a user from the list, just double-click the username on the list.
|
||||
|
||||
sebserver.exam.form.sebrestriction.title=SEB Restriction Details
|
||||
sebserver.exam.form.sebrestriction.info=Info
|
||||
sebserver.exam.form.sebrestriction.info-text=A detailed description of the SEB restriction can be found within this page:<br/><a href="https://seb-openedx.readthedocs.io/en/latest/usage.html">https://seb-openedx.readthedocs.io/en/latest/usage.html</a>
|
||||
sebserver.exam.form.sebrestriction.configKeys=Config Keys
|
||||
sebserver.exam.form.sebrestriction.configKeys.tooltip=A comma-separated list of SEB Config Keys that are automatically generated from the attached SEB exam configurations<br/>and are checked by the LMS for the restricted SEB access for every request
|
||||
sebserver.exam.form.sebrestriction.browserExamKeys=Browser Exam Keys
|
||||
sebserver.exam.form.sebrestriction.browserExamKeys.tooltip=A comma-separated list of SEB Browser Exam Keys<br/>that are checked by the LMS for the restricted SEB access for every request
|
||||
sebserver.exam.form.sebrestriction.WHITELIST_PATHS=Component White-List
|
||||
sebserver.exam.form.sebrestriction.WHITELIST_PATHS.tooltip=Grant no-restriction to each of the given Open edX path components by select them for white-list.
|
||||
sebserver.exam.form.sebrestriction.BLACKLIST_CHAPTERS=Chapters Black-List
|
||||
sebserver.exam.form.sebrestriction.BLACKLIST_CHAPTERS.tooltip=Explicitly restrict a course chapter by adding the course-chapter-identifier to this comma-separated list
|
||||
sebserver.exam.form.sebrestriction.PERMISSION_COMPONENTS=Permissions
|
||||
sebserver.exam.form.sebrestriction.PERMISSION_COMPONENTS.tooltip=Define the additional SEB restriction permissions
|
||||
sebserver.exam.form.sebrestriction.USER_BANNING_ENABLED=User Banning
|
||||
sebserver.exam.form.sebrestriction.USER_BANNING_ENABLED.tooltip=Indicates whether the user of a restricted access shall be banned on authentication failure or not.
|
||||
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.ABOUT=About
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.ABOUT.tooltip=The "About" section of the Open edX course
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.COURSE_OUTLINE=Course Outline
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.COURSE_OUTLINE.tooltip=The outline section of the Open edX course
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.COURSE_WARE=Course Ware
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.COURSE_WARE.tooltip=The actual course and course content
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.DISCUSSION=Discussion
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.DISCUSSION.tooltip=The discussion section of the Open edX course
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.PROGRESS=Progress
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.PROGRESS.tooltip=The progress overview of the Open edX course
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.WIKI=Description (Wiki)
|
||||
sebserver.exam.form.sebrestriction.whiteListPaths.WIKI.tooltip=The wikipedia section of the Open edX course
|
||||
|
||||
sebserver.exam.form.sebrestriction.permissions.ALWAYS_ALLOW_STUFF=Stuff Role Always Allowed
|
||||
sebserver.exam.form.sebrestriction.permissions.ALWAYS_ALLOW_STUFF.tooltip=Set this to always allow none-restricted access for a user that has "stuff" privileges.
|
||||
sebserver.exam.form.sebrestriction.permissions.CHECK_BROWSER_EXAM_KEY=Check Browser-Exam-Key
|
||||
sebserver.exam.form.sebrestriction.permissions.CHECK_BROWSER_EXAM_KEY.tooltip=Always check received SEB Browser Exam Key with the defined ones for every request.
|
||||
sebserver.exam.form.sebrestriction.permissions.CHECK_CONFIG_KEY=Check Config-Key
|
||||
sebserver.exam.form.sebrestriction.permissions.CHECK_CONFIG_KEY.tooltip=Always check received SEB Config Key with the defined ones for every request.
|
||||
sebserver.exam.form.sebrestriction.permissions.CHECK_BROWSER_EXAM_OR_CONFIG_KEY=Check Browser-Exam- Or Config-Key
|
||||
sebserver.exam.form.sebrestriction.permissions.CHECK_BROWSER_EXAM_OR_CONFIG_KEY.tooltip=Always check either SEB Browser Exam Key or SEB Config Key with the defined ones for every request.
|
||||
|
||||
|
||||
sebserver.exam.type.UNDEFINED=Not Defined
|
||||
sebserver.exam.type.UNDEFINED.tooltip=No exam type specified
|
||||
sebserver.exam.type.MANAGED=Managed Devices
|
||||
sebserver.exam.type.MANAGED.tooltip=Exam type specified for managed devices
|
||||
sebserver.exam.type.BYOD=Bring Your Own Device
|
||||
sebserver.exam.type.BYOD.tooltip=Exam type specified for bring your own devices
|
||||
sebserver.exam.type.VDI=VDI (Virtual Desktop Infrastructure)
|
||||
sebserver.exam.type.VDI.tooltip=Exam type specified for Virtual Desktop Infrastructure
|
||||
|
||||
sebserver.exam.status.UP_COMING=Up Coming
|
||||
sebserver.exam.status.RUNNING=Running
|
||||
|
@ -413,9 +482,13 @@ sebserver.exam.status.FINISHED=Finished
|
|||
|
||||
sebserver.exam.configuration.list.actions=
|
||||
sebserver.exam.configuration.list.title=SEB Exam Configuration
|
||||
sebserver.exam.configuration.list.title.tooltip=A list of all attached SEB exam configuration for this exam.
|
||||
sebserver.exam.configuration.list.column.name=Name
|
||||
sebserver.exam.configuration.list.column.name.tooltip=The name of the attached SEB exam configuration.
|
||||
sebserver.exam.configuration.list.column.description=Description
|
||||
sebserver.exam.configuration.list.column.description.tooltip=The description of the attached SEB exam configuration.
|
||||
sebserver.exam.configuration.list.column.status=Status
|
||||
sebserver.exam.configuration.list.column.status.tooltip=The current status of the attached SEB exam configuration.
|
||||
sebserver.exam.configuration.list.empty=There is currently no SEB Configuration defined for this Exam. Please add one
|
||||
sebserver.exam.configuration.list.pleaseSelect=Please select first a SEB Configuration from the list
|
||||
sebserver.exam.configuration.action.noconfig.message=There is currently no SEB exam configuration to select.<br/>Please create one in SEB Configuration / Exam Configuration
|
||||
|
@ -431,25 +504,34 @@ sebserver.exam.configuration.action.get-config-key=Export Config-Key
|
|||
sebserver.exam.configuration.form.title.new=Add SEB Configuration Mapping
|
||||
sebserver.exam.configuration.form.title=SEB Configuration Mapping
|
||||
sebserver.exam.configuration.form.name=SEB Configuration
|
||||
sebserver.exam.configuration.form.name.tooltip=Please select a SEB exam configuration to attach to the exam
|
||||
sebserver.exam.configuration.form.encryptSecret=Encryption Password
|
||||
sebserver.exam.configuration.form.encryptSecret.tooltip=Define a encryption password if the SEB exam configuration should be encrypted by password
|
||||
sebserver.exam.configuration.form.description=Description
|
||||
sebserver.exam.configuration.form.description.tooltip=The description of the selected SEB exam configuration
|
||||
sebserver.exam.configuration.form.status=Status
|
||||
sebserver.exam.configuration.form.status.tooltip=The current status of the selected SEB exam configuration
|
||||
sebserver.exam.configuration.form.encryptSecret.confirm=Confirm Password
|
||||
sebserver.exam.configuration.form.encryptSecret.confirm.tooltip=Please confirm the encryption password if there is one
|
||||
|
||||
sebserver.exam.indicator.list.actions=
|
||||
sebserver.exam.indicator.list.title=Indicators
|
||||
sebserver.exam.indicator.list.title.tooltip=A list of indicators that are shown on the exam monitoring view
|
||||
sebserver.exam.indicator.list.column.type=Type
|
||||
sebserver.exam.indicator.list.column.type.tooltip=The type of indicator
|
||||
sebserver.exam.indicator.list.column.name=Name
|
||||
sebserver.exam.indicator.list.column.name.tooltip=The name of the indicator
|
||||
sebserver.exam.indicator.list.column.thresholds=Thresholds
|
||||
sebserver.exam.indicator.list.column.thresholds.tooltip=The thresholds of the indicator
|
||||
sebserver.exam.indicator.list.empty=There is currently no indicator defined for this exam. Please create a new one
|
||||
sebserver.exam.indicator.list.pleaseSelect=Please select first an indicator from the list
|
||||
|
||||
sebserver.exam.indicator.type.LAST_PING=Last Ping Time
|
||||
sebserver.exam.indicator.type.ERROR_COUNT=Errors
|
||||
sebserver.exam.indicator.type.WARN_COUNT=Warnings
|
||||
sebserver.exam.indicator.type.description.LAST_PING=This indicator shows the time in milliseconds since</br> the last ping has been received from a SEB Client.</br>This indicator can be used to track a SEB Client connection and indicate connection losse.</br></br>Thresholds are defined in milliseconds.
|
||||
sebserver.exam.indicator.type.description.ERROR_COUNT=This indicator shows the number of error log messages that</br> has been received from a SEB Client.</br>This indicator can be used to track errors of connected SEB Clients</br></br>Thresholds are defined by natural numbers.
|
||||
sebserver.exam.indicator.type.description.WARN_COUNT=This indicator shows the number of warn log messages that</br> has been received from a SEB Client.</br>This indicator can be used to track warnings of connected SEB Clients</br></br>Thresholds are defined by natural numbers.
|
||||
sebserver.exam.indicator.type.description.LAST_PING=This indicator shows the time in milliseconds since<br/> the last ping has been received from a SEB Client.<br/>This indicator can be used to track a SEB Client connection and indicate connection loss.<br/><br/>The value is in milliseconds.
|
||||
sebserver.exam.indicator.type.description.ERROR_COUNT=This indicator shows the number of error log messages that<br/> has been received from a SEB Client.<br/>This indicator can be used to track errors of connected SEB Clients<br/><br/>The value is natural numbers.
|
||||
sebserver.exam.indicator.type.description.WARN_COUNT=This indicator shows the number of warn log messages that<br/> has been received from a SEB Client.<br/>This indicator can be used to track warnings of connected SEB Clients<br/><br/>The value is natural numbers.
|
||||
|
||||
|
||||
sebserver.exam.indicator.info.pleaseSelect=Please select first an indicator from the list
|
||||
|
@ -462,19 +544,27 @@ sebserver.exam.indicator.action.save=Save
|
|||
sebserver.exam.indicator.form.title=Indicator
|
||||
sebserver.exam.indicator.form.title.new=Add Indicator
|
||||
sebserver.exam.indicator.form.exam=Exam
|
||||
sebserver.exam.indicator.form.exam.tooltip=The exam this indicator belongs to.
|
||||
sebserver.exam.indicator.form.name=Name
|
||||
sebserver.exam.indicator.form.name.tooltip=The name of the indicator.<br/><br/>This name is also displayed as the column title of the indicator on the exam monitoring view
|
||||
sebserver.exam.indicator.form.type=Type
|
||||
sebserver.exam.indicator.form.type.tooltip=The type of the indicator.<br/><br/>There are only a set of defined indicators to choose from.<br/>Choose one to see a detailed description for each indicator below.
|
||||
sebserver.exam.indicator.form.description=Type Description
|
||||
sebserver.exam.indicator.form.description.tooltip=A detailed description of the selected indicator.
|
||||
sebserver.exam.indicator.form.color=Default Color
|
||||
sebserver.exam.indicator.form.color.tooltip=The default color that is displayed on the exam monitoring for this indicator.
|
||||
sebserver.exam.indicator.form.color.action=Please select a color
|
||||
sebserver.exam.indicator.form.thresholds=Thresholds
|
||||
sebserver.exam.indicator.form.thresholds.tooltip=A list of value / color pairs that defines the thresholds of the indicator.<br/><br/>On the exam monitoring view a cell of the indicator is displayed in the specified color when the defined threshold value is reached
|
||||
sebserver.exam.indicator.thresholds.select.color=Please select a color
|
||||
|
||||
sebserver.exam.indicator.thresholds.list.title=Thresholds
|
||||
sebserver.exam.indicator.thresholds.list.value=Value
|
||||
sebserver.exam.indicator.thresholds.list.value.tooltip=The threshold value.
|
||||
sebserver.exam.indicator.thresholds.list.color=Color
|
||||
sebserver.exam.indicator.thresholds.list.add=Add Threshold
|
||||
sebserver.exam.indicator.thresholds.list.remove=Delete Threshold
|
||||
sebserver.exam.indicator.thresholds.list.color.tooltip=The color that is displayed on the exam monitoring view when indicator value has reached the defined threshold value.
|
||||
sebserver.exam.indicator.thresholds.list.add=Add a new threshold
|
||||
sebserver.exam.indicator.thresholds.list.remove=Delete this threshold
|
||||
|
||||
################################
|
||||
# SEB Client Configuration
|
||||
|
@ -489,28 +579,40 @@ sebserver.clientconfig.list.empty=There is currently no SEB-Client configuration
|
|||
sebserver.clientconfig.list.title=SEB Client Configurations
|
||||
sebserver.clientconfig.list.actions=
|
||||
sebserver.clientconfig.list.column.institution=Institution
|
||||
sebserver.clientconfig.list.column.institution.tooltip=The institution of the SEB client configuration.</br></br>Use the filter above to specify the institution.</br>{0}
|
||||
sebserver.clientconfig.list.column.institution.tooltip=The institution of the SEB client configuration.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.clientconfig.list.column.name=Name
|
||||
sebserver.clientconfig.list.column.name.tooltip=The name of the SEB client configuration.</br></br>Use the filter above to narrow down a specific name.</br>{0}
|
||||
sebserver.clientconfig.list.column.name.tooltip=The name of the SEB client configuration.<br/><br/>Use the filter above to narrow down a specific name.<br/>{0}
|
||||
sebserver.clientconfig.list.column.date=Creation Date {0}
|
||||
sebserver.clientconfig.list.column.date.tooltip=The date when the SEB client configuration was first created.</br></br>Use the filter above to specify a from-date.</br>{0}
|
||||
sebserver.clientconfig.list.column.date.tooltip=The date when the SEB client configuration was first created.<br/><br/>Use the filter above to specify a from-date.<br/>{0}
|
||||
sebserver.clientconfig.list.column.active=Active
|
||||
sebserver.clientconfig.list.column.active.tooltip=The activity of SEB client configuration.</br></br>Use the filter above to specify the activity.</br>{0}
|
||||
sebserver.clientconfig.list.column.active.tooltip=The activity of SEB client configuration.<br/><br/>Use the filter above to specify the activity.<br/>{0}
|
||||
sebserver.clientconfig.info.pleaseSelect=Please select first a Client Configuration from the list
|
||||
sebserver.clientconfig.list.action.no.modify.privilege=No Access: A SEB Client Configuration from other institution cannot be modified.
|
||||
|
||||
sebserver.clientconfig.form.title.new=Add Client Configuration
|
||||
sebserver.clientconfig.form.title=SEB Client Configuration
|
||||
sebserver.clientconfig.form.name=Name
|
||||
sebserver.clientconfig.form.name.tooltip=The name of the SEB Client Configuration.</br>Can be any name that not already exists for another SEB Client Configuration
|
||||
sebserver.clientconfig.form.name.tooltip=The name of the SEB Client Configuration.<br/>Can be any name that not already exists for another SEB Client Configuration
|
||||
sebserver.clientconfig.form.fallback=With Fallback
|
||||
sebserver.clientconfig.form.fallback.tooltip=Indicates whether this SEB Client Configuration has a fallback definition or not
|
||||
sebserver.clientconfig.form.fallback-url=Fallback Start URL
|
||||
sebserver.clientconfig.form.fallback-url.tooltip=A fallback URL that tells the SEB where to go when the SEB Server service is unavailable.
|
||||
sebserver.clientconfig.form.sebServerFallbackTimeout=Fallback Timeout
|
||||
sebserver.clientconfig.form.sebServerFallbackTimeout.tooltip=Defines the fallback timeout for the SEB Client in milli-seconds.
|
||||
sebserver.clientconfig.form.sebServerFallbackAttempts=Fallback Attempts
|
||||
sebserver.clientconfig.form.sebServerFallbackAttempts.tooltip=The number of connection attempts a SEB Client is trying before switching to fallback case.
|
||||
sebserver.clientconfig.form.sebServerFallbackAttemptInterval=Attempt Interval
|
||||
sebserver.clientconfig.form.sebServerFallbackAttemptInterval.tooltip=The interval (in milli-seconds) between connection attempts a SEB Client shall use.
|
||||
sebserver.clientconfig.form.sebServerFallbackPasswordHash=Fallback Password
|
||||
sebserver.clientconfig.form.sebServerFallbackPasswordHash.tooltip=A password if set, a SEB Client user must give before the SEB Client starts the fallback procedure.
|
||||
sebserver.clientconfig.form.date=Creation Date
|
||||
sebserver.clientconfig.form.date.tooltip=The date when the SEB client configuration was first created.
|
||||
sebserver.clientconfig.form.encryptSecret=Configuration Password
|
||||
sebserver.clientconfig.form.encryptSecret.tooltip=Define a password if the SEB client configuration shall be password-encrypted
|
||||
sebserver.clientconfig.form.encryptSecret.confirm=Confirm Password
|
||||
sebserver.clientconfig.form.encryptSecret.confirm.tooltip=Please retype the given password for configrmation
|
||||
sebserver.clientconfig.form.encryptSecret.confirm.tooltip=Please retype the given password for confirmation
|
||||
sebserver.clientconfig.form.sebConfigPurpose=Configuration Purpose
|
||||
sebserver.clientconfig.form.sebConfigPurpose.tooltip=This indicates whether this client configuration shall be used to configure the SEB Client or to start an exam
|
||||
|
||||
sebserver.clientconfig.action.list.new=Add Configuration
|
||||
sebserver.clientconfig.action.list.view=View Configuration
|
||||
|
@ -527,13 +629,13 @@ sebserver.clientconfig.action.deactivate=Deactivate Configuration
|
|||
sebserver.examconfig.action.list=Exam Configuration
|
||||
sebserver.examconfig.list.title=Exam Configurations
|
||||
sebserver.examconfig.list.column.institution=Institution
|
||||
sebserver.examconfig.list.column.institution.tooltip=The institution of the SEB exam configuration.</br></br>Use the filter above to specify the institution.</br>{0}
|
||||
sebserver.examconfig.list.column.institution.tooltip=The institution of the SEB exam configuration.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.examconfig.list.column.name=Name
|
||||
sebserver.examconfig.list.column.name.tooltip=The name of the SEB exam configuration.</br></br>Use the filter above to narrow down a specific name.</br>{0}
|
||||
sebserver.examconfig.list.column.name.tooltip=The name of the SEB exam configuration.<br/><br/>Use the filter above to narrow down a specific name.<br/>{0}
|
||||
sebserver.examconfig.list.column.description=Description
|
||||
sebserver.examconfig.list.column.description.tooltip=The description of the SEB exam configuration.</br></br>Use the filter above to find configurations that contains specific words or phrases within the description.</br>{0}
|
||||
sebserver.examconfig.list.column.description.tooltip=The description of the SEB exam configuration.<br/><br/>Use the filter above to find configurations that contains specific words or phrases within the description.<br/>{0}
|
||||
sebserver.examconfig.list.column.status=Status
|
||||
sebserver.examconfig.list.column.status.tooltip=The status of the SEB exam configuration.</br></br>Use the filter above to specify a status.</br>{0}
|
||||
sebserver.examconfig.list.column.status.tooltip=The status of the SEB exam configuration.<br/><br/>Use the filter above to specify a status.<br/>{0}
|
||||
|
||||
sebserver.examconfig.list.actions=
|
||||
|
||||
|
@ -577,10 +679,10 @@ sebserver.examconfig.form.with-history=With History
|
|||
sebserver.examconfig.form.template=Template
|
||||
sebserver.examconfig.form.template.tooltip=The template this SEB exam configuration depends on.
|
||||
sebserver.examconfig.form.status=Status
|
||||
sebserver.examconfig.form.status.tooltip=The status of this SEB exam configuration.</br></br>Under Construction marks a SEB exam configuration to not be able to attach to an exam so far.</br></br>Ready to use marks an SEB exam configuration to be able to attach to an exam.</br></br>In Use marks a SEB exam configuration is already been used from one or more exam(s)
|
||||
sebserver.examconfig.form.status.tooltip=The status of this SEB exam configuration.<br/><br/>Under Construction marks a SEB exam configuration to not be able to attach to an exam so far.<br/><br/>Ready to use marks an SEB exam configuration to be able to attach to an exam.<br/><br/>In Use marks a SEB exam configuration is already been used from one or more exam(s)
|
||||
sebserver.examconfig.form.config-key.title=Config Key
|
||||
sebserver.examconfig.form.attached-to=Attached To Exam
|
||||
sebserver.examconfig.form.attached-to.tooltip=This SEB exam configuration is currently attached to the following exams.</br></br>Select an exam from the list and use the "View Exam" or Double-Click on the list to go to a specific exam.
|
||||
sebserver.examconfig.form.attached-to.tooltip=This SEB exam configuration is currently attached to the following exams.<br/><br/>Select an exam from the list and use the "View Exam" or Double-Click on the list to go to a specific exam.
|
||||
|
||||
sebserver.examconfig.status.CONSTRUCTION=Under Construction
|
||||
sebserver.examconfig.status.READY_TO_USE=Ready To Use
|
||||
|
@ -603,9 +705,9 @@ sebserver.examconfig.props.form.views.hooked_keys=Hooked Keys
|
|||
sebserver.examconfig.props.label.hashedAdminPassword=Administrator password
|
||||
sebserver.examconfig.props.label.hashedAdminPassword.confirm=Confirm password
|
||||
sebserver.examconfig.props.label.allowQuit=Allow user to quit SEB
|
||||
sebserver.examconfig.props.label.allowQuit.tooltip=Users can quit SEB with Control-Q, window close or quit button.</br>Otherwise use a quit link in your exam system or shutdown/restart the computer.
|
||||
sebserver.examconfig.props.label.allowQuit.tooltip=Users can quit SEB with Control-Q, window close or quit button.<br/>Otherwise use a quit link in your exam system or shutdown/restart the computer.
|
||||
sebserver.examconfig.props.label.ignoreExitKeys=Ignore exit keys
|
||||
sebserver.examconfig.props.label.ignoreExitKeys.tooltip=SEB ignores the exit keys and can only be quit manually by entering the quit password.</br>(click Quit button in SEB taskbar, press Ctrl-Q or click the main browser window close button)
|
||||
sebserver.examconfig.props.label.ignoreExitKeys.tooltip=SEB ignores the exit keys and can only be quit manually by entering the quit password.<br/>(click Quit button in SEB taskbar, press Ctrl-Q or click the main browser window close button)
|
||||
sebserver.examconfig.props.label.hashedQuitPassword=Quit/unlock password
|
||||
sebserver.examconfig.props.label.hashedQuitPassword.confirm=Confirm password
|
||||
sebserver.examconfig.props.group.exitSequence=Exit Sequence
|
||||
|
@ -645,15 +747,15 @@ sebserver.examconfig.props.label.mainBrowserWindowPositioning.2=Right
|
|||
|
||||
sebserver.examconfig.props.group.wintoolbar=Browser Window Toolbar
|
||||
sebserver.examconfig.props.label.enableBrowserWindowToolbar=Enable browser window toolbar
|
||||
sebserver.examconfig.props.label.enableBrowserWindowToolbar.tooltip=Displays a toolbar on top of the browser window</br>which can also be hidden by the user.
|
||||
sebserver.examconfig.props.label.enableBrowserWindowToolbar.tooltip=Displays a toolbar on top of the browser window<br/>which can also be hidden by the user.
|
||||
sebserver.examconfig.props.label.hideBrowserWindowToolbar=Hide toolbar as default (Mac)
|
||||
sebserver.examconfig.props.label.hideBrowserWindowToolbar.tooltip=Hide browser window toolbar by default.</br>It can be shown again by using the View menu or Alt-Command-T.
|
||||
sebserver.examconfig.props.label.hideBrowserWindowToolbar.tooltip=Hide browser window toolbar by default.<br/>It can be shown again by using the View menu or Alt-Command-T.
|
||||
sebserver.examconfig.props.label.showMenuBar=Show menu bar (Mac)
|
||||
sebserver.examconfig.props.label.showMenuBar.tooltip=Show the OS X menu bar to allow to access settings like Wi-Fi.
|
||||
|
||||
sebserver.examconfig.props.group.taskbar=SEB Taskbar/Dock
|
||||
sebserver.examconfig.props.label.showTaskBar=Show SEB taskbar
|
||||
sebserver.examconfig.props.label.showTaskBar.tooltip=The SEB task bar shows and switches between open browser windows,</br> allowed resources and applications and displays additional controls
|
||||
sebserver.examconfig.props.label.showTaskBar.tooltip=The SEB task bar shows and switches between open browser windows,<br/> allowed resources and applications and displays additional controls
|
||||
sebserver.examconfig.props.label.taskBarHeight=Taskbar/dock height
|
||||
sebserver.examconfig.props.label.taskBarHeight.tooltip=Height of SEB dock/task bar in points/pixels
|
||||
sebserver.examconfig.props.label.showReloadButton=Show reload button
|
||||
|
@ -665,9 +767,9 @@ sebserver.examconfig.props.label.showInputLanguage.tooltip=Shows current keyboar
|
|||
|
||||
sebserver.examconfig.props.group.zoom=Enable Zoom (Win/Mac)
|
||||
sebserver.examconfig.props.label.enableZoomPage=Enable page zoom
|
||||
sebserver.examconfig.props.label.enableZoomPage.tooltip=Pages can be zoomed with ctrl - cmd +/-</br> or the commands in the view menu and browser window toolbar (Mac)
|
||||
sebserver.examconfig.props.label.enableZoomPage.tooltip=Pages can be zoomed with ctrl - cmd +/-<br/> or the commands in the view menu and browser window toolbar (Mac)
|
||||
sebserver.examconfig.props.label.enableZoomText=Enable text zoom
|
||||
sebserver.examconfig.props.label.enableZoomText.tooltip=Text in browser windows can be zoomed with cmd +/-</br> or the commands in the view menu and browser window toolbar (Mac)
|
||||
sebserver.examconfig.props.label.enableZoomText.tooltip=Text in browser windows can be zoomed with cmd +/-<br/> or the commands in the view menu and browser window toolbar (Mac)
|
||||
sebserver.examconfig.props.group.zoomMode=Zoom Mode Win (Ctrl-Mousewheel)
|
||||
sebserver.examconfig.props.label.zoomMode.0=Use page zoom
|
||||
sebserver.examconfig.props.label.zoomMode.0.tooltip=Zoom whole web pages using Ctrl-Mousewheel (Win)"
|
||||
|
@ -687,7 +789,7 @@ sebserver.examconfig.props.label.allowSpellCheck=Allow spell checking
|
|||
sebserver.examconfig.props.label.allowSpellCheck.tooltip=Allow to use "Check spelling" in the SEB browser
|
||||
sebserver.examconfig.props.label.allowDictionaryLookup=Allow dictionary lookup (Mac)
|
||||
sebserver.examconfig.props.label.allowDictionaryLookup.tooltip=Allow to use the OS X dictionary lookup using a 3 finger tap
|
||||
sebserver.examconfig.props.label.allowSpellCheckDictionary=The list below shows all dictionaries currently available for spell checking.</br>SEB comes with a list of standard dictionaries that can be activated/deactivated here.
|
||||
sebserver.examconfig.props.label.allowSpellCheckDictionary=The list below shows all dictionaries currently available for spell checking.<br/>SEB comes with a list of standard dictionaries that can be activated/deactivated here.
|
||||
sebserver.examconfig.props.label.allowSpellCheckDictionary.da-DK=Danish (Denmark) (da-DK)
|
||||
sebserver.examconfig.props.label.allowSpellCheckDictionary.en-AU=English (Australia) (en-AU)
|
||||
sebserver.examconfig.props.label.allowSpellCheckDictionary.en-GB=English (United Kingdom) (en-GB)
|
||||
|
@ -702,8 +804,8 @@ sebserver.examconfig.props.group.newBrowserWindow=Links requesting to be opened
|
|||
sebserver.examconfig.props.label.newBrowserWindowByLinkPolicy.0=get generally blocked
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkPolicy.1=open in same window
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkPolicy.2=open in new window
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkBlockForeign=Block when directing</br>to a different server
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkBlockForeign.tooltip=USE WITH CARE: Hyperlinks invoked by JavaScript/plug-ins</br> which direct to a different host than the one of the current main page will be ignored.
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkBlockForeign=Block when directing<br/>to a different server
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkBlockForeign.tooltip=USE WITH CARE: Hyperlinks invoked by JavaScript/plug-ins<br/> which direct to a different host than the one of the current main page will be ignored.
|
||||
|
||||
sebserver.examconfig.props.group.newwinsize=New browser window size and position
|
||||
sebserver.examconfig.props.label.newBrowserWindowByLinkWidth=Width
|
||||
|
@ -717,19 +819,19 @@ sebserver.examconfig.props.label.newBrowserWindowByLinkPositioning.2=Right
|
|||
|
||||
sebserver.examconfig.props.group.browserSecurity=Browser security
|
||||
sebserver.examconfig.props.label.enablePlugIns=Enable plug-ins (Win: only Flash)
|
||||
sebserver.examconfig.props.label.enablePlugIns.tooltip=Enables web plugins (Mac) or just Flash (Win).</br> For security reasons it\'s recommended to disable this option if you don\'t use any plugin/Flash content.
|
||||
sebserver.examconfig.props.label.enablePlugIns.tooltip=Enables web plugins (Mac) or just Flash (Win).<br/> For security reasons it\'s recommended to disable this option if you don\'t use any plugin/Flash content.
|
||||
sebserver.examconfig.props.label.enableJavaScript=Enable JavaScript
|
||||
sebserver.examconfig.props.label.enableJavaScript.tooltip=Enables JavaScript.</br> Please note that most modern web-sites need JavaScript for full functionality.
|
||||
sebserver.examconfig.props.label.enableJavaScript.tooltip=Enables JavaScript.<br/> Please note that most modern web-sites need JavaScript for full functionality.
|
||||
sebserver.examconfig.props.label.enableJava=Enable Java
|
||||
sebserver.examconfig.props.label.enableJava.tooltip=Enables Java applets.</br> Note: Only applets with the highest Java security level will run in SEB.
|
||||
sebserver.examconfig.props.label.enableJava.tooltip=Enables Java applets.<br/> Note: Only applets with the highest Java security level will run in SEB.
|
||||
sebserver.examconfig.props.label.blockPopUpWindows=Block pop-up windows
|
||||
sebserver.examconfig.props.label.blockPopUpWindows.tooltip=Disables pop-up windows</br> (often advertisement) opened by JavaScript without an user action such as a button click.
|
||||
sebserver.examconfig.props.label.blockPopUpWindows.tooltip=Disables pop-up windows<br/> (often advertisement) opened by JavaScript without an user action such as a button click.
|
||||
sebserver.examconfig.props.label.allowVideoCapture=Allow video capture (webcam)
|
||||
sebserver.examconfig.props.label.allowVideoCapture.tooltip=Allow web applications to access camera
|
||||
sebserver.examconfig.props.label.allowAudioCapture=Allow audio capture (microphone)
|
||||
sebserver.examconfig.props.label.allowAudioCapture.tooltip=Allow web applications to access microphone
|
||||
sebserver.examconfig.props.label.allowBrowsingBackForward=Allow navigating back/forward in exam
|
||||
sebserver.examconfig.props.label.allowBrowsingBackForward.tooltip=Disabling browsing to previously visited pages may increase security,</br> because browsing back might allow to leave an exam
|
||||
sebserver.examconfig.props.label.allowBrowsingBackForward.tooltip=Disabling browsing to previously visited pages may increase security,<br/> because browsing back might allow to leave an exam
|
||||
sebserver.examconfig.props.label.newBrowserWindowNavigation=Allow navigating in additional windows
|
||||
sebserver.examconfig.props.label.browserWindowAllowReload=Allow reload exam
|
||||
sebserver.examconfig.props.label.browserWindowAllowReload.tooltip=Allow reload in the exam window with F5 reload button (if displayed)
|
||||
|
@ -742,7 +844,7 @@ sebserver.examconfig.props.label.newBrowserWindowShowReloadWarning.tooltip=User
|
|||
sebserver.examconfig.props.label.removeBrowserProfile=Remove profile (Win)
|
||||
sebserver.examconfig.props.label.removeBrowserProfile.tooltip=Remove XULRunner browser profile (containing caches and also local storage) when quitting SEB
|
||||
sebserver.examconfig.props.label.removeLocalStorage=Disable local storage (Mac)
|
||||
sebserver.examconfig.props.label.removeLocalStorage.tooltip=If your web application uses local storage, you have to be sure data is saved encrypted</br> and removed when no longer needed as SEB doesn't remove local storage
|
||||
sebserver.examconfig.props.label.removeLocalStorage.tooltip=If your web application uses local storage, you have to be sure data is saved encrypted<br/> and removed when no longer needed as SEB doesn't remove local storage
|
||||
|
||||
sebserver.examconfig.props.label.browserUserAgent=Suffix to be added to any user agent
|
||||
sebserver.examconfig.props.group.userAgentDesktop=User agent for desktop mode
|
||||
|
@ -750,7 +852,7 @@ sebserver.examconfig.props.label.browserUserAgentWinDesktopMode.0=Desktop defaul
|
|||
sebserver.examconfig.props.label.browserUserAgentWinDesktopMode.0.tooltip=Zoom whole web pages using Ctrl-Mousewheel (Win)
|
||||
sebserver.examconfig.props.label.browserUserAgentWinDesktopMode.1=Custom
|
||||
sebserver.examconfig.props.label.browserUserAgentWinDesktopMode.1.tooltip=Zoom only text on web pages using Ctrl-Mousewheel (Win)
|
||||
sebserver.examconfig.props.label.browserUserAgentWinDesktopModeCustom.tooltip=Custom desktop user agent string</br>(SEB appends its version number automatically)
|
||||
sebserver.examconfig.props.label.browserUserAgentWinDesktopModeCustom.tooltip=Custom desktop user agent string<br/>(SEB appends its version number automatically)
|
||||
|
||||
sebserver.examconfig.props.group.userAgentTouch=User agent for touch/table mode
|
||||
sebserver.examconfig.props.label.browserUserAgentWinTouchMode.0=Touch default
|
||||
|
@ -764,28 +866,28 @@ sebserver.examconfig.props.label.browserUserAgentMac.1=Custom
|
|||
sebserver.examconfig.props.label.browserUserAgentMac.1.tooltip=Zoom only text on web pages using Ctrl-Mousewheel (Win)
|
||||
|
||||
sebserver.examconfig.props.label.enableSebBrowser=Enable SEB with browser window
|
||||
sebserver.examconfig.props.label.enableSebBrowser.tooltip=Disable this to start another application in kiosk mode</br>(for example a virtual desktop infrastructure client)
|
||||
sebserver.examconfig.props.label.enableSebBrowser.tooltip=Disable this to start another application in kiosk mode<br/>(for example a virtual desktop infrastructure client)
|
||||
sebserver.examconfig.props.label.browserWindowTitleSuffix=Suffix to be added to every browser window
|
||||
|
||||
sebserver.examconfig.props.label.allowDownUploads=Allow downloading and uploading files (Mac)
|
||||
sebserver.examconfig.props.label.allowDownUpload.tooltip=Usually to be used with permitted third party applications</br> for which you want to provide files to be down-loaded.
|
||||
sebserver.examconfig.props.label.allowDownUpload.tooltip=Usually to be used with permitted third party applications<br/> for which you want to provide files to be down-loaded.
|
||||
sebserver.examconfig.props.label.downloadDirectoryWin=Download directory (Win)
|
||||
sebserver.examconfig.props.label.downloadDirectoryOSX=Download directory (Mac)
|
||||
sebserver.examconfig.props.label.openDownloads=Open files after downloading (Mac)
|
||||
sebserver.examconfig.props.label.chooseFileToUploadPolicy=Choose file to upload (Mac)
|
||||
sebserver.examconfig.props.label.chooseFileToUploadPolicy.tooltip=SEB can let users choose the file to upload or automatically use the same file which was down-loaded before.</br>If not found, a file requester or an error is presented depending on this setting.
|
||||
sebserver.examconfig.props.label.chooseFileToUploadPolicy.tooltip=SEB can let users choose the file to upload or automatically use the same file which was down-loaded before.<br/>If not found, a file requester or an error is presented depending on this setting.
|
||||
sebserver.examconfig.props.label.chooseFileToUploadPolicy.0=manually with file requester
|
||||
sebserver.examconfig.props.label.chooseFileToUploadPolicy.1=by attempting to upload the same file downloaded before
|
||||
sebserver.examconfig.props.label.chooseFileToUploadPolicy.2=by only allowing to upload the same file downloaded before
|
||||
sebserver.examconfig.props.label.downloadPDFFiles=Download and open PDF files instead of displaying them inline (Mac)
|
||||
sebserver.examconfig.props.label.downloadPDFFiles.tooltip=PDF files will not be displayed by SEB but downloaded and openend (if "Open files after downloading" is active!)</br> by the application set in Finder (usually Preview or Adobe Acrobat).
|
||||
sebserver.examconfig.props.label.downloadPDFFiles.tooltip=PDF files will not be displayed by SEB but downloaded and openend (if "Open files after downloading" is active!)<br/> by the application set in Finder (usually Preview or Adobe Acrobat).
|
||||
sebserver.examconfig.props.label.allowPDFPlugIn=Allow using Acrobat Reader PDF plugin (insecure! Mac only)
|
||||
sebserver.examconfig.props.label.allowPDFPlugIn.tooltip=The Adobe Acrobat Reader browser plugin should only be used on secured managed Mac computers,</br> at it allows limited access the file system and unlimited to cloud services
|
||||
sebserver.examconfig.props.label.allowPDFPlugIn.tooltip=The Adobe Acrobat Reader browser plugin should only be used on secured managed Mac computers,<br/> at it allows limited access the file system and unlimited to cloud services
|
||||
sebserver.examconfig.props.label.downloadAndOpenSebConfig=Download and open SEB Config Files
|
||||
sebserver.examconfig.props.label.downloadAndOpenSebConfig.tooltip=Download and open .seb config files regardless if downloading and opening other file types is allowed.
|
||||
|
||||
sebserver.examconfig.props.group.quitLink=Link to quit SEB after exam
|
||||
sebserver.examconfig.props.label.quitURL=Place this quit link to the 'feedback' page displayed after an exam was successfully finished.</br> Clicking that link will quit SEB without having to enter the quit password.
|
||||
sebserver.examconfig.props.label.quitURL=Place this quit link to the 'feedback' page displayed after an exam was successfully finished.<br/> Clicking that link will quit SEB without having to enter the quit password.
|
||||
sebserver.examconfig.props.label.quitURLConfirm=Ask user to confirm quitting
|
||||
|
||||
sebserver.examconfig.props.group.backToStart=Back to Start Button
|
||||
|
@ -798,7 +900,7 @@ sebserver.examconfig.props.label.restartExamPasswordProtected=Protect back to st
|
|||
sebserver.examconfig.props.label.restartExamPasswordProtected.tooltip=The quit/restart password (if set) must be entered when the back to start button was pressed.
|
||||
|
||||
sebserver.examconfig.props.label.allowSwitchToApplications=Allow switching to third party application (Mac)
|
||||
sebserver.examconfig.props.label.allowSwitchToApplications.tooltip=Decreases security of the kiosk mode by allowing process switcher (Cmd+Tab).</br> The blacked out background of SEB also doesn't cover some alerts and modal windows in this mode.
|
||||
sebserver.examconfig.props.label.allowSwitchToApplications.tooltip=Decreases security of the kiosk mode by allowing process switcher (Cmd+Tab).<br/> The blacked out background of SEB also doesn't cover some alerts and modal windows in this mode.
|
||||
sebserver.examconfig.props.label.allowFlashFullscreen=Allow Flash to switch to fullscreen mode (Mac)
|
||||
sebserver.examconfig.props.label.permittedProcesses.add.tooltip=Add permitted process
|
||||
sebserver.examconfig.props.label.permittedProcesses.remove.tooltip=Remove selected permitted process
|
||||
|
@ -811,11 +913,11 @@ sebserver.examconfig.props.label.permittedProcesses.os.tooltip=Indicates on whic
|
|||
sebserver.examconfig.props.label.permittedProcesses.os.0=OS X
|
||||
sebserver.examconfig.props.label.permittedProcesses.os.1=Win
|
||||
sebserver.examconfig.props.label.permittedProcesses.title=Title
|
||||
sebserver.examconfig.props.label.permittedProcesses.title.tooltip=Application title which is displayed in the application chooser.</br> Background processes don't have a title, because they can't be selected by users.
|
||||
sebserver.examconfig.props.label.permittedProcesses.title.tooltip=Application title which is displayed in the application chooser.<br/> Background processes don't have a title, because they can't be selected by users.
|
||||
sebserver.examconfig.props.label.permittedProcesses.description=Description
|
||||
sebserver.examconfig.props.label.permittedProcesses.description.tooltip=Optional, should explain what kind of process this is,</br> because this might not be obvious only from the executable's name.
|
||||
sebserver.examconfig.props.label.permittedProcesses.description.tooltip=Optional, should explain what kind of process this is,<br/> because this might not be obvious only from the executable's name.
|
||||
sebserver.examconfig.props.label.permittedProcesses.executable=Executable
|
||||
sebserver.examconfig.props.label.permittedProcesses.executable.tooltip=File name of the executable, which should not contain any parts of a file system path,</br> only the filename of the exe file (like calc.exe).
|
||||
sebserver.examconfig.props.label.permittedProcesses.executable.tooltip=File name of the executable, which should not contain any parts of a file system path,<br/> only the filename of the exe file (like calc.exe).
|
||||
sebserver.examconfig.props.label.permittedProcesses.originalName=Original Name
|
||||
sebserver.examconfig.props.label.permittedProcesses.allowedExecutables=Window handling process
|
||||
sebserver.examconfig.props.label.permittedProcesses.path=Path
|
||||
|
@ -825,13 +927,13 @@ sebserver.examconfig.props.label.permittedProcesses.arguments.argument=Argument
|
|||
sebserver.examconfig.props.label.permittedProcesses.arguments.addAction=Add new argument
|
||||
sebserver.examconfig.props.label.permittedProcesses.arguments.removeAction=Remove this argument
|
||||
sebserver.examconfig.props.label.permittedProcesses.identifier=Identifier
|
||||
sebserver.examconfig.props.label.permittedProcesses.identifier.tooltip=(Sub) string in the title of the main window of a tricky third party application (Java, Acrobat etc.).</br> Mac OS X: Bundle identifier of the process in reverse domain notation.
|
||||
sebserver.examconfig.props.label.permittedProcesses.identifier.tooltip=(Sub) string in the title of the main window of a tricky third party application (Java, Acrobat etc.).<br/> Mac OS X: Bundle identifier of the process in reverse domain notation.
|
||||
sebserver.examconfig.props.label.permittedProcesses.iconInTaskbar=Icon in taskbar
|
||||
sebserver.examconfig.props.label.permittedProcesses.iconInTaskbar.tooltip=Show icon of permitted application in task bar</br> (not possible when 'run in background' is enabled).
|
||||
sebserver.examconfig.props.label.permittedProcesses.iconInTaskbar.tooltip=Show icon of permitted application in task bar<br/> (not possible when 'run in background' is enabled).
|
||||
sebserver.examconfig.props.label.permittedProcesses.autostart=Autostart
|
||||
sebserver.examconfig.props.label.permittedProcesses.autostart.tooltip=Start the process automatically together with SEB.
|
||||
sebserver.examconfig.props.label.permittedProcesses.runInBackground=Allow running in background
|
||||
sebserver.examconfig.props.label.permittedProcesses.runInBackground.tooltip=Allow the permitted process to already be running when SEB starts.</br> Such a process can't have an icon in the task bar.
|
||||
sebserver.examconfig.props.label.permittedProcesses.runInBackground.tooltip=Allow the permitted process to already be running when SEB starts.<br/> Such a process can't have an icon in the task bar.
|
||||
sebserver.examconfig.props.label.permittedProcesses.allowUserToChooseApp=Allow user to select location of application
|
||||
sebserver.examconfig.props.label.permittedProcesses.strongKill=Force quit (risk of data loss)
|
||||
sebserver.examconfig.props.label.permittedProcesses.strongKill.tooltip=Terminate process in a not-nice way, which may cause data loss if the application had unsaved data
|
||||
|
@ -846,15 +948,15 @@ sebserver.examconfig.props.label.prohibitedProcesses.os=OS
|
|||
sebserver.examconfig.props.label.prohibitedProcesses.os.0=OS X
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.os.1=Win
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.description=Description
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.description.tooltip=Optional, to explain what kind of process this is,</br> because this might not be obvious only from the executable's name.
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.description.tooltip=Optional, to explain what kind of process this is,<br/> because this might not be obvious only from the executable's name.
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.executable=Executable
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.executable.tooltip=File name of the executable, which should not contain any parts of a file system path,</br> only the filename of the exe file (like calc.exe).
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.executable.tooltip=File name of the executable, which should not contain any parts of a file system path,<br/> only the filename of the exe file (like calc.exe).
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.originalName=Original Name
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.originalName.tooltip=Original file name (optional)
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.identifier=Identifier
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.identifier.tooltip=Title of the main window of a Java third party application.</br> Mac OS X: Bundle identifier of the process in reverse domain notation.
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.identifier.tooltip=Title of the main window of a Java third party application.<br/> Mac OS X: Bundle identifier of the process in reverse domain notation.
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.strongKill=Force quit (risk of data loss)
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.strongKill.tooltip=Terminate process in a not-nice way,</br> which may cause data loss if the application had unsaved data
|
||||
sebserver.examconfig.props.label.prohibitedProcesses.strongKill.tooltip=Terminate process in a not-nice way,<br/> which may cause data loss if the application had unsaved data
|
||||
|
||||
sebserver.examconfig.props.group.urlFilter=Filter
|
||||
sebserver.examconfig.props.label.URLFilterEnable=Activate URL Filtering
|
||||
|
@ -1014,7 +1116,7 @@ sebserver.examconfig.props.label.insideSebEnableLogOff.tooltip=Activates the but
|
|||
sebserver.examconfig.props.label.insideSebEnableShutDown=Enable Shut down
|
||||
sebserver.examconfig.props.label.insideSebEnableShutDown.tooltip=Activates the button "Shutdown"
|
||||
sebserver.examconfig.props.label.insideSebEnableEaseOfAccess=Enable Ease of Access
|
||||
sebserver.examconfig.props.label.insideSebEnableEaseOfAccess.tooltip=Shows options when the button "Ease of Access" in the lower left corner is clicked,</br>which offers help e.g. to visually or aurally handicapped persons, like the Magnifier Glass.
|
||||
sebserver.examconfig.props.label.insideSebEnableEaseOfAccess.tooltip=Shows options when the button "Ease of Access" in the lower left corner is clicked,<br/>which offers help e.g. to visually or aurally handicapped persons, like the Magnifier Glass.
|
||||
sebserver.examconfig.props.label.insideSebEnableVmWareClientShade=Enable VMware Client Shade
|
||||
sebserver.examconfig.props.label.insideSebEnableVmWareClientShade.tooltip=Activates the "Shade" bar at the upper edge of a virtual desktop, if existent. If you're not using VMware, this setting doesn't have any effect.
|
||||
sebserver.examconfig.props.label.insideSebEnableNetworkConnectionSelector=Enable network connection selector
|
||||
|
@ -1103,13 +1205,13 @@ sebserver.configtemplate.attr.type.COMPOSITE_TABLE=Table
|
|||
sebserver.configtemplate.attrs.list.title=Configuration Attributes
|
||||
sebserver.configtemplate.attrs.list.title.tooltip=Table of all SEB exam configuration attributes of this template
|
||||
sebserver.configtemplate.attrs.list.name=Name
|
||||
sebserver.configtemplate.attrs.list.name.tooltip=The technical name of the SEB exam configuration attribute with the display name in brackets if available.</br></br>{0}
|
||||
sebserver.configtemplate.attrs.list.name.tooltip=The technical name of the SEB exam configuration attribute with the display name in brackets if available.<br/><br/>{0}
|
||||
sebserver.configtemplate.attrs.list.view=View
|
||||
sebserver.configtemplate.attrs.list.view.tooltip=The view/tab where the SEB exam configuration attribute belongs to.</br></br>{0}
|
||||
sebserver.configtemplate.attrs.list.view.tooltip=The view/tab where the SEB exam configuration attribute belongs to.<br/><br/>{0}
|
||||
sebserver.configtemplate.attrs.list.group=Group
|
||||
sebserver.configtemplate.attrs.list.group.tooltip=The group on the view/tab where the SEB exam configuration attribute belongs to.</br></br>{0}
|
||||
sebserver.configtemplate.attrs.list.group.tooltip=The group on the view/tab where the SEB exam configuration attribute belongs to.<br/><br/>{0}
|
||||
sebserver.configtemplate.attrs.list.type=Type
|
||||
sebserver.configtemplate.attrs.list.type.tooltip=The type of the SEB exam configuration attribute.</br></br>{0}
|
||||
sebserver.configtemplate.attrs.list.type.tooltip=The type of the SEB exam configuration attribute.<br/><br/>{0}
|
||||
|
||||
sebserver.configtemplate.attr.list.actions=
|
||||
sebserver.configtemplate.attr.list.actions.modify=Edit Attribute
|
||||
|
@ -1149,17 +1251,31 @@ sebserver.monitoring.exam.info.pleaseSelect=Please select first an Exam from the
|
|||
sebserver.monitoring.exam.list.empty=There are currently no running exams
|
||||
|
||||
sebserver.monitoring.exam.list.column.name=Name
|
||||
sebserver.monitoring.exam.list.column.name.tooltip=The name of the exam.<br/><br/>Use the filter above to narrow down a specific exam name.<br/>{0}
|
||||
sebserver.monitoring.exam.list.column.type=Type
|
||||
sebserver.monitoring.exam.list.column.type.tooltip=The type of the exam.<br/><br/>Use the filter above to set a specific exam type.<br/>{0}
|
||||
sebserver.monitoring.exam.list.column.startTime=Start Time {0}
|
||||
sebserver.monitoring.exam.list.column.startTime.tooltip=The start date and time of the exam.<br/><br/>{0}
|
||||
sebserver.monitoring.exam.list.column.endTime=End Time {0}
|
||||
sebserver.monitoring.exam.list.column.endTime.tooltip=The end date and time of the exam.<br/><br/>{0}
|
||||
|
||||
sebserver.monitoring.exam=Monitoring Exam: {0}
|
||||
|
||||
sebserver.monitoring.connection.list.column.id=Client Identifier
|
||||
sebserver.monitoring.connection.list.column.id=User Name or Session
|
||||
sebserver.monitoring.connection.list.column.id.tooltip=The user session identifier or username sent by the SEB client after LMS login.
|
||||
sebserver.monitoring.connection.list.column.address=IP Address
|
||||
sebserver.monitoring.connection.list.column.address.tooltip=The IP address from the host the SEB client is connecting to the SEB Server.
|
||||
sebserver.monitoring.connection.list.column.status=Status
|
||||
sebserver.monitoring.connection.list.column.examname=Exam
|
||||
sebserver.monitoring.connection.list.column.vdiAddress=IP Address (VDI)
|
||||
sebserver.monitoring.connection.list.column.status.tooltip=The current connection status
|
||||
|
||||
sebserver.monitoring.connection.form.id=User Name or Session
|
||||
sebserver.monitoring.connection.form.id.tooltip=The user session identifier or username sent by the SEB client after LMS login.
|
||||
sebserver.monitoring.connection.form.address=IP Address
|
||||
sebserver.monitoring.connection.form.address.tooltip=The IP address from the host the SEB client is connecting to the SEB Server.
|
||||
sebserver.monitoring.connection.form.status=Status
|
||||
sebserver.monitoring.connection.form.status.tooltip=The current connection status
|
||||
sebserver.monitoring.connection.form.exam=Exam
|
||||
sebserver.monitoring.connection.form.exam.tooltip=The exam name
|
||||
|
||||
sebserver.monitoring.exam.connection.emptySelection=Please select first a Connection from the list
|
||||
sebserver.monitoring.exam.connection.emptySelection.active=Please select first an active Connection from the list
|
||||
|
@ -1186,10 +1302,15 @@ sebserver.monitoring.exam.connection.action.show.undefined=Show Undefined
|
|||
sebserver.monitoring.exam.connection.eventlist.title=Events
|
||||
sebserver.monitoring.exam.connection.eventlist.empty=No event found
|
||||
sebserver.monitoring.exam.connection.eventlist.type=Event Type
|
||||
sebserver.monitoring.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.monitoring.exam.connection.eventlist.clienttime=Client Time {0}
|
||||
sebserver.monitoring.exam.connection.eventlist.clienttime.tooltip=The time the SEB client has sent within the log event.<br/><br/>{0}
|
||||
sebserver.monitoring.exam.connection.eventlist.servertime=Server Time {0}
|
||||
sebserver.monitoring.exam.connection.eventlist.servertime.tooltip=The exact time (UTC) the SEB Server has received the log event.<br/><br/>{0}
|
||||
sebserver.monitoring.exam.connection.eventlist.value=Value
|
||||
sebserver.monitoring.exam.connection.eventlist.value.tooltip=The value of the log event.<br/><br/>{0}
|
||||
sebserver.monitoring.exam.connection.eventlist.text=Text
|
||||
sebserver.monitoring.exam.connection.eventlist.text.tooltip=The text of the log event.<br/><br/>{0}
|
||||
|
||||
sebserver.monitoring.exam.connection.event.type.UNKNOWN=Unknown
|
||||
sebserver.monitoring.exam.connection.event.type.DEBUG_LOG=Debug
|
||||
|
@ -1218,15 +1339,15 @@ sebserver.logs.activity.seblogs.details=Show Details
|
|||
|
||||
sebserver.userlogs.list.title=User Activity Logs
|
||||
sebserver.userlogs.list.column.institution=Institution
|
||||
sebserver.userlogs.list.column.institution.tooltip=The institution of the user activity log.</br></br>Use the filter above to specify the institution.</br>{0}
|
||||
sebserver.userlogs.list.column.institution.tooltip=The institution of the user activity log.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.userlogs.list.column.user=User
|
||||
sebserver.userlogs.list.column.user.tooltip=The user account of the user activity log.</br></br>Use the filter above to specify a user account.</br>{0}
|
||||
sebserver.userlogs.list.column.user.tooltip=The user account of the user activity log.<br/><br/>Use the filter above to specify a user account.<br/>{0}
|
||||
sebserver.userlogs.list.column.dateTime=Date {0}
|
||||
sebserver.userlogs.list.column.dateTime.tooltip=The date when the user activity log happened.</br></br>Use the filter above to specify a from- and to-date range.</br>{0}
|
||||
sebserver.userlogs.list.column.dateTime.tooltip=The date when the user activity log happened.<br/><br/>Use the filter above to specify a from- and to-date range.<br/>{0}
|
||||
sebserver.userlogs.list.column.activityType=User Activity
|
||||
sebserver.userlogs.list.column.activityType.tooltip=The type of the user activity.</br></br>Use the filter above to specify a activity type.</br>{0}
|
||||
sebserver.userlogs.list.column.activityType.tooltip=The type of the user activity.<br/><br/>Use the filter above to specify a activity type.<br/>{0}
|
||||
sebserver.userlogs.list.column.entityType=Domain Type
|
||||
sebserver.userlogs.list.column.entityType.tooltip=The domain type of the user activity.</br></br>Use the filter above to specify a domain type.</br>{0}
|
||||
sebserver.userlogs.list.column.entityType.tooltip=The domain type of the user activity.<br/><br/>Use the filter above to specify a domain type.<br/>{0}
|
||||
sebserver.userlogs.list.column.entityId=Entity-ID
|
||||
sebserver.userlogs.list.column.message=Message
|
||||
|
||||
|
@ -1240,13 +1361,19 @@ sebserver.seblogs.list.title=SEB Client Logs
|
|||
sebserver.seblogs.list.actions=
|
||||
sebserver.seblogs.list.empty=No SEB client logs has been found. Please adapt or clear the filter
|
||||
|
||||
sebserver.seblogs.info.pleaseSelect=Please select first a SEB Client Log from the list
|
||||
sebserver.seblogs.info.pleaseSelect=Please select first a SEB client Log from the list
|
||||
sebserver.seblogs.list.column.institution=Institution
|
||||
sebserver.seblogs.list.column.institution.tooltip=The institution where the exam belongs to.<br/><br/>Use the filter above to specify the institution.<br/>{0}
|
||||
sebserver.seblogs.list.column.exam=Exam
|
||||
sebserver.seblogs.list.column.exam.tooltip=The exam of the SEB client logs.<br/><br/>Use the filter above to specify an exam.<br/>{0}
|
||||
sebserver.seblogs.list.column.client-session=User Session-ID
|
||||
sebserver.seblogs.list.column.client-session.tooltip=The user or user-session identifier.<br/><br/>Use the filter above narrow down a user identifier name.<br/>{0}
|
||||
sebserver.seblogs.list.column.type=Event Type
|
||||
sebserver.seblogs.list.column.type.tooltip=The SEB client log event type.<br/><br/>Use the filter above to specify log type.<br/>{0}
|
||||
sebserver.seblogs.list.column.time=Event Time {0}
|
||||
sebserver.seblogs.list.column.time.tooltip=The SEB client log time.<br/><br/>Use the filter above to specify from- and to-date and time.<br/>{0}
|
||||
sebserver.seblogs.list.column.value=Value
|
||||
sebserver.seblogs.list.column.value.tooltip=The SEB client log value.<br/><br/>{0}
|
||||
|
||||
sebserver.seblogs.details.title=SEB Client Log Details
|
||||
sebserver.seblogs.details.event.title=Event
|
||||
|
@ -1255,19 +1382,34 @@ sebserver.seblogs.details.exam.title=Exam Details
|
|||
sebserver.seblogs.details.dateTime=Date
|
||||
|
||||
sebserver.seblogs.form.column.client-session=Session-ID
|
||||
sebserver.seblogs.form.column.client-session.tooltip=The user or user-session identifier.
|
||||
sebserver.seblogs.form.column.type=Event Type
|
||||
sebserver.seblogs.form.column.type.tooltip=The SEB client log event type.
|
||||
sebserver.seblogs.form.column.server-time=Server Time
|
||||
sebserver.seblogs.form.column.server-time.tooltip=The exact time when the SEB Server got the event log sent by an SEB client.
|
||||
sebserver.seblogs.form.column.client-time=SEB Client Time
|
||||
sebserver.seblogs.form.column.client-time.tooltip=The time that was send within the log from SEB client.
|
||||
sebserver.seblogs.form.column.value=Value
|
||||
sebserver.seblogs.form.column.value.tooltip=The SEB client log event value
|
||||
sebserver.seblogs.form.column.message=Message
|
||||
sebserver.seblogs.form.column.message.tooltip=The SEB client log message
|
||||
|
||||
sebserver.seblogs.form.column.connection.session-id=User Session-ID
|
||||
sebserver.seblogs.form.column.connection.address=SEB Client Address
|
||||
sebserver.seblogs.form.column.connection.session-id.tooltip=The user or user-session identifier.
|
||||
sebserver.seblogs.form.column.connection.address=SEB client Address
|
||||
sebserver.seblogs.form.column.connection.address.tooltip=The IP address of the SEB client
|
||||
sebserver.seblogs.form.column.connection.token=SEB Connection Token
|
||||
sebserver.seblogs.form.column.connection.token.tooltip=The connection token that was generated by the SEB Server to identify the SEB client connection.
|
||||
sebserver.seblogs.form.column.connection.status=Connection Status
|
||||
sebserver.seblogs.form.column.connection.status.tooltip=The current SEB client connection status.
|
||||
|
||||
sebserver.seblogs.form.column.exam.name=Name
|
||||
sebserver.seblogs.form.column.exam.name.tooltip=The name of the exam.
|
||||
sebserver.seblogs.form.column.exam.description=Description
|
||||
sebserver.seblogs.form.column.exam.description.tooltip=The description of the exam.
|
||||
sebserver.seblogs.form.column.exam.type=Type
|
||||
sebserver.seblogs.form.column.exam.type.tooltip=The type of the exam
|
||||
sebserver.seblogs.form.column.exam.startTime=Start Time
|
||||
sebserver.seblogs.form.column.exam.startTime.tooltip=The start date and time of the exam
|
||||
sebserver.seblogs.form.column.exam.endTime=End Time
|
||||
sebserver.seblogs.form.column.exam.endTime.tooltip=The end date and time of the exam
|
Loading…
Add table
Reference in a new issue