X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=blobdiff_plain;f=org.argeo.suite.workbench.rap%2Fsrc%2Forg%2Fargeo%2Fsuite%2Fworkbench%2Fparts%2FDefaultDashboardEditor.java;h=d879d7e54c2017af63c0aaba321921b409dc0938;hp=7751d6bca47bfb6784c80f75b641953b370fa68c;hb=9d3b4e769feed8314ef92f894a580016fa09813d;hpb=c3fd8f7a83ca1d907f9fd59d309a0822ca58f90c diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java index 7751d6b..d879d7e 100644 --- a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java @@ -7,6 +7,7 @@ import java.util.List; import javax.jcr.Node; import javax.jcr.NodeIterator; +import javax.jcr.Property; 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.cms.ui.workbench.util.CommandUtils; 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.commands.OpenEntityEditor; 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.tracker.core.TrackerUtils; 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.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.RowLayout; 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.Link; /** 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 String datePattern = "dd MMM yyyy"; + private Composite headerCmp; private Composite taskListCmp; private TaskVirtualListComposite tvlc; @@ -53,10 +69,11 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re // Header try { - // Control overviewCmp = - createUi(bodyCmp, NodeUtils.getUserHome(getSession())); + headerCmp = createHeaderPart(bodyCmp, NodeUtils.getUserHome(getSession())); + headerCmp.setLayoutData(EclipseUiUtils.fillWidth()); + } catch (RepositoryException e) { - e.printStackTrace(); + throw new SuiteException("Cannot create dashboard overview", e); } 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()); } - 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); - 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 - Label titleLbl = new Label(bodyCmp, SWT.WRAP | SWT.LEAD); + Label titleLbl = new Label(leftCmp, SWT.WRAP | SWT.LEAD); CmsUtils.markup(titleLbl); String titleStr = " Hello " + CurrentUser.getDisplayName() + " "; 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); @@ -109,34 +133,152 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re 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(); - 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); + List openMilestones = new ArrayList<>(); + if (nit.hasNext()) { List 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()) { - Label overdueLbl = new Label(bodyCmp, SWT.WRAP | SWT.LEAD); - CmsUtils.markup(overdueLbl); + Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS); 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 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; } + 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("").append(ConnectJcrUtils.get(project, Property.JCR_TITLE)).append(""); + 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("").append(ConnectJcrUtils.get(milestone, Property.JCR_TITLE)).append(""); + 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("").append(ConnectJcrUtils.get(task, Property.JCR_TITLE)).append(""); + 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(); @@ -149,4 +291,43 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re 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)); + } + }); + } + } + }