diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java index 7664dac6576..314011781a6 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java @@ -1103,8 +1103,8 @@ public void onSpanCreated(SpanCreatedEvent aEvent) return; } - reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget(), aEvent.getLayer(), - aEvent.getDocument()); + reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget().orElse(null), + aEvent.getLayer(), aEvent.getDocument()); } @OnEvent @@ -1122,7 +1122,7 @@ public void onRelationCreated(RelationCreatedEvent aEvent) return; } - reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget(), aEvent.getLayer(), + reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget().get(), aEvent.getLayer(), aEvent.getDocument()); } @@ -1153,7 +1153,7 @@ public void onFeatureValueUpdated(FeatureValueUpdatedEvent aEvent) return; } - reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget(), + reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget().get(), aEvent.getFeature().getLayer(), aEvent.getDocument()); } @@ -1180,7 +1180,7 @@ public void onAnnotationDeleted(SpanDeletedEvent aEvent) return; } - reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget(), aEvent.getLayer(), + reactToAnnotationsBeingCreatedOrDeleted(aEvent.getRequestTarget().get(), aEvent.getLayer(), aEvent.getDocument()); } @@ -1381,7 +1381,7 @@ public void onDocumentOpenedEvent(DocumentOpenedEvent aEvent) // If active learning is not active, update the sidebar in case the session auto-terminated ActiveLearningUserState alState = alStateModel.getObject(); if (!alState.isSessionActive()) { - aEvent.getRequestTarget().add(alMainContainer); + aEvent.getRequestTarget().ifPresent(target -> target.add(alMainContainer)); return; } @@ -1390,11 +1390,11 @@ public void onDocumentOpenedEvent(DocumentOpenedEvent aEvent) // Maybe the prediction switch has made a new suggestion available for us to go to if (alState.getSuggestion().isEmpty()) { - moveToNextSuggestion(aEvent.getRequestTarget()); + moveToNextSuggestion(aEvent.getRequestTarget().get()); return; } - refreshCurrentSuggestionOrMoveToNextSuggestion(aEvent.getRequestTarget()); + refreshCurrentSuggestionOrMoveToNextSuggestion(aEvent.getRequestTarget().get()); } @OnEvent @@ -1405,7 +1405,7 @@ public void onPredictionsSwitched(PredictionsSwitchedEvent aEvent) // If active learning is not active, update the sidebar in case the session auto-terminated ActiveLearningUserState alState = alStateModel.getObject(); if (!alState.isSessionActive()) { - aEvent.getRequestTarget().add(alMainContainer); + aEvent.getRequestTarget().ifPresent(target -> target.add(alMainContainer)); return; } @@ -1414,11 +1414,11 @@ public void onPredictionsSwitched(PredictionsSwitchedEvent aEvent) // Maybe the prediction switch has made a new suggestion available for us to go to if (alState.getSuggestion().isEmpty()) { - moveToNextSuggestion(aEvent.getRequestTarget()); + moveToNextSuggestion(aEvent.getRequestTarget().get()); return; } - refreshCurrentSuggestionOrMoveToNextSuggestion(aEvent.getRequestTarget()); + refreshCurrentSuggestionOrMoveToNextSuggestion(aEvent.getRequestTarget().get()); } private void refreshCurrentSuggestionOrMoveToNextSuggestion(AjaxRequestTarget aTarget) diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarIcon.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarIcon.java index 51c19214910..da4ea38acbb 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarIcon.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebarIcon.java @@ -103,12 +103,12 @@ private IconType getStateIcon() @OnEvent public void sessionStarted(ActiveLearningSessionStartedEvent aEvent) { - aEvent.getRequestTarget().add(this); + aEvent.getRequestTarget().ifPresent(target -> target.add(this)); } @OnEvent public void sessionStarted(ActiveLearningSessionCompletedEvent aEvent) { - aEvent.getRequestTarget().add(this); + aEvent.getRequestTarget().ifPresent(target -> target.add(this)); } } diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/link/LinkFeatureEditor.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/link/LinkFeatureEditor.java index bbe3bcc8b93..c15f261cf70 100644 --- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/link/LinkFeatureEditor.java +++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/link/LinkFeatureEditor.java @@ -681,7 +681,7 @@ public static void handleException(Component aComponent, AjaxRequestTarget aTarg public void onAnnotationDeleted(AnnotationDeletedEvent aEvent) { // It could be that a slot filler was deleted - so just in case, we re-render ourself. - aEvent.getRequestTarget().add(this); + aEvent.getRequestTarget().ifPresent(target -> target.add(this)); } @OnEvent diff --git a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/string/KendoComboboxTextFeatureEditor.java b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/string/KendoComboboxTextFeatureEditor.java index 72f8eeeba41..0a8ab22406f 100644 --- a/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/string/KendoComboboxTextFeatureEditor.java +++ b/inception/inception-api-annotation/src/main/java/de/tudarmstadt/ukp/inception/annotation/feature/string/KendoComboboxTextFeatureEditor.java @@ -110,10 +110,7 @@ public void onTagEvent(TagEvent aEvent) // If the tag was created in the tagset used by this editor, then we re-render the editor // to ensure it picks up the new tag - AjaxRequestTarget target = aEvent.getRequestTarget(); - if (target != null) { - target.add(this); - } + aEvent.getRequestTarget().ifPresent(target -> target.add(this)); } @SuppressWarnings("rawtypes") diff --git a/inception/inception-bootstrap/src/main/ts/bootstrap/inception-tables.scss b/inception/inception-bootstrap/src/main/ts/bootstrap/inception-tables.scss index d85d18de7f2..22072e899a5 100644 --- a/inception/inception-bootstrap/src/main/ts/bootstrap/inception-tables.scss +++ b/inception/inception-bootstrap/src/main/ts/bootstrap/inception-tables.scss @@ -39,6 +39,7 @@ tr.even:hover{ .headers, .headers a:link, .headers a:visited{ + --bs-table-color: var(--bs-light); --bs-table-bg: #B90F22 !important; background-color:#B90F22 !important; color:white !important; diff --git a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java index cdbf75d6e2d..5e086be50ce 100644 --- a/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java +++ b/inception/inception-layer-docmetadata/src/main/java/de/tudarmstadt/ukp/inception/ui/core/docanno/sidebar/DocumentMetadataAnnotationSelectionPanel.java @@ -392,8 +392,9 @@ private List listAnnotations() @OnEvent public void onDocumentMetadataEvent(DocumentMetadataEvent aEvent) { - aEvent.getRequestTarget().add(annotationsContainer); - findParent(AnnotationPageBase.class).actionRefreshDocument(aEvent.getRequestTarget()); + aEvent.getRequestTarget().ifPresent(target -> target.add(annotationsContainer)); + findParent(AnnotationPageBase.class) + .actionRefreshDocument(aEvent.getRequestTarget().orElse(null)); } @OnEvent @@ -403,7 +404,8 @@ public void onFeatureValueUpdated(FeatureValueUpdatedEvent aEvent) annotationsContainer.visitChildren(DocumentMetadataAnnotationDetailPanel.class, (c, v) -> { var detailPanel = (DocumentMetadataAnnotationDetailPanel) c; if (detailPanel.getModelObject().getId() == vid.getId()) { - aEvent.getRequestTarget().add(detailPanel.findParent(ListItem.class)); + aEvent.getRequestTarget() + .ifPresent(target -> target.add(detailPanel.findParent(ListItem.class))); } }); @@ -416,7 +418,8 @@ public void onFeatureValueUpdated(FeatureValueUpdatedEvent aEvent) // aEvent.getRequestTarget().add(selectedDetailPanel); // } - findParent(AnnotationPageBase.class).actionRefreshDocument(aEvent.getRequestTarget()); + findParent(AnnotationPageBase.class) + .actionRefreshDocument((aEvent.getRequestTarget().orElse(null))); } protected static void handleException(Component aComponent, AjaxRequestTarget aTarget, diff --git a/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/service/RecommendationServiceImpl.java b/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/service/RecommendationServiceImpl.java index f189f5af57f..bb9a87270f0 100644 --- a/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/service/RecommendationServiceImpl.java +++ b/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/service/RecommendationServiceImpl.java @@ -566,7 +566,7 @@ public void onDocumentOpened(DocumentOpenedEvent aEvent) // suggestions that need to be processed (in particular ones that may have been generated // by the non-trainable recommenders triggered above or from already existing predictions if (aEvent.getStateBeforeOpening() == AnnotationDocumentState.NEW) { - autoAccept(aEvent.getRequestTarget(), sessionOwner, doc, ON_FIRST_ACCESS); + autoAccept(aEvent.getRequestTarget().orElse(null), sessionOwner, doc, ON_FIRST_ACCESS); } // Trigger a training and prediction run if there is no prediction state yet diff --git a/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/sidebar/RecommenderInfoPanel.java b/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/sidebar/RecommenderInfoPanel.java index 66dcccfe239..29d8b0ed3df 100644 --- a/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/sidebar/RecommenderInfoPanel.java +++ b/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/sidebar/RecommenderInfoPanel.java @@ -242,7 +242,7 @@ public AnnotatorState getModelObject() @OnEvent public void onPredictionsSwitched(PredictionsSwitchedEvent aEvent) { - aEvent.getRequestTarget().add(this); + aEvent.getRequestTarget().ifPresent(target -> target.add(this)); } private void actionShowDetails(AjaxRequestTarget aTarget, Recommender aRecommender) diff --git a/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/event/HybridApplicationUIEvent.java b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/event/HybridApplicationUIEvent.java index 9705bf556a6..a0690c292dd 100644 --- a/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/event/HybridApplicationUIEvent.java +++ b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/event/HybridApplicationUIEvent.java @@ -17,6 +17,8 @@ */ package de.tudarmstadt.ukp.clarin.webanno.support.wicket.event; +import java.util.Optional; + import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.request.cycle.RequestCycle; @@ -29,8 +31,8 @@ public interface HybridApplicationUIEvent * @return the request target which can be used to update the UI (if the event was triggered in * the context of a UI action). */ - default AjaxRequestTarget getRequestTarget() + default Optional getRequestTarget() { - return RequestCycle.get().find(AjaxRequestTarget.class).get(); + return RequestCycle.get().find(AjaxRequestTarget.class); } } diff --git a/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/AnnotationPage.java b/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/AnnotationPage.java index 5e12dc1b4a3..422db523201 100755 --- a/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/AnnotationPage.java +++ b/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/AnnotationPage.java @@ -244,7 +244,7 @@ public void onAnnotationEvent(AnnotationEvent aEvent) return; } - actionRefreshDocument(aEvent.getRequestTarget()); + aEvent.getRequestTarget().ifPresent(this::actionRefreshDocument); } /** @@ -267,7 +267,7 @@ public void onFeatureValueUpdatedEvent(FeatureValueUpdatedEvent aEvent) return; } - actionRefreshDocument(aEvent.getRequestTarget()); + actionRefreshDocument(aEvent.getRequestTarget().orElse(null)); } /** diff --git a/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/detail/AnnotationDetailEditorPanel.java b/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/detail/AnnotationDetailEditorPanel.java index 9c9f216487d..dc3867df390 100644 --- a/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/detail/AnnotationDetailEditorPanel.java +++ b/inception/inception-ui-annotation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/annotation/detail/AnnotationDetailEditorPanel.java @@ -1247,11 +1247,11 @@ public void onBulkAnnotationEvent(BulkAnnotationEvent aEvent) if (!annotationStillExists) { selection.clear(); - refresh(aEvent.getRequestTarget()); + aEvent.getRequestTarget().ifPresent(this::refresh); } } catch (Exception e) { - handleException(this, aEvent.getRequestTarget(), e); + handleException(this, aEvent.getRequestTarget().orElse(null), e); } } diff --git a/inception/inception-ui-curation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/curation/page/CurationPage.java b/inception/inception-ui-curation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/curation/page/CurationPage.java index 75b7b2da6dd..dac66ebac4c 100644 --- a/inception/inception-ui-curation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/curation/page/CurationPage.java +++ b/inception/inception-ui-curation/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/curation/page/CurationPage.java @@ -341,9 +341,7 @@ && getModelObject().getDocument() != null @OnEvent public void onAnnotationEvent(AnnotationEvent aEvent) { - if (aEvent.getRequestTarget() != null) { - actionRefreshDocument(aEvent.getRequestTarget()); - } + actionRefreshDocument(aEvent.getRequestTarget().orElse(null)); } /** diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.html b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.html index 80fdc29d0d6..2266af889e2 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.html +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.html @@ -20,9 +20,12 @@ -
+
+ diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.java b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.java index 4b85c951071..eca8af2ab61 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.java +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/annotation/DynamicAnnotatorWorkflowActionBarItemGroup.java @@ -21,22 +21,25 @@ import static de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocumentState.FINISHED; import static de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocumentStateChangeFlag.EXPLICIT_ANNOTATOR_USER_ACTION; import static de.tudarmstadt.ukp.clarin.webanno.support.lambda.LambdaBehavior.enabledWhen; +import static de.tudarmstadt.ukp.clarin.webanno.support.lambda.LambdaBehavior.visibleWhen; import static wicket.contrib.input.events.EventType.click; import static wicket.contrib.input.events.key.KeyType.Ctrl; import static wicket.contrib.input.events.key.KeyType.End; import java.io.IOException; -import java.util.Optional; import javax.persistence.EntityManager; +import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalDialog; import org.apache.wicket.feedback.IFeedback; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; import org.apache.wicket.model.LambdaModel; +import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.spring.injection.annot.SpringBean; @@ -47,10 +50,7 @@ import de.tudarmstadt.ukp.clarin.webanno.api.annotation.actionbar.finish.FinishDocumentDialogModel; import de.tudarmstadt.ukp.clarin.webanno.api.annotation.exception.ValidationException; import de.tudarmstadt.ukp.clarin.webanno.api.annotation.page.AnnotationPageBase; -import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocument; -import de.tudarmstadt.ukp.clarin.webanno.model.Project; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; -import de.tudarmstadt.ukp.clarin.webanno.security.model.User; import de.tudarmstadt.ukp.clarin.webanno.support.bootstrap.BootstrapModalDialog; import de.tudarmstadt.ukp.clarin.webanno.support.lambda.LambdaAjaxLink; import de.tudarmstadt.ukp.clarin.webanno.support.wicket.input.InputBehavior; @@ -61,7 +61,7 @@ import de.tudarmstadt.ukp.inception.workload.dynamic.trait.DynamicWorkloadTraits; import de.tudarmstadt.ukp.inception.workload.dynamic.workflow.WorkflowExtensionPoint; import de.tudarmstadt.ukp.inception.workload.model.WorkloadManagementService; -import de.tudarmstadt.ukp.inception.workload.model.WorkloadManager; +import de.tudarmstadt.ukp.inception.workload.ui.ResetAnnotationDocumentConfirmationDialogContentPanel; import wicket.contrib.input.events.key.KeyType; /** @@ -77,9 +77,8 @@ public class DynamicAnnotatorWorkflowActionBarItemGroup private AnnotationPageBase page; - protected ModalDialog finishDocumentDialog; - - private final LambdaAjaxLink finishDocumentLink; + private ModalDialog dialog; + private final IModel traits; // SpringBeans private @SpringBean DocumentService documentService; @@ -95,30 +94,42 @@ public DynamicAnnotatorWorkflowActionBarItemGroup(String aId, AnnotationPageBase page = aPage; - finishDocumentDialog = new BootstrapModalDialog("finishDocumentDialog"); - finishDocumentDialog.setContent(new FinishDocumentDialogContent(ModalDialog.CONTENT_ID, - Model.of(new FinishDocumentDialogModel()), - this::actionFinishDocumentDialogSubmitted)); - add(finishDocumentDialog); + traits = LoadableDetachableModel.of(() -> dynamicWorkloadExtension + .readTraits(workloadManagementService.loadOrCreateWorkloadManagerConfiguration( + page.getModelObject().getProject()))); + + dialog = new BootstrapModalDialog("dialog"); + add(dialog); - queue(finishDocumentLink = new LambdaAjaxLink("showFinishDocumentDialog", - this::actionFinishDocument)); - finishDocumentLink.setOutputMarkupId(true); - finishDocumentLink.add(enabledWhen(page::isEditable)); - finishDocumentLink.add(new InputBehavior(new KeyType[] { Ctrl, End }, click)); + queue(createFinishDocumentLink("showFinishDocumentDialog")); + + queue(createResetDocumentLink("showResetDocumentDialog")); queue(new Label("state") .add(new CssClassNameModifier(LambdaModel.of(this::getStateClass)))); } - public AnnotatorState getModelObject() + private LambdaAjaxLink createFinishDocumentLink(String aId) { - return page.getModelObject(); + var link = new LambdaAjaxLink(aId, this::actionFinishDocument); + link.setOutputMarkupId(true); + link.add(enabledWhen(page::isEditable)); + link.add(new InputBehavior(new KeyType[] { Ctrl, End }, click)); + return link; + } + + private Component createResetDocumentLink(String aString) + { + var link = new LambdaAjaxLink(aString, this::actionRequestResetDocumentConfirmation); + link.add(enabledWhen(() -> page.isEditable())); + link.add(visibleWhen( + traits.map(DynamicWorkloadTraits::isDocumentResetAllowed).orElse(false))); + return link; } - protected AnnotationPageBase getAnnotationPage() + public AnnotatorState getModelObject() { - return page; + return page.getModelObject(); } public String getStateClass() @@ -126,15 +137,33 @@ public String getStateClass() return FontAwesome5IconType.check_circle_r.cssClassName(); } + protected void actionRequestResetDocumentConfirmation(AjaxRequestTarget aTarget) + throws IOException, AnnotationException + { + var content = new ResetAnnotationDocumentConfirmationDialogContentPanel( + ModalDialog.CONTENT_ID); + + content.setExpectedResponseModel( + page.getModel().map(AnnotatorState::getDocument).map(SourceDocument::getName)); + content.setConfirmAction(_target -> { + var state = page.getModelObject(); + documentService.resetAnnotationCas(state.getDocument(), state.getUser(), + EXPLICIT_ANNOTATOR_USER_ACTION); + page.actionLoadDocument(_target); + }); + + dialog.open(content, aTarget); + } + /** * This method represents the opening dialog upon clicking "Finish" for the current document. */ private void actionFinishDocument(AjaxRequestTarget aTarget) throws IOException, AnnotationException { - WorkloadManager manager = workloadManagementService + var manager = workloadManagementService .loadOrCreateWorkloadManagerConfiguration(getModelObject().getProject()); - DynamicWorkloadTraits traits = dynamicWorkloadExtension.readTraits(manager); + var traits = dynamicWorkloadExtension.readTraits(manager); try { page.actionValidateDocument(aTarget, page.getEditorCas()); @@ -146,7 +175,10 @@ private void actionFinishDocument(AjaxRequestTarget aTarget) } if (traits.isConfirmFinishingDocuments()) { - finishDocumentDialog.open(aTarget); + var content = new FinishDocumentDialogContent(ModalDialog.CONTENT_ID, + Model.of(new FinishDocumentDialogModel()), + this::actionFinishDocumentDialogSubmitted); + dialog.open(content, aTarget); } else { actionFinishDocumentConfirmedNoDialog(aTarget); @@ -157,12 +189,12 @@ private void actionFinishDocumentDialogSubmitted(AjaxRequestTarget aTarget, Form aForm) throws IOException, AnnotationException { - AnnotatorState state = getModelObject(); + var state = getModelObject(); var newState = aForm.getModelObject().getState(); - AnnotationDocument annotationDocument = documentService - .getAnnotationDocument(state.getDocument(), state.getUser()); + var annotationDocument = documentService.getAnnotationDocument(state.getDocument(), + state.getUser()); annotationDocument.setAnnotatorComment(aForm.getModelObject().getComment()); documentService.setAnnotationDocumentState(annotationDocument, newState, EXPLICIT_ANNOTATOR_USER_ACTION); @@ -173,10 +205,10 @@ private void actionFinishDocumentDialogSubmitted(AjaxRequestTarget aTarget, private void actionFinishDocumentConfirmedNoDialog(AjaxRequestTarget aTarget) throws IOException, AnnotationException { - AnnotatorState state = getModelObject(); + var state = getModelObject(); - AnnotationDocument annotationDocument = documentService - .getAnnotationDocument(state.getDocument(), state.getUser()); + var annotationDocument = documentService.getAnnotationDocument(state.getDocument(), + state.getUser()); annotationDocument.setAnnotatorComment(null); documentService.setAnnotationDocumentState(annotationDocument, FINISHED, EXPLICIT_ANNOTATOR_USER_ACTION); @@ -186,16 +218,15 @@ private void actionFinishDocumentConfirmedNoDialog(AjaxRequestTarget aTarget) private void goToNextDocument(AjaxRequestTarget aTarget) { - AnnotatorState state = getModelObject(); - User user = state.getUser(); - Project project = state.getProject(); - Optional nextDocument = dynamicWorkloadExtension - .nextDocumentToAnnotate(project, user); + var state = getModelObject(); + var user = state.getUser(); + var project = state.getProject(); + var nextDocument = dynamicWorkloadExtension.nextDocumentToAnnotate(project, user); if (!nextDocument.isPresent()) { // Nothing left, so returning to homepage and showing hint page.getSession().info("There are no more documents to annotate available for you."); - page.setResponsePage(getAnnotationPage().getApplication().getHomePage()); + page.setResponsePage(page.getApplication().getHomePage()); return; } diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.html b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.html index 3a6d4727e21..3c58a238b14 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.html +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.html @@ -192,6 +192,15 @@

class="form-control" />

+
diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.java b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.java index 22f6a60570c..675e6687a29 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.java +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.java @@ -45,10 +45,7 @@ import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox; @@ -81,7 +78,6 @@ import com.googlecode.wicket.jquery.core.JQueryBehavior; import com.googlecode.wicket.jquery.core.Options; -import com.googlecode.wicket.jquery.ui.widget.menu.IMenuItem; import com.googlecode.wicket.kendo.ui.KendoDataSource; import com.googlecode.wicket.kendo.ui.form.multiselect.lazy.MultiSelect; import com.googlecode.wicket.kendo.ui.renderer.ChoiceRenderer; @@ -126,6 +122,7 @@ import de.tudarmstadt.ukp.inception.workload.dynamic.workflow.WorkflowExtensionPoint; import de.tudarmstadt.ukp.inception.workload.dynamic.workflow.types.WorkflowType; import de.tudarmstadt.ukp.inception.workload.model.WorkloadManagementService; +import de.tudarmstadt.ukp.inception.workload.ui.ResetAnnotationDocumentConfirmationDialogContentPanel; /** * The workload page. It shall give project admins a fast overview on how each annotators progress @@ -170,7 +167,7 @@ public class DynamicWorkloadManagementPage private DataTable table; // Modal dialog - private ModalDialog modalDialog; + private ModalDialog dialog; private ChallengeResponseDialog resetDocumentDialog; private ContextMenu contextMenu; @@ -243,8 +240,8 @@ public void commonInit() add(createSettingsForm()); add(new LambdaAjaxLink("refresh", this::actionRefresh)); - modalDialog = new BootstrapModalDialog("modalDialog"); - add(modalDialog); + dialog = new BootstrapModalDialog("modalDialog"); + add(dialog); add(resetDocumentDialog = new ChallengeResponseDialog("resetDocumentDialog")); add(contextMenu = new ContextMenu("contextMenu")); @@ -356,15 +353,16 @@ protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) */ public Form createSettingsForm() { - DynamicWorkloadTraits traits = dynamicWorkloadExtension.readTraits(workloadManagementService + var traits = dynamicWorkloadExtension.readTraits(workloadManagementService .loadOrCreateWorkloadManagerConfiguration(currentProject.getObject())); - Form settingsForm = new Form<>("settingsForm", - new CompoundPropertyModel<>(traits)); + var settingsForm = new Form<>("settingsForm", new CompoundPropertyModel<>(traits)); settingsForm.setOutputMarkupId(true); settingsForm.add(new DocLink("workflowHelpLink", "sect_dynamic_workload")); + settingsForm.add(new CheckBox("documentResetAllowed")); + settingsForm.add(new CheckBox("confirmFinishingDocuments")); settingsForm.add(new NumberTextField<>("defaultNumberOfAnnotations", Integer.class) // @@ -372,7 +370,7 @@ public Form createSettingsForm() .setConvertEmptyInputStringToNull(false) // .setRequired(true)); - CheckBox abandonationToggle = new CheckBox("abandonationToggle"); + var abandonationToggle = new CheckBox("abandonationToggle"); abandonationToggle.setModel(new LambdaModelAdapter(() -> { Duration d = settingsForm.getModelObject().getAbandonationTimeout(); return !(d.isNegative() || d.isZero()); @@ -388,7 +386,7 @@ public Form createSettingsForm() _target -> _target.add(settingsForm))); settingsForm.add(abandonationToggle); - Component abandonationTimeout = new NumberTextField<>("abandonationTimeout", Long.class) // + var abandonationTimeout = new NumberTextField<>("abandonationTimeout", Long.class) // .setMinimum(0l) // .setConvertEmptyInputStringToNull(false) // .setRequired(true) @@ -409,8 +407,7 @@ public Form createSettingsForm() _target.add(settingsForm); }).add(visibleWhen(abandonationToggle.getModel()))); - DropDownChoice abandonationState = new DropDownChoice<>( - "abandonationState"); + var abandonationState = new DropDownChoice("abandonationState"); abandonationState.setRequired(true); abandonationState.setNullValid(false); abandonationState.setChoiceRenderer(new EnumChoiceRenderer<>(abandonationState)); @@ -419,7 +416,7 @@ public Form createSettingsForm() abandonationState.add(visibleWhen(abandonationToggle.getModel())); settingsForm.add(abandonationState); - DropDownChoice workflowChoices = new DropDownChoice<>("workflowType"); + var workflowChoices = new DropDownChoice("workflowType"); workflowChoices.setChoiceRenderer( new LambdaChoiceRenderer<>(id -> workflowExtensionPoint.getExtension(id) .map(WorkflowExtension::getLabel).orElse("<" + id + " not available>"))); @@ -641,11 +638,11 @@ public void onSourceDocumentFilterStateChanged(SourceDocumentFilterStateChanged private List getQueue() { - Project project = currentProject.getObject(); + var project = currentProject.getObject(); dynamicWorkloadExtension.freshenStatus(project); - Map> documentMap = new HashMap<>(); + var documentMap = new HashMap>(); documentService.listSourceDocuments(project) .forEach(d -> documentMap.put(d, new ArrayList<>())); @@ -653,11 +650,11 @@ private List getQueue() documentService.listAnnotationDocuments(project).forEach(ad -> documentMap .computeIfAbsent(ad.getDocument(), d -> new ArrayList<>()).add(ad)); - DynamicWorkloadTraits traits = dynamicWorkloadExtension.readTraits(workloadManagementService + var traits = dynamicWorkloadExtension.readTraits(workloadManagementService .loadOrCreateWorkloadManagerConfiguration(currentProject.getObject())); - List queue = new ArrayList<>(); - for (Entry> e : documentMap.entrySet()) { + var queue = new ArrayList(); + for (var e : documentMap.entrySet()) { queue.add(new AnnotationQueueItem(e.getKey(), e.getValue(), traits.getDefaultNumberOfAnnotations(), traits.getAbandonationTimeout())); } @@ -667,10 +664,10 @@ private List getQueue() @OnEvent public void onAnnotatorColumnCellClickEvent(AnnotatorColumnCellClickEvent aEvent) { - AnnotationDocument annotationDocument = documentService + var annotationDocument = documentService .createOrGetAnnotationDocument(aEvent.getSourceDocument(), aEvent.getUser()); - AnnotationDocumentState targetState = oneClickTransition(annotationDocument); + var targetState = oneClickTransition(annotationDocument); documentService.setAnnotationDocumentState(annotationDocument, targetState); @@ -682,9 +679,9 @@ public void onAnnotatorColumnCellClickEvent(AnnotatorColumnCellClickEvent aEvent @OnEvent public void onAnnotatorColumnCellClickEvent(AnnotatorColumnCellShowAnnotatorCommentEvent aEvent) { - AnnotationDocument annDoc = documentService - .getAnnotationDocument(aEvent.getSourceDocument(), aEvent.getUser()); - modalDialog.open(new AnnotatorCommentDialogPanel(ModalDialog.CONTENT_ID, Model.of(annDoc)), + var annDoc = documentService.getAnnotationDocument(aEvent.getSourceDocument(), + aEvent.getUser()); + dialog.open(new AnnotatorCommentDialogPanel(ModalDialog.CONTENT_ID, Model.of(annDoc)), aEvent.getTarget()); } @@ -697,7 +694,7 @@ public void onAnnotatorStateOpenContextMenuEvent(AnnotatorStateOpenContextMenuEv return; } - List items = contextMenu.getItemList(); + var items = contextMenu.getItemList(); items.clear(); // The AnnotatorColumnCellOpenContextMenuEvent is not serializable, so we need to extract @@ -715,11 +712,12 @@ public void onAnnotatorStateOpenContextMenuEvent(AnnotatorStateOpenContextMenuEv private void actionResetAnnotationDocument(AjaxRequestTarget aTarget, SourceDocument aDocument, User aUser) { - resetDocumentDialog.setTitleModel(new ResourceModel("ResetDocumentDialog.title")); - resetDocumentDialog.setMessageModel(new ResourceModel("ResetDocumentDialog.text")); - resetDocumentDialog.setExpectedResponseModel( + var dialogContent = new ResetAnnotationDocumentConfirmationDialogContentPanel( + ModalDialog.CONTENT_ID); + + dialogContent.setExpectedResponseModel( Model.of(aUser.getUiName() + " / " + aDocument.getName())); - resetDocumentDialog.setConfirmAction(_target -> { + dialogContent.setConfirmAction(_target -> { documentService.resetAnnotationCas(aDocument, aUser); success(format("The annotations of document [%s] for user [%s] have been set reset.", @@ -728,13 +726,14 @@ private void actionResetAnnotationDocument(AjaxRequestTarget aTarget, SourceDocu updateTable(_target); }); - resetDocumentDialog.show(aTarget); + + dialog.open(dialogContent, aTarget); } private void actionTouchAnnotationDocument(AjaxRequestTarget aTarget, SourceDocument aDocument, User aUser) { - AnnotationDocument ann = documentService.getAnnotationDocument(aDocument, aUser); + var ann = documentService.getAnnotationDocument(aDocument, aUser); ann.setTimestamp(new Date()); documentService.createAnnotationDocument(ann); diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.properties b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.properties index dbe010d830d..d26608cec4d 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.properties +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/DynamicWorkloadManagementPage.properties @@ -69,6 +69,7 @@ assignDocument=Assign document(s) unassignDocument=Delete a document stateFilter=Document state confirmFinishingDocuments=Confirm finishing documents +documentResetAllowed=Allow resetting the document to its original state assignDocument.null=Please select a document unassignDocument.null=Please select a document diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/support/AnnotationStateList.html b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/support/AnnotationStateList.html index 21732a323ca..026fbf32f1f 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/support/AnnotationStateList.html +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/management/support/AnnotationStateList.html @@ -19,7 +19,7 @@ - + diff --git a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/trait/DynamicWorkloadTraits.java b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/trait/DynamicWorkloadTraits.java index 54455e5c956..ac2520fa7b3 100644 --- a/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/trait/DynamicWorkloadTraits.java +++ b/inception/inception-workload-dynamic/src/main/java/de/tudarmstadt/ukp/inception/workload/dynamic/trait/DynamicWorkloadTraits.java @@ -39,6 +39,7 @@ public class DynamicWorkloadTraits private String workflowType; private int defaultNumberOfAnnotations; private boolean confirmFinishingDocuments = true; + private boolean documentResetAllowed = true; private Duration abandonationTimeout; private AnnotationDocumentState abandonationState = IGNORE; @@ -112,4 +113,14 @@ public void setConfirmFinishingDocuments(boolean aConfirmFinishingDocuments) { confirmFinishingDocuments = aConfirmFinishingDocuments; } + + public boolean isDocumentResetAllowed() + { + return documentResetAllowed; + } + + public void setDocumentResetAllowed(boolean aDocumentResetAllowed) + { + documentResetAllowed = aDocumentResetAllowed; + } } diff --git a/inception/inception-workload-matrix/src/main/java/de/tudarmstadt/ukp/inception/workload/matrix/annotation/MatrixWorkflowActionBarItemGroup.html b/inception/inception-workload-matrix/src/main/java/de/tudarmstadt/ukp/inception/workload/matrix/annotation/MatrixWorkflowActionBarItemGroup.html index 8bfec017dce..11a1f7e3018 100644 --- a/inception/inception-workload-matrix/src/main/java/de/tudarmstadt/ukp/inception/workload/matrix/annotation/MatrixWorkflowActionBarItemGroup.html +++ b/inception/inception-workload-matrix/src/main/java/de/tudarmstadt/ukp/inception/workload/matrix/annotation/MatrixWorkflowActionBarItemGroup.html @@ -19,8 +19,7 @@ -
-
+