View Javadoc
1   package org.argeo.tracker.ui.dialogs;
2   
3   import static org.argeo.eclipse.ui.EclipseUiUtils.isEmpty;
4   
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.RepositoryException;
12  
13  import org.argeo.activities.ActivitiesNames;
14  import org.argeo.activities.ActivitiesService;
15  import org.argeo.activities.ActivitiesTypes;
16  import org.argeo.connect.UserAdminService;
17  import org.argeo.connect.core.OfficeRole;
18  import org.argeo.connect.ui.AppWorkbenchService;
19  import org.argeo.connect.ui.ConnectUiUtils;
20  import org.argeo.connect.ui.widgets.DateText;
21  import org.argeo.connect.ui.widgets.GroupDropDown;
22  import org.argeo.connect.util.ConnectJcrUtils;
23  import org.argeo.eclipse.ui.EclipseUiUtils;
24  import org.argeo.tracker.TrackerException;
25  import org.argeo.tracker.TrackerNames;
26  import org.argeo.tracker.TrackerService;
27  import org.argeo.tracker.TrackerTypes;
28  import org.argeo.tracker.core.TrackerUtils;
29  import org.argeo.tracker.ui.controls.MilestoneDropDown;
30  import org.argeo.tracker.ui.controls.ProjectDropDown;
31  import org.argeo.tracker.ui.controls.RelatedToList;
32  import org.eclipse.jface.dialogs.MessageDialog;
33  import org.eclipse.jface.wizard.Wizard;
34  import org.eclipse.jface.wizard.WizardPage;
35  import org.eclipse.swt.SWT;
36  import org.eclipse.swt.events.FocusAdapter;
37  import org.eclipse.swt.events.FocusEvent;
38  import org.eclipse.swt.layout.GridData;
39  import org.eclipse.swt.layout.GridLayout;
40  import org.eclipse.swt.widgets.Combo;
41  import org.eclipse.swt.widgets.Composite;
42  import org.eclipse.swt.widgets.Label;
43  import org.eclipse.swt.widgets.Text;
44  
45  /**
46   * Generic wizard to configure an tracker:task
47   * 
48   * Warning: the passed session is not saved to enable roll-back: all changes are
49   * only transient until the caller saves the session
50   */
51  
52  public class ConfigureTaskWizard extends Wizard {
53  	// private final static Log log = LogFactory.getLog(NewIssueWizard.class);
54  
55  	private final UserAdminService userAdminService;
56  	private final TrackerService trackerService;
57  	private final ActivitiesService activitiesService;
58  	private final AppWorkbenchService appWorkbenchService;
59  	private final Node project;
60  	private final Node task;
61  
62  	// Business objects
63  	private Node chosenProject;
64  
65  	// This page widgets
66  	private ProjectDropDown projectDD;
67  	private MilestoneDropDown milestoneDD;
68  	private Text titleTxt;
69  	private GroupDropDown assignedToDD;
70  	private DateText dueDateCmp;
71  	// TODO add wake up date management
72  	// private DateText wakeUpDateCmp;
73  	private Combo importanceCmb;
74  	private Combo priorityCmb;
75  	private RelatedToList relatedToCmp;
76  	private Text descTxt;
77  
78  	public ConfigureTaskWizard(UserAdminService userAdminService, ActivitiesService activitiesService,
79  			TrackerService trackerService, AppWorkbenchService appWorkbenchService, Node draftEntity) {
80  		this.userAdminService = userAdminService;
81  		this.trackerService = trackerService;
82  		this.activitiesService = activitiesService;
83  		this.appWorkbenchService = appWorkbenchService;
84  		this.task = draftEntity;
85  		project = TrackerUtils.getRelatedProject(trackerService, task);
86  		chosenProject = project;
87  	}
88  
89  	@Override
90  	public void addPages() {
91  		setWindowTitle("Task configuration");
92  		addPage(new ConfigureTaskPage("Main page"));
93  	}
94  
95  	@Override
96  	public boolean performFinish() {
97  		String msg = null;
98  		String title = titleTxt.getText();
99  		if (chosenProject == null && ConnectJcrUtils.isNodeType(task, TrackerTypes.TRACKER_TASK))
100 			msg = "Please pick up a project";
101 		else if (isEmpty(title))
102 			msg = "Please give at least a title";
103 
104 		if (msg != null) {
105 			MessageDialog.openError(getShell(), "Uncomplete information", msg);
106 			return false;
107 		}
108 
109 		try {
110 			// TODO implement a cleaner overwritting of default
111 			// ActivitiesService task creation
112 			if (ConnectJcrUtils.isNodeType(task, ActivitiesTypes.ACTIVITIES_TASK)
113 					&& !ConnectJcrUtils.isNodeType(task, TrackerTypes.TRACKER_TASK)) {
114 				if (chosenProject == null)
115 					// simple task
116 					activitiesService.configureTask(task, ActivitiesTypes.ACTIVITIES_TASK, title, descTxt.getText(),
117 							assignedToDD.getText());
118 
119 				else {
120 					task.addMixin(TrackerTypes.TRACKER_TASK);
121 					trackerService.configureTask(task, chosenProject, milestoneDD.getChosenMilestone(), title,
122 							descTxt.getText(), assignedToDD.getText()); // priority,
123 				}
124 			} else
125 				trackerService.configureTask(task, chosenProject, milestoneDD.getChosenMilestone(), title,
126 						descTxt.getText(), assignedToDD.getText()); // priority,
127 
128 			// Additionnal values
129 			String importanceStr = TrackerUtils.getKeyByValue(TrackerUtils.MAPS_ISSUE_IMPORTANCES,
130 					importanceCmb.getText());
131 			int importance = new Integer(importanceStr).intValue();
132 			task.setProperty(TrackerNames.TRACKER_IMPORTANCE, importance);
133 
134 			String priorityStr = TrackerUtils.getKeyByValue(TrackerUtils.MAPS_ISSUE_PRIORITIES, priorityCmb.getText());
135 			int priority = new Integer(priorityStr).intValue();
136 			task.setProperty(TrackerNames.TRACKER_PRIORITY, priority);
137 
138 			Calendar dueDate = dueDateCmp.getCalendar();
139 			if (dueDate != null)
140 				task.setProperty(ActivitiesNames.ACTIVITIES_DUE_DATE, dueDate);
141 
142 			// Calendar wakeUpDate = wakeUpDateCmp.getCalendar();
143 			// if (wakeUpDate != null) {
144 			// task.setProperty(ActivitiesNames.ACTIVITIES_WAKE_UP_DATE,
145 			// wakeUpDate);
146 			// }
147 			if (relatedToCmp != null) {
148 				List<String> relatedTos = relatedToCmp.getChosenValues();
149 				if (relatedTos != null && !relatedTos.isEmpty()) {
150 					List<Node> nodes = new ArrayList<>();
151 					for (String uid : relatedTos) {
152 						nodes.add(ConnectJcrUtils.getNodeByIdentifier(task, uid));
153 					}
154 					ConnectJcrUtils.setMultipleReferences(task, ActivitiesNames.ACTIVITIES_RELATED_TO, nodes);
155 				}
156 			}
157 		} catch (RepositoryException e) {
158 			throw new TrackerException("Unable to create issue on project " + project, e);
159 		}
160 		return true;
161 	}
162 
163 	@Override
164 	public boolean performCancel() {
165 		return true;
166 	}
167 
168 	@Override
169 	public boolean canFinish() {
170 		return true;
171 	}
172 
173 	protected class ConfigureTaskPage extends WizardPage {
174 		private static final long serialVersionUID = -4341854690472102086L;
175 
176 		private Text projectTxt;
177 
178 		public ConfigureTaskPage(String pageName) {
179 			super(pageName);
180 			setMessage("Please complete below information.");
181 		}
182 
183 		public void createControl(Composite parent) {
184 			parent.setLayout(new GridLayout(4, false));
185 
186 			// Project
187 			ConnectUiUtils.createBoldLabel(parent, "Project");
188 			projectTxt = new Text(parent, SWT.BORDER);
189 			projectTxt.setMessage("Choose a relevant project");
190 			GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
191 			gd.horizontalSpan = 3;
192 			projectTxt.setLayoutData(gd);
193 
194 			if (project == null) {
195 				projectDD = new ProjectDropDown(ConnectJcrUtils.getSession(task), projectTxt, false);
196 
197 				projectTxt.addFocusListener(new FocusAdapter() {
198 					private static final long serialVersionUID = 1719432159240562984L;
199 
200 					@Override
201 					public void focusLost(FocusEvent event) {
202 						Node project = projectDD.getChosenProject();
203 						if (project == null)
204 							setErrorMessage("Choose a valid project");
205 						else {
206 							setErrorMessage(null);
207 							chosenProject = project;
208 							milestoneDD.setProject(chosenProject);
209 						}
210 					}
211 				});
212 			} else
213 				projectTxt.setEditable(false);
214 
215 			// Target milestone
216 			ConnectUiUtils.createBoldLabel(parent, "Milestone");
217 			Text milestoneTxt = new Text(parent, SWT.BORDER);
218 			milestoneTxt.setMessage("Choose a milestone");
219 			gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
220 			milestoneTxt.setLayoutData(gd);
221 			milestoneDD = new MilestoneDropDown(ConnectJcrUtils.getSession(task), milestoneTxt, false);
222 			if (project != null)
223 				milestoneDD.setProject(project);
224 
225 			// Title
226 			ConnectUiUtils.createBoldLabel(parent, "Title");
227 			titleTxt = new Text(parent, SWT.BORDER);
228 			titleTxt.setMessage("A precise and concise description of the task");
229 			gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
230 			gd.horizontalSpan = 3;
231 			titleTxt.setLayoutData(gd);
232 
233 			// Assigned to
234 			Text assignedToTxt = createBoldLT(parent, "Assigned to", "Choose a group or a person",
235 					"Pick up the group or person that will be responsible for doing this task", 1);
236 			assignedToDD = new GroupDropDown(assignedToTxt, userAdminService, OfficeRole.coworker.dn());
237 
238 			// DUE DATE
239 			ConnectUiUtils.createBoldLabel(parent, "Due date");
240 			dueDateCmp = new DateText(parent, SWT.NO_FOCUS);
241 
242 			// // WAKE UP DATE
243 			// Label lbl = ConnectWorkbenchUtils.createBoldLabel(parent, "Wake
244 			// up date");
245 			// gd = new GridData();
246 			// gd.horizontalIndent = 15;
247 			// lbl.setLayoutData(gd);
248 			// wakeUpDateCmp = new DateText(parent, SWT.NO_FOCUS);
249 
250 			// Importance
251 			ConnectUiUtils.createBoldLabel(parent, "Importance");
252 			importanceCmb = new Combo(parent, SWT.READ_ONLY);
253 			gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
254 			importanceCmb.setLayoutData(gd);
255 			importanceCmb.setItems(TrackerUtils.MAPS_ISSUE_IMPORTANCES.values().toArray(new String[0]));
256 			importanceCmb.select(0);
257 
258 			// Priority
259 			ConnectUiUtils.createBoldLabel(parent, "Priority");
260 			priorityCmb = new Combo(parent, SWT.READ_ONLY);
261 			gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
262 			priorityCmb.setLayoutData(gd);
263 			priorityCmb.setItems(TrackerUtils.MAPS_ISSUE_PRIORITIES.values().toArray(new String[0]));
264 			priorityCmb.select(0);
265 
266 			// Related to list
267 			// TODO we do not yet have access to the AppWorkbenchService when
268 			// creating a task from the coolbar via Eclipse command mechanism
269 			if (appWorkbenchService != null) {
270 				ConnectUiUtils.createBoldLabel(parent, "Related to");
271 				relatedToCmp = new RelatedToList(parent, SWT.NO_FOCUS, task, ActivitiesNames.ACTIVITIES_RELATED_TO,
272 						appWorkbenchService);
273 				relatedToCmp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
274 			}
275 			// Description
276 			Label label = new Label(parent, SWT.LEAD | SWT.TOP);
277 			label.setText("Description");
278 			label.setFont(EclipseUiUtils.getBoldFont(parent));
279 			gd = new GridData(SWT.LEAD, SWT.TOP, false, false);
280 			label.setLayoutData(gd);
281 			descTxt = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP);
282 			descTxt.setMessage("A longer description");
283 			gd = EclipseUiUtils.fillAll();
284 			gd.horizontalSpan = 3;
285 			gd.heightHint = 150;
286 			descTxt.setLayoutData(gd);
287 
288 			Node milestone = null;
289 			// Initialise
290 			try {
291 				if (task.hasProperty(Property.JCR_TITLE))
292 					titleTxt.setText(task.getProperty(Property.JCR_TITLE).getString());
293 				if (task.hasProperty(Property.JCR_DESCRIPTION))
294 					descTxt.setText(task.getProperty(Property.JCR_DESCRIPTION).getString());
295 				if (project != null)
296 					projectTxt.setText(ConnectJcrUtils.get(project, Property.JCR_TITLE));
297 
298 				// if
299 				// (task.hasProperty(ActivitiesNames.ACTIVITIES_WAKE_UP_DATE))
300 				// wakeUpDateCmp.setText(task.getProperty(ActivitiesNames.ACTIVITIES_WAKE_UP_DATE).getDate());
301 				String muid = ConnectJcrUtils.get(task, TrackerNames.TRACKER_MILESTONE_UID);
302 				if (EclipseUiUtils.notEmpty(muid)) {
303 					milestone = trackerService.getEntityByUid(ConnectJcrUtils.getSession(task), null, muid);
304 					milestoneDD.resetMilestone(milestone);
305 				}
306 
307 				if (task.hasProperty(ActivitiesNames.ACTIVITIES_ASSIGNED_TO))
308 					assignedToDD.resetDN(task.getProperty(ActivitiesNames.ACTIVITIES_ASSIGNED_TO).getString());
309 				else if (milestone != null && milestone.hasProperty(TrackerNames.TRACKER_DEFAULT_ASSIGNEE))
310 					assignedToDD.resetDN(milestone.getProperty(TrackerNames.TRACKER_DEFAULT_ASSIGNEE).getString());
311 
312 				if (task.hasProperty(ActivitiesNames.ACTIVITIES_DUE_DATE))
313 					dueDateCmp.setText(task.getProperty(ActivitiesNames.ACTIVITIES_DUE_DATE).getDate());
314 				else if (milestone != null && milestone.hasProperty(TrackerNames.TRACKER_TARGET_DATE))
315 					dueDateCmp.setText(milestone.getProperty(TrackerNames.TRACKER_TARGET_DATE).getDate());
316 
317 				Long importance = ConnectJcrUtils.getLongValue(task, TrackerNames.TRACKER_IMPORTANCE);
318 				if (importance != null) {
319 					String iv = TrackerUtils.MAPS_ISSUE_IMPORTANCES.get(importance.toString());
320 					importanceCmb.setText(iv);
321 				}
322 				Long priority = ConnectJcrUtils.getLongValue(task, TrackerNames.TRACKER_PRIORITY);
323 				if (priority != null) {
324 					String iv = TrackerUtils.MAPS_ISSUE_PRIORITIES.get(priority.toString());
325 					priorityCmb.setText(iv);
326 				}
327 
328 			} catch (RepositoryException e) {
329 				throw new TrackerException("Cannot initialise widgets with existing data on " + task, e);
330 			}
331 
332 			milestoneTxt.addFocusListener(new FocusAdapter() {
333 				private static final long serialVersionUID = 1719432159240562984L;
334 
335 				@Override
336 				public void focusLost(FocusEvent event) {
337 					Node milestone = milestoneDD.getChosenMilestone();
338 					if (milestone != null) {
339 						try {
340 							if (EclipseUiUtils.isEmpty(assignedToDD.getText())
341 									&& milestone.hasProperty(TrackerNames.TRACKER_DEFAULT_ASSIGNEE))
342 								assignedToDD.resetDN(
343 										milestone.getProperty(TrackerNames.TRACKER_DEFAULT_ASSIGNEE).getString());
344 							if (dueDateCmp.getCalendar() == null
345 									&& milestone.hasProperty(TrackerNames.TRACKER_TARGET_DATE))
346 								dueDateCmp.setText(milestone.getProperty(TrackerNames.TRACKER_TARGET_DATE).getDate());
347 						} catch (RepositoryException e) {
348 							throw new TrackerException("Cannot set default values for milestone " + milestone, e);
349 						}
350 					}
351 				}
352 			});
353 
354 			// Don't forget this.
355 			if (project == null) {
356 				setControl(projectTxt);
357 				projectTxt.setFocus();
358 			} else if (milestone == null) {
359 				setControl(milestoneTxt);
360 				milestoneTxt.setFocus();
361 			} else {
362 				setControl(titleTxt);
363 				titleTxt.setFocus();
364 			}
365 		}
366 	}
367 
368 	private Text createBoldLT(Composite parent, String title, String message, String tooltip, int colspan) {
369 		ConnectUiUtils.createBoldLabel(parent, title);
370 		Text text = new Text(parent, SWT.BOTTOM | SWT.BORDER);
371 		text.setLayoutData(EclipseUiUtils.fillAll(colspan, 1));
372 		text.setMessage(message);
373 		text.setToolTipText(tooltip);
374 		return text;
375 	}
376 }