1 package com.atlassian.theplugin.idea.action.issues;
2
3 import com.atlassian.theplugin.commons.remoteapi.ServerData;
4 import com.atlassian.theplugin.idea.Constants;
5 import com.atlassian.theplugin.idea.IdeaHelper;
6 import com.atlassian.theplugin.idea.jira.*;
7 import com.atlassian.theplugin.idea.ui.DialogWithDetails;
8 import com.atlassian.theplugin.jira.JIRAIssueProgressTimestampCache;
9 import com.atlassian.theplugin.jira.JIRAServerFacade;
10 import com.atlassian.theplugin.jira.JiraActionFieldType;
11 import com.atlassian.theplugin.jira.api.JIRAAction;
12 import com.atlassian.theplugin.jira.api.JIRAActionField;
13 import com.atlassian.theplugin.jira.api.JIRAException;
14 import com.atlassian.theplugin.jira.api.JIRAIssue;
15 import com.atlassian.theplugin.jira.model.JIRAIssueListModelBuilder;
16 import com.intellij.openapi.actionSystem.AnAction;
17 import com.intellij.openapi.actionSystem.AnActionEvent;
18 import com.intellij.openapi.progress.ProgressIndicator;
19 import com.intellij.openapi.progress.ProgressManager;
20 import com.intellij.openapi.progress.Task;
21 import com.intellij.openapi.project.Project;
22 import com.intellij.openapi.ui.DialogWrapper;
23
24 import java.awt.*;
25 import java.util.List;
26
27 public class RunIssueActionAction extends AnAction {
28 private final JIRAIssue issue;
29 private JIRAAction action;
30 private JIRAServerFacade facade;
31 private IssueActionProvider window;
32 private JIRAIssueListModelBuilder jiraIssueListModelBuilder;
33
34 public RunIssueActionAction(IssueActionProvider toolWindow, JIRAServerFacade facade,
35 JIRAIssue issue, JIRAAction jiraAction, final JIRAIssueListModelBuilder jiraIssueListModelBuilder) {
36 super(jiraAction.getName());
37 this.issue = issue;
38 action = jiraAction;
39 window = toolWindow;
40 this.facade = facade;
41 this.jiraIssueListModelBuilder = jiraIssueListModelBuilder;
42 }
43
44 @Override
45 public void actionPerformed(AnActionEvent event) {
46 runIssueAction(IdeaHelper.getCurrentProject(event), null);
47 }
48
49 public void runIssueAction(Project project, DeactivateIssueResultHandler resultHandler) {
50 ProgressManager.getInstance().run(new IssueActionRunnable(project, resultHandler));
51 }
52
53 private class IssueActionRunnable extends Task.Modal {
54 private Project project;
55 private DeactivateIssueResultHandler resultHandler;
56
57 IssueActionRunnable(Project project, DeactivateIssueResultHandler resultHandler) {
58 super(project, "Running Issue Action", true);
59 this.project = project;
60 this.resultHandler = resultHandler;
61 }
62
63 public void run(final ProgressIndicator indicator) {
64
65 if (indicator != null) {
66 indicator.setFraction(0.0);
67 indicator.setIndeterminate(true);
68 }
69
70 showInfo("Retrieving fields for action \"" + action.getName() + "\" in issue " + issue.getKey() + "...");
71
72 final ServerData server = issue.getServer();
73
74 if (server != null) {
75 final List<JIRAActionField> fields;
76 try {
77 fields = facade.getFieldsForAction(server, issue, action);
78 } catch (JIRAException e) {
79 showError(
80 "Cannot retrieve fields for action [" + action.getName() + "] on issue [" + issue.getKey() + "]"
81 + e.getMessage(), e);
82 showDialogDetailedInfo(project, e);
83 notifyResultHandler(resultHandler, e);
84 return;
85 }
86
87 showInfo("Retrieving issue details");
88 final JIRAIssue detailedIssue;
89 try {
90 JIRAIssue issueWithTime = facade.getIssue(issue.getServer(),
91 issue.getKey());
92 detailedIssue = facade.getIssueDetails(issue.getServer(), issueWithTime);
93 } catch (JIRAException e) {
94 showError("Cannot retrieve issue details for [" + issue.getKey() + "]: " + e.getMessage(), e);
95 showDialogDetailedInfo(project, e);
96 notifyResultHandler(resultHandler, e);
97 return;
98 }
99
100 showInfo("Running action [" + action.getName() + "] on issue [" + issue.getKey() + "]...");
101
102 showInfo("Retrieving values for action fields");
103 final List<JIRAActionField> preFilleddfields = JiraActionFieldType.fillFieldValues(detailedIssue, fields);
104
105 if (preFilleddfields.isEmpty()) {
106 try {
107 facade.progressWorkflowAction(server, issue, action);
108 performPostActionActivity(server);
109 } catch (JIRAException e) {
110 showError("Unable to run action [" + action.getName() + "] on issue [" + issue.getKey() + "]: "
111 + e.getMessage(), e);
112 showDialogDetailedInfo(project, e);
113 notifyResultHandler(resultHandler, e);
114 }
115 } else {
116 EventQueue.invokeLater(new LocalDisplayActionDialogRunnable(project, detailedIssue,
117 preFilleddfields, server, resultHandler));
118 }
119 }
120 }
121 }
122
123 private void showInfo(final String s) {
124 window.setStatusInfoMessage(s);
125 }
126
127 private void showError(final String error, final Throwable exception) {
128 window.setStatusErrorMessage(error, exception);
129 }
130
131 private void showDialogDetailedInfo(final Project project, final Throwable e) {
132 EventQueue.invokeLater(new Runnable() {
133 public void run() {
134 DialogWithDetails.showExceptionDialog(project, e.getMessage(), e);
135 }
136 });
137 }
138
139
140
141
142
143
144
145 private void performPostActionActivity(final ServerData server) throws JIRAException {
146 if (action.getId() == Constants.JiraActionId.START_PROGRESS.getId()) {
147 JIRAIssueProgressTimestampCache.getInstance().setTimestamp(server, issue);
148 } else if (action.getId() == Constants.JiraActionId.STOP_PROGRESS.getId()) {
149 JIRAIssueProgressTimestampCache.getInstance().removeTimestamp(server, issue);
150 }
151
152 JiraIssueAdapter.get(issue).clearCachedActions();
153
154 if (jiraIssueListModelBuilder != null) {
155 jiraIssueListModelBuilder.reloadIssue(issue.getKey(), server);
156 }
157 showInfo("Action [" + action.getName() + "] on issue " + issue.getKey() + " run succesfully");
158 }
159
160 private class LocalDisplayActionDialogRunnable implements Runnable {
161 private Project project;
162 private JIRAIssue detailedIssue;
163 private List<JIRAActionField> preFilleddfields;
164 private ServerData server;
165 private DeactivateIssueResultHandler resultHandler;
166
167 public LocalDisplayActionDialogRunnable(final Project project, final JIRAIssue detailedIssue,
168 final List<JIRAActionField> preFilleddfields, final ServerData server,
169 DeactivateIssueResultHandler resultHandler) {
170 this.project = project;
171 this.detailedIssue = detailedIssue;
172 this.preFilleddfields = preFilleddfields;
173 this.server = server;
174 this.resultHandler = resultHandler;
175 }
176
177 public void run() {
178
179 final PerformIssueActionForm dialog =
180 new PerformIssueActionForm(project, detailedIssue, preFilleddfields,
181 action.getName() + " " + detailedIssue.getKey());
182 dialog.show();
183 if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
184
185 ProgressManager.getInstance().run(
186 new Task.Backgroundable(project, "Running Workflow Action", false) {
187 public void run(final ProgressIndicator indicator) {
188 if (indicator != null) {
189 indicator.setFraction(0.0);
190 indicator.setIndeterminate(true);
191 }
192 try {
193 facade.progressWorkflowAction(server, issue, action, dialog.getFields());
194 } catch (JIRAException e) {
195 showError("Unable to run action [" + action.getName() + "] on issue ["
196 + issue.getKey() + "]: " + e.getMessage(), e);
197 showDialogDetailedInfo(project, e);
198 notifyResultHandler(resultHandler, e);
199 return;
200 }
201 try {
202 if (dialog.getComment() != null && dialog.getComment().length() > 0) {
203 facade.addComment(server, issue.getKey(), dialog.getComment());
204 }
205 } catch (JIRAException e) {
206 showError("Unable to add comment to action [" + action.getName()
207 + "] on issue [" + issue.getKey() + "]: " + e.getMessage(), e);
208 showDialogDetailedInfo(project, e);
209 notifyResultHandler(resultHandler, e);
210 }
211 try {
212 performPostActionActivity(server);
213 if (resultHandler != null) {
214 resultHandler.success();
215 }
216 } catch (JIRAException e) {
217 showError(e.getMessage(), e);
218 showDialogDetailedInfo(project, e);
219 notifyResultHandler(resultHandler, e);
220 }
221 }
222 });
223 } else {
224 showInfo("Running workflow action [" + action.getName() + "] cancelled");
225 }
226 }
227 }
228
229 private void notifyResultHandler(DeactivateIssueResultHandler resultHandler, JIRAException e) {
230 if (resultHandler != null) {
231 resultHandler.failure(e);
232 }
233 }
234 }