Add more info to the default dashboard
authorbsinou <bsinou@argeo.org>
Tue, 4 Apr 2017 21:42:43 +0000 (23:42 +0200)
committerbsinou <bsinou@argeo.org>
Tue, 4 Apr 2017 21:42:43 +0000 (23:42 +0200)
org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java

index 7751d6bca47bfb6784c80f75b641953b370fa68c..d879d7e54c2017af63c0aaba321921b409dc0938 100644 (file)
@@ -7,6 +7,7 @@ import java.util.List;
 
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
+import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
 import javax.jcr.RepositoryException;
 
 import org.apache.commons.logging.Log;
@@ -14,22 +15,35 @@ import org.apache.commons.logging.LogFactory;
 import org.argeo.activities.ActivitiesNames;
 import org.argeo.activities.ActivitiesService;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.activities.ActivitiesNames;
 import org.argeo.activities.ActivitiesService;
 import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.ui.workbench.util.CommandUtils;
 import org.argeo.cms.util.CmsUtils;
 import org.argeo.cms.util.CmsUtils;
+import org.argeo.connect.ConnectNames;
+import org.argeo.connect.util.ConnectJcrUtils;
 import org.argeo.connect.workbench.Refreshable;
 import org.argeo.connect.workbench.Refreshable;
+import org.argeo.connect.workbench.commands.OpenEntityEditor;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.node.NodeUtils;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.node.NodeUtils;
+import org.argeo.suite.SuiteException;
 import org.argeo.suite.workbench.AsUiPlugin;
 import org.argeo.tracker.TrackerNames;
 import org.argeo.tracker.TrackerService;
 import org.argeo.suite.workbench.AsUiPlugin;
 import org.argeo.tracker.TrackerNames;
 import org.argeo.tracker.TrackerService;
+import org.argeo.tracker.core.TrackerUtils;
 import org.argeo.tracker.ui.TaskListLabelProvider;
 import org.argeo.tracker.ui.TaskVirtualListComposite;
 import org.argeo.tracker.ui.TaskListLabelProvider;
 import org.argeo.tracker.ui.TaskVirtualListComposite;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
 
 /** Argeo Suite Default Dashboard */
 public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Refreshable {
 
 /** Argeo Suite Default Dashboard */
 public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Refreshable {
@@ -39,6 +53,8 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re
        private ActivitiesService activitiesService;
        private TrackerService trackerService;
 
        private ActivitiesService activitiesService;
        private TrackerService trackerService;
 
+       private String datePattern = "dd MMM yyyy";
+
        private Composite headerCmp;
        private Composite taskListCmp;
        private TaskVirtualListComposite tvlc;
        private Composite headerCmp;
        private Composite taskListCmp;
        private TaskVirtualListComposite tvlc;
@@ -53,10 +69,11 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re
 
                // Header
                try {
 
                // Header
                try {
-                       // Control overviewCmp =
-                       createUi(bodyCmp, NodeUtils.getUserHome(getSession()));
+                       headerCmp = createHeaderPart(bodyCmp, NodeUtils.getUserHome(getSession()));
+                       headerCmp.setLayoutData(EclipseUiUtils.fillWidth());
+
                } catch (RepositoryException e) {
                } catch (RepositoryException e) {
-                       e.printStackTrace();
+                       throw new SuiteException("Cannot create dashboard overview", e);
                }
 
                taskListCmp = new Composite(bodyCmp, SWT.NO_FOCUS);
                }
 
                taskListCmp = new Composite(bodyCmp, SWT.NO_FOCUS);
@@ -83,16 +100,23 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re
                tvlc.getTableViewer().setInput(JcrUtils.nodeIteratorToList(nit).toArray());
        }
 
                tvlc.getTableViewer().setInput(JcrUtils.nodeIteratorToList(nit).toArray());
        }
 
