Commit e46087af authored by Adrien's avatar Adrien Committed by Romain Bioteau
Browse files

feat(deploy all) save dirty editors (#1862)

* If some editors are in dirty state, the user has the possibility to
save them or not before the deploy operation, or to cancel the deploy.
* Buttons order does not depend on the platform anymore on this dialog

[BST-485](https://bonitasoft.atlassian.net/browse/BST-485)
parent 3d4d0a10
......@@ -96,3 +96,7 @@ portalAppName=Portal
youCanOpenApp=You can open an application
artifactCounter=%s artifacts selected to be deployed
pagesAndLayouts=Pages & Layouts
deployCancel=Deploy operation has been canceled.
saveOpenedEditorsTitle=Save opened editors
saveOpenedEditors=Save opened editors before deploy?
savingEditors=Saving editors...
\ No newline at end of file
......@@ -21,6 +21,7 @@ import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
......@@ -62,7 +63,9 @@ import org.bonitasoft.studio.engine.BOSEngineManager;
import org.bonitasoft.studio.engine.operation.GetApiSessionOperation;
import org.bonitasoft.studio.preferences.browser.OpenBrowserOperation;
import org.bonitasoft.studio.ui.dialog.MultiStatusDialog;
import org.bonitasoft.studio.ui.dialog.SaveBeforeDeployDialog;
import org.bonitasoft.studio.ui.wizard.WizardBuilder;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
......@@ -70,9 +73,12 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.statushandlers.StatusManager;
......@@ -94,7 +100,7 @@ public class DeployArtifactsHandler {
SelectArtifactToDeployPage page = new SelectArtifactToDeployPage(repositoryModel,
new EnvironmentProviderFactory().getEnvironmentProvider());
if(defaultSelection != null) {
if (defaultSelection != null) {
page.setDefaultSelectedElements(defaultSelection.stream()
.map(fStore -> asArtifact(fStore))
.filter(Objects::nonNull)
......@@ -109,16 +115,16 @@ public class DeployArtifactsHandler {
openStatusDialog(activeShell, result.get());
}
}
private Artifact asArtifact(IRepositoryFileStore fStore) {
return repositoryModel.getArtifacts().stream()
.filter(FileStoreArtifact.class::isInstance)
.map(FileStoreArtifact.class::cast)
.filter(artifact -> Objects.equals(artifact.getFileStore().getResource(),fStore.getResource()))
.filter(artifact -> Objects.equals(artifact.getFileStore().getResource(), fStore.getResource()))
.findFirst()
.orElse(null);
}
public void setDefaultSelection(List<IRepositoryFileStore> defaultSelection) {
this.defaultSelection = defaultSelection;
}
......@@ -128,6 +134,9 @@ public class DeployArtifactsHandler {
Map<String, Object> deployOptions,
IWizardContainer container) {
MultiStatus status = new MultiStatus(ApplicationPlugin.PLUGIN_ID, 0, null, null);
if (!checkDirtyState()) {
return ValidationStatus.cancel(Messages.deployCancel);
}
try {
if ((boolean) deployOptions.get(DeployOptions.RUN_VALIDATION)) {
container.run(true, true,
......@@ -148,6 +157,57 @@ public class DeployArtifactsHandler {
return status;
}
private boolean checkDirtyState() {
if (PlatformUI.isWorkbenchRunning()
&& PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null
&& PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) {
List<IEditorPart> dirtyEditors = Arrays
.asList(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences())
.stream()
.map(ref -> ref.getEditor(false))
.filter(IEditorPart::isDirty)
.collect(Collectors.toList());
if (!dirtyEditors.isEmpty()) {
SaveStrategy strategy = saveDirtyEditors();
if (Objects.equals(strategy, SaveStrategy.CANCEL)) {
return false;
} else if (Objects.equals(strategy, SaveStrategy.SAVE)) {
try {
PlatformUI.getWorkbench().getProgressService().run(true, false, monitor -> {
monitor.beginTask(Messages.savingEditors, dirtyEditors.size());
dirtyEditors.forEach(editor -> {
editor.doSave(monitor);
monitor.worked(1);
});
monitor.done();
});
} catch (InvocationTargetException | InterruptedException e) {
throw new RuntimeException("An error occured while saving editors", e);
}
}
}
}
return true;
}
private SaveStrategy saveDirtyEditors() {
int choice = SaveBeforeDeployDialog.open(Messages.saveOpenedEditorsTitle,
Messages.saveOpenedEditors,
IDialogConstants.CANCEL_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.YES_LABEL);
switch (choice) {
case 0:
return SaveStrategy.CANCEL;
case 1:
return SaveStrategy.DONT_SAVE;
default:
return SaveStrategy.SAVE;
}
}
enum SaveStrategy {
SAVE, DONT_SAVE, CANCEL
}
private IRunnableWithProgress performFinish(RepositoryAccessor repositoryAccessor,
Collection<Artifact> artifactsToDeploy,
Map<String, Object> deployOptions,
......@@ -202,7 +262,7 @@ public class DeployArtifactsHandler {
}
private Map<String, Object> buildOptions(SelectArtifactToDeployPage page) {
HashMap<String, Object> options = new HashMap<String, Object>();
HashMap<String, Object> options = new HashMap<>();
options.put(DeployOptions.CLEAN_BDM, page.isCleanBDM());
options.put(DeployOptions.DEFAULT_USERNAME, page.getDefaultUsername());
options.put(DeployOptions.RUN_VALIDATION, page.isValidate());
......@@ -222,9 +282,11 @@ public class DeployArtifactsHandler {
openSuccessDialog(activeShell, status);
} catch (LoginException | BonitaHomeNotSetException | ServerAPIException | UnknownAPITypeException e) {
BonitaStudioLog.error(e);
new BonitaErrorDialog(activeShell, Messages.deployErrorTitle, e.getMessage(), e).open();
new BonitaErrorDialog(activeShell, Messages.deployErrorTitle, e.getMessage(), e).open();
}
}
} else if (status.getSeverity() == IStatus.CANCEL) {
MessageDialog.openInformation(activeShell, IDialogConstants.CANCEL_LABEL, status.getMessage());
} else {
StatusManager.getManager().handle(status, StatusManager.SHOW);
}
......@@ -237,14 +299,15 @@ public class DeployArtifactsHandler {
BOSEngineManager.getInstance().getApplicationAPI(session),
BOSEngineManager.getInstance().getProfileAPI(session),
BOSEngineManager.getInstance().getIdentityAPI(session));
if (IDialogConstants.OPEN_ID == DeploySuccessDialog.open(activeShell, contentProvider, WorkbenchPlugin.getDefault().getDialogSettings())) {
if (IDialogConstants.OPEN_ID == DeploySuccessDialog.open(activeShell, contentProvider,
WorkbenchPlugin.getDefault().getDialogSettings())) {
try {
new OpenBrowserOperation(contentProvider.getSelectedURL()).execute();
} catch (MalformedURLException | UnsupportedEncodingException | URISyntaxException e) {
BonitaStudioLog.error(e);
}
}
if(session != null) {
if (session != null) {
BOSEngineManager.getInstance().logoutDefaultTenant(session);
}
}
......
......@@ -133,6 +133,10 @@ public class Messages extends NLS {
public static String youCanOpenApp;
public static String artifactCounter;
public static String pagesAndLayouts;
public static String deployCancel;
public static String saveOpenedEditorsTitle;
public static String saveOpenedEditors;
public static String savingEditors;
static {
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
......
......@@ -11,26 +11,44 @@ package org.bonitasoft.studio.ui.dialog;
import org.bonitasoft.studio.ui.i18n.Messages;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
public class SaveBeforeDeployDialog {
public static DeployStrategy open(String resourceName) {
int choice = MessageDialog.open(MessageDialog.QUESTION, Display.getDefault().getActiveShell(),
Messages.saveBeforeTitle,
int choice = open(Messages.saveBeforeTitle,
String.format(Messages.saveBeforeMessage, resourceName),
SWT.NONE, Messages.saveAndDeploy, IDialogConstants.CANCEL_LABEL, Messages.deployCurrent);
IDialogConstants.CANCEL_LABEL, Messages.deployCurrent, Messages.saveAndDeploy);
switch (choice) {
case 2:
return DeployStrategy.DEPLOY_CURRENT;
return DeployStrategy.SAVE_AND_DEPLOY;
case 1:
return DeployStrategy.CANCEL;
return DeployStrategy.DEPLOY_CURRENT;
default:
return DeployStrategy.SAVE_AND_DEPLOY;
return DeployStrategy.CANCEL;
}
}
/**
* According to the documentation of
* {@link org.eclipse.jface.dialogs.Dialog#createButton(Composite parent, int id, String label, boolean defaultButton)}:
* <p>
* On some platforms, {@link org.eclipse.jface.dialogs.Dialog#initializeBounds()} will move the default button to the
* right.
* </p>
* -> To avoid different behavior depending on the platform, the default index is the index of the last element of the
* buttons arrays (i.e the button on the right), so buttons are always in the same order, no matter of the platform
*/
public static int open(String title, String message, String... buttons) {
return new MessageDialog(Display.getDefault().getActiveShell(),
title,
null,
message,
MessageDialog.QUESTION,
buttons.length - 1,
buttons).open();
}
public enum DeployStrategy {
SAVE_AND_DEPLOY, DEPLOY_CURRENT, CANCEL
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment