From beb5e6f076b22822c9a94839dccca1c28922f19b Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Thu, 2 Jun 2022 10:34:52 +0200 Subject: [PATCH] Start migrating Suite UI to ACR. --- org.argeo.app.ui/OSGI-INF/cmsApp.xml | 2 + org.argeo.app.ui/OSGI-INF/peopleEntryArea.xml | 5 +- .../src/org/argeo/app/ui/SuiteApp.java | 68 ++++++-- .../src/org/argeo/app/ui/SuiteEvent.java | 15 +- .../src/org/argeo/app/ui/SuiteUi.java | 73 +++++---- .../argeo/app/ui/people/UsersEntryArea.java | 149 ++++++++++++++++++ .../argeo/app/ui/publish/PublishingApp.java | 4 +- 7 files changed, 261 insertions(+), 55 deletions(-) create mode 100644 org.argeo.app.ui/src/org/argeo/app/ui/people/UsersEntryArea.java diff --git a/org.argeo.app.ui/OSGI-INF/cmsApp.xml b/org.argeo.app.ui/OSGI-INF/cmsApp.xml index 534a1af..c710661 100644 --- a/org.argeo.app.ui/OSGI-INF/cmsApp.xml +++ b/org.argeo.app.ui/OSGI-INF/cmsApp.xml @@ -12,4 +12,6 @@ + + diff --git a/org.argeo.app.ui/OSGI-INF/peopleEntryArea.xml b/org.argeo.app.ui/OSGI-INF/peopleEntryArea.xml index c68a753..6cf2f9a 100644 --- a/org.argeo.app.ui/OSGI-INF/peopleEntryArea.xml +++ b/org.argeo.app.ui/OSGI-INF/peopleEntryArea.xml @@ -1,9 +1,10 @@ - + - + + diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/SuiteApp.java b/org.argeo.app.ui/src/org/argeo/app/ui/SuiteApp.java index f6770db..e0a21c6 100644 --- a/org.argeo.app.ui/src/org/argeo/app/ui/SuiteApp.java +++ b/org.argeo.app.ui/src/org/argeo/app/ui/SuiteApp.java @@ -21,6 +21,12 @@ import javax.jcr.nodetype.NodeType; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; +import org.argeo.api.acr.Content; +import org.argeo.api.acr.ContentRepository; +import org.argeo.api.acr.ContentSession; +import org.argeo.api.acr.spi.ProvidedSession; +import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsSession; import org.argeo.api.cms.CmsTheme; import org.argeo.api.cms.CmsUi; @@ -30,15 +36,16 @@ import org.argeo.app.api.EntityNames; import org.argeo.app.api.EntityType; import org.argeo.app.api.RankedObject; import org.argeo.app.core.SuiteUtils; -import org.argeo.api.cms.CmsLog; import org.argeo.cms.AbstractCmsApp; import org.argeo.cms.CmsUserManager; import org.argeo.cms.LocaleUtils; import org.argeo.cms.Localized; import org.argeo.cms.jcr.CmsJcrUtils; +import org.argeo.cms.jcr.acr.JcrContentProvider; import org.argeo.cms.swt.CmsSwtUtils; import org.argeo.cms.swt.dialogs.CmsFeedback; import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ux.CmsUxUtils; import org.argeo.eclipse.ui.specific.UiContext; import org.argeo.jcr.Jcr; import org.argeo.jcr.JcrException; @@ -89,6 +96,11 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { // TODO make more optimal or via CmsSession/CmsView private Map managedUis = new HashMap<>(); + // ACR + private ContentRepository contentRepository; + private JcrContentProvider jcrContentProvider; + + // JCR private Repository repository; public void init(Map properties) { @@ -178,6 +190,9 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { if (uiName == null) throw new IllegalStateException("UI name should not be null"); CmsView cmsView = CmsSwtUtils.getCmsView(ui); + + ContentSession contentSession = CmsUxUtils.getContentSession(contentRepository, cmsView); + CmsUiProvider headerUiProvider = findUiProvider(headerPid); CmsUiProvider footerUiProvider = findUiProvider(footerPid); CmsUiProvider leadPaneUiProvider; @@ -207,17 +222,21 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { if (LOGIN.equals(state)) state = null; CmsSession cmsSession = cmsView.getCmsSession(); - if (ui.getUserDir() == null) { + if (ui.getUserDirNode() == null) { // FIXME NPE on CMSSession when logging in from anonymous if (cmsSession == null || cmsView.isAnonymous()) { assert publicBasePath != null; - ui.initSessions(getRepository(), publicBasePath); + Content userDir = contentSession.get(CmsConstants.SYS_WORKSPACE + publicBasePath); + ui.setUserDir(userDir); +// ui.initSessions(getRepository(), publicBasePath); } else { Session adminSession = null; try { adminSession = CmsJcrUtils.openDataAdminSession(getRepository(), null); - Node userDir = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession); - ui.initSessions(getRepository(), userDir.getPath()); + Node userDirNode = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession); + Content userDir = contentSession.get(CmsConstants.SYS_WORKSPACE + userDirNode.getPath()); + ui.setUserDir(userDir); +// ui.initSessions(getRepository(), userDirNode.getPath()); } finally { Jcr.logout(adminSession); } @@ -226,7 +245,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { initLocale(cmsSession); context = stateToNode(ui, state); if (context == null) - context = ui.getUserDir(); + context = ui.getUserDirNode(); if (headerUiProvider != null) refreshPart(headerUiProvider, ui.getHeader(), context); @@ -417,7 +436,11 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { path = "/"; } } - Session session = suiteUi.getSession(workspace); + + ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository, + suiteUi.getCmsView()); + Session session = jcrContentProvider.getJcrSession(contentSession, workspace); +// Session session = suiteUi.getSession(workspace); if (session == null) return null; Node node = Jcr.getNode(session, path); @@ -469,12 +492,12 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { throw new IllegalArgumentException("No layer '" + layerId + "' available."); Localized layerTitle = suiteLayer.getTitle(); // FIXME make sure we don't rebuild the work area twice - Composite workArea = ui.getCmsView().doAs(() -> ui.switchToLayer(layerId, ui.getUserDir())); + Composite workArea = ui.getCmsView().doAs(() -> ui.switchToLayer(layerId, ui.getUserDirNode())); String title = null; if (layerTitle != null) title = layerTitle.lead(); Node nodeFromState = getNode(ui, event); - if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDir().getPath())) { + if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDirNode().getPath())) { // default layer view is forced String state = defaultLayerPid.equals(layerId) ? "~" : layerId; ui.getCmsView().stateChanged(state, appTitle + title); @@ -506,11 +529,16 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { } private Node getNode(SuiteUi ui, Event event) { + ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository, + ui.getCmsView()); + String nodePath = get(event, SuiteEvent.NODE_PATH); if (nodePath != null && nodePath.equals(HOME_STATE)) - return ui.getUserDir(); - String workspaceName = get(event, SuiteEvent.WORKSPACE); - Session session = ui.getSession(workspaceName); + return ui.getUserDirNode(); + String workspace = get(event, SuiteEvent.WORKSPACE); + + Session session = jcrContentProvider.getJcrSession(contentSession, workspace); +// Session session = ui.getSession(workspace); Node node; if (nodePath == null) { // look for a user @@ -532,7 +560,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { else { Session adminSession = null; try { - adminSession = CmsJcrUtils.openDataAdminSession(getRepository(), workspaceName); + adminSession = CmsJcrUtils.openDataAdminSession(getRepository(), workspace); SuiteUtils.getOrCreateUserNode(adminSession, userDn); } finally { Jcr.logout(adminSession); @@ -632,7 +660,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { this.cmsUserManager = cmsUserManager; } - public Repository getRepository() { + protected Repository getRepository() { return repository; } @@ -640,4 +668,16 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { this.repository = repository; } + protected ContentRepository getContentRepository() { + return contentRepository; + } + + public void setContentRepository(ContentRepository contentRepository) { + this.contentRepository = contentRepository; + } + + public void setJcrContentProvider(JcrContentProvider jcrContentProvider) { + this.jcrContentProvider = jcrContentProvider; + } + } diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/SuiteEvent.java b/org.argeo.app.ui/src/org/argeo/app/ui/SuiteEvent.java index 6eaa607..c80be8e 100644 --- a/org.argeo.app.ui/src/org/argeo/app/ui/SuiteEvent.java +++ b/org.argeo.app.ui/src/org/argeo/app/ui/SuiteEvent.java @@ -5,6 +5,7 @@ import java.util.Map; import javax.jcr.Node; +import org.argeo.api.acr.Content; import org.argeo.api.cms.CmsEvent; import org.argeo.jcr.Jcr; import org.osgi.service.useradmin.User; @@ -14,15 +15,25 @@ public enum SuiteEvent implements CmsEvent { openNewPart, refreshPart, switchLayer; public final static String LAYER = "layer"; -// public final static String NODE_ID = "nodeId"; - public final static String NODE_PATH = "path"; public final static String USERNAME = "username"; + + // ACR + public final static String CONTENT_PATH = "contentPath"; + + // JCR + public final static String NODE_PATH = "path"; public final static String WORKSPACE = "workspace"; public String getTopicBase() { return "argeo/suite/ui"; } + public static Map eventProperties(Content content) { + Map properties = new HashMap<>(); + properties.put(CONTENT_PATH, content.getPath()); + return properties; + } + public static Map eventProperties(Node node) { Map properties = new HashMap<>(); properties.put(NODE_PATH, Jcr.getPath(node)); diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/SuiteUi.java b/org.argeo.app.ui/src/org/argeo/app/ui/SuiteUi.java index b2e4385..2e0007b 100644 --- a/org.argeo.app.ui/src/org/argeo/app/ui/SuiteUi.java +++ b/org.argeo.app.ui/src/org/argeo/app/ui/SuiteUi.java @@ -4,17 +4,14 @@ import java.util.HashMap; import java.util.Map; import javax.jcr.Node; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; +import org.argeo.api.acr.Content; +import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsUi; import org.argeo.api.cms.CmsView; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsConstants; import org.argeo.cms.Localized; +import org.argeo.cms.jcr.acr.JcrContent; import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.jcr.Jcr; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Composite; @@ -32,9 +29,9 @@ class SuiteUi extends Composite implements CmsUi { private Composite sidePane; private Composite dynamicArea; - private Session sysSession; - private Session homeSession; - private Node userDir; +// private Session sysSession; +// private Session homeSession; + private Content userDir; private Map layers = new HashMap<>(); private Map workAreas = new HashMap<>(); @@ -123,7 +120,7 @@ class SuiteUi extends Composite implements CmsUi { } if (context == null) { if (!cmsView.isAnonymous()) - context = userDir; + context = getUserDirNode(); } Composite toShow = getLayer(layerId, context); if (toShow != null) { @@ -180,8 +177,8 @@ class SuiteUi extends Composite implements CmsUi { synchronized void logout() { userDir = null; - Jcr.logout(sysSession); - Jcr.logout(homeSession); +// Jcr.logout(sysSession); +// Jcr.logout(homeSession); currentLayerId = null; workAreas.clear(); } @@ -214,34 +211,40 @@ class SuiteUi extends Composite implements CmsUi { // return sysSession; // } // - synchronized void initSessions(Repository repository, String userDirPath) throws RepositoryException { - this.sysSession = repository.login(); - this.homeSession = repository.login(CmsConstants.HOME_WORKSPACE); - userDir = sysSession.getNode(userDirPath); - addDisposeListener((e) -> { - Jcr.logout(sysSession); - Jcr.logout(homeSession); - }); - } +// synchronized void initSessions(Repository repository, String userDirPath) throws RepositoryException { +// this.sysSession = repository.login(); +// this.homeSession = repository.login(CmsConstants.HOME_WORKSPACE); +// userDir = sysSession.getNode(userDirPath); +// addDisposeListener((e) -> { +// Jcr.logout(sysSession); +// Jcr.logout(homeSession); +// }); +// } - Node getUserDir() { - return userDir; + Node getUserDirNode() { + if (userDir == null) + return null; + return ((JcrContent) userDir).getJcrNode(); } - Session getSysSession() { - return sysSession; + void setUserDir(Content userDir) { + this.userDir = userDir; } - Session getSession(String workspaceName) { - if (workspaceName == null) - return sysSession; - if (CmsConstants.SYS_WORKSPACE.equals(workspaceName)) - return sysSession; - else if (CmsConstants.HOME_WORKSPACE.equals(workspaceName)) - return homeSession; - else - throw new IllegalArgumentException("Unknown workspace " + workspaceName); - } +// Session getSysSession() { +// return sysSession; +// } + +// Session getSession(String workspaceName) { +// if (workspaceName == null) +// return sysSession; +// if (CmsConstants.SYS_WORKSPACE.equals(workspaceName)) +// return sysSession; +// else if (CmsConstants.HOME_WORKSPACE.equals(workspaceName)) +// return homeSession; +// else +// throw new IllegalArgumentException("Unknown workspace " + workspaceName); +// } public CmsView getCmsView() { return cmsView; diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/people/UsersEntryArea.java b/org.argeo.app.ui/src/org/argeo/app/ui/people/UsersEntryArea.java new file mode 100644 index 0000000..b7720ae --- /dev/null +++ b/org.argeo.app.ui/src/org/argeo/app/ui/people/UsersEntryArea.java @@ -0,0 +1,149 @@ +package org.argeo.app.ui.people; + +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.api.acr.Content; +import org.argeo.api.cms.CmsTheme; +import org.argeo.app.ui.SuiteEvent; +import org.argeo.app.ui.SuiteIcon; +import org.argeo.app.ui.dialogs.NewUserWizard; +import org.argeo.cms.CmsUserManager; +import org.argeo.cms.jcr.acr.JcrContent; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.swt.Selected; +import org.argeo.cms.swt.acr.SwtUiProvider; +import org.argeo.cms.swt.dialogs.CmsWizardDialog; +import org.argeo.cms.ui.CmsUiProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.osgi.service.useradmin.Group; +import org.osgi.service.useradmin.User; + +/** Entry to the admin area. */ +public class UsersEntryArea implements SwtUiProvider, CmsUiProvider { + + private CmsUserManager cmsUserManager; + + @Override + public Control createUiPart(Composite parent, Content context) { + CmsTheme theme = CmsSwtUtils.getCmsTheme(parent); + parent.setLayout(new GridLayout()); + + List orgs = cmsUserManager.listGroups(null, true, false); + + final Tree tree = new Tree(parent, SWT.VIRTUAL | SWT.BORDER); + tree.addListener(SWT.SetData, event -> { + TreeItem item = (TreeItem) event.item; + TreeItem parentItem = item.getParentItem(); + String text = null; + if (parentItem == null) { + int index = tree.indexOf(item); + User org = (User) orgs.get(index); + item.setData(org); + text = org.getName(); + } else { + text = parentItem.getText() + " - " + parentItem.indexOf(item); + } + item.setText(text); + item.setItemCount(10); + }); + tree.setItemCount(orgs.size()); + tree.setLayoutData(CmsSwtUtils.fillAll()); + + Composite bottom = new Composite(parent, SWT.NONE); + bottom.setLayoutData(CmsSwtUtils.fillWidth()); + bottom.setLayout(CmsSwtUtils.noSpaceGridLayout()); + ToolBar bottomToolBar = new ToolBar(bottom, SWT.NONE); + bottomToolBar.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); + ToolItem deleteItem = new ToolItem(bottomToolBar, SWT.FLAT); + deleteItem.setEnabled(false); +// CmsUiUtils.style(deleteItem, SuiteStyle.recentItems); + deleteItem.setImage(SuiteIcon.delete.getSmallIcon(theme)); + ToolItem addItem = new ToolItem(bottomToolBar, SWT.FLAT); + addItem.setImage(SuiteIcon.add.getSmallIcon(theme)); + +// tree.addSelectionListener((Selected) (e) -> { +// User user = (User) e.item.getData(); +// if (user != null) { +// CmsSwtUtils.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), +// SuiteEvent.eventProperties(user)); +// deleteItem.setEnabled(true); +// } else { +// deleteItem.setEnabled(false); +// } +// }); +// tree.addListener(SWT.MouseDoubleClick, (e) -> { +// User user = (User) e.item.getData(); +// if (user != null) { +// CmsSwtUtils.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), +// SuiteEvent.eventProperties(user)); +// } +// +// }); + + tree.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + User user = (User) e.item.getData(); + if (user != null) { + CmsSwtUtils.getCmsView(parent).sendEvent(SuiteEvent.refreshPart.topic(), + SuiteEvent.eventProperties(user)); + deleteItem.setEnabled(true); + } else { + deleteItem.setEnabled(false); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + User user = (User) e.item.getData(); + if (user != null) { + CmsSwtUtils.getCmsView(parent).sendEvent(SuiteEvent.openNewPart.topic(), + SuiteEvent.eventProperties(user)); + } + } + }); + + addItem.addSelectionListener((Selected) (e) -> { + // SuiteUtils.getOrCreateUserNode(adminSession, userDn); + Wizard wizard = new NewUserWizard(null); + CmsWizardDialog dialog = new CmsWizardDialog(parent.getShell(), wizard); + // WizardDialog dialog = new WizardDialog(shell, wizard); + if (dialog.open() == Window.OK) { + // TODO create + } + }); + + return tree; + } + + private String getUserProperty(Object element, String key) { + Object value = ((User) element).getProperties().get(key); + return value != null ? value.toString() : null; + } + + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; + } + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + return createUiPart(parent, JcrContent.nodeToContent(context)); + } + +} diff --git a/org.argeo.app.ui/src/org/argeo/app/ui/publish/PublishingApp.java b/org.argeo.app.ui/src/org/argeo/app/ui/publish/PublishingApp.java index d57706c..6e32012 100644 --- a/org.argeo.app.ui/src/org/argeo/app/ui/publish/PublishingApp.java +++ b/org.argeo.app.ui/src/org/argeo/app/ui/publish/PublishingApp.java @@ -97,9 +97,9 @@ public class PublishingApp extends AbstractCmsApp implements EventHandler { Composite parent = (Composite) cmsUi; parent.setLayout(new GridLayout()); if (landingPage != null) - landingPage.createUiPart(parent, null); + landingPage.createUiPart(parent, (Node) null); else - defaultProvider.createUiPart(parent, null); + defaultProvider.createUiPart(parent, (Node) null); } @Override -- 2.30.2