1 package org
.argeo
.suite
.workbench
.parts
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Calendar
;
5 import java
.util
.GregorianCalendar
;
9 import javax
.jcr
.NodeIterator
;
10 import javax
.jcr
.Property
;
11 import javax
.jcr
.RepositoryException
;
13 import org
.apache
.commons
.logging
.Log
;
14 import org
.apache
.commons
.logging
.LogFactory
;
15 import org
.argeo
.activities
.ActivitiesNames
;
16 import org
.argeo
.activities
.ActivitiesService
;
17 import org
.argeo
.activities
.workbench
.parts
.TaskViewerContextMenu
;
18 import org
.argeo
.cms
.auth
.CurrentUser
;
19 import org
.argeo
.cms
.ui
.workbench
.util
.CommandUtils
;
20 import org
.argeo
.cms
.util
.CmsUtils
;
21 import org
.argeo
.connect
.ConnectNames
;
22 import org
.argeo
.connect
.ui
.ConnectUiUtils
;
23 import org
.argeo
.connect
.util
.ConnectJcrUtils
;
24 import org
.argeo
.connect
.workbench
.Refreshable
;
25 import org
.argeo
.connect
.workbench
.commands
.OpenEntityEditor
;
26 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
27 import org
.argeo
.jcr
.JcrUtils
;
28 import org
.argeo
.node
.NodeUtils
;
29 import org
.argeo
.suite
.SuiteException
;
30 import org
.argeo
.suite
.workbench
.AsUiPlugin
;
31 import org
.argeo
.tracker
.TrackerNames
;
32 import org
.argeo
.tracker
.TrackerService
;
33 import org
.argeo
.tracker
.TrackerTypes
;
34 import org
.argeo
.tracker
.core
.TrackerUtils
;
35 import org
.argeo
.tracker
.ui
.TaskListLabelProvider
;
36 import org
.argeo
.tracker
.ui
.TaskVirtualListComposite
;
37 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
38 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
39 import org
.eclipse
.jface
.viewers
.TableViewer
;
40 import org
.eclipse
.swt
.SWT
;
41 import org
.eclipse
.swt
.events
.MouseAdapter
;
42 import org
.eclipse
.swt
.events
.MouseEvent
;
43 import org
.eclipse
.swt
.events
.SelectionAdapter
;
44 import org
.eclipse
.swt
.events
.SelectionEvent
;
45 import org
.eclipse
.swt
.graphics
.Color
;
46 import org
.eclipse
.swt
.graphics
.Point
;
47 import org
.eclipse
.swt
.layout
.GridData
;
48 import org
.eclipse
.swt
.layout
.GridLayout
;
49 import org
.eclipse
.swt
.layout
.RowLayout
;
50 import org
.eclipse
.swt
.widgets
.Composite
;
51 import org
.eclipse
.swt
.widgets
.Display
;
52 import org
.eclipse
.swt
.widgets
.Group
;
53 import org
.eclipse
.swt
.widgets
.Label
;
54 import org
.eclipse
.swt
.widgets
.Link
;
56 /** Argeo Suite Default Dashboard */
57 public class DefaultDashboardEditor
extends AbstractSuiteDashboard
implements Refreshable
{
58 final static Log log
= LogFactory
.getLog(DefaultDashboardEditor
.class);
59 public final static String ID
= AsUiPlugin
.PLUGIN_ID
+ ".defaultDashboardEditor";
61 private ActivitiesService activitiesService
;
62 private TrackerService trackerService
;
64 private String datePattern
= "dd MMM yyyy";
66 private Composite headerCmp
;
67 private Composite taskListCmp
;
68 private TaskVirtualListComposite tvlc
;
71 public void createPartControl(Composite parent
) {
72 super.createPartControl(parent
);
73 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
74 Composite bodyCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
75 bodyCmp
.setLayoutData(EclipseUiUtils
.fillAll());
76 bodyCmp
.setLayout(new GridLayout());
78 headerCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
79 headerCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
81 taskListCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
82 taskListCmp
.setLayoutData(EclipseUiUtils
.fillAll());
87 public void forceRefresh(Object object
) {
88 CmsUtils
.clear(headerCmp
);
89 populateHeaderPart(headerCmp
, NodeUtils
.getUserHome(getSession()));
91 CmsUtils
.clear(taskListCmp
);
92 populateTaskListCmp(taskListCmp
);
94 headerCmp
.getParent().layout(true, true);
97 private void populateTaskListCmp(Composite parent
) {
98 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
99 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
100 if (!nit
.hasNext()) {
101 Composite noTaskCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
102 noTaskCmp
.setLayoutData(EclipseUiUtils
.fillAll());
103 noTaskCmp
.setLayout(new GridLayout());
105 Label noTaskLbl
= new Label(noTaskCmp
, SWT
.CENTER
);
106 noTaskLbl
.setText("<i> <big> You have no pending Task. </big> </i>");
107 CmsUtils
.markup(noTaskLbl
);
108 noTaskLbl
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.BOTTOM
, true, true));
110 final Link createTaskLk
= new Link(noTaskCmp
, SWT
.CENTER
);
111 createTaskLk
.setText("<a> Create a task </a>");
112 createTaskLk
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.TOP
, true, true));
114 createTaskLk
.addSelectionListener(new SelectionAdapter() {
115 private static final long serialVersionUID
= -9028457805156989935L;
118 public void widgetSelected(SelectionEvent e
) {
119 String mainMixin
= TrackerTypes
.TRACKER_TASK
;
120 String pathCreated
= ConnectUiUtils
.createAndConfigureEntity(createTaskLk
.getShell(), getSession(),
121 getSystemAppService(), getSystemWorkbenchService(), mainMixin
);
122 if (EclipseUiUtils
.notEmpty(pathCreated
))
128 TaskListLabelProvider labelProvider
= new TaskListLabelProvider(trackerService
);
129 tvlc
= new TaskVirtualListComposite(parent
, SWT
.NO_FOCUS
, labelProvider
, 54);
130 tvlc
.setLayoutData(EclipseUiUtils
.fillAll());
131 final TableViewer viewer
= tvlc
.getTableViewer();
132 viewer
.setInput(JcrUtils
.nodeIteratorToList(nit
).toArray());
133 final TaskViewerContextMenu contextMenu
= new TaskViewerContextMenu(viewer
, getSession(),
135 private static final long serialVersionUID
= 1640863021424194303L;
138 public boolean performAction(String actionId
) {
139 boolean hasChanged
= super.performAction(actionId
);
141 viewer
.getTable().setFocus();
143 // NodeIterator nit =
144 // activitiesService.getMyTasks(getSession(), true);
145 // viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray());
150 viewer
.getTable().addMouseListener(new MouseAdapter() {
151 private static final long serialVersionUID
= 6737579410648595940L;
154 public void mouseDown(MouseEvent e
) {
156 // contextMenu.setCurrFolderPath(currDisplayedFolder);
157 contextMenu
.show(viewer
.getTable(), new Point(e
.x
, e
.y
),
158 (IStructuredSelection
) viewer
.getSelection());
166 private boolean isOverdue(Node node
, String propName
) {
168 Calendar now
= GregorianCalendar
.getInstance();
169 return node
.hasProperty(propName
) && node
.getProperty(propName
).getDate().before(now
);
170 } catch (RepositoryException e
) {
171 throw new SuiteException("Cannot check overdue status with property " + propName
+ " on " + node
, e
);
175 private void populateHeaderPart(Composite bodyCmp
, Node context
) {
176 bodyCmp
.setLayout(EclipseUiUtils
.noSpaceGridLayout(new GridLayout(2, true)));
178 Composite leftCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
179 leftCmp
.setLayout(new GridLayout());
180 leftCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
181 Composite rightCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
182 rightCmp
.setLayout(new GridLayout());
183 rightCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
186 Label titleLbl
= new Label(leftCmp
, SWT
.WRAP
| SWT
.LEAD
);
187 CmsUtils
.markup(titleLbl
);
188 String titleStr
= "<big><b> Hello " + CurrentUser
.getDisplayName() + " </b></big>";
189 titleLbl
.setText(titleStr
);
190 GridData gd
= new GridData(SWT
.TOP
, SWT
.BOTTOM
, false, false);
191 gd
.verticalIndent
= 5;
192 gd
.horizontalIndent
= 10;
193 titleLbl
.setLayoutData(gd
);
195 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
197 List
<Node
> overdueTasks
= new ArrayList
<>();
198 while (nit
.hasNext()) {
199 Node currNode
= nit
.nextNode();
200 if (isOverdue(currNode
, ActivitiesNames
.ACTIVITIES_DUE_DATE
))
201 overdueTasks
.add(currNode
);
203 if (!overdueTasks
.isEmpty()) {
204 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
205 long size
= overdueTasks
.size();
206 String overdueStr
= "You have " + size
+ " overdue task" + (size
> 1 ?
"s" : "") + ": ";
207 populateMuliValueClickableList(overdueCmp
, overdueTasks
.toArray(new Node
[0]), new TaskLp(), overdueStr
);
211 nit
= trackerService
.getMyMilestones(getSession(), true);
212 List
<Node
> openMilestones
= new ArrayList
<>();
215 List
<Node
> overdueMilestones
= new ArrayList
<>();
216 while (nit
.hasNext()) {
217 Node currNode
= nit
.nextNode();
218 openMilestones
.add(currNode
);
219 if (isOverdue(currNode
, TrackerNames
.TRACKER_TARGET_DATE
))
220 overdueMilestones
.add(currNode
);
222 if (!overdueMilestones
.isEmpty()) {
223 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
224 long size
= overdueMilestones
.size();
225 String overdueStr
= "You have " + size
+ " overdue milestone" + (size
> 1 ?
"s" : "") + ": ";
226 populateMuliValueClickableList(overdueCmp
, overdueMilestones
.toArray(new Node
[0]), new MilestoneLp(),
232 List
<Node
> openProjects
= JcrUtils
.nodeIteratorToList(trackerService
.getMyProjects(getSession(), true));
233 if (!openProjects
.isEmpty()) {
234 Group myProjectsGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
235 myProjectsGp
.setText("My open projects");
236 myProjectsGp
.setLayoutData(EclipseUiUtils
.fillWidth());
237 populateMuliValueClickableList(myProjectsGp
, openProjects
.toArray(new Node
[0]), new ProjectLp(), null);
241 if (!openMilestones
.isEmpty()) {
242 Group myMilestoneGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
243 myMilestoneGp
.setText("My open milestones");
244 myMilestoneGp
.setLayoutData(EclipseUiUtils
.fillWidth());
245 populateMuliValueClickableList(myMilestoneGp
, openMilestones
.toArray(new Node
[0]), new MilestoneLp(), null);
249 private class ProjectLp
extends ColumnLabelProvider
{
250 private static final long serialVersionUID
= 7231233932794865555L;
253 public String
getText(Object element
) {
254 Node project
= (Node
) element
;
257 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, null, null, true);
258 long openNb
= nit
.getSize();
260 nit
= TrackerUtils
.getIssues(project
, null, null, null, false);
261 long allNb
= nit
.getSize();
266 double num
= allNb
- openNb
;
267 double result
= num
/ allNb
* 100;
268 percent
= String
.format("%.1f", result
) + "% done";
270 StringBuilder builder
= new StringBuilder();
271 builder
.append("<a>").append(ConnectJcrUtils
.get(project
, Property
.JCR_TITLE
)).append("</a>");
272 builder
.append(" (").append(percent
).append(")");
274 return builder
.toString();
278 private class MilestoneLp
extends ColumnLabelProvider
{
279 private static final long serialVersionUID
= 7231233932794865555L;
282 public String
getText(Object element
) {
283 Node milestone
= (Node
) element
;
284 Node project
= TrackerUtils
.getRelatedProject(trackerService
, milestone
);
285 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(milestone
, TrackerNames
.TRACKER_TARGET_DATE
,
289 String propName
= TrackerNames
.TRACKER_MILESTONE_UID
;
290 String muid
= ConnectJcrUtils
.get(milestone
, ConnectNames
.CONNECT_UID
);
291 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, true);
292 long openNb
= nit
.getSize();
294 nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, false);
295 long allNb
= nit
.getSize();
300 double num
= allNb
- openNb
;
301 double result
= num
/ allNb
* 100;
302 percent
= String
.format("%.1f", result
) + "% done";
304 StringBuilder builder
= new StringBuilder();
305 builder
.append("<a>").append(ConnectJcrUtils
.get(milestone
, Property
.JCR_TITLE
)).append("</a>");
306 builder
.append(" (");
307 if (EclipseUiUtils
.notEmpty(dueDate
))
308 builder
.append("due to ").append(dueDate
).append(", ");
310 builder
.append(percent
).append(")");
311 return builder
.toString();
315 public Color
getForeground(Object element
) {
316 Node milestone
= (Node
) element
;
317 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
318 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
319 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
324 private class TaskLp
extends ColumnLabelProvider
{
325 private static final long serialVersionUID
= 7231233932794865555L;
328 public String
getText(Object element
) {
329 Node task
= (Node
) element
;
330 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(task
, ActivitiesNames
.ACTIVITIES_DUE_DATE
,
333 StringBuilder builder
= new StringBuilder();
334 builder
.append("<a>").append(ConnectJcrUtils
.get(task
, Property
.JCR_TITLE
)).append("</a>");
335 if (EclipseUiUtils
.notEmpty(dueDate
))
336 builder
.append(" (").append("due to ").append(dueDate
).append(")");
337 return builder
.toString();
341 public Color
getForeground(Object element
) {
342 Node milestone
= (Node
) element
;
343 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
344 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
345 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
351 public void setFocus() {
352 // refreshDocListGadget();
355 public void setActivitiesService(ActivitiesService activitiesService
) {
356 this.activitiesService
= activitiesService
;
359 public void setTrackerService(TrackerService trackerService
) {
360 this.trackerService
= trackerService
;
364 private void populateMuliValueClickableList(Composite parent
, Node
[] nodes
, ColumnLabelProvider lp
,
366 CmsUtils
.clear(parent
);
367 RowLayout rl
= new RowLayout(SWT
.HORIZONTAL
| SWT
.WRAP
);
369 rl
.marginLeft
= rl
.marginTop
= rl
.marginBottom
= 0;
371 parent
.setLayout(rl
);
373 if (EclipseUiUtils
.notEmpty(listLabel
)) {
374 Link link
= new Link(parent
, SWT
.NONE
);
375 link
.setText(listLabel
);
376 link
.setFont(EclipseUiUtils
.getBoldFont(parent
));
380 for (Node node
: nodes
) {
381 Link link
= new Link(parent
, SWT
.NONE
);
382 CmsUtils
.markup(link
);
383 link
.setText(lp
.getText(node
) + (i
!= nodes
.length ?
", " : ""));
385 // Color fc = lp.getForeground(node);
387 // link.setForeground(fc);
389 link
.addSelectionListener(new SelectionAdapter() {
390 private static final long serialVersionUID
= 1L;
393 public void widgetSelected(final SelectionEvent event
) {
394 CommandUtils
.callCommand(getSystemWorkbenchService().getOpenEntityEditorCmdId(),
395 OpenEntityEditor
.PARAM_JCR_ID
, ConnectJcrUtils
.getIdentifier(node
));