1 package org.argeo.activities.ui;
2
3 import java.text.DateFormat;
4 import java.text.SimpleDateFormat;
5 import java.util.ArrayList;
6 import java.util.Calendar;
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
15 import org.argeo.activities.ActivitiesException;
16 import org.argeo.activities.ActivitiesNames;
17 import org.argeo.activities.ActivitiesService;
18 import org.argeo.cms.ui.eclipse.forms.AbstractFormPart;
19 import org.argeo.cms.ui.eclipse.forms.FormToolkit;
20 import org.argeo.cms.ui.useradmin.PickUpUserDialog;
21 import org.argeo.connect.ConnectConstants;
22 import org.argeo.connect.UserAdminService;
23 import org.argeo.connect.resources.ResourcesService;
24 import org.argeo.connect.ui.ConnectEditor;
25 import org.argeo.connect.ui.ConnectUiUtils;
26 import org.argeo.connect.ui.ConnectWorkbenchUtils;
27 import org.argeo.connect.ui.SystemWorkbenchService;
28 import org.argeo.connect.ui.parts.AbstractPanelFormPart;
29 import org.argeo.connect.ui.parts.DateTextPart;
30 import org.argeo.connect.util.ConnectJcrUtils;
31 import org.argeo.eclipse.ui.EclipseUiUtils;
32 import org.eclipse.jface.window.Window;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.events.SelectionAdapter;
35 import org.eclipse.swt.events.SelectionEvent;
36 import org.eclipse.swt.layout.GridData;
37 import org.eclipse.swt.layout.GridLayout;
38 import org.eclipse.swt.widgets.Combo;
39 import org.eclipse.swt.widgets.Composite;
40 import org.eclipse.swt.widgets.Label;
41 import org.eclipse.swt.widgets.Link;
42 import org.eclipse.swt.widgets.Text;
43 import org.osgi.service.useradmin.User;
44
45
46 public class TaskBasicHeader extends Composite {
47 private static final long serialVersionUID = -5813631462166187272L;
48
49
50 private final Session session;
51
52 private final UserAdminService userAdminService;
53 private final ResourcesService resourceService;
54 private final ActivitiesService activityService;
55 private final SystemWorkbenchService systemWorkbenchService;
56 private final Node task;
57 private final String taskTypeId;
58
59
60 private String assignedToGroupId;
61
62 private List<String> hiddenItemIds;
63 private List<String> modifiedPaths = new ArrayList<String>();
64
65
66 private final ConnectEditor editor;
67 private final MyFormPart myFormPart;
68 private final FormToolkit toolkit;
69
70
71
72 private Combo statusCmb;
73 private DateTextPart dueDateCmp;
74 private DateTextPart wakeUpDateCmp;
75 private Link changeAssignationLk;
76
77 private Label statusROLbl;
78 private Label assignedToROLbl;
79
80
81 private LinkListPart relatedCmp;
82 private Text titleTxt;
83 private Text descTxt;
84
85 private DateFormat dtFormat = new SimpleDateFormat(ConnectConstants.DEFAULT_DATE_TIME_FORMAT);
86 private DateFormat dateFormat = new SimpleDateFormat(ConnectConstants.DEFAULT_DATE_FORMAT);
87
88 public TaskBasicHeader(ConnectEditor editor, Composite parent, int style, UserAdminService uas,
89 ResourcesService resourceService, ActivitiesService activityService,
90 SystemWorkbenchService systemWorkbenchService, String taskTypeId, Node task) {
91 this(editor, parent, style, uas, resourceService, activityService, systemWorkbenchService, taskTypeId, task,
92 null);
93 }
94
95 public TaskBasicHeader(ConnectEditor editor, Composite parent, int style, UserAdminService uas,
96 ResourcesService resourceService, ActivitiesService activityService,
97 SystemWorkbenchService systemWorkbenchService, String taskTypeId, Node task, List<String> hiddenItemIds) {
98 super(parent, style);
99 this.editor = editor;
100 this.toolkit = editor.getFormToolkit();
101 this.resourceService = resourceService;
102 this.activityService = activityService;
103 this.userAdminService = uas;
104 this.systemWorkbenchService = systemWorkbenchService;
105 this.taskTypeId = taskTypeId;
106 this.task = task;
107
108
109 session = ConnectJcrUtils.getSession(task);
110
111 this.hiddenItemIds = hiddenItemIds;
112
113
114 myFormPart = new MyFormPart(this);
115 myFormPart.initialize(editor.getManagedForm());
116 editor.getManagedForm().addPart(myFormPart);
117 }
118
119 public void refresh() {
120 myFormPart.refresh();
121 }
122
123 private class MyFormPart extends AbstractPanelFormPart {
124
125 public MyFormPart(Composite parent) {
126 super(parent, editor, task);
127 }
128
129 @Override
130 public void commit(boolean onSave) {
131 super.commit(onSave);
132 if (onSave) {
133 ConnectJcrUtils.saveAndPublish(task, false);
134 String path = ConnectJcrUtils.getPath(task);
135 if (!modifiedPaths.contains(path))
136 modifiedPaths.add(path);
137 ConnectJcrUtils.checkPoint(ConnectJcrUtils.getSession(task), modifiedPaths, true);
138 modifiedPaths.clear();
139 }
140 }
141
142 protected void reCreateChildComposite(Composite panel, Node node) {
143 if (isEditing())
144 createEditComposite(panel);
145 else
146 createROComposite(panel);
147 refreshContent(panel, node);
148 }
149
150 protected void refreshContent(Composite parent, Node node) {
151 if (TaskBasicHeader.this.isDisposed())
152 return;
153 if (isEditing()) {
154 refreshStatusCombo(statusCmb, node);
155
156 dueDateCmp.refresh();
157 wakeUpDateCmp.refresh();
158
159 String manager = activityService.getAssignedToDisplayName(node);
160 manager += " ~ <a>Change</a>";
161 changeAssignationLk.setText(manager);
162 changeAssignationLk.getParent().layout();
163 } else {
164 statusROLbl.setText(getStatusText());
165 assignedToROLbl.setText(activityService.getAssignedToDisplayName(task));
166 }
167
168 ConnectWorkbenchUtils.refreshFormTextWidget(editor, titleTxt, task, Property.JCR_TITLE);
169 ConnectWorkbenchUtils.refreshFormTextWidget(editor, descTxt, task, Property.JCR_DESCRIPTION);
170 relatedCmp.refresh();
171
172
173
174 parent.getParent().layout(true, true);
175 }
176 }
177
178
179 private void createROComposite(Composite parent) {
180 parent.setLayout(new GridLayout(2, false));
181
182 ConnectUiUtils.createBoldLabel(toolkit, parent, "Status");
183 statusROLbl = new Label(parent, SWT.NO_FOCUS | SWT.WRAP);
184 statusROLbl.setLayoutData(EclipseUiUtils.fillWidth());
185
186 ConnectUiUtils.createBoldLabel(toolkit, parent, "Assigned to");
187 assignedToROLbl = new Label(parent, SWT.NO_FOCUS | SWT.WRAP);
188 assignedToROLbl.setLayoutData(EclipseUiUtils.fillWidth());
189
190
191
192 ConnectUiUtils.createBoldLabel(toolkit, parent, "Related to");
193 relatedCmp = new LinkListPart(editor, myFormPart, parent, SWT.NO_FOCUS, systemWorkbenchService, task,
194 ActivitiesNames.ACTIVITIES_RELATED_TO, hiddenItemIds);
195 relatedCmp.setLayoutData(EclipseUiUtils.fillWidth());
196
197
198 ConnectUiUtils.createBoldLabel(parent, "Title");
199 titleTxt = toolkit.createText(parent, "", SWT.BORDER);
200 titleTxt.setLayoutData(EclipseUiUtils.fillWidth());
201
202
203 ConnectUiUtils.createBoldLabel(parent, "Description");
204 descTxt = toolkit.createText(parent, "", SWT.BORDER);
205 descTxt.setLayoutData(EclipseUiUtils.fillWidth());
206 }
207
208
209 private void createEditComposite(Composite parent) {
210 parent.setLayout(new GridLayout(4, false));
211
212
213 ConnectUiUtils.createBoldLabel(toolkit, parent, "Status");
214 statusCmb = new Combo(parent, SWT.READ_ONLY);
215 statusCmb.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
216
217
218 ConnectUiUtils.createBoldLabel(toolkit, parent, "Due date");
219 dueDateCmp = new DateTextPart(editor, parent, SWT.NO_FOCUS, myFormPart, task,
220 ActivitiesNames.ACTIVITIES_DUE_DATE);
221 dueDateCmp.setLayoutData(EclipseUiUtils.fillWidth());
222
223
224 ConnectUiUtils.createBoldLabel(toolkit, parent, "Assigned to");
225 changeAssignationLk = new Link(parent, SWT.NONE);
226 changeAssignationLk.setLayoutData(EclipseUiUtils.fillWidth());
227
228
229 ConnectUiUtils.createBoldLabel(toolkit, parent, "Wake up date");
230 wakeUpDateCmp = new DateTextPart(editor, parent, SWT.NO_FOCUS, myFormPart, task,
231 ActivitiesNames.ACTIVITIES_WAKE_UP_DATE);
232 wakeUpDateCmp.setLayoutData(EclipseUiUtils.fillWidth());
233
234
235 ConnectUiUtils.createBoldLabel(toolkit, parent, "Related to");
236 relatedCmp = new LinkListPart(editor, myFormPart, parent, SWT.NO_FOCUS, systemWorkbenchService, task,
237 ActivitiesNames.ACTIVITIES_RELATED_TO, hiddenItemIds);
238 relatedCmp.setLayoutData(EclipseUiUtils.fillWidth(3));
239 relatedCmp.layout();
240
241
242 ConnectUiUtils.createBoldLabel(parent, "Title");
243 titleTxt = toolkit.createText(parent, "", SWT.BORDER);
244 titleTxt.setLayoutData(EclipseUiUtils.fillWidth(3));
245
246
247 ConnectUiUtils.createBoldLabel(parent, "Description");
248 descTxt = toolkit.createText(parent, "", SWT.BORDER);
249 descTxt.setLayoutData(EclipseUiUtils.fillWidth(3));
250
251
252 dueDateCmp.setFormPart(myFormPart);
253 wakeUpDateCmp.setFormPart(myFormPart);
254 addStatusCmbSelListener(myFormPart, statusCmb, task, ActivitiesNames.ACTIVITIES_TASK_STATUS,
255 PropertyType.STRING);
256 ConnectWorkbenchUtils.addModifyListener(titleTxt, task, Property.JCR_TITLE, myFormPart);
257 ConnectWorkbenchUtils.addModifyListener(descTxt, task, Property.JCR_DESCRIPTION, myFormPart);
258 addChangeAssignListener();
259 }
260
261 private String getStatusText() {
262 try {
263 StringBuilder builder = new StringBuilder();
264 String status = ConnectJcrUtils.get(task, ActivitiesNames.ACTIVITIES_TASK_STATUS);
265
266 String dueDateStr = null;
267 if (task.hasProperty(ActivitiesNames.ACTIVITIES_DUE_DATE)) {
268 Calendar dueDate = task.getProperty(ActivitiesNames.ACTIVITIES_DUE_DATE).getDate();
269 dueDateStr = dateFormat.format(dueDate.getTime());
270 }
271 builder.append(status);
272
273 if (activityService.isTaskDone(task)) {
274 String closeBy = ConnectJcrUtils.get(task, ActivitiesNames.ACTIVITIES_CLOSED_BY);
275 Calendar closedDate = task.getProperty(ActivitiesNames.ACTIVITIES_CLOSE_DATE).getDate();
276 builder.append(" - Marked as closed by ").append(userAdminService.getUserDisplayName(closeBy));
277 builder.append(" on ").append(dtFormat.format(closedDate.getTime())).append(".");
278 if (EclipseUiUtils.notEmpty(dueDateStr))
279 builder.append(" Due date was ").append(dueDateStr);
280 } else if (activityService.isTaskSleeping(task)) {
281 Calendar wakeUpDate = task.getProperty(ActivitiesNames.ACTIVITIES_WAKE_UP_DATE).getDate();
282 builder.append(" - Sleeping until ");
283 builder.append(dateFormat.format(wakeUpDate.getTime()));
284 if (EclipseUiUtils.notEmpty(dueDateStr))
285 builder.append(". Due date is ").append(dueDateStr);
286 } else if (EclipseUiUtils.notEmpty(dueDateStr))
287 builder.append(" - Due date is ").append(dueDateStr);
288
289 return builder.toString();
290 } catch (RepositoryException e) {
291 throw new ActivitiesException("Unable to get status text for task " + task, e);
292 }
293 }
294
295
296
297 protected void addStatusCmbSelListener(final AbstractFormPart part, final Combo combo, final Node entity,
298 final String propName, final int propType) {
299 combo.addSelectionListener(new SelectionAdapter() {
300 private static final long serialVersionUID = 1L;
301
302 @Override
303 public void widgetSelected(SelectionEvent e) {
304 int index = combo.getSelectionIndex();
305 if (index != -1) {
306 String newStatus = combo.getItem(index);
307 try {
308 if (activityService.updateStatus(taskTypeId, task, newStatus, modifiedPaths))
309 part.markDirty();
310 } catch (RepositoryException e1) {
311 throw new ActivitiesException("Cannot update status to " + newStatus + " for " + task, e1);
312 }
313 }
314
315 }
316 });
317 }
318
319
320 protected void refreshStatusCombo(Combo combo, Node currTask) {
321 List<String> values = resourceService.getTemplateCatalogue(session, taskTypeId,
322 ActivitiesNames.ACTIVITIES_TASK_STATUS, null);
323 combo.setItems(values.toArray(new String[values.size()]));
324 ConnectWorkbenchUtils.refreshFormCombo(editor, combo, currTask, ActivitiesNames.ACTIVITIES_TASK_STATUS);
325 combo.setEnabled(editor.isEditing());
326 }
327
328 private void addChangeAssignListener() {
329 changeAssignationLk.addSelectionListener(new SelectionAdapter() {
330 private static final long serialVersionUID = 1L;
331
332 @Override
333 public void widgetSelected(final SelectionEvent event) {
334 try {
335 PickUpUserDialog diag = new PickUpUserDialog(changeAssignationLk.getShell(), "Choose a group",
336 userAdminService.getUserAdmin());
337 int result = diag.open();
338 if (Window.OK == result) {
339 User newGroup = diag.getSelected();
340 if (newGroup == null)
341 return;
342
343 String newGroupName = newGroup.getName();
344 if (newGroupName.equals(assignedToGroupId))
345 return;
346 else {
347
348 task.setProperty(ActivitiesNames.ACTIVITIES_ASSIGNED_TO, newGroupName);
349
350 assignedToGroupId = newGroupName;
351 changeAssignationLk
352 .setText(userAdminService.getUserDisplayName(newGroupName) + " ~ <a>Change</a>");
353 myFormPart.markDirty();
354 }
355 }
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376 } catch (RepositoryException re) {
377 throw new ActivitiesException("Unable to change assignation for node " + task, re);
378 }
379 }
380 });
381 }
382 }