SEBSERV-133 added deletion to SEB client events
This commit is contained in:
parent
532ca816bc
commit
9438206c9d
24 changed files with 601 additions and 26 deletions
|
@ -8,7 +8,9 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
@ -113,4 +115,11 @@ public class EntityProcessingReport {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public static EntityProcessingReport ofEmptyError() {
|
||||
return new EntityProcessingReport(
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Arrays.asList(new ErrorEntry(null, APIMessage.ErrorMessage.RESOURCE_NOT_FOUND.of())));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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 java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
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.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.event.ActionEvent;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.DeleteAllClientEvents;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SEBClientEventDeletePopup {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SEBClientEventDeletePopup.class);
|
||||
|
||||
private final static LocTextKey FORM_TITLE =
|
||||
new LocTextKey("sebserver.seblogs.delete.form.title");
|
||||
private final static LocTextKey ACTION_DELETE =
|
||||
new LocTextKey("sebserver.seblogs.delete.action.delete");
|
||||
private final static LocTextKey DELETE_CONFIRM_TITLE =
|
||||
new LocTextKey("sebserver.seblogs.delete.confirm.title");
|
||||
|
||||
private final PageService pageService;
|
||||
|
||||
protected SEBClientEventDeletePopup(final PageService pageService) {
|
||||
this.pageService = pageService;
|
||||
}
|
||||
|
||||
public Function<PageAction, PageAction> deleteWizardFunction(final PageContext pageContext) {
|
||||
return action -> {
|
||||
|
||||
final ModelInputWizard<PageContext> wizard =
|
||||
new ModelInputWizard<PageContext>(
|
||||
action.pageContext().getParent().getShell(),
|
||||
this.pageService.getWidgetFactory())
|
||||
.setVeryLargeDialogWidth();
|
||||
|
||||
final String page1Id = "DELETE_PAGE";
|
||||
final Predicate<PageContext> callback = pc -> doDelete(this.pageService, pc);
|
||||
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage1 =
|
||||
(prefPageContext, content) -> composeDeleteDialog(content,
|
||||
(prefPageContext != null) ? prefPageContext : pageContext);
|
||||
|
||||
final WizardPage<PageContext> page1 = new WizardPage<>(
|
||||
page1Id,
|
||||
true,
|
||||
composePage1,
|
||||
new WizardAction<>(ACTION_DELETE, callback));
|
||||
|
||||
wizard.open(FORM_TITLE, Utils.EMPTY_EXECUTION, page1);
|
||||
|
||||
return action;
|
||||
};
|
||||
}
|
||||
|
||||
private boolean doDelete(
|
||||
final PageService pageService,
|
||||
final PageContext pageContext) {
|
||||
|
||||
try {
|
||||
final String idsToDelete = pageContext.getAttribute(PageContext.AttributeKeys.ENTITY_ID_LIST);
|
||||
|
||||
final RestCall<EntityProcessingReport>.RestCallBuilder restCallBuilder = this.pageService.getRestService()
|
||||
.getBuilder(DeleteAllClientEvents.class)
|
||||
.withFormParam(API.PARAM_MODEL_ID_LIST, idsToDelete)
|
||||
.withFormParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.HARD_DELETE.name());
|
||||
|
||||
final EntityProcessingReport report = restCallBuilder.call().getOrThrow();
|
||||
|
||||
final PageAction action = this.pageService.pageActionBuilder(pageContext)
|
||||
.newAction(ActionDefinition.LOGS_SEB_CLIENT)
|
||||
.create();
|
||||
|
||||
this.pageService.firePageEvent(
|
||||
new ActionEvent(action),
|
||||
action.pageContext());
|
||||
|
||||
pageContext.publishPageMessage(
|
||||
DELETE_CONFIRM_TITLE,
|
||||
new LocTextKey(
|
||||
"sebserver.seblogs.delete.confirm.message",
|
||||
report.results.size(),
|
||||
(report.errors.isEmpty()) ? "no" : String.valueOf((report.errors.size()))));
|
||||
|
||||
return true;
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to delete SEB client logs:", e);
|
||||
pageContext.notifyUnexpectedError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Supplier<PageContext> composeDeleteDialog(
|
||||
final Composite parent,
|
||||
final PageContext pageContext) {
|
||||
|
||||
final String idsToDelete = pageContext.getAttribute(PageContext.AttributeKeys.ENTITY_ID_LIST);
|
||||
final int number = (StringUtils.isNotBlank(idsToDelete))
|
||||
? idsToDelete.split(Constants.LIST_SEPARATOR).length
|
||||
: 0;
|
||||
|
||||
final Composite grid = this.pageService.getWidgetFactory()
|
||||
.createPopupScrollComposite(parent);
|
||||
|
||||
final Label title = this.pageService.getWidgetFactory().labelLocalized(
|
||||
grid,
|
||||
CustomVariant.TEXT_H3,
|
||||
new LocTextKey("sebserver.seblogs.delete.form.info", number));
|
||||
final GridData gridData = new GridData();
|
||||
gridData.horizontalIndent = 10;
|
||||
gridData.verticalIndent = 10;
|
||||
title.setLayoutData(gridData);
|
||||
|
||||
return () -> pageContext;
|
||||
}
|
||||
|
||||
}
|
|
@ -8,16 +8,25 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.tomcat.util.buf.StringUtils;
|
||||
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 org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
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;
|
||||
|
@ -31,8 +40,10 @@ import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetExtendedClientEventPage;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientEventNames;
|
||||
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;
|
||||
|
@ -42,7 +53,9 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
|||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SEBClientLogs implements TemplateComposer {
|
||||
public class SEBClientEvents implements TemplateComposer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SEBClientEvents.class);
|
||||
|
||||
private static final LocTextKey TITLE_TEXT_KEY =
|
||||
new LocTextKey("sebserver.seblogs.list.title");
|
||||
|
@ -71,11 +84,13 @@ public class SEBClientLogs implements TemplateComposer {
|
|||
private final RestService restService;
|
||||
private final I18nSupport i18nSupport;
|
||||
private final SEBClientLogDetailsPopup sebClientLogDetailsPopup;
|
||||
private final SEBClientEventDeletePopup sebClientEventDeletePopup;
|
||||
private final int pageSize;
|
||||
|
||||
public SEBClientLogs(
|
||||
public SEBClientEvents(
|
||||
final PageService pageService,
|
||||
final SEBClientLogDetailsPopup sebClientLogDetailsPopup,
|
||||
final SEBClientEventDeletePopup sebClientEventDeletePopup,
|
||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||
|
||||
this.pageService = pageService;
|
||||
|
@ -83,6 +98,7 @@ public class SEBClientLogs implements TemplateComposer {
|
|||
this.restService = this.resourceService.getRestService();
|
||||
this.i18nSupport = this.resourceService.getI18nSupport();
|
||||
this.sebClientLogDetailsPopup = sebClientLogDetailsPopup;
|
||||
this.sebClientEventDeletePopup = sebClientEventDeletePopup;
|
||||
this.pageSize = pageSize;
|
||||
|
||||
this.examFilter = new TableFilterAttribute(
|
||||
|
@ -113,6 +129,9 @@ public class SEBClientLogs implements TemplateComposer {
|
|||
.clearEntityKeys()
|
||||
.clearAttributes());
|
||||
|
||||
final boolean writeGrant = this.pageService.getCurrentUser()
|
||||
.hasInstitutionalPrivilege(PrivilegeType.WRITE, EntityType.CLIENT_EVENT);
|
||||
|
||||
// table
|
||||
final EntityTable<ExtendedClientEvent> table = this.pageService.entityTableBuilder(
|
||||
this.restService.getRestCall(GetExtendedClientEventPage.class))
|
||||
|
@ -185,7 +204,37 @@ public class SEBClientLogs implements TemplateComposer {
|
|||
action -> this.sebClientLogDetailsPopup.showDetails(action, table.getSingleSelectedROWData()),
|
||||
EMPTY_SELECTION_TEXT)
|
||||
.noEventPropagation()
|
||||
.publishIf(table::hasAnyContent, false);
|
||||
.publishIf(table::hasAnyContent, false)
|
||||
|
||||
.newAction(ActionDefinition.LOGS_SEB_CLIENT_DELETE_ALL)
|
||||
.withExec(action -> this.getOpenDelete(action, table.getFilterCriteria()))
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> writeGrant);
|
||||
}
|
||||
|
||||
private PageAction getOpenDelete(final PageAction pageAction, final MultiValueMap<String, String> filterCriteria) {
|
||||
try {
|
||||
final List<String> ids = this.restService.getBuilder(GetClientEventNames.class)
|
||||
.withQueryParams(filterCriteria)
|
||||
.call()
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.map(EntityName::getModelId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
final PageAction deleteAction = pageAction.withAttribute(
|
||||
PageContext.AttributeKeys.ENTITY_ID_LIST,
|
||||
StringUtils.join(ids, Constants.COMMA))
|
||||
.withAttribute(
|
||||
PageContext.AttributeKeys.ENTITY_LIST_TYPE,
|
||||
EntityType.CLIENT_EVENT.name());
|
||||
|
||||
return this.sebClientEventDeletePopup.deleteWizardFunction(deleteAction.pageContext())
|
||||
.apply(deleteAction);
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while try to open SEB client log delete popup", e);
|
||||
return pageAction;
|
||||
}
|
||||
}
|
||||
|
||||
private Function<ExtendedClientEvent, String> examNameFunction() {
|
|
@ -683,6 +683,11 @@ public enum ActionDefinition {
|
|||
new LocTextKey("sebserver.logs.activity.seblogs.details"),
|
||||
ImageIcon.SHOW,
|
||||
ActionCategory.LOGS_SEB_CLIENT_LIST),
|
||||
LOGS_SEB_CLIENT_DELETE_ALL(
|
||||
new LocTextKey("sebserver.seblogs.action.delete"),
|
||||
ImageIcon.DELETE,
|
||||
PageStateDefinitionImpl.SEB_CLIENT_LOGS,
|
||||
ActionCategory.FORM),
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import ch.ethz.seb.sebserver.gui.content.MonitoringRunningExamList;
|
|||
import ch.ethz.seb.sebserver.gui.content.QuizLookupList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBClientConfigForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBClientConfigList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBClientLogs;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBClientEvents;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBExamConfigList;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBExamConfigForm;
|
||||
import ch.ethz.seb.sebserver.gui.content.SEBSettingsForm;
|
||||
|
@ -85,7 +85,7 @@ public enum PageStateDefinitionImpl implements PageStateDefinition {
|
|||
MONITORING_CLIENT_CONNECTION(Type.FORM_VIEW, MonitoringClientConnection.class, ActivityDefinition.MONITORING_EXAMS),
|
||||
|
||||
USER_ACTIVITY_LOGS(Type.LIST_VIEW, UserActivityLogs.class, ActivityDefinition.USER_ACTIVITY_LOGS),
|
||||
SEB_CLIENT_LOGS(Type.LIST_VIEW, SEBClientLogs.class, ActivityDefinition.SEB_CLIENT_LOGS)
|
||||
SEB_CLIENT_LOGS(Type.LIST_VIEW, SEBClientEvents.class, ActivityDefinition.SEB_CLIENT_LOGS)
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.page;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
@ -39,6 +40,8 @@ public interface PageContext {
|
|||
String PARENT_ENTITY_ID = "PARENT_ENTITY_ID";
|
||||
String ENTITY_TYPE = "ENTITY_TYPE";
|
||||
String PARENT_ENTITY_TYPE = "PARENT_ENTITY_TYPE";
|
||||
String ENTITY_ID_LIST = "ENTITY_ID_LIST";
|
||||
String ENTITY_LIST_TYPE = "ENTITY_TYPE";
|
||||
|
||||
String IMPORT_FROM_QUIZ_DATA = "IMPORT_FROM_QUIZ_DATA";
|
||||
|
||||
|
@ -149,6 +152,11 @@ public interface PageContext {
|
|||
* @return the EntityKey of the parent Entity that is associated within this PageContext */
|
||||
EntityKey getParentEntityKey();
|
||||
|
||||
/** Get a list of entity keys within the attribute ENTITY_ID_LIST and ENTITY_LIST_TYPE.
|
||||
*
|
||||
* @return A list of entity keys if available from the attributes map */
|
||||
List<EntityKey> getEntityKeyList();
|
||||
|
||||
/** Adds a given EntityKey as base Entity key to a new PageContext that is returned as a copy of this PageContext.
|
||||
*
|
||||
* @param entityKey the EntityKey to add as base Entity key
|
||||
|
@ -161,6 +169,12 @@ public interface PageContext {
|
|||
* @return the new PageContext with the EntityKey added */
|
||||
PageContext withParentEntityKey(EntityKey entityKey);
|
||||
|
||||
/** Adds a given collection of EntityKey to a new PageContext that is returned as a copy of this PageContext.
|
||||
*
|
||||
* @param entityKeys the list of EntityKey to add
|
||||
* @return the new PageContext with the list of EntityKey added */
|
||||
PageContext withEntityKeys(List<EntityKey> entityKeys);
|
||||
|
||||
/** Create a copy of this PageContext and resets both entity keys attributes, the base and the parent EntityKey
|
||||
*
|
||||
* @return copy of this PageContext with reset EntityKey attributes (base and parent) */
|
||||
|
|
|
@ -565,6 +565,11 @@ public interface PageService {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PageActionBuilder withEntityKeys(final List<EntityKey> entityKeys) {
|
||||
this.pageContext = this.pageContext.withEntityKeys(entityKeys);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PageActionBuilder ignoreMoveAwayFromEdit() {
|
||||
this.ignoreMoveAwayFromEdit = true;
|
||||
return this;
|
||||
|
|
|
@ -8,12 +8,16 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.page.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.rap.rwt.widgets.DialogCallback;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
@ -22,6 +26,7 @@ import org.eclipse.swt.widgets.Shell;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessageError;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
|
@ -39,6 +44,8 @@ public class PageContextImpl implements PageContext {
|
|||
|
||||
private static final Logger log = LoggerFactory.getLogger(PageContextImpl.class);
|
||||
|
||||
private static final String ENTITY_LIST_TYPE = null;
|
||||
|
||||
private final I18nSupport i18nSupport;
|
||||
private final ComposerService composerService;
|
||||
private final Composite root;
|
||||
|
@ -185,6 +192,34 @@ public class PageContextImpl implements PageContext {
|
|||
.withAttribute(AttributeKeys.PARENT_ENTITY_TYPE, entityKey.entityType.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntityKey> getEntityKeyList() {
|
||||
if (hasAttribute(AttributeKeys.ENTITY_ID_LIST) && hasAttribute(AttributeKeys.ENTITY_LIST_TYPE)) {
|
||||
final EntityType type = EntityType.valueOf(getAttribute(ENTITY_LIST_TYPE));
|
||||
Arrays.asList(StringUtils.split(getAttribute(AttributeKeys.ENTITY_ID_LIST), Constants.COMMA))
|
||||
.stream()
|
||||
.map(id -> new EntityKey(id, type))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageContext withEntityKeys(final List<EntityKey> entityKeys) {
|
||||
if (entityKeys == null || entityKeys.isEmpty()) {
|
||||
return removeAttribute(AttributeKeys.ENTITY_ID_LIST)
|
||||
.removeAttribute(AttributeKeys.ENTITY_LIST_TYPE);
|
||||
}
|
||||
final List<String> ids = entityKeys
|
||||
.stream()
|
||||
.map(EntityKey::getModelId)
|
||||
.collect(Collectors.toList());
|
||||
final String joinedIds = StringUtils.join(ids, Constants.COMMA);
|
||||
return withAttribute(AttributeKeys.ENTITY_ID_LIST, joinedIds)
|
||||
.withAttribute(AttributeKeys.ENTITY_LIST_TYPE, entityKeys.get(0).entityType.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageContext clearEntityKeys() {
|
||||
return withEntityKey(null)
|
||||
|
|
|
@ -316,6 +316,18 @@ public abstract class RestCall<T> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public RestCallBuilder withFormParams(final MultiValueMap<String, String> params) {
|
||||
if (params != null) {
|
||||
params.entrySet()
|
||||
.stream()
|
||||
.forEach(param -> {
|
||||
final String name = param.getKey();
|
||||
param.getValue().stream().forEach(p -> withFormParam(name, p));
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestCallBuilder withPaging(final int pageNumber, final int pageSize) {
|
||||
this.queryParams.put(Page.ATTR_PAGE_NUMBER, Arrays.asList(String.valueOf(pageNumber)));
|
||||
this.queryParams.put(Page.ATTR_PAGE_SIZE, Arrays.asList(String.valueOf(pageSize)));
|
||||
|
@ -375,7 +387,6 @@ public abstract class RestCall<T> {
|
|||
+ this.queryParams
|
||||
+ ", uriVariables=" + this.uriVariables + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final class TypeKey<T> {
|
||||
|
|
|
@ -28,7 +28,7 @@ public class DeleteExam extends RestCall<EntityProcessingReport> {
|
|||
|
||||
public DeleteExam() {
|
||||
super(new TypeKey<>(
|
||||
CallType.ACTIVATION_DEACTIVATE,
|
||||
CallType.DELETE,
|
||||
EntityType.EXAM,
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
}),
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.service.remote.webservice.api.session;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class DeleteAllClientEvents extends RestCall<EntityProcessingReport> {
|
||||
|
||||
public DeleteAllClientEvents() {
|
||||
super(new TypeKey<>(
|
||||
CallType.DELETE,
|
||||
EntityType.CLIENT_EVENT,
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
}),
|
||||
HttpMethod.DELETE,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.SEB_CLIENT_EVENT_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.service.remote.webservice.api.session;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class GetClientEventNames extends RestCall<List<EntityName>> {
|
||||
|
||||
public GetClientEventNames() {
|
||||
super(new TypeKey<>(
|
||||
CallType.GET_NAMES,
|
||||
EntityType.CLIENT_EVENT,
|
||||
new TypeReference<List<EntityName>>() {
|
||||
}),
|
||||
HttpMethod.GET,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.SEB_CLIENT_EVENT_ENDPOINT + API.NAMES_PATH_SEGMENT);
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ import org.eclipse.swt.widgets.Widget;
|
|||
import org.joda.time.DateTime;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
|
@ -294,6 +295,14 @@ public class EntityTable<ROW> {
|
|||
}
|
||||
}
|
||||
|
||||
public MultiValueMap<String, String> getFilterCriteria() {
|
||||
if (this.filter == null) {
|
||||
return new LinkedMultiValueMap<>();
|
||||
}
|
||||
|
||||
return this.filter.getFilterParameter();
|
||||
}
|
||||
|
||||
public void applySort(final String columnName) {
|
||||
try {
|
||||
this.sortColumn = columnName;
|
||||
|
|
|
@ -179,7 +179,15 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
|||
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
|
||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||
.andForRole(UserRole.EXAM_ADMIN)
|
||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||
.withOwnerPrivilege(PrivilegeType.READ)
|
||||
.create();
|
||||
|
||||
// grants for SEB client events
|
||||
addPrivilege(EntityType.CLIENT_EVENT)
|
||||
.forRole(UserRole.EXAM_ADMIN)
|
||||
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||
.withOwnerPrivilege(PrivilegeType.READ)
|
||||
.create();
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
|
||||
|
||||
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent;
|
||||
import static org.mybatis.dynamic.sql.SqlBuilder.isIn;
|
||||
import static org.mybatis.dynamic.sql.SqlBuilder.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -79,7 +79,17 @@ public class ClientEventDAOImpl implements ClientEventDAO {
|
|||
|
||||
return Result.tryCatch(() -> this.clientEventRecordMapper
|
||||
.selectByExample()
|
||||
.leftJoin(ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord)
|
||||
.on(
|
||||
ClientConnectionRecordDynamicSqlSupport.id,
|
||||
equalTo(ClientEventRecordDynamicSqlSupport.clientConnectionId))
|
||||
.where(
|
||||
ClientConnectionRecordDynamicSqlSupport.institutionId,
|
||||
isEqualToWhenPresent(filterMap.getInstitutionId()))
|
||||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.examId,
|
||||
isEqualToWhenPresent(filterMap.getClientEventExamId()))
|
||||
.and(
|
||||
ClientEventRecordDynamicSqlSupport.clientConnectionId,
|
||||
isEqualToWhenPresent(filterMap.getClientEventConnectionId()))
|
||||
.and(
|
||||
|
@ -205,9 +215,22 @@ public class ClientEventDAOImpl implements ClientEventDAO {
|
|||
@Override
|
||||
@Transactional
|
||||
public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Delete is not supported for particular client events. "
|
||||
+ "Use delete of a client connection to delete also all client events of this connection.");
|
||||
return Result.tryCatch(() -> {
|
||||
return all
|
||||
.stream()
|
||||
.map(EntityKey::getModelId)
|
||||
.map(Long::parseLong)
|
||||
.map(pk -> {
|
||||
final int deleted = this.clientEventRecordMapper.deleteByPrimaryKey(pk);
|
||||
if (deleted == 1) {
|
||||
return new EntityKey(String.valueOf(pk), EntityType.CLIENT_EVENT);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
});
|
||||
}
|
||||
|
||||
private Result<ClientEventRecord> recordById(final Long id) {
|
||||
|
|
|
@ -19,7 +19,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.MoodleSEBRestriction;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory.MoodleAPIRestTemplate;
|
||||
|
@ -48,18 +47,15 @@ public class MoodleCourseRestriction {
|
|||
private static final String MOODLE_DEFAULT_COURSE_RESTRICTION_BROWSER_KEY = "browserKey";
|
||||
|
||||
private final JSONMapper jsonMapper;
|
||||
private final LmsSetup lmsSetup;
|
||||
private final MoodleRestTemplateFactory moodleRestTemplateFactory;
|
||||
|
||||
private MoodleAPIRestTemplate restTemplate;
|
||||
|
||||
protected MoodleCourseRestriction(
|
||||
final JSONMapper jsonMapper,
|
||||
final LmsSetup lmsSetup,
|
||||
final MoodleRestTemplateFactory moodleRestTemplateFactory) {
|
||||
|
||||
this.jsonMapper = jsonMapper;
|
||||
this.lmsSetup = lmsSetup;
|
||||
this.moodleRestTemplateFactory = moodleRestTemplateFactory;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@ public class MoodleLmsAPITemplateFactory {
|
|||
|
||||
final MoodleCourseRestriction moodleCourseRestriction = new MoodleCourseRestriction(
|
||||
this.jsonMapper,
|
||||
lmsSetup,
|
||||
moodleRestTemplateFactory);
|
||||
|
||||
return new MoodleLmsAPITemplate(
|
||||
|
|
|
@ -630,7 +630,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
// check Exam has an default SEB Exam configuration attached
|
||||
if (!this.examSessionService.hasDefaultConfigurationAttached(examId)) {
|
||||
throw new APIConstraintViolationException(
|
||||
"Exam is currently has no default SEB Exam configuration attached");
|
||||
"Exam is currently running but has no default SEB Exam configuration attached");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
@ -23,14 +28,20 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry;
|
||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||
|
@ -49,7 +60,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
|
|||
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_EVENT_ENDPOINT)
|
||||
public class ClientEventController extends ReadonlyEntityController<ClientEvent, ClientEvent> {
|
||||
|
||||
private final ExamDAO examDAO;
|
||||
private final ExamDAO examDao;
|
||||
private final ClientEventDAO clientEventDAO;
|
||||
|
||||
protected ClientEventController(
|
||||
|
@ -59,7 +70,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
|||
final UserActivityLogDAO userActivityLogDAO,
|
||||
final PaginationService paginationService,
|
||||
final BeanValidationService beanValidationService,
|
||||
final ExamDAO examDAO) {
|
||||
final ExamDAO examDao) {
|
||||
|
||||
super(authorization,
|
||||
bulkActionService,
|
||||
|
@ -68,7 +79,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
|||
paginationService,
|
||||
beanValidationService);
|
||||
|
||||
this.examDAO = examDAO;
|
||||
this.examDao = examDao;
|
||||
this.clientEventDAO = entityDAO;
|
||||
}
|
||||
|
||||
|
@ -114,6 +125,45 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping(
|
||||
method = RequestMethod.DELETE,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public EntityProcessingReport hardDeleteAll(
|
||||
@RequestParam(name = API.PARAM_MODEL_ID_LIST) final List<String> ids,
|
||||
@RequestParam(name = API.PARAM_BULK_ACTION_ADD_INCLUDES, defaultValue = "false") final boolean addIncludes,
|
||||
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes,
|
||||
@RequestParam(
|
||||
name = API.PARAM_INSTITUTION_ID,
|
||||
required = true,
|
||||
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
|
||||
|
||||
this.checkWritePrivilege(institutionId);
|
||||
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return EntityProcessingReport.ofEmptyError();
|
||||
}
|
||||
|
||||
final Set<EntityKey> sources = ids.stream()
|
||||
.map(id -> new EntityKey(id, EntityType.CLIENT_EVENT))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final Result<Collection<EntityKey>> delete = this.clientEventDAO.delete(sources);
|
||||
|
||||
if (delete.hasError()) {
|
||||
return new EntityProcessingReport(
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Arrays.asList(new ErrorEntry(null, APIMessage.ErrorMessage.UNEXPECTED.of(delete.getError()))));
|
||||
} else {
|
||||
return new EntityProcessingReport(
|
||||
sources,
|
||||
delete.get(),
|
||||
Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EntityDependency> getDependencies(
|
||||
final String modelId,
|
||||
|
@ -128,10 +178,34 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
|||
return ClientEventRecordDynamicSqlSupport.clientEventRecord;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<ClientEvent> checkReadAccess(final ClientEvent entity) {
|
||||
return Result.tryCatch(() -> {
|
||||
final EnumSet<UserRole> userRoles = this.authorization
|
||||
.getUserService()
|
||||
.getCurrentUser()
|
||||
.getUserRoles();
|
||||
final boolean isSupporterOnly = userRoles.size() == 1 && userRoles.contains(UserRole.EXAM_SUPPORTER);
|
||||
if (isSupporterOnly) {
|
||||
// check owner grant be getting exam
|
||||
return super.checkReadAccess(entity)
|
||||
.getOrThrow();
|
||||
} else {
|
||||
// institutional read access
|
||||
return entity;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasReadAccess(final ClientEvent entity) {
|
||||
return !checkReadAccess(entity).hasError();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrantEntity toGrantEntity(final ClientEvent entity) {
|
||||
return this.examDAO
|
||||
.byClientConnection(entity.connectionId)
|
||||
return this.examDao
|
||||
.byPK(entity.connectionId)
|
||||
.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -339,6 +339,46 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
.getOrThrow();
|
||||
}
|
||||
|
||||
// **************************
|
||||
// * DELETE ALL (hard-delete)
|
||||
// **************************
|
||||
|
||||
@RequestMapping(
|
||||
method = RequestMethod.DELETE,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public EntityProcessingReport hardDeleteAll(
|
||||
@RequestParam(name = API.PARAM_MODEL_ID_LIST) final List<String> ids,
|
||||
@RequestParam(name = API.PARAM_BULK_ACTION_ADD_INCLUDES, defaultValue = "false") final boolean addIncludes,
|
||||
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes,
|
||||
@RequestParam(
|
||||
name = API.PARAM_INSTITUTION_ID,
|
||||
required = true,
|
||||
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
|
||||
|
||||
this.checkWritePrivilege(institutionId);
|
||||
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return EntityProcessingReport.ofEmptyError();
|
||||
}
|
||||
|
||||
final EntityType entityType = this.entityDAO.entityType();
|
||||
final Collection<EntityKey> sources = ids.stream()
|
||||
.map(id -> new EntityKey(id, entityType))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
final BulkAction bulkAction = new BulkAction(
|
||||
BulkActionType.HARD_DELETE,
|
||||
entityType,
|
||||
sources,
|
||||
convertToEntityType(addIncludes, includes));
|
||||
|
||||
return this.bulkActionService
|
||||
.createReport(bulkAction)
|
||||
.flatMap(this::notifyAllDeleted)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
protected EnumSet<EntityType> convertToEntityType(final boolean addIncludes, final List<String> includes) {
|
||||
final EnumSet<EntityType> includeDependencies = (includes != null)
|
||||
? (includes.isEmpty())
|
||||
|
@ -387,6 +427,13 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
institutionId);
|
||||
}
|
||||
|
||||
protected void checkWritePrivilege(final Long institutionId) {
|
||||
this.authorization.check(
|
||||
PrivilegeType.WRITE,
|
||||
getGrantEntityType(),
|
||||
institutionId);
|
||||
}
|
||||
|
||||
protected Result<Collection<T>> getAll(final FilterMap filterMap) {
|
||||
return this.entityDAO.allMatching(
|
||||
filterMap,
|
||||
|
@ -430,6 +477,10 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
|
|||
return Result.of(pair);
|
||||
}
|
||||
|
||||
protected Result<EntityProcessingReport> notifyAllDeleted(final EntityProcessingReport pair) {
|
||||
return Result.of(pair);
|
||||
}
|
||||
|
||||
protected Result<T> checkReadAccess(final T entity) {
|
||||
final GrantEntity grantEntity = toGrantEntity(entity);
|
||||
if (grantEntity != null) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.List;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.mybatis.dynamic.sql.SqlTable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
|
@ -68,6 +69,22 @@ public abstract class ReadonlyEntityController<T extends Entity, M extends Entit
|
|||
throw new UnsupportedOperationException(ONLY_READ_ACCESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityProcessingReport hardDeleteAll(
|
||||
final List<String> ids,
|
||||
final boolean addIncludes,
|
||||
final List<String> includes,
|
||||
final Long institutionId) {
|
||||
|
||||
throw new UnsupportedOperationException(ONLY_READ_ACCESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SqlTable getSQLTableOfEntity() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected M createNew(final POSTMapper postParams) {
|
||||
throw new UnsupportedOperationException(ONLY_READ_ACCESS);
|
||||
|
|
|
@ -5,3 +5,5 @@ server.port=8080
|
|||
server.servlet.context-path=/
|
||||
server.tomcat.uri-encoding=UTF-8
|
||||
|
||||
logging.level.ch=DEBUG
|
||||
|
||||
|
|
|
@ -616,7 +616,7 @@ sebserver.exam.delete.report.list.type=Type
|
|||
sebserver.exam.delete.report.list.name=Name
|
||||
sebserver.exam.delete.report.list.description=Description
|
||||
sebserver.exam.delete.action.delete=Delete Exam
|
||||
sebserver.exam.delete.confirm.title==Deletion Successful
|
||||
sebserver.exam.delete.confirm.title=Deletion Successful
|
||||
sebserver.exam.delete.confirm.message=The Exam ({0}) was successfully deleted.<br/>Also the following number dependencies where successfully deleted: {1}.<br/><br/>And there where {2} errors.
|
||||
sebserver.exam.delete.report.list.empty=No dependencies will be deleted.
|
||||
|
||||
|
@ -1504,4 +1504,11 @@ 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
|
||||
sebserver.seblogs.form.column.exam.endTime.tooltip=The end date and time of the exam
|
||||
|
||||
sebserver.seblogs.action.delete=Delete Logs
|
||||
sebserver.seblogs.delete.form.title=Delete SEB Logs
|
||||
sebserver.seblogs.delete.form.info=This will delete all SEB client logs from the current filtered list.<br/>Please check carefully if all SEB client logs from the list shall be deleted.<br/><br/>There are currently {0} logs within the list.
|
||||
sebserver.seblogs.delete.action.delete=Delete All Logs
|
||||
sebserver.seblogs.delete.confirm.title=Deletion Successful
|
||||
sebserver.seblogs.delete.confirm.message={0} SEB client logs where successfully deleted.<br/><br/>And there where {1} errors.
|
||||
|
|
|
@ -40,6 +40,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult.ErrorType;
|
|||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigCreationInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Configuration;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
|
||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
|
||||
|
@ -125,6 +126,10 @@ public class ModelObjectJSONGenerator {
|
|||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
||||
domainObject = new Configuration(1L, 1L, 1L, "v1", DateTime.now(), false);
|
||||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
||||
domainObject = new View(1L, "name", 20, 1, 1L);
|
||||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
@ -265,6 +270,29 @@ public class ModelObjectJSONGenerator {
|
|||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
||||
domainObject = new EntityDependency(
|
||||
new EntityKey(1L, EntityType.EXAM),
|
||||
new EntityKey(1L, EntityType.INDICATOR),
|
||||
"IndicatorName", "some description");
|
||||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
||||
domainObject = new EntityProcessingReport(
|
||||
Arrays.asList(new EntityKey(1L, EntityType.EXAM)),
|
||||
Arrays.asList(new EntityKey(1L, EntityType.INDICATOR), new EntityKey(2L, EntityType.INDICATOR)),
|
||||
Arrays.asList(new EntityProcessingReport.ErrorEntry(new EntityKey(2L, EntityType.INDICATOR),
|
||||
APIMessage.ErrorMessage.UNEXPECTED.of())));
|
||||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
||||
domainObject = APIMessage.ErrorMessage.UNEXPECTED.of(
|
||||
new RuntimeException("some unexpected exception"),
|
||||
"attribute1",
|
||||
"attribute2",
|
||||
"attribute3");
|
||||
System.out.println(domainObject.getClass().getSimpleName() + ":");
|
||||
System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue