1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.atlassian.theplugin.idea.crucible;
18
19 import com.atlassian.theplugin.commons.crucible.CrucibleServerFacade;
20 import com.atlassian.theplugin.commons.crucible.CrucibleServerFacadeImpl;
21 import com.atlassian.theplugin.commons.crucible.ValueNotYetInitialized;
22 import com.atlassian.theplugin.commons.crucible.api.model.Action;
23 import com.atlassian.theplugin.commons.crucible.api.model.*;
24 import com.atlassian.theplugin.commons.exception.ServerPasswordNotProvidedException;
25 import com.atlassian.theplugin.commons.remoteapi.RemoteApiException;
26 import com.atlassian.theplugin.idea.Constants;
27 import com.atlassian.theplugin.idea.IdeaHelper;
28 import com.intellij.ide.BrowserUtil;
29 import com.intellij.openapi.ui.DialogWrapper;
30 import com.intellij.openapi.ui.Messages;
31 import static com.intellij.openapi.ui.Messages.showMessageDialog;
32 import com.intellij.openapi.util.IconLoader;
33 import com.intellij.ui.HyperlinkLabel;
34 import com.intellij.uiDesigner.core.GridConstraints;
35 import com.intellij.uiDesigner.core.GridLayoutManager;
36 import com.intellij.uiDesigner.core.Spacer;
37 import org.jetbrains.annotations.Nullable;
38
39 import javax.swing.*;
40 import javax.swing.border.Border;
41 import javax.swing.event.HyperlinkEvent;
42 import javax.swing.event.HyperlinkListener;
43 import java.awt.*;
44
45
46 public class CrucibleChangeReviewStateForm extends DialogWrapper {
47 private static final Icon ICON_COMPLETED = IconLoader.getIcon("/icons/icn_complete.gif");
48
49 private JPanel rootComponent;
50 private JPanel detailsPanel;
51 private JPanel summaryPanel;
52 private JPanel commentsPanel;
53 private JCheckBox publishDraftsCheckBox;
54 private JPanel publishPanel;
55
56 private ReviewData review;
57 private CrucibleServerFacade crucibleServerFacade;
58 private Action action;
59 private DescriptionPanel descriptionPanel;
60
61 protected CrucibleChangeReviewStateForm(ReviewData review, Action action) {
62 super(false);
63 this.review = review;
64 this.action = action;
65 this.crucibleServerFacade = CrucibleServerFacadeImpl.getInstance();
66
67 $$$setupUI$$$();
68 init();
69
70 publishPanel.setVisible(false);
71
72 switch (action) {
73 case CLOSE:
74 setTitle("Close review");
75 getOKAction().putValue(javax.swing.Action.NAME, "Close review...");
76 break;
77 case APPROVE:
78 setTitle("Approve review");
79 getOKAction().putValue(javax.swing.Action.NAME, "Approve review...");
80 break;
81 case SUBMIT:
82 setTitle("Submit review");
83 getOKAction().putValue(javax.swing.Action.NAME, "Submit review...");
84 break;
85 case ABANDON:
86 setTitle("Abandon review");
87 getOKAction().putValue(javax.swing.Action.NAME, "Abandon review...");
88 break;
89 case SUMMARIZE:
90 setTitle("Summarize review");
91 getOKAction().putValue(javax.swing.Action.NAME, "Summarize review...");
92 break;
93 case REOPEN:
94 setTitle("Reopen review");
95 getOKAction().putValue(javax.swing.Action.NAME, "Reopen review...");
96 break;
97 case RECOVER:
98 setTitle("Recover abandoned review");
99 getOKAction().putValue(javax.swing.Action.NAME, "Recover abandoned review...");
100 break;
101 case COMPLETE:
102 setTitle("Complete review");
103 getOKAction().putValue(javax.swing.Action.NAME, "Complete review...");
104 publishPanel.setVisible(true);
105 break;
106 case UNCOMPLETE:
107 setTitle("Uncomplete review");
108 getOKAction().putValue(javax.swing.Action.NAME, "Uncomplete review...");
109 break;
110 }
111
112 fillReviewInfo(review);
113 }
114
115 private void fillReviewInfo(final ReviewData review) {
116 getOKAction().setEnabled(false);
117
118 new Thread(new Runnable() {
119 public void run() {
120 Review reviewInfo = null;
121 try {
122 reviewInfo = crucibleServerFacade.getReview(review.getServer(), review.getPermId());
123 } catch (RemoteApiException e) {
124
125 } catch (ServerPasswordNotProvidedException e) {
126
127 }
128 final ReviewData finalReviewInfo = new ReviewDataImpl(reviewInfo, review.getServer());
129 EventQueue.invokeLater(new Runnable() {
130 public void run() {
131 updateReviewInfo(finalReviewInfo);
132 }
133 });
134 }
135 }, "atlassian-idea-plugin crucible patch upload combos refresh").start();
136 }
137
138 private void updateReviewInfo(ReviewData reviewInfo) {
139 detailsPanel.add(new DetailsPanel(reviewInfo), BorderLayout.CENTER);
140 if (Action.CLOSE.equals(action) || !"".equals(reviewInfo.getSummary())) {
141 descriptionPanel = new DescriptionPanel(review);
142 summaryPanel.add(descriptionPanel, BorderLayout.CENTER);
143 }
144 commentsPanel.add(new CommentsPanel(review), BorderLayout.CENTER);
145 if (Action.CLOSE.equals(action)) {
146 descriptionPanel.setEnabled(true);
147 descriptionPanel.setEditable(true);
148 } else {
149 if (!"".equals(reviewInfo.getSummary())) {
150 descriptionPanel.setEnabled(false);
151 descriptionPanel.setEditable(false);
152 }
153 }
154 pack();
155 getOKAction().setEnabled(true);
156 }
157
158 public JComponent getRootComponent() {
159 return rootComponent;
160 }
161
162 @Nullable
163 protected JComponent createCenterPanel() {
164 return getRootComponent();
165 }
166
167 protected void doOKAction() {
168 try {
169 switch (action) {
170 case APPROVE:
171 crucibleServerFacade.approveReview(review.getServer(), review.getPermId());
172 break;
173 case SUBMIT:
174 crucibleServerFacade.submitReview(review.getServer(), review.getPermId());
175 break;
176 case ABANDON:
177 crucibleServerFacade.abandonReview(review.getServer(), review.getPermId());
178 break;
179 case SUMMARIZE:
180 crucibleServerFacade.summarizeReview(review.getServer(), review.getPermId());
181 break;
182 case CLOSE:
183 crucibleServerFacade.closeReview(review.getServer(), review.getPermId(), descriptionPanel.getText());
184 break;
185 case REOPEN:
186 crucibleServerFacade.reopenReview(review.getServer(), review.getPermId());
187 break;
188 case RECOVER:
189 crucibleServerFacade.recoverReview(review.getServer(), review.getPermId());
190 break;
191 case COMPLETE:
192 if (this.publishDraftsCheckBox.isSelected()) {
193 crucibleServerFacade.publishAllCommentsForReview(review.getServer(), review.getPermId());
194 }
195 crucibleServerFacade.completeReview(review.getServer(), review.getPermId(), true);
196 break;
197 case UNCOMPLETE:
198 crucibleServerFacade.completeReview(review.getServer(), review.getPermId(), false);
199 break;
200 }
201 IdeaHelper.getAppComponent().rescheduleStatusCheckers(true);
202 } catch (RemoteApiException e) {
203 showMessageDialog(e.getMessage(),
204 "Error changing review state: " + review.getServer().getUrl(), Messages.getErrorIcon());
205 } catch (ServerPasswordNotProvidedException e) {
206 showMessageDialog(e.getMessage(), "Error changing review state: " + review.getServer().getUrl(),
207 Messages.getErrorIcon());
208 }
209
210 super.doOKAction();
211 }
212
213 private void createUIComponents() {
214 }
215
216
217
218
219
220
221
222
223 private void $$$setupUI$$$() {
224 rootComponent = new JPanel();
225 rootComponent.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1));
226 rootComponent.setMinimumSize(new Dimension(450, 300));
227 detailsPanel = new JPanel();
228 detailsPanel.setLayout(new BorderLayout(0, 0));
229 rootComponent.add(detailsPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
230 GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
231 GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
232 commentsPanel = new JPanel();
233 commentsPanel.setLayout(new BorderLayout(0, 0));
234 rootComponent.add(commentsPanel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
235 GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
236 GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
237 publishPanel = new JPanel();
238 publishPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
239 rootComponent.add(publishPanel, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
240 GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
241 GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
242 publishDraftsCheckBox = new JCheckBox();
243 publishDraftsCheckBox.setSelected(true);
244 publishDraftsCheckBox.setText("Publish all my draft comments");
245 publishPanel.add(publishDraftsCheckBox, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST,
246 GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
247 GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
248 final Spacer spacer1 = new Spacer();
249 publishPanel.add(spacer1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL,
250 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
251 summaryPanel = new JPanel();
252 summaryPanel.setLayout(new BorderLayout(0, 0));
253 rootComponent.add(summaryPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
254 GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
255 GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
256 }
257
258
259
260
261 public JComponent $$$getRootComponent$$$() {
262 return rootComponent;
263 }
264
265 private class BoldLabel extends JLabel {
266 public BoldLabel(String text) {
267 super(text);
268 setFont(getFont().deriveFont(Font.BOLD));
269 }
270
271 public BoldLabel() {
272 this("");
273 }
274 }
275
276 private class ReviewLabel extends HyperlinkLabel {
277 ReviewLabel(final ReviewData review) {
278 super(review.getPermId().getId());
279 addListener(review.getReviewUrl());
280 }
281
282 private void addListener(final String reviewUrl) {
283 addHyperlinkListener(new HyperlinkListener() {
284 public void hyperlinkUpdate(HyperlinkEvent e) {
285 BrowserUtil.launchBrowser(reviewUrl);
286 }
287 });
288 }
289 }
290
291 private class DetailsPanel extends JPanel {
292 public DetailsPanel(final ReviewData review) {
293 JPanel body = new JPanel();
294
295 setLayout(new GridBagLayout());
296 body.setLayout(new GridBagLayout());
297
298 GridBagConstraints gbc1 = new GridBagConstraints();
299 GridBagConstraints gbc2 = new GridBagConstraints();
300 gbc1.anchor = GridBagConstraints.FIRST_LINE_START;
301 gbc1.insets = new Insets(0, Constants.DIALOG_MARGIN, 0, Constants.DIALOG_MARGIN);
302 gbc2.anchor = GridBagConstraints.FIRST_LINE_START;
303 gbc2.fill = GridBagConstraints.HORIZONTAL;
304 gbc2.weightx = 1.0;
305 gbc1.gridx = 0;
306 gbc2.gridx = 1;
307 gbc1.gridy = 0;
308 gbc2.gridy = 0;
309
310 body.add(new BoldLabel("Id"), gbc1);
311 body.add(new ReviewLabel(review), gbc2);
312 gbc1.gridy++;
313 gbc2.gridy++;
314 body.add(new BoldLabel("Name"), gbc1);
315 body.add(new JLabel(review.getName(), SwingConstants.LEFT), gbc2);
316 gbc1.gridy++;
317 gbc2.gridy++;
318 body.add(new BoldLabel("State"), gbc1);
319 body.add(new JLabel(review.getState().value(), SwingConstants.LEFT), gbc2);
320 gbc1.gridy++;
321 gbc2.gridy++;
322 body.add(new BoldLabel("Author"), gbc1);
323 body.add(new JLabel(review.getAuthor().getDisplayName(), SwingConstants.LEFT), gbc2);
324 gbc1.gridy++;
325 gbc2.gridy++;
326 body.add(new BoldLabel("Moderator"), gbc1);
327 body.add(new JLabel(review.getModerator().getDisplayName(), SwingConstants.LEFT), gbc2);
328 gbc1.gridy++;
329 gbc2.gridy++;
330 body.add(new BoldLabel("Project key"), gbc1);
331 body.add(new JLabel(review.getProjectKey(), SwingConstants.LEFT), gbc2);
332 gbc1.gridy++;
333 gbc2.gridy++;
334 body.add(new BoldLabel("Repository name"), gbc1);
335 body.add(new JLabel(review.getRepoName(), SwingConstants.LEFT), gbc2);
336 gbc1.gridy++;
337 gbc2.gridy++;
338 body.add(new BoldLabel("Created"), gbc1);
339 if (review.getCreateDate() != null) {
340 body.add(new JLabel(review.getCreateDate().toString()), gbc2);
341 }
342 gbc1.gridy++;
343 gbc2.gridy++;
344 body.add(new BoldLabel("Closed"), gbc1);
345 if (review.getCloseDate() != null) {
346 body.add(new JLabel(review.getCloseDate().toString()), gbc2);
347 }
348 gbc1.gridy++;
349 gbc2.gridy++;
350
351 body.add(new BoldLabel("Reviewers"), gbc1);
352
353 try {
354 for (Reviewer reviewer : review.getReviewers()) {
355 if (reviewer.isCompleted()) {
356 body.add(new JLabel(reviewer.getDisplayName(), ICON_COMPLETED, SwingConstants.LEFT), gbc2);
357 } else {
358 body.add(new JLabel(reviewer.getDisplayName(), SwingConstants.LEFT), gbc2);
359 }
360 gbc1.gridy++;
361 gbc2.gridy++;
362 }
363 } catch (ValueNotYetInitialized valueNotYetInitialized) {
364 valueNotYetInitialized
365 .printStackTrace();
366 }
367
368
369 gbc1.gridy++;
370 gbc1.weighty = 1.0;
371 gbc1.fill = GridBagConstraints.VERTICAL;
372 body.add(new JPanel(), gbc1);
373
374 GridBagConstraints gbc = new GridBagConstraints();
375 gbc.gridx = 0;
376 gbc.gridy = 0;
377 gbc.weightx = 1.0;
378 gbc.weighty = 1.0;
379 gbc.fill = GridBagConstraints.BOTH;
380 JScrollPane scroll = new JScrollPane(body);
381 scroll.setBorder(BorderFactory.createEmptyBorder());
382 add(scroll, gbc);
383
384 Border b = BorderFactory.createTitledBorder("Review");
385 setBorder(b);
386 Insets i = b.getBorderInsets(this);
387 setMinimumSize(new Dimension(0, i.top + i.bottom));
388
389 }
390 }
391
392 private class CommentsPanel extends JPanel {
393 public CommentsPanel(final ReviewData review) {
394 JPanel body = new JPanel();
395
396 setLayout(new GridBagLayout());
397 body.setLayout(new GridBagLayout());
398
399 GridBagConstraints gbc1 = new GridBagConstraints();
400 GridBagConstraints gbc2 = new GridBagConstraints();
401 gbc1.anchor = GridBagConstraints.FIRST_LINE_START;
402 gbc1.insets = new Insets(0, Constants.DIALOG_MARGIN, 0, Constants.DIALOG_MARGIN);
403 gbc2.anchor = GridBagConstraints.FIRST_LINE_START;
404 gbc2.fill = GridBagConstraints.HORIZONTAL;
405 gbc2.weightx = 1.0;
406 gbc1.gridx = 0;
407 gbc2.gridx = 1;
408 gbc1.gridy = 0;
409 gbc2.gridy = 0;
410
411 String userName = review.getServer().getUsername();
412 int generalComments = 0;
413 int versionedComments = 0;
414 int myGeneralComments = 0;
415 int myVersionedComments = 0;
416 int myDefects = 0;
417 int myDrafts = 0;
418 int allDefects = 0;
419 int allDrafts = 0;
420 try {
421 generalComments = review.getGeneralComments().size();
422 versionedComments = review.getVersionedComments().size();
423 for (GeneralComment generalComment : review.getGeneralComments()) {
424 if (generalComment.getAuthor().equals(userName)) {
425 myGeneralComments++;
426 if (generalComment.isDraft()) {
427 myDrafts++;
428 allDrafts++;
429 }
430 if (generalComment.isDefectRaised()) {
431 myDefects++;
432 allDefects++;
433 }
434 } else {
435 if (generalComment.isDraft()) {
436 allDrafts++;
437 }
438 if (generalComment.isDefectRaised()) {
439 allDefects++;
440 }
441 }
442
443 }
444 for (VersionedComment comment : review.getVersionedComments()) {
445 if (comment.getAuthor().equals(userName)) {
446 myVersionedComments++;
447 if (comment.isDraft()) {
448 myDrafts++;
449 allDrafts++;
450 }
451 if (comment.isDefectRaised()) {
452 myDefects++;
453 allDefects++;
454 }
455 } else {
456 if (comment.isDraft()) {
457 allDrafts++;
458 }
459 if (comment.isDefectRaised()) {
460 allDefects++;
461 }
462 }
463
464 }
465 } catch (ValueNotYetInitialized valueNotYetInitialized) {
466 valueNotYetInitialized
467 .printStackTrace();
468 }
469
470
471 body.add(new BoldLabel("My draft comments"), gbc1);
472 body.add(new JLabel(Integer.toString(myDrafts), SwingConstants.LEFT), gbc2);
473 gbc1.gridy++;
474 gbc2.gridy++;
475
476 body.add(new BoldLabel("All my comments"), gbc1);
477 body.add(new JLabel(Integer.toString(myGeneralComments + myVersionedComments), SwingConstants.LEFT), gbc2);
478 gbc1.gridy++;
479 gbc2.gridy++;
480
481 body.add(new BoldLabel("Total comments"), gbc1);
482 body.add(new JLabel(Integer.toString(generalComments + versionedComments), SwingConstants.LEFT), gbc2);
483 gbc1.gridy++;
484 gbc2.gridy++;
485
486 body.add(new BoldLabel("Total defects"), gbc1);
487 body.add(new JLabel(Integer.toString(allDefects), SwingConstants.LEFT), gbc2);
488 gbc1.gridy++;
489 gbc2.gridy++;
490
491 body.add(new BoldLabel("My defects comments"), gbc1);
492 body.add(new JLabel(Integer.toString(myDefects), SwingConstants.LEFT), gbc2);
493 gbc1.gridy++;
494 gbc2.gridy++;
495
496 gbc1.gridy++;
497 gbc1.weighty = 1.0;
498 gbc1.fill = GridBagConstraints.VERTICAL;
499 body.add(new JPanel(), gbc1);
500
501 GridBagConstraints gbc = new GridBagConstraints();
502 gbc.gridx = 0;
503 gbc.gridy = 0;
504 gbc.weightx = 1.0;
505 gbc.weighty = 1.0;
506 gbc.fill = GridBagConstraints.BOTH;
507 JScrollPane scroll = new JScrollPane(body);
508 scroll.setBorder(BorderFactory.createEmptyBorder());
509 add(scroll, gbc);
510
511 Border b = BorderFactory.createTitledBorder("Comments");
512 setBorder(b);
513 Insets i = b.getBorderInsets(this);
514 setMinimumSize(new Dimension(0, i.top + i.bottom));
515
516 }
517 }
518
519 private class DescriptionPanel extends JPanel {
520 JEditorPane body = new JEditorPane();
521
522 public DescriptionPanel(final ReviewData review) {
523 setLayout(new GridBagLayout());
524 GridBagConstraints gbc = new GridBagConstraints();
525
526 gbc.gridx = 0;
527 gbc.gridy = 0;
528
529 gbc.insets = new Insets(0, 0, 0, 0);
530 gbc.fill = GridBagConstraints.BOTH;
531 gbc.weightx = 1.0;
532 gbc.weighty = 1.0;
533
534 JScrollPane sp = new JScrollPane(body,
535 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
536 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
537 sp.setBorder(BorderFactory.createEmptyBorder());
538 sp.setOpaque(false);
539 body.setEditable(false);
540 body.addHyperlinkListener(new HyperlinkListener() {
541 public void hyperlinkUpdate(HyperlinkEvent e) {
542 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
543 BrowserUtil.launchBrowser(e.getURL().toString());
544 }
545 }
546 });
547
548 body.setOpaque(false);
549 body.setBorder(BorderFactory.createEmptyBorder());
550
551
552 body.setText(review.getSummary());
553 sp.getViewport().setOpaque(false);
554 body.setCaretPosition(0);
555 add(sp, gbc);
556
557 Border b = BorderFactory.createTitledBorder("Review summary");
558 setBorder(b);
559 Insets i = b.getBorderInsets(this);
560 int minHeight = i.top + i.bottom;
561 setMinimumSize(new Dimension(0, minHeight));
562 }
563
564 public void setEditable(boolean editable) {
565 body.setEditable(editable);
566 }
567
568 public void setEnabled(boolean enabled) {
569 body.setEnabled(enabled);
570 }
571
572 public String getText() {
573 return body.getText();
574 }
575 }
576 }