1 package org
.argeo
.suite
.e4
.parts
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Calendar
;
5 import java
.util
.GregorianCalendar
;
8 import javax
.annotation
.PostConstruct
;
9 import javax
.inject
.Inject
;
10 import javax
.jcr
.Node
;
11 import javax
.jcr
.NodeIterator
;
12 import javax
.jcr
.Property
;
13 import javax
.jcr
.RepositoryException
;
15 import org
.apache
.commons
.logging
.Log
;
16 import org
.apache
.commons
.logging
.LogFactory
;
17 import org
.argeo
.activities
.ActivitiesNames
;
18 import org
.argeo
.activities
.ActivitiesService
;
19 import org
.argeo
.activities
.ui
.TaskViewerContextMenu
;
20 import org
.argeo
.cms
.auth
.CurrentUser
;
21 import org
.argeo
.cms
.util
.CmsUtils
;
22 import org
.argeo
.connect
.ConnectException
;
23 import org
.argeo
.connect
.ConnectNames
;
24 import org
.argeo
.connect
.ui
.ConnectWorkbenchUtils
;
25 import org
.argeo
.connect
.ui
.Refreshable
;
26 import org
.argeo
.connect
.util
.ConnectJcrUtils
;
27 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
28 import org
.argeo
.jcr
.JcrUtils
;
29 import org
.argeo
.node
.NodeUtils
;
30 import org
.argeo
.tracker
.TrackerNames
;
31 import org
.argeo
.tracker
.TrackerService
;
32 import org
.argeo
.tracker
.TrackerTypes
;
33 import org
.argeo
.tracker
.core
.TrackerUtils
;
34 import org
.argeo
.tracker
.ui
.TaskListLabelProvider
;
35 import org
.argeo
.tracker
.ui
.TaskVirtualListComposite
;
36 import org
.eclipse
.e4
.ui
.di
.Focus
;
37 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
38 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
39 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
40 import org
.eclipse
.jface
.viewers
.TableViewer
;
41 import org
.eclipse
.swt
.SWT
;
42 import org
.eclipse
.swt
.events
.MouseAdapter
;
43 import org
.eclipse
.swt
.events
.MouseEvent
;
44 import org
.eclipse
.swt
.events
.SelectionAdapter
;
45 import org
.eclipse
.swt
.events
.SelectionEvent
;
46 import org
.eclipse
.swt
.graphics
.Color
;
47 import org
.eclipse
.swt
.graphics
.Point
;
48 import org
.eclipse
.swt
.layout
.GridData
;
49 import org
.eclipse
.swt
.layout
.GridLayout
;
50 import org
.eclipse
.swt
.layout
.RowLayout
;
51 import org
.eclipse
.swt
.widgets
.Composite
;
52 import org
.eclipse
.swt
.widgets
.Display
;
53 import org
.eclipse
.swt
.widgets
.Group
;
54 import org
.eclipse
.swt
.widgets
.Label
;
55 import org
.eclipse
.swt
.widgets
.Link
;
57 /** Argeo Suite Default Dashboard */
58 public class DefaultDashboardEditor
extends AbstractSuiteDashboard
implements Refreshable
{
59 final static Log log
= LogFactory
.getLog(DefaultDashboardEditor
.class);
60 // public final static String ID = AsUiPlugin.PLUGIN_ID +
61 // ".defaultDashboardEditor";
64 private ActivitiesService activitiesService
;
66 private TrackerService trackerService
;
68 private String datePattern
= "dd MMM yyyy";
70 private Composite headerCmp
;
71 private Composite taskListCmp
;
72 private TaskVirtualListComposite tvlc
;
75 public void createPartControl(Composite parent
) {
76 super.createPartControl(parent
);
77 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
78 Composite bodyCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
79 bodyCmp
.setLayoutData(EclipseUiUtils
.fillAll());
80 bodyCmp
.setLayout(new GridLayout());
82 headerCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
83 headerCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
85 taskListCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
86 taskListCmp
.setLayoutData(EclipseUiUtils
.fillAll());
91 public void forceRefresh(Object object
) {
92 CmsUtils
.clear(headerCmp
);
93 populateHeaderPart(headerCmp
, NodeUtils
.getUserHome(getSession()));
95 CmsUtils
.clear(taskListCmp
);
96 populateTaskListCmp(taskListCmp
);
98 headerCmp
.getParent().layout(true, true);
101 private void populateTaskListCmp(Composite parent
) {
102 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
103 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
104 if (!nit
.hasNext()) {
105 Composite noTaskCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
106 noTaskCmp
.setLayoutData(EclipseUiUtils
.fillAll());
107 noTaskCmp
.setLayout(new GridLayout());
109 Label noTaskLbl
= new Label(noTaskCmp
, SWT
.CENTER
);
110 noTaskLbl
.setText("<i> <big> You have no pending Task. </big> </i>");
111 CmsUtils
.markup(noTaskLbl
);
112 noTaskLbl
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.BOTTOM
, true, true));
114 final Link createTaskLk
= new Link(noTaskCmp
, SWT
.CENTER
);
115 createTaskLk
.setText("<a> Create a task </a>");
116 createTaskLk
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.TOP
, true, true));
118 createTaskLk
.addSelectionListener(new SelectionAdapter() {
119 private static final long serialVersionUID
= -9028457805156989935L;
122 public void widgetSelected(SelectionEvent e
) {
123 String mainMixin
= TrackerTypes
.TRACKER_TASK
;
124 String pathCreated
= ConnectWorkbenchUtils
.createAndConfigureEntity(createTaskLk
.getShell(),
125 getSession(), getSystemAppService(), getSystemWorkbenchService(), mainMixin
);
126 if (EclipseUiUtils
.notEmpty(pathCreated
))
132 TaskListLabelProvider labelProvider
= new TaskListLabelProvider(trackerService
);
133 tvlc
= new TaskVirtualListComposite(parent
, SWT
.NO_FOCUS
, (ILabelProvider
) labelProvider
, 54);
134 tvlc
.setLayoutData(EclipseUiUtils
.fillAll());
135 final TableViewer viewer
= tvlc
.getTableViewer();
136 viewer
.setInput(JcrUtils
.nodeIteratorToList(nit
).toArray());
137 final TaskViewerContextMenu contextMenu
= new TaskViewerContextMenu(viewer
, getSession(),
140 public boolean performAction(String actionId
) {
141 boolean hasChanged
= super.performAction(actionId
);
143 viewer
.getTable().setFocus();
145 // NodeIterator nit =
146 // activitiesService.getMyTasks(getSession(), true);
147 // viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray());
152 viewer
.getTable().addMouseListener(new MouseAdapter() {
153 private static final long serialVersionUID
= 6737579410648595940L;
156 public void mouseDown(MouseEvent e
) {
158 // contextMenu.setCurrFolderPath(currDisplayedFolder);
159 contextMenu
.show(viewer
.getTable(), new Point(e
.x
, e
.y
),
160 (IStructuredSelection
) viewer
.getSelection());
168 private boolean isOverdue(Node node
, String propName
) {
170 Calendar now
= GregorianCalendar
.getInstance();
171 return node
.hasProperty(propName
) && node
.getProperty(propName
).getDate().before(now
);
172 } catch (RepositoryException e
) {
173 throw new ConnectException("Cannot check overdue status with property " + propName
+ " on " + node
, e
);
177 private void populateHeaderPart(Composite bodyCmp
, Node context
) {
178 bodyCmp
.setLayout(EclipseUiUtils
.noSpaceGridLayout(new GridLayout(2, true)));
180 Composite leftCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
181 leftCmp
.setLayout(new GridLayout());
182 leftCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
183 Composite rightCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
184 rightCmp
.setLayout(new GridLayout());
185 rightCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
188 Label titleLbl
= new Label(leftCmp
, SWT
.WRAP
| SWT
.LEAD
);
189 CmsUtils
.markup(titleLbl
);
190 String titleStr
= "<big><b> Hello " + CurrentUser
.getDisplayName() + " </b></big>";
191 titleLbl
.setText(titleStr
);
192 GridData gd
= new GridData(SWT
.TOP
, SWT
.BOTTOM
, false, false);
193 gd
.verticalIndent
= 5;
194 gd
.horizontalIndent
= 10;
195 titleLbl
.setLayoutData(gd
);
197 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
199 List
<Node
> overdueTasks
= new ArrayList
<>();
200 while (nit
.hasNext()) {
201 Node currNode
= nit
.nextNode();
202 if (isOverdue(currNode
, ActivitiesNames
.ACTIVITIES_DUE_DATE
))
203 overdueTasks
.add(currNode
);
205 if (!overdueTasks
.isEmpty()) {
206 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
207 long size
= overdueTasks
.size();
208 String overdueStr
= "You have " + size
+ " overdue task" + (size
> 1 ?
"s" : "") + ": ";
209 populateMuliValueClickableList(overdueCmp
, overdueTasks
.toArray(new Node
[0]), new TaskLp(), overdueStr
);
213 nit
= trackerService
.getMyMilestones(getSession(), true);
214 List
<Node
> openMilestones
= new ArrayList
<>();
217 List
<Node
> overdueMilestones
= new ArrayList
<>();
218 while (nit
.hasNext()) {
219 Node currNode
= nit
.nextNode();
220 openMilestones
.add(currNode
);
221 if (isOverdue(currNode
, TrackerNames
.TRACKER_TARGET_DATE
))
222 overdueMilestones
.add(currNode
);
224 if (!overdueMilestones
.isEmpty()) {
225 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
226 long size
= overdueMilestones
.size();
227 String overdueStr
= "You have " + size
+ " overdue milestone" + (size
> 1 ?
"s" : "") + ": ";
228 populateMuliValueClickableList(overdueCmp
, overdueMilestones
.toArray(new Node
[0]), new MilestoneLp(),
234 List
<Node
> openProjects
= JcrUtils
.nodeIteratorToList(trackerService
.getMyProjects(getSession(), true));
235 if (!openProjects
.isEmpty()) {
236 Group myProjectsGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
237 myProjectsGp
.setText("My open projects");
238 myProjectsGp
.setLayoutData(EclipseUiUtils
.fillWidth());
239 populateMuliValueClickableList(myProjectsGp
, openProjects
.toArray(new Node
[0]), new ProjectLp(), null);
243 if (!openMilestones
.isEmpty()) {
244 Group myMilestoneGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
245 myMilestoneGp
.setText("My open milestones");
246 myMilestoneGp
.setLayoutData(EclipseUiUtils
.fillWidth());
247 populateMuliValueClickableList(myMilestoneGp
, openMilestones
.toArray(new Node
[0]), new MilestoneLp(), null);
251 private class ProjectLp
extends ColumnLabelProvider
{
252 private static final long serialVersionUID
= 7231233932794865555L;
255 public String
getText(Object element
) {
256 Node project
= (Node
) element
;
259 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, null, null, true);
260 long openNb
= nit
.getSize();
262 nit
= TrackerUtils
.getIssues(project
, null, null, null, false);
263 long allNb
= nit
.getSize();
268 double num
= allNb
- openNb
;
269 double result
= num
/ allNb
* 100;
270 percent
= String
.format("%.1f", result
) + "% done";
272 StringBuilder builder
= new StringBuilder();
273 builder
.append("<a>").append(ConnectJcrUtils
.get(project
, Property
.JCR_TITLE
)).append("</a>");
274 builder
.append(" (").append(percent
).append(")");
276 return builder
.toString();
280 private class MilestoneLp
extends ColumnLabelProvider
{
281 private static final long serialVersionUID
= 7231233932794865555L;
284 public String
getText(Object element
) {
285 Node milestone
= (Node
) element
;
286 Node project
= TrackerUtils
.getRelatedProject(trackerService
, milestone
);
287 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(milestone
, TrackerNames
.TRACKER_TARGET_DATE
,
291 String propName
= TrackerNames
.TRACKER_MILESTONE_UID
;
292 String muid
= ConnectJcrUtils
.get(milestone
, ConnectNames
.CONNECT_UID
);
293 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, true);
294 long openNb
= nit
.getSize();
296 nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, false);
297 long allNb
= nit
.getSize();
302 double num
= allNb
- openNb
;
303 double result
= num
/ allNb
* 100;
304 percent
= String
.format("%.1f", result
) + "% done";
306 StringBuilder builder
= new StringBuilder();
307 builder
.append("<a>").append(ConnectJcrUtils
.get(milestone
, Property
.JCR_TITLE
)).append("</a>");
308 builder
.append(" (");
309 if (EclipseUiUtils
.notEmpty(dueDate
))
310 builder
.append("due to ").append(dueDate
).append(", ");
312 builder
.append(percent
).append(")");
313 return builder
.toString();
317 public Color
getForeground(Object element
) {
318 Node milestone
= (Node
) element
;
319 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
320 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
321 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
326 private class TaskLp
extends ColumnLabelProvider
{
327 private static final long serialVersionUID
= 7231233932794865555L;
330 public String
getText(Object element
) {
331 Node task
= (Node
) element
;
332 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(task
, ActivitiesNames
.ACTIVITIES_DUE_DATE
,
335 StringBuilder builder
= new StringBuilder();
336 builder
.append("<a>").append(ConnectJcrUtils
.get(task
, Property
.JCR_TITLE
)).append("</a>");
337 if (EclipseUiUtils
.notEmpty(dueDate
))
338 builder
.append(" (").append("due to ").append(dueDate
).append(")");
339 return builder
.toString();
343 public Color
getForeground(Object element
) {
344 Node milestone
= (Node
) element
;
345 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
346 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
347 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
353 public void setFocus() {
354 // refreshDocListGadget();
357 public void setActivitiesService(ActivitiesService activitiesService
) {
358 this.activitiesService
= activitiesService
;
361 public void setTrackerService(TrackerService trackerService
) {
362 this.trackerService
= trackerService
;
366 private void populateMuliValueClickableList(Composite parent
, Node
[] nodes
, ColumnLabelProvider lp
,
368 CmsUtils
.clear(parent
);
369 RowLayout rl
= new RowLayout(SWT
.HORIZONTAL
| SWT
.WRAP
);
371 rl
.marginLeft
= rl
.marginTop
= rl
.marginBottom
= 0;
373 parent
.setLayout(rl
);
375 if (EclipseUiUtils
.notEmpty(listLabel
)) {
376 Link link
= new Link(parent
, SWT
.NONE
);
377 link
.setText(listLabel
);
378 link
.setFont(EclipseUiUtils
.getBoldFont(parent
));
382 for (Node node
: nodes
) {
383 Link link
= new Link(parent
, SWT
.NONE
);
384 CmsUtils
.markup(link
);
385 link
.setText(lp
.getText(node
) + (i
!= nodes
.length ?
", " : ""));
387 // Color fc = lp.getForeground(node);
389 // link.setForeground(fc);
391 link
.addSelectionListener(new SelectionAdapter() {
392 private static final long serialVersionUID
= 1L;
395 public void widgetSelected(final SelectionEvent event
) {
396 // CommandUtils.callCommand(getSystemWorkbenchService().getOpenEntityEditorCmdId(),
397 // ConnectEditor.PARAM_JCR_ID, ConnectJcrUtils.getIdentifier(node));
398 getSystemWorkbenchService().openEntityEditor(node
);