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
.ui
.TaskViewerContextMenu
;
18 import org
.argeo
.cms
.auth
.CurrentUser
;
19 import org
.argeo
.cms
.util
.CmsUtils
;
20 import org
.argeo
.connect
.ConnectNames
;
21 import org
.argeo
.connect
.ui
.ConnectWorkbenchUtils
;
22 import org
.argeo
.connect
.ui
.Refreshable
;
23 import org
.argeo
.connect
.util
.ConnectJcrUtils
;
24 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
25 import org
.argeo
.jcr
.JcrUtils
;
26 import org
.argeo
.node
.NodeUtils
;
27 import org
.argeo
.suite
.workbench
.AsUiPlugin
;
28 import org
.argeo
.suite
.workbench
.SuiteWorkbenchException
;
29 import org
.argeo
.tracker
.TrackerNames
;
30 import org
.argeo
.tracker
.TrackerService
;
31 import org
.argeo
.tracker
.TrackerTypes
;
32 import org
.argeo
.tracker
.core
.TrackerUtils
;
33 import org
.argeo
.tracker
.ui
.TaskListLabelProvider
;
34 import org
.argeo
.tracker
.ui
.TaskVirtualListComposite
;
35 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
36 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
37 import org
.eclipse
.jface
.viewers
.TableViewer
;
38 import org
.eclipse
.swt
.SWT
;
39 import org
.eclipse
.swt
.events
.MouseAdapter
;
40 import org
.eclipse
.swt
.events
.MouseEvent
;
41 import org
.eclipse
.swt
.events
.SelectionAdapter
;
42 import org
.eclipse
.swt
.events
.SelectionEvent
;
43 import org
.eclipse
.swt
.graphics
.Color
;
44 import org
.eclipse
.swt
.graphics
.Point
;
45 import org
.eclipse
.swt
.layout
.GridData
;
46 import org
.eclipse
.swt
.layout
.GridLayout
;
47 import org
.eclipse
.swt
.layout
.RowLayout
;
48 import org
.eclipse
.swt
.widgets
.Composite
;
49 import org
.eclipse
.swt
.widgets
.Display
;
50 import org
.eclipse
.swt
.widgets
.Group
;
51 import org
.eclipse
.swt
.widgets
.Label
;
52 import org
.eclipse
.swt
.widgets
.Link
;
53 import org
.eclipse
.ui
.IEditorInput
;
54 import org
.eclipse
.ui
.IEditorSite
;
55 import org
.eclipse
.ui
.PartInitException
;
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
+ ".defaultDashboardEditor";
62 private ActivitiesService activitiesService
;
63 private TrackerService trackerService
;
65 private String datePattern
= "dd MMM yyyy";
67 private Composite headerCmp
;
68 private Composite taskListCmp
;
69 private TaskVirtualListComposite tvlc
;
72 public void init(IEditorSite site
, IEditorInput input
) throws PartInitException
{
73 super.init(site
, input
);
77 public void createPartControl(Composite parent
) {
78 super.createPartControl(parent
);
79 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
80 Composite bodyCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
81 bodyCmp
.setLayoutData(EclipseUiUtils
.fillAll());
82 bodyCmp
.setLayout(new GridLayout());
84 headerCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
85 headerCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
87 taskListCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
88 taskListCmp
.setLayoutData(EclipseUiUtils
.fillAll());
93 public void forceRefresh(Object object
) {
94 CmsUtils
.clear(headerCmp
);
95 populateHeaderPart(headerCmp
, NodeUtils
.getUserHome(getSession()));
97 CmsUtils
.clear(taskListCmp
);
98 populateTaskListCmp(taskListCmp
);
100 headerCmp
.getParent().layout(true, true);
103 private void populateTaskListCmp(Composite parent
) {
104 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
105 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
106 if (!nit
.hasNext()) {
107 Composite noTaskCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
108 noTaskCmp
.setLayoutData(EclipseUiUtils
.fillAll());
109 noTaskCmp
.setLayout(new GridLayout());
111 Label noTaskLbl
= new Label(noTaskCmp
, SWT
.CENTER
);
112 noTaskLbl
.setText("<i> <big> You have no pending Task. </big> </i>");
113 CmsUtils
.markup(noTaskLbl
);
114 noTaskLbl
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.BOTTOM
, true, true));
116 final Link createTaskLk
= new Link(noTaskCmp
, SWT
.CENTER
);
117 createTaskLk
.setText("<a> Create a task </a>");
118 createTaskLk
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.TOP
, true, true));
120 createTaskLk
.addSelectionListener(new SelectionAdapter() {
121 private static final long serialVersionUID
= -9028457805156989935L;
124 public void widgetSelected(SelectionEvent e
) {
125 String mainMixin
= TrackerTypes
.TRACKER_TASK
;
126 String pathCreated
= ConnectWorkbenchUtils
.createAndConfigureEntity(createTaskLk
.getShell(),
127 getSession(), getSystemAppService(), getSystemWorkbenchService(), mainMixin
);
128 if (EclipseUiUtils
.notEmpty(pathCreated
))
134 TaskListLabelProvider labelProvider
= new TaskListLabelProvider(getSystemAppService());
135 tvlc
= new TaskVirtualListComposite(parent
, SWT
.NO_FOCUS
, labelProvider
, 54);
136 tvlc
.setLayoutData(EclipseUiUtils
.fillAll());
137 final TableViewer viewer
= tvlc
.getTableViewer();
138 viewer
.setInput(JcrUtils
.nodeIteratorToList(nit
).toArray());
139 final TaskViewerContextMenu contextMenu
= new TaskViewerContextMenu(viewer
, getSession(),
142 public boolean performAction(String actionId
) {
143 boolean hasChanged
= super.performAction(actionId
);
145 viewer
.getTable().setFocus();
147 // NodeIterator nit =
148 // activitiesService.getMyTasks(getSession(), true);
149 // viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray());
154 viewer
.getTable().addMouseListener(new MouseAdapter() {
155 private static final long serialVersionUID
= 6737579410648595940L;
158 public void mouseDown(MouseEvent e
) {
160 // contextMenu.setCurrFolderPath(currDisplayedFolder);
161 contextMenu
.show(viewer
.getTable(), new Point(e
.x
, e
.y
),
162 (IStructuredSelection
) viewer
.getSelection());
170 private boolean isOverdue(Node node
, String propName
) {
172 Calendar now
= GregorianCalendar
.getInstance();
173 return node
.hasProperty(propName
) && node
.getProperty(propName
).getDate().before(now
);
174 } catch (RepositoryException e
) {
175 throw new SuiteWorkbenchException("Cannot check overdue status with property " + propName
+ " on " + node
,
180 private void populateHeaderPart(Composite bodyCmp
, Node context
) {
181 bodyCmp
.setLayout(EclipseUiUtils
.noSpaceGridLayout(new GridLayout(2, true)));
183 Composite leftCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
184 leftCmp
.setLayout(new GridLayout());
185 leftCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
186 Composite rightCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
187 rightCmp
.setLayout(new GridLayout());
188 rightCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
191 Label titleLbl
= new Label(leftCmp
, SWT
.WRAP
| SWT
.LEAD
);
192 CmsUtils
.markup(titleLbl
);
193 String titleStr
= "<big><b> Hello " + CurrentUser
.getDisplayName() + " </b></big>";
194 titleLbl
.setText(titleStr
);
195 GridData gd
= new GridData(SWT
.TOP
, SWT
.BOTTOM
, false, false);
196 gd
.verticalIndent
= 5;
197 gd
.horizontalIndent
= 10;
198 titleLbl
.setLayoutData(gd
);
200 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
202 List
<Node
> overdueTasks
= new ArrayList
<>();
203 while (nit
.hasNext()) {
204 Node currNode
= nit
.nextNode();
205 if (isOverdue(currNode
, ActivitiesNames
.ACTIVITIES_DUE_DATE
))
206 overdueTasks
.add(currNode
);
208 if (!overdueTasks
.isEmpty()) {
209 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
210 long size
= overdueTasks
.size();
211 String overdueStr
= "You have " + size
+ " overdue task" + (size
> 1 ?
"s" : "") + ": ";
212 populateMuliValueClickableList(overdueCmp
, overdueTasks
.toArray(new Node
[0]), new TaskLp(), overdueStr
);
216 nit
= trackerService
.getMyMilestones(getSession(), true);
217 List
<Node
> openMilestones
= new ArrayList
<>();
220 List
<Node
> overdueMilestones
= new ArrayList
<>();
221 while (nit
.hasNext()) {
222 Node currNode
= nit
.nextNode();
223 openMilestones
.add(currNode
);
224 if (isOverdue(currNode
, TrackerNames
.TRACKER_TARGET_DATE
))
225 overdueMilestones
.add(currNode
);
227 if (!overdueMilestones
.isEmpty()) {
228 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
229 long size
= overdueMilestones
.size();
230 String overdueStr
= "You have " + size
+ " overdue milestone" + (size
> 1 ?
"s" : "") + ": ";
231 populateMuliValueClickableList(overdueCmp
, overdueMilestones
.toArray(new Node
[0]), new MilestoneLp(),
237 List
<Node
> openProjects
= JcrUtils
.nodeIteratorToList(trackerService
.getMyProjects(getSession(), true));
238 if (!openProjects
.isEmpty()) {
239 Group myProjectsGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
240 myProjectsGp
.setText("My open projects");
241 myProjectsGp
.setLayoutData(EclipseUiUtils
.fillWidth());
242 populateMuliValueClickableList(myProjectsGp
, openProjects
.toArray(new Node
[0]), new ProjectLp(), null);
246 if (!openMilestones
.isEmpty()) {
247 Group myMilestoneGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
248 myMilestoneGp
.setText("My open milestones");
249 myMilestoneGp
.setLayoutData(EclipseUiUtils
.fillWidth());
250 populateMuliValueClickableList(myMilestoneGp
, openMilestones
.toArray(new Node
[0]), new MilestoneLp(), null);
254 private class ProjectLp
extends ColumnLabelProvider
{
255 private static final long serialVersionUID
= 7231233932794865555L;
258 public String
getText(Object element
) {
259 Node project
= (Node
) element
;
262 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, null, null, true);
263 long openNb
= nit
.getSize();
265 nit
= TrackerUtils
.getIssues(project
, null, null, null, false);
266 long allNb
= nit
.getSize();
271 double num
= allNb
- openNb
;
272 double result
= num
/ allNb
* 100;
273 percent
= String
.format("%.1f", result
) + "% done";
275 StringBuilder builder
= new StringBuilder();
276 builder
.append("<a>").append(ConnectJcrUtils
.get(project
, Property
.JCR_TITLE
)).append("</a>");
277 builder
.append(" (").append(percent
).append(")");
279 return builder
.toString();
283 private class MilestoneLp
extends ColumnLabelProvider
{
284 private static final long serialVersionUID
= 7231233932794865555L;
287 public String
getText(Object element
) {
288 Node milestone
= (Node
) element
;
289 Node project
= TrackerUtils
.getRelatedProject(trackerService
, milestone
);
290 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(milestone
, TrackerNames
.TRACKER_TARGET_DATE
,
294 String propName
= TrackerNames
.TRACKER_MILESTONE_UID
;
295 String muid
= ConnectJcrUtils
.get(milestone
, ConnectNames
.CONNECT_UID
);
296 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, true);
297 long openNb
= nit
.getSize();
299 nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, false);
300 long allNb
= nit
.getSize();
305 double num
= allNb
- openNb
;
306 double result
= num
/ allNb
* 100;
307 percent
= String
.format("%.1f", result
) + "% done";
309 StringBuilder builder
= new StringBuilder();
310 builder
.append("<a>").append(ConnectJcrUtils
.get(milestone
, Property
.JCR_TITLE
)).append("</a>");
311 builder
.append(" (");
312 if (EclipseUiUtils
.notEmpty(dueDate
))
313 builder
.append("due to ").append(dueDate
).append(", ");
315 builder
.append(percent
).append(")");
316 return builder
.toString();
320 public Color
getForeground(Object element
) {
321 Node milestone
= (Node
) element
;
322 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
323 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
324 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
329 private class TaskLp
extends ColumnLabelProvider
{
330 private static final long serialVersionUID
= 7231233932794865555L;
333 public String
getText(Object element
) {
334 Node task
= (Node
) element
;
335 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(task
, ActivitiesNames
.ACTIVITIES_DUE_DATE
,
338 StringBuilder builder
= new StringBuilder();
339 builder
.append("<a>").append(ConnectJcrUtils
.get(task
, Property
.JCR_TITLE
)).append("</a>");
340 if (EclipseUiUtils
.notEmpty(dueDate
))
341 builder
.append(" (").append("due to ").append(dueDate
).append(")");
342 return builder
.toString();
346 public Color
getForeground(Object element
) {
347 Node milestone
= (Node
) element
;
348 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
349 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
350 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
356 public void setFocus() {
357 // refreshDocListGadget();
360 public void setActivitiesService(ActivitiesService activitiesService
) {
361 this.activitiesService
= activitiesService
;
364 public void setTrackerService(TrackerService trackerService
) {
365 this.trackerService
= trackerService
;
369 private void populateMuliValueClickableList(Composite parent
, Node
[] nodes
, ColumnLabelProvider lp
,
371 CmsUtils
.clear(parent
);
372 RowLayout rl
= new RowLayout(SWT
.HORIZONTAL
| SWT
.WRAP
);
374 rl
.marginLeft
= rl
.marginTop
= rl
.marginBottom
= 0;
376 parent
.setLayout(rl
);
378 if (EclipseUiUtils
.notEmpty(listLabel
)) {
379 Link link
= new Link(parent
, SWT
.NONE
);
380 link
.setText(listLabel
);
381 link
.setFont(EclipseUiUtils
.getBoldFont(parent
));
385 for (Node node
: nodes
) {
386 Link link
= new Link(parent
, SWT
.NONE
);
387 CmsUtils
.markup(link
);
388 link
.setText(lp
.getText(node
) + (i
!= nodes
.length ?
", " : ""));
390 // Color fc = lp.getForeground(node);
392 // link.setForeground(fc);
394 link
.addSelectionListener(new SelectionAdapter() {
395 private static final long serialVersionUID
= 1L;
398 public void widgetSelected(final SelectionEvent event
) {
399 // CommandUtils.callCommand(getSystemWorkbenchService().getOpenEntityEditorCmdId(),
400 // ConnectEditor.PARAM_JCR_ID, ConnectJcrUtils.getIdentifier(node));
401 getSystemWorkbenchService().openEntityEditor(node
);