-       private Control createUi(Composite parent, Node context) throws RepositoryException {
+       private Composite createHeaderPart(Composite parent, Node context) throws RepositoryException {
                Composite bodyCmp = new Composite(parent, SWT.NO_FOCUS);
                Composite bodyCmp = new Composite(parent, SWT.NO_FOCUS);
-               bodyCmp.setLayout(new GridLayout());
+               bodyCmp.setLayout(EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, true)));
+
+               Composite leftCmp = new Composite(bodyCmp, SWT.NO_FOCUS);
+               leftCmp.setLayout(new GridLayout());
+               leftCmp.setLayoutData(EclipseUiUtils.fillWidth());
+               Composite rightCmp = new Composite(bodyCmp, SWT.NO_FOCUS);
+               rightCmp.setLayout(new GridLayout());
+               rightCmp.setLayoutData(EclipseUiUtils.fillWidth());
 
                // Title
 
                // Title
-               Label titleLbl = new Label(bodyCmp, SWT.WRAP | SWT.LEAD);
+               Label titleLbl = new Label(leftCmp, SWT.WRAP | SWT.LEAD);
                CmsUtils.markup(titleLbl);
                String titleStr = "<big><b> Hello " + CurrentUser.getDisplayName() + " </b></big>";
                titleLbl.setText(titleStr);
                CmsUtils.markup(titleLbl);
                String titleStr = "<big><b> Hello " + CurrentUser.getDisplayName() + " </b></big>";
                titleLbl.setText(titleStr);
-               GridData gd = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
+               GridData gd = new GridData(SWT.TOP, SWT.BOTTOM, false, false);
                gd.verticalIndent = 5;
                gd.horizontalIndent = 10;
                titleLbl.setLayoutData(gd);
                gd.verticalIndent = 5;
                gd.horizontalIndent = 10;
                titleLbl.setLayoutData(gd);
@@ -109,34 +133,152 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re
                                        overdueTasks.add(currNode);
                        }
                        if (!overdueTasks.isEmpty()) {
                                        overdueTasks.add(currNode);
                        }
                        if (!overdueTasks.isEmpty()) {
-                               Label overdueLbl = new Label(bodyCmp, SWT.WRAP | SWT.LEAD);
-                               CmsUtils.markup(overdueLbl);
+                               Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS);
                                long size = overdueTasks.size();
                                long size = overdueTasks.size();
-                               String overdueStr = "You have " + size + " overdue task" + (size > 1 ? "s" : "") + ".";
-                               overdueLbl.setText(overdueStr);
+                               String overdueStr = "You have " + size + " overdue task" + (size > 1 ? "s" : "") + "";
+                               populateMuliValueClickableList(overdueCmp, overdueTasks.toArray(new Node[0]), new TaskLp(), overdueStr);
                        }
                }
 
                nit = trackerService.getMyMilestones(getSession(), true);
                        }
                }
 
                nit = trackerService.getMyMilestones(getSession(), true);
+               List<Node> openMilestones = new ArrayList<>();
+
                if (nit.hasNext()) {
                        List<Node> overdueMilestones = new ArrayList<>();
                        while (nit.hasNext()) {
                                Node currNode = nit.nextNode();
                if (nit.hasNext()) {
                        List<Node> overdueMilestones = new ArrayList<>();
                        while (nit.hasNext()) {
                                Node currNode = nit.nextNode();
+                               openMilestones.add(currNode);
                                if (currNode.hasProperty(TrackerNames.TRACKER_TARGET_DATE)
                                                && currNode.getProperty(TrackerNames.TRACKER_TARGET_DATE).getDate().before(now))
                                        overdueMilestones.add(currNode);
                        }
                        if (!overdueMilestones.isEmpty()) {
                                if (currNode.hasProperty(TrackerNames.TRACKER_TARGET_DATE)
                                                && currNode.getProperty(TrackerNames.TRACKER_TARGET_DATE).getDate().before(now))
                                        overdueMilestones.add(currNode);
                        }
                        if (!overdueMilestones.isEmpty()) {
-                               Label overdueLbl = new Label(bodyCmp, SWT.WRAP | SWT.LEAD);
-                               CmsUtils.markup(overdueLbl);
+                               Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS);
                                long size = overdueMilestones.size();
                                long size = overdueMilestones.size();
-                               String overdueStr = "You have " + size + " overdue milestone" + (size > 1 ? "s" : "") + ".";
-                               overdueLbl.setText(overdueStr);
+                               String overdueStr = "You have " + size + " overdue milestone" + (size > 1 ? "s" : "") + ": ";
+                               populateMuliValueClickableList(overdueCmp, overdueMilestones.toArray(new Node[0]), new MilestoneLp(),
+                                               overdueStr);
                        }
                }
                        }
                }
