1 package org.argeo.tracker.e4.parts;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Map;
6
7 import javax.jcr.Node;
8 import javax.jcr.NodeIterator;
9 import javax.jcr.Property;
10 import javax.jcr.PropertyType;
11 import javax.jcr.RepositoryException;
12 import javax.jcr.Session;
13
14 import org.argeo.activities.ActivitiesNames;
15 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
16 import org.argeo.cms.ui.eclipse.forms.FormToolkit;
17 import org.argeo.cms.ui.eclipse.forms.IFormPart;
18 import org.argeo.cms.ui.eclipse.forms.IManagedForm;
19 import org.argeo.cms.util.CmsUtils;
20 import org.argeo.connect.AppService;
21 import org.argeo.connect.ConnectException;
22 import org.argeo.connect.ConnectNames;
23 import org.argeo.connect.ui.ConnectImages;
24 import org.argeo.connect.ui.ConnectUiConstants;
25 import org.argeo.connect.ui.ConnectUiSnippets;
26 import org.argeo.connect.ui.ConnectWorkbenchUtils;
27 import org.argeo.connect.ui.parts.AskTitleDescriptionDialog;
28 import org.argeo.connect.util.ConnectJcrUtils;
29 import org.argeo.eclipse.ui.ColumnDefinition;
30 import org.argeo.eclipse.ui.EclipseUiUtils;
31 import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider;
32 import org.argeo.jcr.JcrUtils;
33 import org.argeo.tracker.TrackerException;
34 import org.argeo.tracker.TrackerNames;
35 import org.argeo.tracker.TrackerService;
36 import org.argeo.tracker.TrackerTypes;
37 import org.argeo.tracker.core.TrackerUtils;
38 import org.argeo.tracker.ui.MilestoneListComposite;
39 import org.argeo.tracker.ui.TrackerLps;
40 import org.argeo.tracker.ui.TrackerUiConstants;
41 import org.argeo.tracker.ui.VersionComparator;
42 import org.argeo.tracker.ui.controls.RepartitionChart;
43 import org.argeo.tracker.ui.dialogs.ConfigureProjectWizard;
44 import org.argeo.tracker.ui.dialogs.ConfigureVersionWizard;
45 import org.eclipse.jface.action.Action;
46 import org.eclipse.jface.action.ToolBarManager;
47 import org.eclipse.jface.dialogs.MessageDialog;
48 import org.eclipse.jface.resource.ImageDescriptor;
49 import org.eclipse.jface.viewers.ColumnLabelProvider;
50 import org.eclipse.jface.viewers.DoubleClickEvent;
51 import org.eclipse.jface.viewers.IDoubleClickListener;
52 import org.eclipse.jface.viewers.IStructuredSelection;
53 import org.eclipse.jface.viewers.TableViewer;
54 import org.eclipse.jface.viewers.Viewer;
55 import org.eclipse.jface.viewers.ViewerComparator;
56 import org.eclipse.jface.window.Window;
57 import org.eclipse.jface.wizard.WizardDialog;
58 import org.eclipse.swt.SWT;
59 import org.eclipse.swt.custom.ScrolledComposite;
60 import org.eclipse.swt.events.ModifyEvent;
61 import org.eclipse.swt.events.ModifyListener;
62 import org.eclipse.swt.events.SelectionAdapter;
63 import org.eclipse.swt.events.SelectionEvent;
64 import org.eclipse.swt.layout.GridData;
65 import org.eclipse.swt.layout.GridLayout;
66 import org.eclipse.swt.widgets.Button;
67 import org.eclipse.swt.widgets.Composite;
68 import org.eclipse.swt.widgets.Label;
69 import org.eclipse.swt.widgets.Link;
70 import org.eclipse.swt.widgets.Shell;
71 import org.eclipse.swt.widgets.Table;
72 import org.eclipse.swt.widgets.Text;
73
74
75 public class ItProjectEditor extends AbstractTrackerEditor {
76
77
78
79
80
81
82 private Node project;
83
84
85 private final static int CHART_DATA_LIMIT = 8;
86 private final static int CHART_WIDTH = 300;
87 private final static int CHART_HEIGHT = 200;
88
89
90
91
92
93
94
95 @Override
96 protected void addPages() {
97
98 project = getNode();
99 try {
100 addPage(new MainPage(this));
101 addPage(new IssuesPage(this));
102 addPage(new MilestoneListPage(this, ".milestoneList", project, getUserAdminService(), getTrackerService(),
103 getAppWorkbenchService()));
104 addPage(new VersionsPage(this));
105 addPage(new ComponentsPage(this));
106
107
108
109 } catch (Exception e) {
110 throw new TrackerException("Cannot add pages for editor of " + getNode(), e);
111 }
112 }
113
114
115 private class MainPage extends AbstractEditorPage {
116 public final static String PAGE_ID = "mainPage";
117
118 private Link managerLk;
119 private Link overdueTasksLk;
120 private Composite chartCmp;
121 private Label descLbl;
122
123 public MainPage(AbstractTrackerEditor editor) {
124 super(editor, PAGE_ID, "Overview");
125 }
126
127 protected void createFormContent(final IManagedForm mf) {
128
129
130 ScrolledComposite form = mf.getForm();
131 Composite body = new Composite(form, SWT.NONE);
132
133 GridLayout layout = new GridLayout();
134 body.setLayout(layout);
135 appendOverviewPart(body);
136 appendOpenMilestonePart(body);
137 }
138
139
140 private void appendOverviewPart(Composite parent) {
141 FormToolkit tk = getPageManagedForm().getToolkit();
142 GridData twd;
143
144 Section section = TrackerUiUtils.addFormSection(tk, parent,
145 ConnectJcrUtils.get(project, Property.JCR_TITLE));
146 section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
147
148 Composite body = (Composite) section.getClient();
149 GridLayout layout = new GridLayout();
150 layout.numColumns = 5;
151 body.setLayout(layout);
152
153
154 createFormBoldLabel(tk, body, "Manager");
155 managerLk = new Link(body, SWT.NONE);
156 managerLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
157
158
159 createFormBoldLabel(tk, body, "Overdue Tasks");
160 overdueTasksLk = new Link(body, SWT.NONE);
161 overdueTasksLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
162
163
164 chartCmp = new Composite(body, SWT.NO_FOCUS);
165 chartCmp.setLayout(EclipseUiUtils.noSpaceGridLayout());
166 twd = new GridData(SWT.CENTER, SWT.CENTER);
167
168
169 chartCmp.setLayoutData(twd);
170
171
172 twd = (GridData) TrackerUiUtils.createFormBoldLabel(tk, body, "Details").getLayoutData();
173
174 descLbl = new Label(body, SWT.WRAP);
175 twd = new GridData(SWT.FILL, SWT.TOP, true, false);
176
177 descLbl.setLayoutData(twd);
178
179 SectionPart part = new SectionPart((Section) body.getParent()) {
180
181 @Override
182 public void refresh() {
183 String managerId = ConnectJcrUtils.get(project, TrackerNames.TRACKER_MANAGER);
184 if (EclipseUiUtils.notEmpty(managerId))
185 managerLk.setText(getUserAdminService().getUserDisplayName(managerId));
186 else
187 managerLk.setText("");
188
189 String desc = ConnectJcrUtils.get(project, Property.JCR_DESCRIPTION);
190 descLbl.setText(desc);
191
192
193 CmsUtils.clear(chartCmp);
194 GridData twd = (GridData) chartCmp.getLayoutData();
195 Map<String, String> ot = TrackerUtils.getOpenTasksByAssignee(getUserAdminService(), project, null,
196 CHART_DATA_LIMIT);
197 if (ot == null || ot.isEmpty()) {
198 Label lbl = new Label(chartCmp, SWT.CENTER);
199 lbl.setFont(EclipseUiUtils.getItalicFont(body));
200 lbl.setText("No open task has been found for this project.");
201 twd.heightHint = SWT.DEFAULT;
202 } else {
203 RepartitionChart coc = new RepartitionChart(chartCmp, SWT.NO_FOCUS);
204 twd.heightHint = CHART_HEIGHT;
205 coc.setLayoutData(EclipseUiUtils.fillAll());
206 coc.setInput("Open tasks by assignee", ot, CHART_WIDTH, CHART_HEIGHT);
207 }
208
209
210 Long nb = TrackerUtils.getProjectOverdueTasksNumber(project);
211 overdueTasksLk.setText(nb < 0 ? "-" : nb.toString());
212
213 parent.layout(true, true);
214 section.setFocus();
215 super.refresh();
216 }
217 };
218 getPageManagedForm().addPart(part);
219 addMainSectionMenu(part);
220 }
221
222 private Section appendOpenMilestonePart(Composite parent) {
223 FormToolkit tk = getPageManagedForm().getToolkit();
224 Section section = TrackerUiUtils.addFormSection(tk, parent, "Open Milestones");
225 section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
226
227 Composite body = (Composite) section.getClient();
228 body.setLayout(new GridLayout());
229 final MilestoneListComposite msBoxCmp = new MilestoneListComposite(body, SWT.NO_FOCUS,
230 getAppWorkbenchService(), project);
231 msBoxCmp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
232
233 SectionPart part = new SectionPart(section) {
234
235 @Override
236 public void refresh() {
237 NodeIterator nit = TrackerUtils.getOpenMilestones(project, null);
238 msBoxCmp.setInput(JcrUtils.nodeIteratorToList(nit).toArray(new Node[0]));
239 super.refresh();
240 }
241 };
242 getPageManagedForm().addPart(part);
243 return section;
244 }
245 }
246
247
248 private void addMainSectionMenu(SectionPart sectionPart) {
249 ToolBarManager toolBarManager = TrackerUiUtils.addMenu(sectionPart.getSection());
250
251 String tooltip = "Edit the project main information";
252 Action action = new OpenConfigureDialog(tooltip, ConnectImages.IMG_DESC_EDIT, sectionPart);
253 toolBarManager.add(action);
254
255 tooltip = "Add a milestone to this project";
256 action = new AddMilestone(sectionPart.getSection().getShell(), tooltip, ConnectImages.IMG_DESC_ADD);
257 toolBarManager.add(action);
258
259 toolBarManager.update(true);
260 }
261
262
263 private class OpenConfigureDialog extends Action {
264 private static final long serialVersionUID = -6798429720348536525L;
265 private final SectionPart sectionPart;
266
267 private OpenConfigureDialog(String name, ImageDescriptor img, SectionPart sectionPart) {
268 super(name, img);
269 this.sectionPart = sectionPart;
270 }
271
272 @Override
273 public void run() {
274 Shell currShell = sectionPart.getSection().getShell();
275 ConfigureProjectWizard wizard = new ConfigureProjectWizard(getUserAdminService(), getTrackerService(),
276 project);
277 WizardDialog dialog = new WizardDialog(currShell, wizard);
278 try {
279 if (dialog.open() == Window.OK && project.getSession().hasPendingChanges()) {
280 updatePartName();
281 sectionPart.getSection().setText(ConnectJcrUtils.get(project, Property.JCR_TITLE));
282 sectionPart.refresh();
283 sectionPart.markDirty();
284 sectionPart.getSection().setFocus();
285 }
286 } catch (RepositoryException e) {
287 throw new TrackerException("Cannot check session state on " + project, e);
288 }
289 }
290 }
291
292 private class AddMilestone extends Action {
293 private static final long serialVersionUID = 5112793747049604434L;
294 final Shell shell;
295
296 private AddMilestone(Shell shell, String name, ImageDescriptor img) {
297 super(name, img);
298 this.shell = shell;
299 }
300
301 @Override
302 public void run() {
303 String mainMixin = TrackerTypes.TRACKER_MILESTONE;
304 Session referenceSession = ConnectJcrUtils.getSession(project);
305 AppService appService = getAppService();
306 String propName1 = TrackerNames.TRACKER_PROJECT_UID;
307 String value1 = ConnectJcrUtils.get(project, ConnectNames.CONNECT_UID);
308 String pathCreated = ConnectWorkbenchUtils.createAndConfigureEntity(shell, referenceSession, appService,
309 getAppWorkbenchService(), mainMixin, propName1, value1);
310 if (EclipseUiUtils.notEmpty(pathCreated)) {
311 Node created = ConnectJcrUtils.getNode(referenceSession, pathCreated);
312
313
314 getAppWorkbenchService().openEntityEditor(created);
315 }
316 }
317 }
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386 private class IssuesPage extends AbstractEditorPage {
387 public final static String PAGE_ID = ".issueListPage";
388
389 private TableViewer tableViewer;
390 private Text filterTxt;
391
392 public IssuesPage(AbstractTrackerEditor editor) {
393 super(editor, PAGE_ID, "Issues");
394 }
395
396 protected void createFormContent(final IManagedForm mf) {
397
398
399 ScrolledComposite form = mf.getForm();
400 Composite body = new Composite(form, SWT.NONE);
401
402 GridLayout mainLayout = new GridLayout();
403 body.setLayout(mainLayout);
404
405 Composite filterCmp = new Composite(body, SWT.NO_FOCUS);
406 createFilterPart(filterCmp);
407 filterCmp.setLayoutData(EclipseUiUtils.fillWidth());
408 Composite tableCmp = new Composite(body, SWT.NO_FOCUS);
409 appendIssuesPart(tableCmp);
410 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
411
412 AbstractFormPart part = new AbstractFormPart() {
413 @Override
414 public void refresh() {
415 refreshViewer(filterTxt.getText());
416 super.refresh();
417 }
418 };
419 mf.addPart(part);
420
421 }
422
423 private void appendIssuesPart(Composite parent) {
424 List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
425 columnDefs.add(new ColumnDefinition(getJcrLP(TrackerNames.TRACKER_ID), "ID", 40));
426 columnDefs.add(new ColumnDefinition(getJcrLP(Property.JCR_TITLE), "Title", 300));
427 columnDefs.add(new ColumnDefinition(getJcrLP(ActivitiesNames.ACTIVITIES_TASK_STATUS), "Status", 100));
428 columnDefs.add(new ColumnDefinition(
429 new TrackerLps().new DnLabelProvider(getUserAdminService(), ActivitiesNames.ACTIVITIES_ASSIGNED_TO),
430 "Assignee", 160));
431 columnDefs.add(new ColumnDefinition(new TrackerLps().new MilestoneLabelProvider(getAppService()),
432 "Milestone", 220));
433 columnDefs.add(new ColumnDefinition(new TrackerLps().new ImportanceLabelProvider(), "Importance", 100));
434 columnDefs.add(new ColumnDefinition(new TrackerLps().new PriorityLabelProvider(), "Priority", 100));
435 columnDefs.add(new ColumnDefinition(new TrackerLps().new CommentNbLabelProvider(), "Comments", 120));
436
437 tableViewer = TrackerUiUtils.createTableViewer(parent, SWT.SINGLE, columnDefs);
438 addDClickListener(tableViewer);
439 refreshViewer(null);
440 }
441
442 private void refreshViewer(String filter) {
443 NodeIterator nit = TrackerUtils.getIssues(project, filter);
444 tableViewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray(new Node[0]));
445 tableViewer.refresh();
446 }
447
448 private void createFilterPart(Composite parent) {
449 GridLayout layout = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, false));
450 layout.horizontalSpacing = 5;
451 parent.setLayout(layout);
452 parent.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
453
454 filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
455 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
456
457 final Button addBtn = new Button(parent, SWT.PUSH);
458 addBtn.setToolTipText("Create an issue");
459 addBtn.setImage(ConnectImages.ADD);
460
461 filterTxt.addModifyListener(new ModifyListener() {
462 private static final long serialVersionUID = 8130545587125370689L;
463
464 public void modifyText(ModifyEvent event) {
465 refreshViewer(filterTxt.getText());
466 }
467 });
468
469 addBtn.addSelectionListener(new SelectionAdapter() {
470 private static final long serialVersionUID = 9141984572082449486L;
471
472 @Override
473 public void widgetSelected(SelectionEvent e) {
474
475 String mainMixin = TrackerTypes.TRACKER_ISSUE;
476 Session referenceSession = ConnectJcrUtils.getSession(project);
477 Shell shell = addBtn.getShell();
478 AppService appService = getAppService();
479 String propName1 = TrackerNames.TRACKER_PROJECT_UID;
480 String value1 = ConnectJcrUtils.get(project, ConnectNames.CONNECT_UID);
481 String pathCreated = ConnectWorkbenchUtils.createAndConfigureEntity(shell, referenceSession,
482 appService, getAppWorkbenchService(), mainMixin, propName1, value1);
483 if (EclipseUiUtils.notEmpty(pathCreated))
484 refreshViewer(filterTxt.getText());
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517 }
518 });
519 }
520 }
521
522 private class VersionsPage extends AbstractEditorPage {
523 public final static String ID = "projectEditor.issuesPage";
524
525 private TableViewer tableViewer;
526 private Text filterTxt;
527
528 public VersionsPage(AbstractTrackerEditor editor) {
529 super(editor, ID, "Versions");
530 }
531
532 protected void createFormContent(IManagedForm mf) {
533
534
535 ScrolledComposite form = mf.getForm();
536 Composite body = new Composite(form, SWT.NONE);
537
538 GridLayout mainLayout = new GridLayout();
539
540 body.setLayout(mainLayout);
541 Composite filterCmp = new Composite(body, SWT.NO_FOCUS);
542 createFilterPart(filterCmp);
543 filterCmp.setLayoutData(EclipseUiUtils.fillWidth());
544 Composite tableCmp = new Composite(body, SWT.NO_FOCUS);
545 appendVersionsPart(mf, tableCmp);
546 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
547
548
549 }
550
551 private void appendVersionsPart(IManagedForm mf, Composite parent) {
552 List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
553 columnDefs.add(new ColumnDefinition(getJcrLP(TrackerNames.TRACKER_ID), "ID", 80));
554 columnDefs.add(new ColumnDefinition(new TrackerLps().new VersionDateLabelProvider(), "Release Date", 120));
555 columnDefs.add(new ColumnDefinition(getCountLP(true), "Open issues", 120));
556 columnDefs.add(new ColumnDefinition(getCountLP(false), "All issues", 120));
557 columnDefs.add(new ColumnDefinition(getJcrLP(Property.JCR_DESCRIPTION), "Description", 300));
558 if (canEdit())
559 columnDefs.add(new ColumnDefinition(getEditionLP(), "", 120));
560
561 tableViewer = TrackerUiUtils.createTableViewer(parent, SWT.SINGLE, columnDefs);
562 tableViewer.setComparator(new ViewerComparator() {
563 private static final long serialVersionUID = 1L;
564 VersionComparator comp = new VersionComparator();
565
566 public int compare(Viewer viewer, Object e1, Object e2) {
567 Node n1 = (Node) e1;
568 Node n2 = (Node) e2;
569
570 return comp.compare(viewer, ConnectJcrUtils.get(n2, TrackerNames.TRACKER_ID),
571 ConnectJcrUtils.get(n1, TrackerNames.TRACKER_ID));
572 };
573 });
574 addDClickListener(tableViewer);
575
576 AbstractFormPart part = new AbstractFormPart() {
577 @Override
578 public void refresh() {
579 refreshViewer(filterTxt.getText());
580 super.refresh();
581 }
582 };
583 mf.addPart(part);
584
585 if (canEdit()) {
586 Table table = tableViewer.getTable();
587 CmsUtils.setItemHeight(table, TrackerUiConstants.DEFAULT_ROW_HEIGHT);
588 CmsUtils.markup(table);
589 table.addSelectionListener(new EditionRwtAdapter(part));
590 }
591 refreshViewer(null);
592 }
593
594 private void refreshViewer(String filter) {
595 NodeIterator nit = TrackerUtils.getAllVersions(project, filter);
596 tableViewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray(new Node[0]));
597 tableViewer.refresh();
598 }
599
600 private void createFilterPart(Composite parent) {
601 GridLayout layout = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, false));
602 layout.horizontalSpacing = 5;
603 parent.setLayout(layout);
604 parent.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
605
606 filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
607 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
608
609 final Button addBtn = new Button(parent, SWT.PUSH);
610 addBtn.setToolTipText("Create a new version");
611 addBtn.setImage(ConnectImages.ADD);
612
613 filterTxt.addModifyListener(new ModifyListener() {
614 private static final long serialVersionUID = 8130545587125370689L;
615
616 public void modifyText(ModifyEvent event) {
617 refreshViewer(filterTxt.getText());
618 }
619 });
620
621 addBtn.addSelectionListener(new SelectionAdapter() {
622 private static final long serialVersionUID = -6057495212496327413L;
623
624 @Override
625 public void widgetSelected(SelectionEvent e) {
626 String mainMixin = TrackerTypes.TRACKER_VERSION;
627 Session referenceSession = ConnectJcrUtils.getSession(project);
628 Shell shell = addBtn.getShell();
629 TrackerService trackerService = getTrackerService();
630 String propName1 = TrackerNames.TRACKER_PROJECT_UID;
631 String value1 = ConnectJcrUtils.get(project, ConnectNames.CONNECT_UID);
632 String pathCreated = ConnectWorkbenchUtils.createAndConfigureEntity(shell, referenceSession,
633 trackerService, getAppWorkbenchService(), mainMixin, propName1, value1);
634 if (EclipseUiUtils.notEmpty(pathCreated))
635 refreshViewer(filterTxt.getText());
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650 }
651 });
652 }
653 }
654
655 private class ComponentsPage extends AbstractEditorPage {
656 public final static String ID = "projectEditor.componentsPage";
657
658 private TableViewer tableViewer;
659 private Text filterTxt;
660
661 public ComponentsPage(AbstractTrackerEditor editor) {
662 super(editor, ID, "Components");
663 }
664
665 protected void createFormContent(final IManagedForm mf) {
666
667
668
669 ScrolledComposite form = mf.getForm();
670 Composite body = new Composite(form, SWT.NONE);
671
672 GridLayout mainLayout = new GridLayout();
673 body.setLayout(mainLayout);
674 Composite filterCmp = new Composite(body, SWT.NO_FOCUS);
675 createFilterPart(filterCmp);
676 filterCmp.setLayoutData(EclipseUiUtils.fillWidth());
677 Composite tableCmp = new Composite(body, SWT.NO_FOCUS);
678 appendComponentsPart(mf, tableCmp);
679 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
680
681 }
682
683 private void appendComponentsPart(IManagedForm mf, Composite parent) {
684 List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
685 columnDefs.add(new ColumnDefinition(getJcrLP(Property.JCR_TITLE), "Title", 150));
686 columnDefs.add(new ColumnDefinition(getJcrLP(Property.JCR_DESCRIPTION), "Description", 300));
687 columnDefs.add(new ColumnDefinition(getCountLP(true), "Open issues", 120));
688 columnDefs.add(new ColumnDefinition(getCountLP(false), "All issues", 120));
689 if (canEdit())
690 columnDefs.add(new ColumnDefinition(getEditionLP(), "", 120));
691
692 tableViewer = TrackerUiUtils.createTableViewer(parent, SWT.SINGLE, columnDefs);
693 tableViewer.setComparator(new ViewerComparator() {
694 private static final long serialVersionUID = 1L;
695
696 public int compare(Viewer viewer, Object e1, Object e2) {
697 try {
698 Node n1 = (Node) e1;
699 Node n2 = (Node) e2;
700 return ConnectJcrUtils.get(n1, Property.JCR_TITLE)
701 .compareToIgnoreCase(ConnectJcrUtils.get(n2, Property.JCR_TITLE));
702 } catch (ConnectException e) {
703
704
705 }
706 return 0;
707 };
708 });
709 addDClickListener(tableViewer);
710
711 AbstractFormPart part = new AbstractFormPart() {
712 @Override
713 public void refresh() {
714 refreshViewer(filterTxt.getText());
715 super.refresh();
716 }
717 };
718 mf.addPart(part);
719
720 if (canEdit()) {
721 Table table = tableViewer.getTable();
722 CmsUtils.setItemHeight(table, TrackerUiConstants.DEFAULT_ROW_HEIGHT);
723 CmsUtils.markup(table);
724 table.addSelectionListener(new EditionRwtAdapter(part));
725 }
726 refreshViewer(null);
727 }
728
729 private void refreshViewer(String filter) {
730 NodeIterator nit = TrackerUtils.getComponents(project, filter);
731 if (nit == null || !nit.hasNext())
732 tableViewer.setInput(null);
733 else
734 tableViewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray(new Node[0]));
735 tableViewer.refresh();
736 }
737
738 private void createFilterPart(Composite parent) {
739 GridLayout layout = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, false));
740 layout.horizontalSpacing = 5;
741 parent.setLayout(layout);
742 parent.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
743 filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
744 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
745 final Button addBtn = new Button(parent, SWT.PUSH);
746 addBtn.setToolTipText("Create a new component");
747 addBtn.setImage(ConnectImages.ADD);
748 filterTxt.addModifyListener(new ModifyListener() {
749 private static final long serialVersionUID = 8130545587125370689L;
750
751 public void modifyText(ModifyEvent event) {
752 refreshViewer(filterTxt.getText());
753 }
754 });
755
756 addBtn.addSelectionListener(new SelectionAdapter() {
757 private static final long serialVersionUID = 9141984572082449486L;
758
759 @Override
760 public void widgetSelected(SelectionEvent e) {
761
762 String mainMixin = TrackerTypes.TRACKER_COMPONENT;
763 Session referenceSession = ConnectJcrUtils.getSession(project);
764 Shell shell = addBtn.getShell();
765 TrackerService trackerService = getTrackerService();
766 String propName1 = TrackerNames.TRACKER_PROJECT_UID;
767 String value1 = ConnectJcrUtils.get(project, ConnectNames.CONNECT_UID);
768 String pathCreated = ConnectWorkbenchUtils.createAndConfigureEntity(shell, referenceSession,
769 trackerService, getAppWorkbenchService(), mainMixin, propName1, value1);
770 if (EclipseUiUtils.notEmpty(pathCreated))
771 refreshViewer(filterTxt.getText());
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788 }
789 });
790 }
791 }
792
793
794
795
796 private static ColumnLabelProvider getJcrLP(String propName) {
797 return new SimpleJcrNodeLabelProvider(propName);
798 }
799
800 private static ColumnLabelProvider getCountLP(boolean onlyOpen) {
801 return new ColumnLabelProvider() {
802 private static final long serialVersionUID = -998161071505982347L;
803
804 @Override
805 public String getText(Object element) {
806 Node category = (Node) element;
807 long currNb = TrackerUtils.getIssueNb(category, onlyOpen);
808 return currNb + "";
809 }
810 };
811 }
812
813 private static ColumnLabelProvider getEditionLP() {
814 return new ColumnLabelProvider() {
815 private static final long serialVersionUID = 6502008085763687925L;
816
817 @Override
818 public String getText(Object element) {
819 Node category = (Node) element;
820 String jcrId = ConnectJcrUtils.getIdentifier(category);
821
822 String editHref = ConnectUiConstants.CRUD_EDIT + "/" + jcrId;
823 String editLinkStr = ConnectUiSnippets.getRWTLink(editHref, ConnectUiConstants.CRUD_EDIT);
824
825
826 if (TrackerUtils.getIssueNb(category, false) == 0) {
827 String removeHref = ConnectUiConstants.CRUD_DELETE + "/" + jcrId;
828 String removeLinkStr = ConnectUiSnippets.getRWTLink(removeHref, ConnectUiConstants.CRUD_DELETE);
829 editLinkStr += " or " + removeLinkStr;
830 }
831 return editLinkStr;
832 }
833 };
834 }
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849 private class EditionRwtAdapter extends SelectionAdapter {
850 private static final long serialVersionUID = -7459078949241763141L;
851
852 private IFormPart part;
853
854 public EditionRwtAdapter(IFormPart part) {
855 this.part = part;
856 }
857
858 public void widgetSelected(SelectionEvent event) {
859 if (event.detail == ConnectUiConstants.MARKUP_VIEWER_HYPERLINK) {
860 String string = event.text;
861 String[] token = string.split("/");
862 String cmdId = token[0];
863 String jcrId = token[1];
864 Shell shell = event.display.getActiveShell();
865 boolean hasChanged = false;
866 try {
867 Node node = project.getSession().getNodeByIdentifier(jcrId);
868 if (ConnectUiConstants.CRUD_DELETE.equals(cmdId)) {
869 if (MessageDialog.openConfirm(shell, "Confirm deletion",
870 "Are you sure you want to delete " + ConnectJcrUtils.get(node, Property.JCR_TITLE))) {
871 node.remove();
872 project.getSession().save();
873 hasChanged = true;
874 }
875 } else if (ConnectUiConstants.CRUD_EDIT.equals(cmdId)) {
876 if (node.isNodeType(TrackerTypes.TRACKER_COMPONENT)) {
877 String title = ConnectJcrUtils.get(node, Property.JCR_TITLE);
878 String desc = ConnectJcrUtils.get(node, Property.JCR_DESCRIPTION);
879 AskTitleDescriptionDialog dialog = new AskTitleDescriptionDialog(shell, "Edit component",
880 title, desc);
881 if (dialog.open() == Window.OK) {
882 hasChanged = ConnectJcrUtils.setJcrProperty(node, Property.JCR_TITLE,
883 PropertyType.STRING, dialog.getTitle());
884 hasChanged |= ConnectJcrUtils.setJcrProperty(node, Property.JCR_DESCRIPTION,
885 PropertyType.STRING, dialog.getDescription());
886 if (hasChanged)
887 project.getSession().save();
888 }
889 } else if (node.isNodeType(TrackerTypes.TRACKER_VERSION)) {
890 ConfigureVersionWizard wizard = new ConfigureVersionWizard(getTrackerService(), node);
891 WizardDialog dialog = new WizardDialog(shell, wizard);
892 if (dialog.open() == Window.OK) {
893 if (project.getSession().hasPendingChanges()) {
894 project.getSession().save();
895 hasChanged = true;
896 }
897 }
898 }
899 }
900 } catch (RepositoryException e) {
901 throw new TrackerException("Cannot " + cmdId + " with JcrId " + jcrId, e);
902 }
903 if (hasChanged)
904 part.refresh();
905 }
906 }
907 }
908
909 private void addDClickListener(TableViewer tableViewer) {
910 tableViewer.addDoubleClickListener(new IDoubleClickListener() {
911 @Override
912 public void doubleClick(DoubleClickEvent event) {
913 Object element = ((IStructuredSelection) event.getSelection()).getFirstElement();
914
915
916
917 getAppWorkbenchService().openEntityEditor((Node) element);
918 }
919 });
920 }
921
922
923
924
925
926
927
928
929
930 }