SEBSERV-137 implementation added texts and auto publish selection

This commit is contained in:
anhefti 2021-06-17 21:46:30 +02:00
parent 921e1959ce
commit ee0960602c
7 changed files with 127 additions and 82 deletions

View file

@ -14,16 +14,21 @@ import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
@ -50,7 +55,9 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCallError;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodeNames; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNodeNames;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfigOnExistingConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportExamConfigOnExistingConfig;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.ImportNewExamConfig;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.SaveExamConfigHistory;
import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection; import ch.ethz.seb.sebserver.gui.widget.FileUploadSelection;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@Lazy @Lazy
@Component @Component
@ -59,8 +66,18 @@ public class SEBExamConfigImportPopup {
private static final Logger log = LoggerFactory.getLogger(SEBExamConfigImportPopup.class); private static final Logger log = LoggerFactory.getLogger(SEBExamConfigImportPopup.class);
private static final LocTextKey EXAM_CONFIG_IMPORT_TEXT =
new LocTextKey("sebserver.examconfig.action.import.config.text");
private static final LocTextKey SEB_SETTINGS_IMPORT_TEXT =
new LocTextKey("sebserver.examconfig.action.import.settings.text");
private static final LocTextKey SEB_SETTINGS_IMPORT_AUTO_PUBLISH =
new LocTextKey("sebserver.examconfig.action.import.auto-publish");
private final static PageMessageException MISSING_PASSWORD = new PageMessageException( private final static PageMessageException MISSING_PASSWORD = new PageMessageException(
new LocTextKey("sebserver.examconfig.action.import.missing-password")); new LocTextKey("sebserver.examconfig.action.import.missing-password"));
private static final LocTextKey MESSAGE_SAVE_INTEGRITY_VIOLATION =
new LocTextKey("sebserver.examconfig.action.saveToHistory.integrity-violation");
private final static String AUTO_PUBLISH_FLAG = "AUTO_PUBLISH_FLAG";
private final PageService pageService; private final PageService pageService;
@ -152,13 +169,20 @@ public class SEBExamConfigImportPopup {
restCall.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId); restCall.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId);
} }
final Result<Configuration> configuration = restCall final Result<Configuration> importResult = restCall.call();
.call(); if (!importResult.hasError()) {
if (!configuration.hasError()) {
context.publishInfo(SEBExamConfigForm.FORM_IMPORT_CONFIRM_TEXT_KEY); context.publishInfo(SEBExamConfigForm.FORM_IMPORT_CONFIRM_TEXT_KEY);
// Auto publish?
if (!newConfig && BooleanUtils.toBoolean(form.getFieldValue(AUTO_PUBLISH_FLAG))) {
this.pageService.getRestService()
.getBuilder(SaveExamConfigHistory.class)
.withURIVariable(API.PARAM_MODEL_ID, importResult.get().getModelId())
.call()
.onError(error -> notifyErrorOnSave(error, context));
}
} else { } else {
handleImportError(formHandle, configuration); handleImportError(formHandle, importResult);
} }
reloadPage(newConfig, context); reloadPage(newConfig, context);
@ -295,8 +319,17 @@ public class SEBExamConfigImportPopup {
@Override @Override
public Supplier<FormHandle<ConfigurationNode>> compose(final Composite parent) { public Supplier<FormHandle<ConfigurationNode>> compose(final Composite parent) {
final Composite grid = this.pageService.getWidgetFactory() final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
.createPopupScrollComposite(parent); final Composite grid = widgetFactory.createPopupScrollComposite(parent);
final Label info = widgetFactory.labelLocalized(
grid,
(this.newConfig) ? EXAM_CONFIG_IMPORT_TEXT : SEB_SETTINGS_IMPORT_TEXT,
true);
final GridData gridData = new GridData(0, 0, this.newConfig, this.newConfig);
gridData.horizontalIndent = 10;
gridData.verticalIndent = 10;
info.setLayoutData(gridData);
final ResourceService resourceService = this.pageService.getResourceService(); final ResourceService resourceService = this.pageService.getResourceService();
final List<Tuple<String>> examConfigTemplateResources = resourceService.getExamConfigTemplateResources(); final List<Tuple<String>> examConfigTemplateResources = resourceService.getExamConfigTemplateResources();
@ -309,6 +342,13 @@ public class SEBExamConfigImportPopup {
null, null,
API.SEB_FILE_EXTENSION)) API.SEB_FILE_EXTENSION))
.addFieldIf(
() -> !this.newConfig,
() -> FormBuilder.checkbox(
AUTO_PUBLISH_FLAG,
SEB_SETTINGS_IMPORT_AUTO_PUBLISH,
Constants.FALSE_STRING))
.addFieldIf( .addFieldIf(
() -> this.newConfig, () -> this.newConfig,
() -> FormBuilder.text( () -> FormBuilder.text(
@ -348,4 +388,22 @@ public class SEBExamConfigImportPopup {
} }
} }
private static void notifyErrorOnSave(final Exception error, final PageContext context) {
if (error instanceof APIMessageError) {
try {
final List<APIMessage> errorMessages = ((APIMessageError) error).getErrorMessages();
final APIMessage apiMessage = errorMessages.get(0);
if (APIMessage.ErrorMessage.INTEGRITY_VALIDATION.isOf(apiMessage)) {
context.publishPageMessage(new PageMessageException(MESSAGE_SAVE_INTEGRITY_VIOLATION));
} else {
context.notifyUnexpectedError(error);
}
} catch (final PageMessageException e) {
throw e;
} catch (final Exception e) {
throw new RuntimeException(error);
}
}
}
} }