+
+               // My projects
+               List<Node> openProjects = JcrUtils.nodeIteratorToList(trackerService.getMyProjects(getSession(), true));
+               if (!openProjects.isEmpty()) {
+                       Group myProjectsGp = new Group(rightCmp, SWT.NO_FOCUS);
+                       myProjectsGp.setText("My open projects");
+                       myProjectsGp.setLayoutData(EclipseUiUtils.fillWidth());
+                       populateMuliValueClickableList(myProjectsGp, openProjects.toArray(new Node[0]), new ProjectLp(), null);
+               }
+
+               // My Milestones
+               if (!openMilestones.isEmpty()) {
+                       Group myMilestoneGp = new Group(rightCmp, SWT.NO_FOCUS);
+                       myMilestoneGp.setText("My open milestones");
+                       myMilestoneGp.setLayoutData(EclipseUiUtils.fillWidth());
+                       populateMuliValueClickableList(myMilestoneGp, openMilestones.toArray(new Node[0]), new MilestoneLp(), null);
+               }
                return bodyCmp;
        }
 
                return bodyCmp;
        }
 
+       private class ProjectLp extends ColumnLabelProvider {
+               private static final long serialVersionUID = 7231233932794865555L;
+
+               @Override
+               public String getText(Object element) {
+                       Node project = (Node) element;
+
+                       String percent;
+                       NodeIterator nit = TrackerUtils.getIssues(project, null, null, null, true);
+                       long openNb = nit.getSize();
+
+                       nit = TrackerUtils.getIssues(project, null, null, null, false);
+                       long allNb = nit.getSize();
+
+                       if (allNb < 1)
+                               percent = "empty";
+                       else {
+                               double result = (allNb - openNb) / allNb * 100;
+                               percent = String.format("%.1f", result) + "% done";
+                       }
+                       StringBuilder builder = new StringBuilder();
+                       builder.append("<a>").append(ConnectJcrUtils.get(project, Property.JCR_TITLE)).append("</a>");
+                       builder.append(" (").append(percent).append(")");
+
+                       return builder.toString();
+               }
+       }
+
+       private class MilestoneLp extends ColumnLabelProvider {
+               private static final long serialVersionUID = 7231233932794865555L;
+
+               @Override
+               public String getText(Object element) {
+                       Node milestone = (Node) element;
+                       Node project = TrackerUtils.getRelatedProject(trackerService, milestone);
+                       String dueDate = ConnectJcrUtils.getDateFormattedAsString(milestone, TrackerNames.TRACKER_TARGET_DATE,
+                                       datePattern);
+
+                       String percent;
+                       String propName = TrackerNames.TRACKER_MILESTONE_UID;
+                       String muid = ConnectJcrUtils.get(milestone, ConnectNames.CONNECT_UID);
+                       NodeIterator nit = TrackerUtils.getIssues(project, null, propName, muid, true);
+                       long openNb = nit.getSize();
+
+                       nit = TrackerUtils.getIssues(project, null, propName, muid, false);
+                       long allNb = nit.getSize();
+
+                       if (allNb < 1)
+                               percent = "empty";
+                       else {
+                               double result = (allNb - openNb) / allNb * 100;
+                               percent = String.format("%.1f", result) + "% done";
+                       }
+                       StringBuilder builder = new StringBuilder();
+                       builder.append("<a>").append(ConnectJcrUtils.get(milestone, Property.JCR_TITLE)).append("</a>");
+                       builder.append(" (");
+                       if (EclipseUiUtils.notEmpty(dueDate))
+                               builder.append("due to ").append(dueDate).append(", ");
+
+                       builder.append(percent).append(")");
+                       return builder.toString();
+               }
+
+               @Override
+               public Color getForeground(Object element) {
+                       Node milestone = (Node) element;
+                       Calendar dueDate = ConnectJcrUtils.getDateValue(milestone, TrackerNames.TRACKER_TARGET_DATE);
+                       if (dueDate != null && dueDate.before(Calendar.getInstance()))
+                               return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
+                       return null;
+               }
+       }
+
+       private class TaskLp extends ColumnLabelProvider {
+               private static final long serialVersionUID = 7231233932794865555L;
+
+               @Override
+               public String getText(Object element) {
+                       Node task = (Node) element;
+                       String dueDate = ConnectJcrUtils.getDateFormattedAsString(task, ActivitiesNames.ACTIVITIES_DUE_DATE,
+                                       datePattern);
+
+                       StringBuilder builder = new StringBuilder();
+                       builder.append("<a>").append(ConnectJcrUtils.get(task, Property.JCR_TITLE)).append("</a>");
+                       if (EclipseUiUtils.notEmpty(dueDate))
+                               builder.append(" (").append("due to ").append(dueDate).append(")");
+                       return builder.toString();
+               }
+
+               @Override
+               public Color getForeground(Object element) {
+                       Node milestone = (Node) element;
+                       Calendar dueDate = ConnectJcrUtils.getDateValue(milestone, TrackerNames.TRACKER_TARGET_DATE);
+                       if (dueDate != null && dueDate.before(Calendar.getInstance()))
+                               return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
+                       return null;
+               }
+       }
+
        @Override
        public void setFocus() {
                // refreshDocListGadget();
        @Override
        public void setFocus() {
                // refreshDocListGadget();
@@ -149,4 +291,43 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re
        public void setTrackerService(TrackerService trackerService) {
                this.trackerService = trackerService;
        }
        public void setTrackerService(TrackerService trackerService) {
                this.trackerService = trackerService;
        }
+
+       // LOCAL HELPERS
+       private void populateMuliValueClickableList(Composite parent, Node[] nodes, ColumnLabelProvider lp,
+                       String listLabel) {
+               CmsUtils.clear(parent);
+               RowLayout rl = new RowLayout(SWT.HORIZONTAL);
+               rl.wrap = true;
+               rl.marginLeft = rl.marginTop = rl.marginBottom = 0;
+               rl.marginRight = 8;
+               parent.setLayout(rl);
+
+               if (EclipseUiUtils.notEmpty(listLabel)) {
+                       Link link = new Link(parent, SWT.NONE);
+                       link.setText(listLabel);
+                       link.setFont(EclipseUiUtils.getBoldFont(parent));
+               }
+
+               int i = 1;
+               for (Node node : nodes) {
+                       Link link = new Link(parent, SWT.NONE);
+                       CmsUtils.markup(link);
+                       link.setText(lp.getText(node) + (i != nodes.length ? ", " : ""));
+                       i++;
+//                     Color fc = lp.getForeground(node);
+//                     if (fc != null)
+//                             link.setForeground(fc);
+
+                       link.addSelectionListener(new SelectionAdapter() {
+                               private static final long serialVersionUID = 1L;
+
+                               @Override
+                               public void widgetSelected(final SelectionEvent event) {
+                                       CommandUtils.callCommand(getSystemWorkbenchService().getOpenEntityEditorCmdId(),
+                                                       OpenEntityEditor.PARAM_JCR_ID, ConnectJcrUtils.getIdentifier(node));
+                               }
+                       });
+               }
+       }
+
 }
 }