Deletion confirmation for CF / Docker elements
Both now work in similar way and can be 'skipped' by setting a oreference or a 'do not show again' checkbox in the dialog.
This commit is contained in:
@@ -26,7 +26,6 @@ Require-Bundle: org.junit,
|
||||
org.reactivestreams.reactive-streams;bundle-version="1.0.0",
|
||||
io.projectreactor.reactor-core;bundle-version="[3.3.1,3.3.2)",
|
||||
org.apache.commons.lang,
|
||||
org.hamcrest;bundle-version="[1.1.0,1.2.0)",
|
||||
org.eclipse.lsp4e,
|
||||
org.eclipse.lsp4j,
|
||||
org.springframework.ide.eclipse.boot.dash;bundle-version="3.9.12",
|
||||
@@ -47,7 +46,8 @@ Require-Bundle: org.junit,
|
||||
org.springframework.ide.eclipse.buildship30,
|
||||
org.eclipse.ui.console,
|
||||
org.springframework.ide.eclipse.docker.client;bundle-version="3.9.14",
|
||||
org.springsource.ide.eclipse.commons.boot.ls;bundle-version="4.8.1"
|
||||
org.springsource.ide.eclipse.commons.boot.ls;bundle-version="4.8.1",
|
||||
org.hamcrest.library;bundle-version="1.3.0"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: org.eclipse.core.runtime,
|
||||
|
||||
@@ -26,6 +26,8 @@ import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.assert
|
||||
import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.assertNotContains;
|
||||
import static org.springsource.ide.eclipse.commons.tests.util.StsTestCase.createFile;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
@@ -51,6 +53,7 @@ import org.eclipse.swt.graphics.Color;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.ide.eclipse.beans.ui.live.model.LiveBeansModel;
|
||||
@@ -618,7 +621,6 @@ public class BootDashDockerTests {
|
||||
String containerId = con.getName();
|
||||
assertEquals(1, listContainersWithId(containerId).size());
|
||||
|
||||
// when(ui().confirmOperation(eq("Deleting Elements"), any())).thenAnswer(answer);
|
||||
DeleteElementsAction<?> delete = actions().getDeleteAppsAction();
|
||||
harness.selection.setElements(con);
|
||||
assertTrue(delete.isEnabled());
|
||||
@@ -1121,8 +1123,15 @@ public class BootDashDockerTests {
|
||||
|
||||
//if (ui().confirmOperation("Deleting Elements", modifiable.getDeletionConfirmationMessage(workitem.getValue()))) {
|
||||
|
||||
// confirm popup was disabled.
|
||||
// when(ui().confirmOperation("Deleting Elements", "Delete webby ?")).thenReturn(true);
|
||||
RunTargetType rtt = model.getRunTarget().getType();
|
||||
Mockito.when(ui().confirmWithToggle(eq(DeleteElementsAction.PREF_SKIP_CONFIRM_DELETE(rtt)),
|
||||
// String title,
|
||||
eq("Deleting Elements"),
|
||||
// String message,
|
||||
anyString(),
|
||||
// String toggleMessage
|
||||
anyString()
|
||||
)).thenReturn(true);
|
||||
deleteAction.run();
|
||||
|
||||
ACondition.waitFor("Everything is deleted", 5_000, () -> {
|
||||
@@ -1136,6 +1145,7 @@ public class BootDashDockerTests {
|
||||
|
||||
// client().listImages(ListImagesParam.allImages()).stream().
|
||||
});
|
||||
// verifyNoMoreInteractions(ui());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1162,6 +1172,14 @@ public class BootDashDockerTests {
|
||||
assertTrue(delete.isEnabled());
|
||||
assertTrue(delete.isVisible());
|
||||
|
||||
Mockito.when(ui().confirmWithToggle(eq(DeleteElementsAction.PREF_SKIP_CONFIRM_DELETE(model.getRunTarget().getType())),
|
||||
// String title,
|
||||
eq("Deleting Elements"),
|
||||
// String message,
|
||||
anyString(),
|
||||
// String toggleMessage
|
||||
anyString()
|
||||
)).thenReturn(true);
|
||||
delete.run();
|
||||
|
||||
ACondition.waitFor("Image and container deletion", 10_000, () -> {
|
||||
@@ -1244,7 +1262,7 @@ public class BootDashDockerTests {
|
||||
Model model = (Model) invocation.getArguments()[0];
|
||||
//model.performOk(); //no clicking ok, so that's like when dialog is 'canceled'.
|
||||
return null;
|
||||
}).when(ui()).selectDockerDaemonDialog(Matchers.any());
|
||||
}).when(ui()).selectDockerDaemonDialog(any());
|
||||
|
||||
createTarget.run();
|
||||
createTarget.waitFor(Duration.ofMillis(2000));
|
||||
|
||||
@@ -240,6 +240,13 @@
|
||||
id="org.springframework.ide.eclipse.boot.dash.ngrok.NGROKInstallPreferencePage"
|
||||
name="ngrok">
|
||||
</page>
|
||||
|
||||
<page
|
||||
category="org.springframework.ide.eclipse.boot.ui.preferences.BootPreferencePage"
|
||||
class="org.springframework.ide.eclipse.boot.dash.prefs.BootDashPrefsPage"
|
||||
id="org.springframework.ide.eclipse.boot.dash.prefs.BootDashPrefsPage"
|
||||
name="Boot Dash">
|
||||
</page>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.eclipse.boot.dash.api;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.DeletionCapabableModel;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.MissingLiveInfoMessages;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.Nameable;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.RunTarget;
|
||||
@@ -96,4 +97,11 @@ public interface RunTargetType<Params> extends Nameable {
|
||||
default MissingLiveInfoMessages getMissingLiveInfoMessages() {
|
||||
return MissingLiveInfoMessages.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must return true if the models of this type are {@link DeletionCapabableModel}s.
|
||||
*/
|
||||
default boolean supportsDeletion() {
|
||||
return true; // true for most models, so we make this the default implementation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.eclipse.boot.dash.model.remote;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -23,6 +24,7 @@ import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.springframework.ide.eclipse.boot.dash.api.App;
|
||||
import org.springframework.ide.eclipse.boot.dash.api.Deletable;
|
||||
import org.springframework.ide.eclipse.boot.dash.api.ProjectDeploymentTarget;
|
||||
import org.springframework.ide.eclipse.boot.dash.api.Styleable;
|
||||
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.RemoteBootDashModel;
|
||||
import org.springframework.ide.eclipse.boot.dash.livexp.DisposingFactory;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.BootDashElement;
|
||||
@@ -144,10 +146,41 @@ public class GenericRemoteBootDashModel<Client, Params> extends RemoteBootDashMo
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeletionConfirmationMessage(Collection<BootDashElement> value) {
|
||||
public String getDeletionConfirmationMessage(Collection<BootDashElement> elements) {
|
||||
|
||||
Set<BootDashElement> withChild = new LinkedHashSet<>();
|
||||
for (BootDashElement toDelete : elements) {
|
||||
ImmutableSet<BootDashElement> children = toDelete.getChildren().getValues();
|
||||
for (BootDashElement child : children) {
|
||||
if (!elements.contains(child)) {
|
||||
//child is implicitly deleted. So we should warn/confirm
|
||||
// See: https://www.pivotaltracker.com/story/show/173538290
|
||||
withChild.add(toDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!withChild.isEmpty()) {
|
||||
StringBuilder confirmMessage = new StringBuilder("These elements have children, which will be deleted implicitly:\n");
|
||||
boolean first = true;
|
||||
for (BootDashElement bde : withChild) {
|
||||
if (!first) {
|
||||
confirmMessage.append(", ");
|
||||
}
|
||||
confirmMessage.append(niceName(bde));
|
||||
first = false;
|
||||
}
|
||||
return confirmMessage.toString();
|
||||
}
|
||||
return null; // no confirmation asked.
|
||||
}
|
||||
|
||||
private String niceName(BootDashElement bde) {
|
||||
if (bde instanceof Styleable) {
|
||||
return ((Styleable) bde).getStyledName(null).getString();
|
||||
}
|
||||
return bde.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeAdded(List<Object> sources) {
|
||||
if (getRunTarget() instanceof ProjectDeploymentTarget) {
|
||||
|
||||
@@ -64,4 +64,12 @@ public class LocalRunTargetType extends AbstractRunTargetType<Void> {
|
||||
public ImageDescriptor getDisconnectedIcon() {
|
||||
return getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDeletion() {
|
||||
//Not supported right now.
|
||||
//It might be possible to support deletion in the future (deleting a local app could amount
|
||||
// to deleting corresponding project from the workspace, for example).
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.eclipse.boot.dash.prefs;
|
||||
|
||||
import org.eclipse.jface.preference.BooleanFieldEditor;
|
||||
import org.eclipse.jface.preference.FieldEditorPreferencePage;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.ui.IWorkbench;
|
||||
import org.eclipse.ui.IWorkbenchPreferencePage;
|
||||
import org.springframework.ide.eclipse.boot.dash.BootDashActivator;
|
||||
import org.springframework.ide.eclipse.boot.dash.api.RunTargetType;
|
||||
import org.springframework.ide.eclipse.boot.dash.views.DeleteElementsAction;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class BootDashPrefsPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
|
||||
|
||||
public BootDashPrefsPage() {
|
||||
super(GRID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IWorkbench workbench) {
|
||||
setPreferenceStore(BootDashActivator.getDefault().getPreferenceStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createFieldEditors() {
|
||||
Composite parent = getFieldEditorParent();
|
||||
for (RunTargetType rtt : BootDashActivator.getDefault().getModel().getRunTargetTypes()) {
|
||||
if (rtt.supportsDeletion()) {
|
||||
addField(new BooleanFieldEditor(DeleteElementsAction.PREF_SKIP_CONFIRM_DELETE(rtt), "Skip Delete Element Confirmation ("+rtt.getName()+")", parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected void adjustGridLayout() {
|
||||
// // Do nothing. Page offers one column grid layout. Group controls layout fields appropriately.
|
||||
// }
|
||||
|
||||
// private void setTooltip(Composite parent, StringFieldEditor fe, String tooltip) {
|
||||
// fe.getLabelControl(parent).setToolTipText(tooltip);
|
||||
// fe.getTextControl(parent).setToolTipText(tooltip);
|
||||
// }
|
||||
//
|
||||
// private void setTooltip(Composite parent, BooleanFieldEditor2 fe, String tooltip) {
|
||||
// fe.getChangeControl(parent).setToolTipText(tooltip);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.springframework.ide.eclipse.boot.core.BootActivator;
|
||||
import org.springframework.ide.eclipse.boot.core.BootPreferences;
|
||||
import org.springframework.ide.eclipse.boot.dash.BootDashActivator;
|
||||
import org.springframework.ide.eclipse.boot.dash.api.RunTargetType;
|
||||
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.deployment.DeployToRemoteTargetAction;
|
||||
@@ -50,6 +51,7 @@ import org.springframework.ide.eclipse.boot.dash.model.runtargettypes.LocalRunTa
|
||||
import org.springframework.ide.eclipse.boot.dash.model.runtargettypes.RemoteRunTarget;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.runtargettypes.RemoteRunTargetType;
|
||||
import org.springframework.ide.eclipse.boot.dash.ngrok.NGROKInstallManager;
|
||||
import org.springframework.ide.eclipse.boot.dash.prefs.BootDashPrefsPage;
|
||||
import org.springframework.ide.eclipse.boot.dash.views.AbstractBootDashAction.Location;
|
||||
import org.springframework.ide.eclipse.boot.dash.views.AbstractBootDashElementsAction.Params;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
|
||||
@@ -84,7 +86,8 @@ public class BootDashActions {
|
||||
private ExposeAppAction exposeRunAppAction;
|
||||
private ExposeAppAction exposeDebugAppAction;
|
||||
|
||||
private OpenFilterPreferencesAction openFilterPreferencesAction;
|
||||
private OpenPreferencesAction openFilterPreferencesAction;
|
||||
private OpenPreferencesAction openBootDashPreferencesAction;
|
||||
|
||||
private DuplicateConfigAction duplicateConfigAction;
|
||||
|
||||
@@ -111,6 +114,7 @@ public class BootDashActions {
|
||||
|
||||
private RestartDevtoolsClientAction restartDevtoolsClientAction;
|
||||
|
||||
|
||||
public interface Factory {
|
||||
Collection<AbstractBootDashAction> create(BootDashActions actions, BootDashViewModel model, MultiSelection<BootDashElement> selection, LiveExpression<BootDashModel> section, SimpleDIContext context, LiveProcessCommandsExecutor liveProcessCmds);
|
||||
}
|
||||
@@ -314,7 +318,14 @@ public class BootDashActions {
|
||||
debugOnTargetActions = createDeployOnTargetActions(RunState.DEBUGGING);
|
||||
runOnTargetActions = createDeployOnTargetActions(RunState.RUNNING);
|
||||
|
||||
openFilterPreferencesAction = new OpenFilterPreferencesAction(context);
|
||||
openFilterPreferencesAction = new OpenPreferencesAction(context, BootPreferences.BOOT_PREFERENCE_PAGE_ID,
|
||||
"Boot Projects Filters Preferences...",
|
||||
"Open Preferences for Spring Boot projects filters"
|
||||
);
|
||||
openBootDashPreferencesAction = new OpenPreferencesAction(context, BootDashPrefsPage.class.getName(),
|
||||
"Boot Dash UI Preferences...",
|
||||
"Open Preferences for Boot Dash"
|
||||
);
|
||||
liveDataConnectionManagement = new LiveDataConnectionManagementActions(defaultActionParams());
|
||||
|
||||
enableRemoteDevtoolsAction = new EnableRemoteDevtoolsAction(defaultActionParams());
|
||||
@@ -583,10 +594,14 @@ public class BootDashActions {
|
||||
return getDeployAndStartOnTargetActions(runOnTargetActions);
|
||||
}
|
||||
|
||||
public OpenFilterPreferencesAction getOpenFilterPreferencesAction() {
|
||||
public OpenPreferencesAction getOpenFilterPreferencesAction() {
|
||||
return openFilterPreferencesAction;
|
||||
}
|
||||
|
||||
public IAction getOpenBootDashPreferencesAction() {
|
||||
return this.openBootDashPreferencesAction;
|
||||
}
|
||||
|
||||
private ImmutableList<IAction> getDeployAndStartOnTargetActions(
|
||||
DisposingFactory<RunTarget, AbstractBootDashAction> actionFactory) {
|
||||
ArrayList<RunTarget> targets = new ArrayList<>(model.getRunTargets().getValues());
|
||||
|
||||
@@ -206,6 +206,7 @@ public class BootDashTreeView extends ViewPartWithSections implements ITabbedPro
|
||||
|
||||
manager.add(new Separator());
|
||||
manager.add(actions.getOpenFilterPreferencesAction());
|
||||
manager.add(actions.getOpenBootDashPreferencesAction());
|
||||
|
||||
// manager.add(refreshAction);
|
||||
// manager.add(new Separator());
|
||||
|
||||
@@ -31,6 +31,10 @@ import com.google.common.collect.Multimap;
|
||||
|
||||
public class DeleteElementsAction<T extends RunTargetType> extends AbstractBootDashElementsAction {
|
||||
|
||||
public static String PREF_SKIP_CONFIRM_DELETE(RunTargetType rtt) {
|
||||
return "boot.dash."+rtt.getName()+".delete.confirm.skip";
|
||||
}
|
||||
|
||||
private Class<T> targetTypeClass;
|
||||
|
||||
public DeleteElementsAction(BootDashActions actions, Class<T> targetType, MultiSelection<BootDashElement> selection, SimpleDIContext context) {
|
||||
@@ -62,7 +66,8 @@ public class DeleteElementsAction<T extends RunTargetType> extends AbstractBootD
|
||||
BootDashModel model = workitem.getKey();
|
||||
final DeletionCapabableModel modifiable = (DeletionCapabableModel)model; //cast is safe. Only DeleteCapabableModel are added to sortingBins
|
||||
String confirmationMsg = modifiable.getDeletionConfirmationMessage(workitem.getValue());
|
||||
if (confirmationMsg==null || ui().confirmOperation("Deleting Elements", confirmationMsg)) {
|
||||
RunTargetType runTargetType = model.getRunTarget().getType();
|
||||
if (confirmationMsg==null || ui().confirmWithToggle(PREF_SKIP_CONFIRM_DELETE(runTargetType), "Deleting Elements", confirmationMsg, "Skip this dialog next time")) {
|
||||
Job job = new Job("Deleting Elements from " + model.getRunTarget().getName()) {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
|
||||
@@ -12,28 +12,27 @@ package org.springframework.ide.eclipse.boot.dash.views;
|
||||
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.ui.dialogs.PreferencesUtil;
|
||||
import org.springframework.ide.eclipse.boot.core.BootPreferences;
|
||||
import org.springframework.ide.eclipse.boot.dash.di.SimpleDIContext;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.UserInteractions;
|
||||
|
||||
/**
|
||||
* Action opens Preferences dialog at Spring -> Boot page to allow Spring Boot
|
||||
* projects filtering
|
||||
* Action opens Preferences dialog on some specific page.
|
||||
*
|
||||
* @author Alex Boyko
|
||||
*
|
||||
*/
|
||||
public class OpenFilterPreferencesAction extends AbstractBootDashAction {
|
||||
public class OpenPreferencesAction extends AbstractBootDashAction {
|
||||
|
||||
protected OpenFilterPreferencesAction(SimpleDIContext context) {
|
||||
private final String PREFERENCE_PAGE_ID;
|
||||
|
||||
protected OpenPreferencesAction(SimpleDIContext context, String pageId, String text, String tooltip) {
|
||||
super(context, IAction.AS_PUSH_BUTTON);
|
||||
setText("Boot Projects Filters Preferences...");
|
||||
setToolTipText("Open Preferences for Spring Boot projects filters");
|
||||
this.PREFERENCE_PAGE_ID = pageId;
|
||||
setText(text);
|
||||
setToolTipText(tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PreferencesUtil.createPreferenceDialogOn(null, BootPreferences.BOOT_PREFERENCE_PAGE_ID, null, null).open();
|
||||
PreferencesUtil.createPreferenceDialogOn(null, PREFERENCE_PAGE_ID, null, null).open();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,9 +28,9 @@ Require-Bundle: org.eclipse.ui,
|
||||
org.glassfish.jersey.core.jersey-common;bundle-version="2.22.1",
|
||||
org.springframework.ide.eclipse.boot.validation,
|
||||
org.springframework.ide.eclipse.boot.launch,
|
||||
org.hamcrest;bundle-version="[1.1.0,1.2.0)",
|
||||
org.apache.commons.lang3,
|
||||
com.google.guava
|
||||
com.google.guava,
|
||||
org.hamcrest.library;bundle-version="1.3.0"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Vendor: Pivotal Inc.
|
||||
|
||||
Reference in New Issue
Block a user