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
.util
.ConnectJcrUtils
;
23 import org
.argeo
.connect
.workbench
.ConnectWorkbenchUtils
;
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
.workbench
.AsUiPlugin
;
30 import org
.argeo
.suite
.workbench
.SuiteWorkbenchException
;
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
;
55 import org
.eclipse
.ui
.IEditorInput
;
56 import org
.eclipse
.ui
.IEditorSite
;
57 import org
.eclipse
.ui
.PartInitException
;
59 /** Argeo Suite Default Dashboard */
60 public class DefaultDashboardEditor
extends AbstractSuiteDashboard
implements Refreshable
{
61 final static Log log
= LogFactory
.getLog(DefaultDashboardEditor
.class);
62 public final static String ID
= AsUiPlugin
.PLUGIN_ID
+ ".defaultDashboardEditor";
64 private ActivitiesService activitiesService
;
65 private TrackerService trackerService
;
67 private String datePattern
= "dd MMM yyyy";
69 private Composite headerCmp
;
70 private Composite taskListCmp
;
71 private TaskVirtualListComposite tvlc
;
74 public void init(IEditorSite site
, IEditorInput input
) throws PartInitException
{
75 super.init(site
, input
);
79 public void createPartControl(Composite parent
) {
80 super.createPartControl(parent
);
81 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
82 Composite bodyCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
83 bodyCmp
.setLayoutData(EclipseUiUtils
.fillAll());
84 bodyCmp
.setLayout(new GridLayout());
86 headerCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
87 headerCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
89 taskListCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
90 taskListCmp
.setLayoutData(EclipseUiUtils
.fillAll());
95 public void forceRefresh(Object object
) {
96 CmsUtils
.clear(headerCmp
);
97 populateHeaderPart(headerCmp
, NodeUtils
.getUserHome(getSession()));
99 CmsUtils
.clear(taskListCmp
);
100 populateTaskListCmp(taskListCmp
);
102 headerCmp
.getParent().layout(true, true);
105 private void populateTaskListCmp(Composite parent
) {
106 parent
.setLayout(EclipseUiUtils
.noSpaceGridLayout());
107 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
108 if (!nit
.hasNext()) {
109 Composite noTaskCmp
= new Composite(parent
, SWT
.NO_FOCUS
);
110 noTaskCmp
.setLayoutData(EclipseUiUtils
.fillAll());
111 noTaskCmp
.setLayout(new GridLayout());
113 Label noTaskLbl
= new Label(noTaskCmp
, SWT
.CENTER
);
114 noTaskLbl
.setText("<i> <big> You have no pending Task. </big> </i>");
115 CmsUtils
.markup(noTaskLbl
);
116 noTaskLbl
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.BOTTOM
, true, true));
118 final Link createTaskLk
= new Link(noTaskCmp
, SWT
.CENTER
);
119 createTaskLk
.setText("<a> Create a task </a>");
120 createTaskLk
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.TOP
, true, true));
122 createTaskLk
.addSelectionListener(new SelectionAdapter() {
123 private static final long serialVersionUID
= -9028457805156989935L;
126 public void widgetSelected(SelectionEvent e
) {
127 String mainMixin
= TrackerTypes
.TRACKER_TASK
;
128 String pathCreated
= ConnectWorkbenchUtils
.createAndConfigureEntity(createTaskLk
.getShell(), getSession(),
129 getSystemAppService(), getSystemWorkbenchService(), mainMixin
);
130 if (EclipseUiUtils
.notEmpty(pathCreated
))
136 TaskListLabelProvider labelProvider
= new TaskListLabelProvider(trackerService
);
137 tvlc
= new TaskVirtualListComposite(parent
, SWT
.NO_FOCUS
, labelProvider
, 54);
138 tvlc
.setLayoutData(EclipseUiUtils
.fillAll());
139 final TableViewer viewer
= tvlc
.getTableViewer();
140 viewer
.setInput(JcrUtils
.nodeIteratorToList(nit
).toArray());
141 final TaskViewerContextMenu contextMenu
= new TaskViewerContextMenu(viewer
, getSession(),
144 public boolean performAction(String actionId
) {
145 boolean hasChanged
= super.performAction(actionId
);
147 viewer
.getTable().setFocus();
149 // NodeIterator nit =
150 // activitiesService.getMyTasks(getSession(), true);
151 // viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray());
156 viewer
.getTable().addMouseListener(new MouseAdapter() {
157 private static final long serialVersionUID
= 6737579410648595940L;
160 public void mouseDown(MouseEvent e
) {
162 // contextMenu.setCurrFolderPath(currDisplayedFolder);
163 contextMenu
.show(viewer
.getTable(), new Point(e
.x
, e
.y
),
164 (IStructuredSelection
) viewer
.getSelection());
172 private boolean isOverdue(Node node
, String propName
) {
174 Calendar now
= GregorianCalendar
.getInstance();
175 return node
.hasProperty(propName
) && node
.getProperty(propName
).getDate().before(now
);
176 } catch (RepositoryException e
) {
177 throw new SuiteWorkbenchException("Cannot check overdue status with property " + propName
+ " on " + node
, e
);
181 private void populateHeaderPart(Composite bodyCmp
, Node context
) {
182 bodyCmp
.setLayout(EclipseUiUtils
.noSpaceGridLayout(new GridLayout(2, true)));
184 Composite leftCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
185 leftCmp
.setLayout(new GridLayout());
186 leftCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
187 Composite rightCmp
= new Composite(bodyCmp
, SWT
.NO_FOCUS
);
188 rightCmp
.setLayout(new GridLayout());
189 rightCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
192 Label titleLbl
= new Label(leftCmp
, SWT
.WRAP
| SWT
.LEAD
);
193 CmsUtils
.markup(titleLbl
);
194 String titleStr
= "<big><b> Hello " + CurrentUser
.getDisplayName() + " </b></big>";
195 titleLbl
.setText(titleStr
);
196 GridData gd
= new GridData(SWT
.TOP
, SWT
.BOTTOM
, false, false);
197 gd
.verticalIndent
= 5;
198 gd
.horizontalIndent
= 10;
199 titleLbl
.setLayoutData(gd
);
201 NodeIterator nit
= activitiesService
.getMyTasks(getSession(), true);
203 List
<Node
> overdueTasks
= new ArrayList
<>();
204 while (nit
.hasNext()) {
205 Node currNode
= nit
.nextNode();
206 if (isOverdue(currNode
, ActivitiesNames
.ACTIVITIES_DUE_DATE
))
207 overdueTasks
.add(currNode
);
209 if (!overdueTasks
.isEmpty()) {
210 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
211 long size
= overdueTasks
.size();
212 String overdueStr
= "You have " + size
+ " overdue task" + (size
> 1 ?
"s" : "") + ": ";
213 populateMuliValueClickableList(overdueCmp
, overdueTasks
.toArray(new Node
[0]), new TaskLp(), overdueStr
);
217 nit
= trackerService
.getMyMilestones(getSession(), true);
218 List
<Node
> openMilestones
= new ArrayList
<>();
221 List
<Node
> overdueMilestones
= new ArrayList
<>();
222 while (nit
.hasNext()) {
223 Node currNode
= nit
.nextNode();
224 openMilestones
.add(currNode
);
225 if (isOverdue(currNode
, TrackerNames
.TRACKER_TARGET_DATE
))
226 overdueMilestones
.add(currNode
);
228 if (!overdueMilestones
.isEmpty()) {
229 Composite overdueCmp
= new Composite(leftCmp
, SWT
.NO_FOCUS
);
230 long size
= overdueMilestones
.size();
231 String overdueStr
= "You have " + size
+ " overdue milestone" + (size
> 1 ?
"s" : "") + ": ";
232 populateMuliValueClickableList(overdueCmp
, overdueMilestones
.toArray(new Node
[0]), new MilestoneLp(),
238 List
<Node
> openProjects
= JcrUtils
.nodeIteratorToList(trackerService
.getMyProjects(getSession(), true));
239 if (!openProjects
.isEmpty()) {
240 Group myProjectsGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
241 myProjectsGp
.setText("My open projects");
242 myProjectsGp
.setLayoutData(EclipseUiUtils
.fillWidth());
243 populateMuliValueClickableList(myProjectsGp
, openProjects
.toArray(new Node
[0]), new ProjectLp(), null);
247 if (!openMilestones
.isEmpty()) {
248 Group myMilestoneGp
= new Group(rightCmp
, SWT
.NO_FOCUS
);
249 myMilestoneGp
.setText("My open milestones");
250 myMilestoneGp
.setLayoutData(EclipseUiUtils
.fillWidth());
251 populateMuliValueClickableList(myMilestoneGp
, openMilestones
.toArray(new Node
[0]), new MilestoneLp(), null);
255 private class ProjectLp
extends ColumnLabelProvider
{
256 private static final long serialVersionUID
= 7231233932794865555L;
259 public String
getText(Object element
) {
260 Node project
= (Node
) element
;
263 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, null, null, true);
264 long openNb
= nit
.getSize();
266 nit
= TrackerUtils
.getIssues(project
, null, null, null, false);
267 long allNb
= nit
.getSize();
272 double num
= allNb
- openNb
;
273 double result
= num
/ allNb
* 100;
274 percent
= String
.format("%.1f", result
) + "% done";
276 StringBuilder builder
= new StringBuilder();
277 builder
.append("<a>").append(ConnectJcrUtils
.get(project
, Property
.JCR_TITLE
)).append("</a>");
278 builder
.append(" (").append(percent
).append(")");
280 return builder
.toString();
284 private class MilestoneLp
extends ColumnLabelProvider
{
285 private static final long serialVersionUID
= 7231233932794865555L;
288 public String
getText(Object element
) {
289 Node milestone
= (Node
) element
;
290 Node project
= TrackerUtils
.getRelatedProject(trackerService
, milestone
);
291 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(milestone
, TrackerNames
.TRACKER_TARGET_DATE
,
295 String propName
= TrackerNames
.TRACKER_MILESTONE_UID
;
296 String muid
= ConnectJcrUtils
.get(milestone
, ConnectNames
.CONNECT_UID
);
297 NodeIterator nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, true);
298 long openNb
= nit
.getSize();
300 nit
= TrackerUtils
.getIssues(project
, null, propName
, muid
, false);
301 long allNb
= nit
.getSize();
306 double num
= allNb
- openNb
;
307 double result
= num
/ allNb
* 100;
308 percent
= String
.format("%.1f", result
) + "% done";
310 StringBuilder builder
= new StringBuilder();
311 builder
.append("<a>").append(ConnectJcrUtils
.get(milestone
, Property
.JCR_TITLE
)).append("</a>");
312 builder
.append(" (");
313 if (EclipseUiUtils
.notEmpty(dueDate
))
314 builder
.append("due to ").append(dueDate
).append(", ");
316 builder
.append(percent
).append(")");
317 return builder
.toString();
321 public Color
getForeground(Object element
) {
322 Node milestone
= (Node
) element
;
323 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
324 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
325 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
330 private class TaskLp
extends ColumnLabelProvider
{
331 private static final long serialVersionUID
= 7231233932794865555L;
334 public String
getText(Object element
) {
335 Node task
= (Node
) element
;
336 String dueDate
= ConnectJcrUtils
.getDateFormattedAsString(task
, ActivitiesNames
.ACTIVITIES_DUE_DATE
,
339 StringBuilder builder
= new StringBuilder();
340 builder
.append("<a>").append(ConnectJcrUtils
.get(task
, Property
.JCR_TITLE
)).append("</a>");
341 if (EclipseUiUtils
.notEmpty(dueDate
))
342 builder
.append(" (").append("due to ").append(dueDate
).append(")");
343 return builder
.toString();
347 public Color
getForeground(Object element
) {
348 Node milestone
= (Node
) element
;
349 Calendar dueDate
= ConnectJcrUtils
.getDateValue(milestone
, TrackerNames
.TRACKER_TARGET_DATE
);
350 if (dueDate
!= null && dueDate
.before(Calendar
.getInstance()))
351 return Display
.getCurrent().getSystemColor(SWT
.COLOR_RED
);
357 public void setFocus() {
358 // refreshDocListGadget();
361 public void setActivitiesService(ActivitiesService activitiesService
) {
362 this.activitiesService
= activitiesService
;
365 public void setTrackerService(TrackerService trackerService
) {
366 this.trackerService
= trackerService
;
370 private void populateMuliValueClickableList(Composite parent
, Node
[] nodes
, ColumnLabelProvider lp
,
372 CmsUtils
.clear(parent
);
373 RowLayout rl
= new RowLayout(SWT
.HORIZONTAL
| SWT
.WRAP
);
375 rl
.marginLeft
= rl
.marginTop
= rl
.marginBottom
= 0;
377 parent
.setLayout(rl
);
379 if (EclipseUiUtils
.notEmpty(listLabel
)) {
380 Link link
= new Link(parent
, SWT
.NONE
);
381 link
.setText(listLabel
);
382 link
.setFont(EclipseUiUtils
.getBoldFont(parent
));
386 for (Node node
: nodes
) {
387 Link link
= new Link(parent
, SWT
.NONE
);
388 CmsUtils
.markup(link
);
389 link
.setText(lp
.getText(node
) + (i
!= nodes
.length ?
", " : ""));
391 // Color fc = lp.getForeground(node);
393 // link.setForeground(fc);
395 link
.addSelectionListener(new SelectionAdapter() {
396 private static final long serialVersionUID
= 1L;
399 public void widgetSelected(final SelectionEvent event
) {
400 CommandUtils
.callCommand(getSystemWorkbenchService().getOpenEntityEditorCmdId(),
401 OpenEntityEditor
.PARAM_JCR_ID
, ConnectJcrUtils
.getIdentifier(node
));