View file

@ -32,7 +32,6 @@ import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessageError; import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration; import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
@ -51,7 +50,6 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService; import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
import ch.ethz.seb.sebserver.gui.service.remote.download.SEBExamConfigPlaintextDownload; import ch.ethz.seb.sebserver.gui.service.remote.download.SEBExamConfigPlaintextDownload;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetExamConfigMappingNames;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetConfigurations;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigNode;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetSettingsPublished; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetSettingsPublished;
@ -122,13 +120,6 @@ public class SEBSettingsForm implements TemplateComposer {
.getOrThrow(); .getOrThrow();
final boolean readonly = pageContext.isReadonly() || configNode.status == ConfigurationStatus.IN_USE; final boolean readonly = pageContext.isReadonly() || configNode.status == ConfigurationStatus.IN_USE;
final boolean isAttachedToExam = !readonly && this.restService
.getBuilder(GetExamConfigMappingNames.class)
.withQueryParam(ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, configNode.getModelId())
.call()
.map(names -> names != null && !names.isEmpty())
.getOr(Boolean.FALSE);
final Composite warningPanelAnchor = new Composite(pageContext.getParent(), SWT.NONE); final Composite warningPanelAnchor = new Composite(pageContext.getParent(), SWT.NONE);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
warningPanelAnchor.setLayoutData(gridData); warningPanelAnchor.setLayoutData(gridData);
@ -251,7 +242,7 @@ public class SEBSettingsForm implements TemplateComposer {
.withExec(this.sebExamConfigImportPopup.importFunction( .withExec(this.sebExamConfigImportPopup.importFunction(
() -> String.valueOf(tabFolder.getSelectionIndex()))) () -> String.valueOf(tabFolder.getSelectionIndex())))
.noEventPropagation() .noEventPropagation()
.publishIf(() -> examConfigGrant.iw() && !readonly && !isAttachedToExam) .publishIf(() -> examConfigGrant.iw() && !readonly)
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP) .newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW_PROP)
.withEntityKey(entityKey) .withEntityKey(entityKey)
@ -298,7 +289,8 @@ public class SEBSettingsForm implements TemplateComposer {
return; return;
} }
final boolean settingsPublished = this.pageService.getRestService() final boolean settingsPublished = this.pageService
.getRestService()
.getBuilder(GetSettingsPublished.class) .getBuilder(GetSettingsPublished.class)
.withURIVariable(API.PARAM_MODEL_ID, this.nodeId) .withURIVariable(API.PARAM_MODEL_ID, this.nodeId)
.call() .call()
@ -322,34 +314,7 @@ public class SEBSettingsForm implements TemplateComposer {
} }
} }
// private Runnable publishedMessagePanelViewCallback( public void notifyErrorOnSave(final Exception error, final PageContext context) {
// final Composite parent,
// final String nodeId) {
// return () -> {
// final boolean settingsPublished = this.restService.getBuilder(GetSettingsPublished.class)
// .withURIVariable(API.PARAM_MODEL_ID, nodeId)
// .call()
// .onError(error -> log.warn("Failed to verify published settings. Cause: ", error.getMessage()))
// .map(result -> result.settingsPublished)
// .getOr(false);
//
// if (!settingsPublished) {
// if (parent.getChildren() != null && parent.getChildren().length == 0) {
// final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
// final Composite warningPanel = widgetFactory.createWarningPanel(parent);
// widgetFactory.labelLocalized(
// warningPanel,
// CustomVariant.MESSAGE,
// UNPUBLISHED_MESSAGE_KEY);
// }
// } else if (parent.getChildren() != null && parent.getChildren().length > 0) {
// parent.getChildren()[0].dispose();
// }
// parent.getParent().layout();
// };
// }
private void notifyErrorOnSave(final Exception error, final PageContext context) {
if (error instanceof APIMessageError) { if (error instanceof APIMessageError) {
try { try {
final List<APIMessage> errorMessages = ((APIMessageError) error).getErrorMessages(); final List<APIMessage> errorMessages = ((APIMessageError) error).getErrorMessages();

View file

@ -231,6 +231,17 @@ public final class ViewContext {
inputField); inputField);
} }
public String getValue(final String name) {
try {
final ConfigurationAttribute attributeByName = getAttributeByName(name);
final InputField inputField = this.inputFieldMapping.get(attributeByName.id);
return inputField.getValue();
} catch (final Exception e) {
log.error("Failed to get attribute value: {}, cause {}", name, e.getMessage());
return null;
}
}
public void setValue(final String name, final String value) { public void setValue(final String name, final String value) {
try { try {
final ConfigurationAttribute attributeByName = getAttributeByName(name); final ConfigurationAttribute attributeByName = getAttributeByName(name);

View file

@ -27,6 +27,7 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -66,7 +67,7 @@ public class FileUploadSelection extends Composite {
super(parent, SWT.NONE); super(parent, SWT.NONE);
final GridLayout gridLayout = new GridLayout(2, false); final GridLayout gridLayout = new GridLayout(2, false);
gridLayout.horizontalSpacing = 0; gridLayout.horizontalSpacing = 5;
gridLayout.marginHeight = 0; gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0; gridLayout.marginWidth = 0;
gridLayout.verticalSpacing = 0; gridLayout.verticalSpacing = 0;
@ -78,14 +79,15 @@ public class FileUploadSelection extends Composite {
if (readonly) { if (readonly) {
this.fileName = new Label(this, SWT.NONE); this.fileName = new Label(this, SWT.NONE);
this.fileName.setText(i18nSupport.getText(PLEASE_SELECT_TEXT)); this.fileName.setText(i18nSupport.getText(PLEASE_SELECT_TEXT));
this.fileName.setLayoutData(new GridData()); this.fileName.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, true));
this.fileUpload = null; this.fileUpload = null;
this.uploadHandler = null; this.uploadHandler = null;
this.inputReceiver = null; this.inputReceiver = null;
} else { } else {
this.fileUpload = new FileUpload(this, SWT.NONE); this.fileUpload = new FileUpload(this, SWT.NONE);
this.fileUpload.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, true));
this.fileUpload.setImage(WidgetFactory.ImageIcon.IMPORT.getImage(parent.getDisplay())); this.fileUpload.setImage(WidgetFactory.ImageIcon.IMPORT.getImage(parent.getDisplay()));
this.fileUpload.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
this.fileUpload.setToolTipText(Utils.formatLineBreaks(this.i18nSupport.getText(PLEASE_SELECT_TEXT))); this.fileUpload.setToolTipText(Utils.formatLineBreaks(this.i18nSupport.getText(PLEASE_SELECT_TEXT)));
this.inputReceiver = new InputReceiver(); this.inputReceiver = new InputReceiver();
this.uploadHandler = new FileUploadHandler(this.inputReceiver); this.uploadHandler = new FileUploadHandler(this.inputReceiver);
@ -96,14 +98,19 @@ public class FileUploadSelection extends Composite {
this.fileName = new Label(this, SWT.NONE); this.fileName = new Label(this, SWT.NONE);
this.fileName.setText(i18nSupport.getText(PLEASE_SELECT_TEXT)); this.fileName.setText(i18nSupport.getText(PLEASE_SELECT_TEXT));
this.fileName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); this.fileName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));
this.fileUpload.addListener(SWT.Selection, event -> { this.fileUpload.addListener(SWT.Selection, this::selectFile);
this.fileName.addListener(SWT.Selection, this::selectFile);
}
}
private void selectFile(final Event event) {
this.selection = true; this.selection = true;
final String fileName = FileUploadSelection.this.fileUpload.getFileName(); final String fileName = FileUploadSelection.this.fileUpload.getFileName();
if (fileName == null || !fileSupported(fileName)) { if (fileName == null || !fileSupported(fileName)) {
if (FileUploadSelection.this.errorHandler != null) { if (FileUploadSelection.this.errorHandler != null) {
final String text = i18nSupport.getText(new LocTextKey( final String text = this.i18nSupport.getText(new LocTextKey(
"sebserver.overall.upload.unsupported.file", "sebserver.overall.upload.unsupported.file",
this.supportedFileExtensions.toString()), this.supportedFileExtensions.toString()),
"Unsupported image file type selected"); "Unsupported image file type selected");
@ -114,9 +121,6 @@ public class FileUploadSelection extends Composite {
FileUploadSelection.this.fileUpload.submit(this.uploadHandler.getUploadUrl()); FileUploadSelection.this.fileUpload.submit(this.uploadHandler.getUploadUrl());
FileUploadSelection.this.fileName.setText(fileName); FileUploadSelection.this.fileName.setText(fileName);
FileUploadSelection.this.errorHandler.accept(null); FileUploadSelection.this.errorHandler.accept(null);
});
}
} }
public void close() { public void close() {

View file

@ -105,8 +105,8 @@ public class ExamSessionCacheService {
key = "#exam.id") key = "#exam.id")
public Exam evict(final Exam exam) { public Exam evict(final Exam exam) {
if (log.isDebugEnabled()) { if (log.isTraceEnabled()) {
log.debug("Conditional eviction of running Exam from cache: {}", isRunning(exam)); log.trace("Conditional eviction of running Exam from cache: {}", isRunning(exam));
} }
return exam; return exam;
@ -117,8 +117,8 @@ public class ExamSessionCacheService {
key = "#examId") key = "#examId")
public Long evict(final Long examId) { public Long evict(final Long examId) {
if (log.isDebugEnabled()) { if (log.isTraceEnabled()) {
log.debug("Conditional eviction of running Exam from cache: {}", examId); log.trace("Conditional eviction of running Exam from cache: {}", examId);
} }
return examId; return examId;
@ -167,8 +167,8 @@ public class ExamSessionCacheService {
cacheNames = CACHE_NAME_ACTIVE_CLIENT_CONNECTION, cacheNames = CACHE_NAME_ACTIVE_CLIENT_CONNECTION,
key = "#connectionToken") key = "#connectionToken")
public void evictClientConnection(final String connectionToken) { public void evictClientConnection(final String connectionToken) {
if (log.isDebugEnabled()) { if (log.isTraceEnabled()) {
log.debug("Eviction of ClientConnectionData from cache: {}", connectionToken); log.trace("Eviction of ClientConnectionData from cache: {}", connectionToken);
} }
} }
@ -197,8 +197,8 @@ public class ExamSessionCacheService {
cacheNames = CACHE_NAME_SEB_CONFIG_EXAM, cacheNames = CACHE_NAME_SEB_CONFIG_EXAM,
key = "#examId") key = "#examId")
public void evictDefaultSEBConfig(final Long examId) { public void evictDefaultSEBConfig(final Long examId) {
if (log.isDebugEnabled()) { if (log.isTraceEnabled()) {
log.debug("Eviction of default SEB Configuration from cache for exam: {}", examId); log.trace("Eviction of default SEB Configuration from cache for exam: {}", examId);
} }
} }
@ -208,6 +208,7 @@ public class ExamSessionCacheService {
unless = "#result == null") unless = "#result == null")
@Transactional @Transactional
public ClientEventRecord getPingRecord(final String connectionToken) { public ClientEventRecord getPingRecord(final String connectionToken) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Verify ClientConnection for ping record to cache by connectionToken: {}", connectionToken); log.debug("Verify ClientConnection for ping record to cache by connectionToken: {}", connectionToken);
} }
@ -240,8 +241,8 @@ public class ExamSessionCacheService {
cacheNames = CACHE_NAME_PING_RECORD, cacheNames = CACHE_NAME_PING_RECORD,
key = "#connectionToken") key = "#connectionToken")
public void evictPingRecord(final String connectionToken) { public void evictPingRecord(final String connectionToken) {
if (log.isDebugEnabled()) { if (log.isTraceEnabled()) {
log.debug("Eviction of ReusableClientEventRecord from cache for connection token: {}", connectionToken); log.trace("Eviction of ReusableClientEventRecord from cache for connection token: {}", connectionToken);
} }
} }

View file

@ -324,17 +324,19 @@ public class ConfigurationNodeController extends EntityController<ConfigurationN
this.entityDAO.byPK(modelId) this.entityDAO.byPK(modelId)
.flatMap(this.authorization::checkModify); .flatMap(this.authorization::checkModify);
// final Configuration newConfig = this.configurationDAO
// .saveToHistory(modelId)
// .flatMap(this.configurationDAO::restoreToDefaultValues)
// .getOrThrow();
final Configuration newConfig = this.configurationDAO final Configuration newConfig = this.configurationDAO
.saveToHistory(modelId) .getFollowupConfiguration(modelId)
.flatMap(this.configurationDAO::restoreToDefaultValues)
.getOrThrow(); .getOrThrow();
final Result<Configuration> doImport = doImport(password, request, newConfig); final Result<Configuration> doImport = doImport(password, request, newConfig);
if (doImport.hasError()) { if (doImport.hasError()) {
// rollback of the existing values // rollback of the existing values
this.configurationDAO.undo(newConfig.configurationNodeId); this.configurationDAO.undo(newConfig.configurationNodeId);
} }
return doImport return doImport

View file

@ -803,6 +803,10 @@ sebserver.examconfig.action.import-file-select=Import From File
sebserver.examconfig.action.import-file-password=Password sebserver.examconfig.action.import-file-password=Password
sebserver.examconfig.action.import-config.confirm=Exam Configuration successfully imported sebserver.examconfig.action.import-config.confirm=Exam Configuration successfully imported
sebserver.examconfig.action.import.missing-password=Missing Password: The chosen exam configuration is password-protected.<br/><br/>Please choose it again and provide the correct password within the password field. sebserver.examconfig.action.import.missing-password=Missing Password: The chosen exam configuration is password-protected.<br/><br/>Please choose it again and provide the correct password within the password field.
sebserver.examconfig.action.import.config.text=To import a valid SEB settings configuration file (.seb) as whole new exam configuration for SEB Server,<br/>please select the file from the local directory and provide a password if the file is protected.<br/>Please also give a name for the new exam configuration.
sebserver.examconfig.action.import.settings.text=To import a valid SEB settings configuration file (.seb) into an existing exam configuration,<br/>please select the file from the local directory and provide a password if the file is protected.<br/>Please note that this import will override the existing SEB settings of this exam configuration<br/>and also try to publish the changes if selected.
sebserver.examconfig.action.import.auto-publish=Publish
sebserver.examconfig.action.import.auto-publish.tooltip=Try to automatically publish the imported changes
sebserver.examconfig.action.state-change.confirm=This configuration is already attached to an exam.<br/>Please note that changing an attached configuration will take effect on the exam when the configuration changes are saved<br/><br/>Are you sure to change this configuration to an editable state? sebserver.examconfig.action.state-change.confirm=This configuration is already attached to an exam.<br/>Please note that changing an attached configuration will take effect on the exam when the configuration changes are saved<br/><br/>Are you sure to change this configuration to an editable state?
sebserver.examconfig.message.error.file=Please select a valid SEB Exam Configuration File sebserver.examconfig.message.error.file=Please select a valid SEB Exam Configuration File