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