1 package org.argeo.tracker.e4.parts;
2
3 import static org.argeo.activities.ActivitiesNames.ACTIVITIES_RELATED_TO;
4 import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty;
5
6 import java.util.ArrayList;
7 import java.util.List;
8
9 import javax.jcr.Node;
10 import javax.jcr.Property;
11 import javax.jcr.PropertyType;
12 import javax.jcr.RepositoryException;
13 import javax.jcr.Session;
14 import javax.jcr.Value;
15
16 import org.argeo.activities.ActivitiesNames;
17 import org.argeo.cms.ui.CmsEditable;
18 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
19 import org.argeo.cms.ui.eclipse.forms.IManagedForm;
20 import org.argeo.cms.util.CmsUtils;
21 import org.argeo.connect.ConnectConstants;
22 import org.argeo.connect.ui.ConnectImages;
23 import org.argeo.connect.ui.ConnectWorkbenchUtils;
24 import org.argeo.connect.util.ConnectJcrUtils;
25 import org.argeo.eclipse.ui.EclipseUiUtils;
26 import org.argeo.tracker.TrackerException;
27 import org.argeo.tracker.TrackerNames;
28 import org.argeo.tracker.TrackerTypes;
29 import org.argeo.tracker.core.TrackerUtils;
30 import org.argeo.tracker.ui.dialogs.ConfigureTaskWizard;
31 import org.eclipse.jface.action.Action;
32 import org.eclipse.jface.action.ToolBarManager;
33 import org.eclipse.jface.resource.ImageDescriptor;
34 import org.eclipse.jface.window.Window;
35 import org.eclipse.jface.wizard.WizardDialog;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.custom.ScrolledComposite;
38 import org.eclipse.swt.events.SelectionAdapter;
39 import org.eclipse.swt.events.SelectionEvent;
40 import org.eclipse.swt.layout.GridData;
41 import org.eclipse.swt.layout.GridLayout;
42 import org.eclipse.swt.layout.RowLayout;
43 import org.eclipse.swt.widgets.Combo;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Label;
46 import org.eclipse.swt.widgets.Link;
47 import org.eclipse.swt.widgets.Listener;
48 import org.eclipse.swt.widgets.Shell;
49
50
51 public class TaskEditor extends AbstractTrackerEditor implements CmsEditable {
52
53
54
55
56
57
58 private Session session;
59 private Node project;
60 private Node task;
61
62
63
64
65
66
67 @Override
68 protected void addPages() {
69
70 task = getNode();
71 session = ConnectJcrUtils.getSession(task);
72 project = TrackerUtils.getRelatedProject(getAppService(), task);
73 try {
74 addPage(new TaskMainPage(this));
75
76
77
78 } catch (Exception e) {
79 throw new TrackerException("Cannot add pages for editor of " + getNode(), e);
80 }
81 }
82
83
84 private class TaskMainPage extends AbstractEditorPage {
85 public final static String PAGE_ID = ".taskMainPage";
86
87 private Combo statusCmb;
88 private Link projectLk;
89 private Link milestoneLk;
90 private Link dueDateLk;
91 private Link reporterLk;
92 private Link assignedToLk;
93 private Composite relatedCmp;
94 private Label descLbl;
95
96 public TaskMainPage(AbstractTrackerEditor editor) {
97 super(editor, PAGE_ID, "Main");
98 }
99
100 protected void createFormContentX(final IManagedForm mf) {
101
102
103 ScrolledComposite form = mf.getForm();
104 Composite body = new Composite(form, SWT.NONE);
105 GridLayout layout = new GridLayout();
106 body.setLayout(layout);
107 appendOverviewPartDebug(body);
108
109
110
111
112
113 }
114
115 @Override
116 protected void createFormContent(Composite body) {
117 appendOverviewPart(body);
118 Composite commentFormPart = new CommentListFormPart(getManagedForm(), body, SWT.NO_FOCUS,
119 getTrackerService(), getNode());
120 commentFormPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
121 }
122
123 private void appendOverviewPartDebug(final Composite parent) {
124 new Label(parent, SWT.NONE).setText("TEST");
125
126 }
127
128
129 private void appendOverviewPart(final Composite parent) {
130
131
132
133
134
135
136
137 Composite body = new Composite(parent, SWT.NONE);
138 GridLayout layout = new GridLayout();
139 layout.numColumns = 2;
140 body.setLayout(layout);
141
142
143 createFormBoldLabel(body, "Status");
144 statusCmb = new Combo(body, SWT.READ_ONLY);
145 statusCmb.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
146
147
148 createFormBoldLabel(body, "Project");
149 projectLk = new Link(body, SWT.NONE);
150 projectLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
151
152
153
154 createFormBoldLabel(body, "Milestone");
155 milestoneLk = new Link(body, SWT.NONE);
156 milestoneLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
157
158
159 createFormBoldLabel(body, "Assigned to");
160 assignedToLk = new Link(body, SWT.NONE);
161 assignedToLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, false, false));
162
163
164 createFormBoldLabel(body, "Due Date");
165 dueDateLk = new Link(body, SWT.NONE);
166 dueDateLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
167
168
169 createFormBoldLabel(body, "Reported by");
170 reporterLk = new Link(body, SWT.NONE);
171 reporterLk.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
172
173
174 createFormBoldLabel(body, "Related to");
175 relatedCmp = new Composite(body, SWT.NO_FOCUS);
176 GridData twd = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
177
178 relatedCmp.setLayoutData(twd);
179
180
181
182
183 twd = (GridData) createFormBoldLabel(body, "Details").getLayoutData();
184
185 descLbl = new Label(body, SWT.WRAP);
186 twd = new GridData(SWT.FILL, SWT.TOP, true, false);
187
188 descLbl.setLayoutData(twd);
189
190 SectionPart part = new SectionPart(body.getParent()) {
191
192 @Override
193 public void refresh() {
194
195 refreshStatusCombo(statusCmb, task);
196 statusCmb.setText(ConnectJcrUtils.get(task, ActivitiesNames.ACTIVITIES_TASK_STATUS));
197
198
199
200 Node milestone = TrackerUtils.getMilestone(getTrackerService(), task);
201 if (milestone != null)
202 configureOpenLink(milestoneLk, milestone);
203
204 String manager = getActivitiesService().getAssignedToDisplayName(task);
205 String importance = TrackerUtils.getImportanceLabel(task);
206 String priority = TrackerUtils.getPriorityLabel(task);
207 String tmp = ConnectJcrUtils.concatIfNotEmpty(importance, priority, "/");
208 if (EclipseUiUtils.notEmpty(tmp))
209 manager += " (" + tmp + " )";
210
211 assignedToLk.setText(manager);
212
213 String dueDateStr = ConnectJcrUtils.getDateFormattedAsString(task,
214 ActivitiesNames.ACTIVITIES_DUE_DATE, ConnectConstants.DEFAULT_DATE_TIME_FORMAT);
215 if (EclipseUiUtils.notEmpty(dueDateStr))
216 dueDateLk.setText(dueDateStr);
217
218 reporterLk.setText(TrackerUtils.getCreationLabel(getUserAdminService(), task));
219
220 try {
221 List<Node> relatedTo = new ArrayList<>();
222 if (task.hasProperty(ACTIVITIES_RELATED_TO)) {
223 Value[] values = task.getProperty(ACTIVITIES_RELATED_TO).getValues();
224 for (Value value : values) {
225 String valueStr = value.getString();
226 Node targetNode = task.getSession().getNodeByIdentifier(valueStr);
227 relatedTo.add(targetNode);
228 }
229 }
230 populateMultiValueClickableList(relatedCmp, relatedTo);
231 } catch (RepositoryException re) {
232 throw new TrackerException("Unable to refresh related to composite on " + task, re);
233 }
234
235 String desc = ConnectJcrUtils.get(task, Property.JCR_DESCRIPTION);
236 descLbl.setText(desc);
237
238 parent.layout(true, true);
239
240 super.refresh();
241 }
242 };
243 addStatusCmbSelListener(part, statusCmb, task, ActivitiesNames.ACTIVITIES_TASK_STATUS, PropertyType.STRING);
244
245
246
247
248
249
250
251
252
253
254
255
256
257 part.initialize(getManagedForm());
258 getManagedForm().addPart(part);
259
260 addMainSectionMenu(part);
261 }
262
263 private void configureOpenLink(Link link, Node targetNode) {
264 link.setText("<a>" + ConnectJcrUtils.get(targetNode, Property.JCR_TITLE) + "</a>");
265
266
267 Listener[] existings = link.getListeners(SWT.Selection);
268 for (Listener l : existings)
269 link.removeListener(SWT.Selection, l);
270
271 link.addSelectionListener(new SelectionAdapter() {
272 private static final long serialVersionUID = 1L;
273
274 @Override
275 public void widgetSelected(SelectionEvent e) {
276
277
278 getAppWorkbenchService().openEntityEditor(targetNode);
279 }
280 });
281 }
282 }
283
284 private void populateMultiValueClickableList(Composite parent, List<Node> nodes) {
285 CmsUtils.clear(parent);
286
287
288
289
290
291
292
293 RowLayout rl = new RowLayout(SWT.HORIZONTAL);
294 rl.wrap = true;
295 rl.marginLeft = rl.marginTop = rl.marginBottom = 0;
296 rl.marginRight = 8;
297 parent.setLayout(rl);
298
299 for (Node node : nodes) {
300 String value = ConnectJcrUtils.get(node, Property.JCR_TITLE);
301 Link link = new Link(parent, SWT.NONE);
302 CmsUtils.markup(link);
303 link.setText(" <a>" + value + "</a>");
304
305 link.addSelectionListener(new SelectionAdapter() {
306 private static final long serialVersionUID = 1L;
307
308 @Override
309 public void widgetSelected(final SelectionEvent event) {
310
311
312 getAppWorkbenchService().openEntityEditor(node);
313 }
314 });
315 }
316 }
317
318
319 private void addMainSectionMenu(SectionPart sectionPart) {
320 ToolBarManager toolBarManager = TrackerUiUtils.addMenu(sectionPart.getComposite());
321 String tooltip = "Edit the task main information";
322 Action action = new OpenConfigureDialog(tooltip, ConnectImages.IMG_DESC_EDIT, sectionPart);
323 toolBarManager.add(action);
324 toolBarManager.update(true);
325 }
326
327
328 private class OpenConfigureDialog extends Action {
329 private static final long serialVersionUID = -6798429720348536525L;
330 private final SectionPart sectionPart;
331
332 private OpenConfigureDialog(String name, ImageDescriptor img, SectionPart sectionPart) {
333 super(name, img);
334 this.sectionPart = sectionPart;
335 }
336
337 @Override
338 public void run() {
339 Shell currShell = sectionPart.getComposite().getShell();
340 ConfigureTaskWizard wizard = new ConfigureTaskWizard(getUserAdminService(), getActivitiesService(),
341 getTrackerService(), getAppWorkbenchService(), task);
342 WizardDialog dialog = new WizardDialog(currShell, wizard);
343 try {
344 if (dialog.open() == Window.OK && task.getSession().hasPendingChanges()) {
345 updatePartName();
346
347 sectionPart.refresh();
348 sectionPart.markDirty();
349 sectionPart.getComposite().setFocus();
350 }
351 } catch (RepositoryException e) {
352 throw new TrackerException("Cannot check session state on " + task, e);
353 }
354 }
355 }
356
357
358 private void addStatusCmbSelListener(final AbstractFormPart part, final Combo combo, final Node entity,
359 final String propName, final int propType) {
360 combo.addSelectionListener(new SelectionAdapter() {
361 private static final long serialVersionUID = 1L;
362
363 @Override
364 public void widgetSelected(SelectionEvent e) {
365 int index = combo.getSelectionIndex();
366 if (index != -1) {
367 String selectedStatus = combo.getItem(index);
368 try {
369 if (getActivitiesService().updateStatus(TrackerTypes.TRACKER_TASK, task, selectedStatus,
370 new ArrayList<String>()))
371 part.markDirty();
372 } catch (RepositoryException e1) {
373 throw new TrackerException("Cannot update status to " + selectedStatus + " for " + task, e1);
374 }
375 }
376 }
377 });
378 }
379
380
381 private void refreshStatusCombo(Combo combo, Node currTask) {
382
383
384
385 List<String> values = new ArrayList<String>();
386 values.add("In progress");
387 values.add("Closed");
388 combo.setItems(values.toArray(new String[values.size()]));
389 ConnectWorkbenchUtils.refreshFormCombo(TaskEditor.this, combo, currTask,
390 ActivitiesNames.ACTIVITIES_TASK_STATUS);
391 combo.setEnabled(TaskEditor.this.isEditing());
392 }
393
394 private String getIssueTitle() {
395 String id = ConnectJcrUtils.get(getNode(), TrackerNames.TRACKER_ID);
396 String name = ConnectJcrUtils.get(getNode(), Property.JCR_TITLE);
397 if (notEmpty(name)) {
398 Node project = TrackerUtils.getRelatedProject(getTrackerService(), getNode());
399 String pname = ConnectJcrUtils.get(project, Property.JCR_TITLE);
400 name = name + (notEmpty(pname) ? " (" + pname + ")" : "");
401 }
402 return "#" + id + " " + name;
403 }
404
405
406
407
408
409
410
411
412
413
414
415
416 }