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=d24ad972cdb6f560e78a73f4d9ec7074bc3e5f20;hp=7751d6bca47bfb6784c80f75b641953b370fa68c;hb=f29206b576a5fbc9715e89377ed8f7c04f623ef1;hpb=ce27112f9bc01fc37b1121496f3ad1eb7593d7eb 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..d24ad97 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,29 +7,54 @@ 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; import org.apache.commons.logging.LogFactory; import org.argeo.activities.ActivitiesNames; import org.argeo.activities.ActivitiesService; +import org.argeo.activities.workbench.parts.TaskViewerContextMenu; 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.ConnectWorkbenchUtils; 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.workbench.AsUiPlugin; +import org.argeo.suite.workbench.SuiteWorkbenchException; import org.argeo.tracker.TrackerNames; import org.argeo.tracker.TrackerService; +import org.argeo.tracker.TrackerTypes; +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.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; 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; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; /** Argeo Suite Default Dashboard */ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Refreshable { @@ -39,10 +64,17 @@ 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; + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + super.init(site, input); + } + @Override public void createPartControl(Composite parent) { super.createPartControl(parent); @@ -51,90 +83,274 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Re bodyCmp.setLayoutData(EclipseUiUtils.fillAll()); bodyCmp.setLayout(new GridLayout()); - // Header - try { - // Control overviewCmp = - createUi(bodyCmp, NodeUtils.getUserHome(getSession())); - } catch (RepositoryException e) { - e.printStackTrace(); - } + headerCmp = new Composite(bodyCmp, SWT.NO_FOCUS); + headerCmp.setLayoutData(EclipseUiUtils.fillWidth()); taskListCmp = new Composite(bodyCmp, SWT.NO_FOCUS); taskListCmp.setLayoutData(EclipseUiUtils.fillAll()); - - populateTaskListCmp(); + forceRefresh(null); } - private void populateTaskListCmp() { + @Override + public void forceRefresh(Object object) { + CmsUtils.clear(headerCmp); + populateHeaderPart(headerCmp, NodeUtils.getUserHome(getSession())); + CmsUtils.clear(taskListCmp); - taskListCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); - // Composite innerCmp = new Composite(taskListCmp, SWT.NO_FOCUS); - // innerCmp.setLayoutData(EclipseUiUtils.fillAll()); + populateTaskListCmp(taskListCmp); - TaskListLabelProvider labelProvider = new TaskListLabelProvider(trackerService); - tvlc = new TaskVirtualListComposite(taskListCmp, SWT.NO_FOCUS, labelProvider, 54); - tvlc.setLayoutData(EclipseUiUtils.fillAll()); - forceRefresh(null); + headerCmp.getParent().layout(true, true); } - @Override - public void forceRefresh(Object object) { + private void populateTaskListCmp(Composite parent) { + parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); NodeIterator nit = activitiesService.getMyTasks(getSession(), true); - tvlc.getTableViewer().setInput(JcrUtils.nodeIteratorToList(nit).toArray()); + if (!nit.hasNext()) { + Composite noTaskCmp = new Composite(parent, SWT.NO_FOCUS); + noTaskCmp.setLayoutData(EclipseUiUtils.fillAll()); + noTaskCmp.setLayout(new GridLayout()); + + Label noTaskLbl = new Label(noTaskCmp, SWT.CENTER); + noTaskLbl.setText(" You have no pending Task. "); + CmsUtils.markup(noTaskLbl); + noTaskLbl.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, true)); + + final Link createTaskLk = new Link(noTaskCmp, SWT.CENTER); + createTaskLk.setText(" Create a task "); + createTaskLk.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, true)); + + createTaskLk.addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = -9028457805156989935L; + + @Override + public void widgetSelected(SelectionEvent e) { + String mainMixin = TrackerTypes.TRACKER_TASK; + String pathCreated = ConnectWorkbenchUtils.createAndConfigureEntity(createTaskLk.getShell(), getSession(), + getSystemAppService(), getSystemWorkbenchService(), mainMixin); + if (EclipseUiUtils.notEmpty(pathCreated)) + forceRefresh(null); + } + }); + + } else { + TaskListLabelProvider labelProvider = new TaskListLabelProvider(trackerService); + tvlc = new TaskVirtualListComposite(parent, SWT.NO_FOCUS, labelProvider, 54); + tvlc.setLayoutData(EclipseUiUtils.fillAll()); + final TableViewer viewer = tvlc.getTableViewer(); + viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray()); + final TaskViewerContextMenu contextMenu = new TaskViewerContextMenu(viewer, getSession(), + activitiesService) { + @Override + public boolean performAction(String actionId) { + boolean hasChanged = super.performAction(actionId); + if (hasChanged) { + viewer.getTable().setFocus(); + forceRefresh(null); + // NodeIterator nit = + // activitiesService.getMyTasks(getSession(), true); + // viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray()); + } + return hasChanged; + } + }; + viewer.getTable().addMouseListener(new MouseAdapter() { + private static final long serialVersionUID = 6737579410648595940L; + + @Override + public void mouseDown(MouseEvent e) { + if (e.button == 3) { + // contextMenu.setCurrFolderPath(currDisplayedFolder); + contextMenu.show(viewer.getTable(), new Point(e.x, e.y), + (IStructuredSelection) viewer.getSelection()); + } + } + }); + + } } - private Control createUi(Composite parent, Node context) throws RepositoryException { - Composite bodyCmp = new Composite(parent, SWT.NO_FOCUS); - bodyCmp.setLayout(new GridLayout()); + private boolean isOverdue(Node node, String propName) { + try { + Calendar now = GregorianCalendar.getInstance(); + return node.hasProperty(propName) && node.getProperty(propName).getDate().before(now); + } catch (RepositoryException e) { + throw new SuiteWorkbenchException("Cannot check overdue status with property " + propName + " on " + node, e); + } + } + + private void populateHeaderPart(Composite bodyCmp, Node context) { + 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); - Calendar now = GregorianCalendar.getInstance(); - NodeIterator nit = activitiesService.getMyTasks(getSession(), true); if (nit.hasNext()) { List overdueTasks = new ArrayList<>(); while (nit.hasNext()) { Node currNode = nit.nextNode(); - if (currNode.hasProperty(ActivitiesNames.ACTIVITIES_DUE_DATE) - && currNode.getProperty(ActivitiesNames.ACTIVITIES_DUE_DATE).getDate().before(now)) + if (isOverdue(currNode, ActivitiesNames.ACTIVITIES_DUE_DATE)) 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(); - if (currNode.hasProperty(TrackerNames.TRACKER_TARGET_DATE) - && currNode.getProperty(TrackerNames.TRACKER_TARGET_DATE).getDate().before(now)) + openMilestones.add(currNode); + if (isOverdue(currNode, TrackerNames.TRACKER_TARGET_DATE)) 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); + } + } + + 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 num = allNb - openNb; + double result = num / 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 num = allNb - openNb; + double result = num / 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; } - return bodyCmp; } @Override @@ -149,4 +365,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 | SWT.WRAP); + 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)); + } + }); + } + } + }