X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.suite.workbench.rap%2Fsrc%2Forg%2Fargeo%2Fsuite%2Fworkbench%2Fparts%2FDefaultDashboardEditor.java;h=535dc7c60cc97898a792edc6c554b5fec3f7462b;hb=992786cb0367dd6ca79522f4eb7d1f29fe2748cc;hp=a9dd0e5e969b4c3d3e78514d7c2d592f4e6b1e4a;hpb=be7cb3f18ce76bde064cbbc2a38de6386f3498d2;p=gpl%2Fargeo-suite.git
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 a9dd0e5..535dc7c 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
@@ -1,104 +1,401 @@
package org.argeo.suite.workbench.parts;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+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.connect.ConnectConstants;
-import org.argeo.connect.activities.ActivitiesTypes;
-import org.argeo.connect.people.PeopleTypes;
-import org.argeo.connect.resources.ResourcesTypes;
-import org.argeo.connect.ui.workbench.ConnectWorkbenchUtils;
-import org.argeo.connect.ui.workbench.Refreshable;
+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.ui.ConnectUiUtils;
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.workbench.SuiteWorkbenchException;
import org.argeo.suite.workbench.AsUiPlugin;
+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.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 {
final static Log log = LogFactory.getLog(DefaultDashboardEditor.class);
public final static String ID = AsUiPlugin.PLUGIN_ID + ".defaultDashboardEditor";
- // Default gadget dimensions
- private int wh = 300;
- private int hh = 350;
+ private ActivitiesService activitiesService;
+ private TrackerService trackerService;
+
+ private String datePattern = "dd MMM yyyy";
- private Composite lastUpdatedDocsGadget;
+ private Composite headerCmp;
+ private Composite taskListCmp;
+ private TaskVirtualListComposite tvlc;
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
+ parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
+ Composite bodyCmp = new Composite(parent, SWT.NO_FOCUS);
+ bodyCmp.setLayoutData(EclipseUiUtils.fillAll());
+ bodyCmp.setLayout(new GridLayout());
- parent.setLayout(new GridLayout());
- // Main Layout
- Composite body = getFormToolkit().createComposite(parent);
- body.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
-
- GridLayout bodyLayout = new GridLayout(2, true);
- bodyLayout.horizontalSpacing = 20;
- bodyLayout.verticalSpacing = 20;
- body.setLayout(bodyLayout);
-
- // Contacts
- Composite contactGadget = createGadgetCmp(body, wh, hh);
- populateContactsGadget(contactGadget);
+ headerCmp = new Composite(bodyCmp, SWT.NO_FOCUS);
+ headerCmp.setLayoutData(EclipseUiUtils.fillWidth());
- // Last updated doc List
- lastUpdatedDocsGadget = createGadgetCmp(body, wh, hh);
+ taskListCmp = new Composite(bodyCmp, SWT.NO_FOCUS);
+ taskListCmp.setLayoutData(EclipseUiUtils.fillAll());
+ forceRefresh(null);
}
@Override
public void forceRefresh(Object object) {
- refreshDocListGadget();
+ CmsUtils.clear(headerCmp);
+ populateHeaderPart(headerCmp, NodeUtils.getUserHome(getSession()));
+
+ CmsUtils.clear(taskListCmp);
+ populateTaskListCmp(taskListCmp);
+
+ headerCmp.getParent().layout(true, true);
}
- @Override
- public void setFocus() {
- refreshDocListGadget();
+ private void populateTaskListCmp(Composite parent) {
+ parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
+ NodeIterator nit = activitiesService.getMyTasks(getSession(), true);
+ 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 = ConnectUiUtils.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) {
+ private static final long serialVersionUID = 1640863021424194303L;
+
+ @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());
+ }
+ }
+ });
+
+ }
}
- /** Links to the various last updated docs */
- private void refreshDocListGadget() {
- EclipseUiUtils.clear(lastUpdatedDocsGadget);
- lastUpdatedDocsGadget.setLayout(EclipseUiUtils.noSpaceGridLayout());
- createGadgetTitleCmp(lastUpdatedDocsGadget, "Last updated documents");
- Composite bodyCmp = createGadgetBodyCmp(lastUpdatedDocsGadget);
-
- NodeIterator nit = getDocumentsService().getLastUpdatedDocuments(getSession());
- while (nit.hasNext()) {
- Node file = nit.nextNode();
- createOpenEntityEditorLink(getAppWorkbenchService(), bodyCmp, ConnectJcrUtils.getName(file), file);
+ 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);
}
- lastUpdatedDocsGadget.layout(true, true);
}
- /** Links to the various contact search pages */
- private void populateContactsGadget(Composite parent) {
- parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
- createGadgetTitleCmp(parent, "Contacts");
- Composite bodyCmp = createGadgetBodyCmp(parent);
+ private void populateHeaderPart(Composite bodyCmp, Node context) {
+ bodyCmp.setLayout(EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, true)));
- ConnectWorkbenchUtils.createOpenSearchEditorLink(getAppWorkbenchService(), bodyCmp, "Persons",
- PeopleTypes.PEOPLE_PERSON, getPeopleService().getBasePath(PeopleTypes.PEOPLE_PERSON));
+ 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());
- ConnectWorkbenchUtils.createOpenSearchEditorLink(getAppWorkbenchService(), bodyCmp, "Organisations",
- PeopleTypes.PEOPLE_ORG, getPeopleService().getBasePath(PeopleTypes.PEOPLE_ORG));
+ // Title
+ 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.TOP, SWT.BOTTOM, false, false);
+ gd.verticalIndent = 5;
+ gd.horizontalIndent = 10;
+ titleLbl.setLayoutData(gd);
- Node tagParent = getResourceService().getTagLikeResourceParent(getSession(), PeopleTypes.PEOPLE_MAILING_LIST);
- ConnectWorkbenchUtils.createOpenSearchEditorLink(getAppWorkbenchService(), bodyCmp, "Mailing lists",
- PeopleTypes.PEOPLE_MAILING_LIST, ConnectJcrUtils.getPath(tagParent));
- ConnectWorkbenchUtils.createOpenSearchEditorLink(getAppWorkbenchService(), bodyCmp, "Tasks",
- ActivitiesTypes.ACTIVITIES_TASK, getPeopleService().getBasePath(null));
+ NodeIterator nit = activitiesService.getMyTasks(getSession(), true);
+ if (nit.hasNext()) {
+ List overdueTasks = new ArrayList<>();
+ while (nit.hasNext()) {
+ Node currNode = nit.nextNode();
+ if (isOverdue(currNode, ActivitiesNames.ACTIVITIES_DUE_DATE))
+ overdueTasks.add(currNode);
+ }
+ if (!overdueTasks.isEmpty()) {
+ Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS);
+ long size = overdueTasks.size();
+ String overdueStr = "You have " + size + " overdue task" + (size > 1 ? "s" : "") + ": ";
+ populateMuliValueClickableList(overdueCmp, overdueTasks.toArray(new Node[0]), new TaskLp(), overdueStr);
+ }
+ }
- tagParent = getResourceService().getTagLikeResourceParent(getSession(), ConnectConstants.RESOURCE_TAG);
+ nit = trackerService.getMyMilestones(getSession(), true);
+ List openMilestones = new ArrayList<>();
- ConnectWorkbenchUtils.createOpenSearchEditorLink(getAppWorkbenchService(), bodyCmp, "Tags",
- ResourcesTypes.RESOURCES_TAG_INSTANCE, ConnectJcrUtils.getPath(tagParent));
+ if (nit.hasNext()) {
+ List overdueMilestones = new ArrayList<>();
+ while (nit.hasNext()) {
+ Node currNode = nit.nextNode();
+ openMilestones.add(currNode);
+ if (isOverdue(currNode, TrackerNames.TRACKER_TARGET_DATE))
+ overdueMilestones.add(currNode);
+ }
+ if (!overdueMilestones.isEmpty()) {
+ Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS);
+ long size = overdueMilestones.size();
+ 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;
+ }
+ }
+
+ @Override
+ public void setFocus() {
+ // refreshDocListGadget();
+ }
+
+ public void setActivitiesService(ActivitiesService activitiesService) {
+ this.activitiesService = activitiesService;
+ }
+
+ 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));
+ }
+ });
+ }
+ }
+
}