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:
Kris De Volder
2020-10-13 15:39:44 -07:00
parent 430da643a9
commit e0bba737d3
12 changed files with 177 additions and 23 deletions

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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);
// }
}

View File

@@ -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());

View File

@@ -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());

View File

@@ -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) {

View File

@@ -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();
}
}