+ Refactor Users Page
authorBruno Sinou <bsinou@argeo.org>
Thu, 26 Mar 2015 14:31:40 +0000 (14:31 +0000)
committerBruno Sinou <bsinou@argeo.org>
Thu, 26 Mar 2015 14:31:40 +0000 (14:31 +0000)
+ and a constant and an utils method to set RWT specific item height parameter on table with RWT custom variant set.

git-svn-id: https://svn.argeo.org/commons/trunk@8040 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.cms/src/org/argeo/cms/CmsApplication.java
org.argeo.cms/src/org/argeo/cms/CmsConstants.java
org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java [deleted file]
org.argeo.cms/src/org/argeo/cms/users/Users.java [deleted file]
org.argeo.cms/src/org/argeo/cms/users/UsersPage.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java
org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java
org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java

index f722befeb201007e59c3ecbe7c61313075279567..d6341e5b346322311d69d39c7c6fa070c6f1ccaf 100644 (file)
@@ -148,12 +148,12 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration,
        }
 
        public void init() throws RepositoryException {
-//             if (workspace == null)
-//                     throw new CmsException(
-//                                     "Workspace must be set when calling initialization."
-//                                                     + " Please make sure that read-only and read-write roles"
-//                                                     + " have been properly configured:"
-//                                                     + " the defaults are open.");
+               // if (workspace == null)
+               // throw new CmsException(
+               // "Workspace must be set when calling initialization."
+               // + " Please make sure that read-only and read-write roles"
+               // + " have been properly configured:"
+               // + " the defaults are open.");
 
                Session session = null;
                try {
@@ -318,7 +318,9 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration,
                                bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY);
                                bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
                                                true));
-                               bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT);
+                               // Should not be set here: it then prevent all children
+                               // composite to define a background color via CSS
+                               // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT);
                                bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
                                refreshBody();
                        } catch (Exception e) {
index cae0167c87904f23a19ea5103b1ee06ab24a47c3..df8c02fb82661de55e1e46c120df49ab971537ae 100644 (file)
@@ -8,6 +8,7 @@ public interface CmsConstants {
        // DATAKEYS
        public final static String STYLE = RWT.CUSTOM_VARIANT;
        public final static String MARKUP = RWT.MARKUP_ENABLED;
+       public final static String ITEM_HEIGHT = RWT.CUSTOM_ITEM_HEIGHT;
 
        // STANDARD RESOURCES
        public final static String LOADING_IMAGE = "icons/loading.gif";
diff --git a/org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java b/org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java
deleted file mode 100644 (file)
index 6b522f5..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-package org.argeo.cms.users;
-
-import java.util.Observable;
-import java.util.Observer;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.cms.CmsEditable;
-import org.argeo.cms.CmsException;
-import org.argeo.cms.util.CmsUtils;
-import org.argeo.cms.viewers.EditablePart;
-import org.argeo.cms.viewers.JcrVersionCmsEditable;
-import org.eclipse.jface.viewers.ContentViewer;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Widget;
-
-/** Manage edition of the users */
-public class UserViewerOld extends ContentViewer implements Observer {
-       private static final long serialVersionUID = -5055220955004863645L;
-
-       private final static Log log = LogFactory.getLog(UserViewerOld.class);
-
-       // private UserPart userPart = new UserPart();
-
-       private CmsEditable cmsEditable;
-       private Node currentDisplayed;
-
-       /** The basis for the layouts, typically the body of a ScrolledPage. */
-       private final Composite page;
-
-       private MouseListener mouseListener;
-
-       private EditablePart edited;
-       private ISelection selection = StructuredSelection.EMPTY;
-
-       protected UserViewerOld(Composite composite) {
-               page = composite;
-       }
-
-       void setDisplayedUser(Node node) {
-               try {
-
-                       if (!hasChanged(node))
-                               return;
-
-                       CmsUtils.clear(page);
-                       // userPart.createUi(page, node);
-                       
-                       page.layout();
-                       page.getParent().layout();
-
-                       // update
-                       cmsEditable = new JcrVersionCmsEditable(node);
-
-                       if (this.cmsEditable instanceof Observable)
-                               ((Observable) this.cmsEditable).addObserver(this);
-                       // // if (cmsEditable.canEdit()) {
-                       // // mouseListener = createMouseListener();
-                       // // refresh();
-                       // // }
-               } catch (RepositoryException re) {
-                       throw new ArgeoException("Unable to display " + node, re);
-               }
-       }
-
-       private boolean hasChanged(Node node) throws RepositoryException {
-               if (currentDisplayed == null && node == null)
-                       return false;
-               else if (currentDisplayed == null || node == null)
-                       return true;
-               else
-                       return node.getIdentifier()
-                                       .equals(currentDisplayed.getIdentifier());
-       }
-
-       /** Create (retrieve) the MouseListener to use. */
-       protected MouseListener createMouseListener() {
-               return new MouseAdapter() {
-                       private static final long serialVersionUID = 1L;
-               };
-       }
-
-       @Override
-       public void update(Observable o, Object arg) {
-               if (o == cmsEditable)
-                       editingStateChanged(cmsEditable);
-       }
-
-       /** To be overridden in order to provide the actual refresh */
-       protected void refresh(Control control) throws RepositoryException {
-       }
-
-       /** To be overridden.Save the edited part. */
-       protected void save(EditablePart part) throws RepositoryException {
-       }
-
-       /** Prepare the edited part */
-       protected void prepare(EditablePart part, Object caretPosition) {
-       }
-
-       /** Notified when the editing state changed. Does nothing, to be overridden */
-       protected void editingStateChanged(CmsEditable cmsEditable) {
-       }
-
-       @Override
-       public Control getControl() {
-               return null;
-       }
-
-       @Override
-       public void refresh() {
-               try {
-                       // if (cmsEditable.canEdit() && !readOnly)
-                       // mouseListener = createMouseListener();
-                       // else
-                       // mouseListener = null;
-                       refresh(getControl());
-                       layout(getControl());
-               } catch (RepositoryException e) {
-                       throw new CmsException("Cannot refresh", e);
-               }
-       }
-
-       @Override
-       public void setSelection(ISelection selection, boolean reveal) {
-               this.selection = selection;
-       }
-
-       protected void updateContent(EditablePart part) throws RepositoryException {
-       }
-
-       // LOW LEVEL EDITION
-       protected void edit(EditablePart part, Object caretPosition) {
-               try {
-                       if (edited == part)
-                               return;
-
-                       if (edited != null && edited != part)
-                               stopEditing(true);
-
-                       part.startEditing();
-                       updateContent(part);
-                       prepare(part, caretPosition);
-                       edited = part;
-                       layout(part.getControl());
-               } catch (RepositoryException e) {
-                       throw new CmsException("Cannot edit " + part, e);
-               }
-       }
-
-       private void stopEditing(Boolean save) throws RepositoryException {
-               if (edited instanceof Widget && ((Widget) edited).isDisposed()) {
-                       edited = null;
-                       return;
-               }
-
-               assert edited != null;
-               if (edited == null) {
-                       if (log.isTraceEnabled())
-                               log.warn("Told to stop editing while not editing anything");
-                       return;
-               }
-
-               if (save)
-                       save(edited);
-
-               edited.stopEditing();
-               updateContent(edited);
-               layout(((EditablePart) edited).getControl());
-               edited = null;
-       }
-
-       // METHODS AVAILABLE TO EXTENDING CLASSES
-       protected void saveEdit() {
-               try {
-                       if (edited != null)
-                               stopEditing(true);
-               } catch (RepositoryException e) {
-                       throw new CmsException("Cannot stop editing", e);
-               }
-       }
-
-       protected void cancelEdit() {
-               try {
-                       if (edited != null)
-                               stopEditing(false);
-               } catch (RepositoryException e) {
-
-                       throw new CmsException("Cannot cancel editing", e);
-               }
-       }
-
-       /** Layout this controls from the related base page. */
-       public void layout(Control... controls) {
-               page.layout(controls);
-       }
-
-       // UTILITIES
-       /** Check whether the edited part is in a proper state */
-       protected void checkEdited() {
-               if (edited == null || (edited instanceof Widget)
-                               && ((Widget) edited).isDisposed())
-                       throw new CmsException(
-                                       "Edited should not be null or disposed at this stage");
-       }
-
-       // GETTERS / SETTERS
-       protected EditablePart getEdited() {
-               return edited;
-       }
-
-       public MouseListener getMouseListener() {
-               return mouseListener;
-       }
-
-       public CmsEditable getCmsEditable() {
-               return cmsEditable;
-       }
-
-       @Override
-       public ISelection getSelection() {
-               return selection;
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.cms/src/org/argeo/cms/users/Users.java b/org.argeo.cms/src/org/argeo/cms/users/Users.java
deleted file mode 100644 (file)
index 2637ed4..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-package org.argeo.cms.users;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.Privilege;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.cms.CmsUiProvider;
-import org.argeo.cms.maintenance.NonAdminPage;
-import org.argeo.cms.util.CmsUtils;
-import org.argeo.eclipse.ui.parts.UsersTable;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.UserAdminService;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.springframework.security.provisioning.UserDetailsManager;
-
-/**
- * Simple page to manage users of a given repository. We still rely on Argeo
- * model; with user stored in the main workspace
- */
-public class Users implements CmsUiProvider {
-
-       private final static Log log = LogFactory.getLog(Users.class);
-
-       // Enable user CRUD // INJECTED
-       private UserAdminService userAdminService;
-       // private UserDetailsManager userDetailsManager;
-       private String userWkspName;
-
-       // Local UI Providers
-       NonAdminPage nap = new NonAdminPage();
-       UserPage userPage = new UserPage();
-
-       // Manage authorization
-       @Override
-       public Control createUi(Composite parent, Node context)
-                       throws RepositoryException {
-               if (isAdmin(context)) {
-                       Session session = context.getSession().getRepository()
-                                       .login(userWkspName);
-                       return createMainLayout(parent, session);
-               } else
-                       nap.createUi(parent, context);
-               return null;
-       }
-
-       // Main layout
-       // Left: User Table - Right User Details Edition
-       private Control createMainLayout(Composite parent, final Session session)
-                       throws RepositoryException {
-
-               Composite layoutCmp = new Composite(parent, SWT.NO_FOCUS);
-               layoutCmp.setLayoutData(CmsUtils.fillAll());
-               layoutCmp
-                               .setLayout(CmsUtils.noSpaceGridLayout(new GridLayout(2, true)));
-
-               Composite left = new Composite(layoutCmp, SWT.NO_FOCUS);
-               left.setLayoutData(CmsUtils.fillAll());
-               UsersTable table = createUsersTable(left, session);
-
-               final Composite right = new Composite(layoutCmp, SWT.NO_FOCUS);
-               right.setLayoutData(CmsUtils.fillAll());
-               // Composite innerPage = createUserPage(right);
-               // final UserViewerOld userViewer = new UserViewerOld(innerPage);
-
-               final TableViewer viewer = table.getTableViewer();
-               viewer.addSelectionChangedListener(new ISelectionChangedListener() {
-
-                       @Override
-                       public void selectionChanged(SelectionChangedEvent event) {
-                               IStructuredSelection selection = (IStructuredSelection) viewer
-                                               .getSelection();
-                               if (selection.isEmpty()) {
-                                       // Should we clean the right column?
-                                       return;
-                               } else {
-                                       Node context = (Node) selection.getFirstElement();
-                                       try {
-                                               CmsUtils.clear(right);
-                                               userPage.createUi(right, context);
-                                               right.layout();
-                                               right.getParent().layout();
-                                       } catch (RepositoryException e) {
-                                               e.printStackTrace();
-                                               throw new ArgeoException("unable to create "
-                                                               + "editor for user " + context, e);
-                                       }
-                               }
-                       }
-               });
-               return left;
-       }
-
-       private UsersTable createUsersTable(Composite parent, final Session session)
-                       throws RepositoryException {
-               parent.setLayout(CmsUtils.noSpaceGridLayout());
-
-               // Add user CRUD buttons
-               Composite buttonCmp = new Composite(parent, SWT.NO_FOCUS);
-               buttonCmp.setLayoutData(CmsUtils.fillWidth());
-               buttonCmp.setLayout(new GridLayout(2, false));
-               // Delete
-               final Button deleteBtn = new Button(buttonCmp, SWT.PUSH);
-               deleteBtn.setText("Delete selected");
-               deleteBtn
-                               .setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
-
-               // Add
-               final Button addBtn = new Button(buttonCmp, SWT.PUSH);
-               addBtn.setText("Create");
-
-               // Create the composite that displays the list and a filter
-               final UsersTable userTableCmp = new UsersTable(parent, SWT.NO_FOCUS,
-                               session);
-               userTableCmp.populate(true, false);
-               userTableCmp.setLayoutData(CmsUtils.fillAll());
-
-               // The various listeners
-               userTableCmp.addDisposeListener(new DisposeListener() {
-                       private static final long serialVersionUID = -8854052549807709846L;
-
-                       @Override
-                       public void widgetDisposed(DisposeEvent event) {
-                               JcrUtils.logoutQuietly(session);
-                       }
-               });
-
-               deleteBtn.addSelectionListener(new SelectionAdapter() {
-                       private static final long serialVersionUID = -7340611909297995666L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-
-                               TableViewer viewer = userTableCmp.getTableViewer();
-                               ISelection selection = viewer.getSelection();
-                               if (selection.isEmpty())
-                                       return;
-
-                               Map<String, Node> toDelete = new TreeMap<String, Node>();
-                               @SuppressWarnings("unchecked")
-                               Iterator<Node> it = ((IStructuredSelection) selection)
-                                               .iterator();
-                               nodes: while (it.hasNext()) {
-                                       Node profileNode = it.next();
-                                       try {
-                                               String userName = profileNode.getProperty(
-                                                               ArgeoNames.ARGEO_USER_ID).getString();
-                                               if (userName.equals(profileNode.getSession()
-                                                               .getUserID())) {
-                                                       log.warn("Cannot delete its own user: " + userName);
-                                                       continue nodes;
-                                               }
-                                               toDelete.put(userName, profileNode);
-                                       } catch (RepositoryException re) {
-                                               log.warn("Cannot interpred user " + profileNode);
-                                       }
-                               }
-
-                               if (!MessageDialog.openQuestion(
-                                               userTableCmp.getShell(),
-                                               "Delete User",
-                                               "Are you sure that you want to delete users "
-                                                               + toDelete.keySet()
-                                                               + "?\n"
-                                                               + "This may lead to inconsistencies in the application."))
-                                       return;
-
-                               for (String username : toDelete.keySet()) {
-                                       Session session = null;
-                                       try {
-                                               Node profileNode = toDelete.get(username);
-                                               userAdminService.deleteUser(username);
-                                               profileNode.getParent().remove();
-                                               session = profileNode.getSession();
-                                               session.save();
-                                       } catch (RepositoryException re) {
-                                               JcrUtils.discardQuietly(session);
-                                               throw new ArgeoException("Cannot list users", re);
-                                       }
-                               }
-                               userTableCmp.refresh();
-                       }
-               });
-
-               addBtn.addSelectionListener(new SelectionAdapter() {
-                       private static final long serialVersionUID = 9214984636836267786L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               NewUserWizard newUserWizard = new NewUserWizard(session,
-                                               userAdminService);
-                               WizardDialog dialog = new WizardDialog(addBtn.getShell(),
-                                               newUserWizard);
-                               if (dialog.open() == Dialog.OK)
-                                       userTableCmp.refresh();
-                       }
-               });
-
-               // Configure
-               // userTableCmp.getTableViewer().addDoubleClickListener(
-               // new ViewDoubleClickListener());
-               // getViewSite().setSelectionProvider(userTableCmp.getTableViewer());
-
-               // Add listener to refresh the list when something changes
-               // userStructureListener = new JcrUserListener(getSite().getShell()
-               // .getDisplay());
-               // JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED
-               // | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null);
-               // userPropertiesListener = new JcrUserListener(getSite().getShell()
-               // .getDisplay());
-               // JcrUtils.addListener(session, userStructureListener,
-               // Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED
-               // | Event.PROPERTY_REMOVED,
-               // ArgeoJcrConstants.PEOPLE_BASE_PATH,
-               // ArgeoTypes.ARGEO_USER_PROFILE);
-
-               return userTableCmp;
-       }
-
-       // protected Composite createUserPage(Composite parent) {
-       // parent.setLayout(CmsUtils.noSpaceGridLayout());
-       // ScrolledPage scrolled = new ScrolledPage(parent, SWT.NONE);
-       // scrolled.setLayoutData(CmsUtils.fillAll());
-       // scrolled.setLayout(CmsUtils.noSpaceGridLayout());
-       // // TODO manage style
-       // // CmsUtils.style(scrolled, "maintenance_user_form");
-       //
-       // Composite page = new Composite(scrolled, SWT.NONE);
-       // page.setLayout(CmsUtils.noSpaceGridLayout());
-       // page.setBackgroundMode(SWT.INHERIT_NONE);
-       //
-       // return page;
-       // }
-
-       private boolean isAdmin(Node node) throws RepositoryException {
-               // FIXME clean this once new user management policy has been
-               // implemented.
-               AccessControlManager acm = node.getSession().getAccessControlManager();
-               Privilege[] privs = new Privilege[1];
-               privs[0] = acm.privilegeFromName(Privilege.JCR_ALL);
-               return acm.hasPrivileges("/", privs);
-       }
-
-       // @Override
-       // public void dispose() {
-       // JcrUtils.removeListenerQuietly(session, userStructureListener);
-       // JcrUtils.removeListenerQuietly(session, userPropertiesListener);
-       // JcrUtils.logoutQuietly(session);
-       // super.dispose();
-       // }
-       //
-       // // public void setSession(Session session) {
-       // // this.session = session;
-       // // }
-       //
-       // public void refresh() {
-       // this.getSite().getShell().getDisplay().asyncExec(new Runnable() {
-       // @Override
-       // public void run() {
-       // userTableCmp.refresh();
-       // }
-       // });
-       // }
-       //
-       // private class JcrUserListener implements EventListener {
-       // private final Display display;
-       //
-       // public JcrUserListener(Display display) {
-       // super();
-       // this.display = display;
-       // }
-       //
-       // @Override
-       // public void onEvent(EventIterator events) {
-       // display.asyncExec(new Runnable() {
-       // @Override
-       // public void run() {
-       // userTableCmp.refresh();
-       // }
-       // });
-       // }
-       // }
-       //
-       // class ViewDoubleClickListener implements IDoubleClickListener {
-       // public void doubleClick(DoubleClickEvent evt) {
-       // if (evt.getSelection().isEmpty())
-       // return;
-       //
-       // Object obj = ((IStructuredSelection) evt.getSelection())
-       // .getFirstElement();
-       // if (obj instanceof Node) {
-       // try {
-       // String username = ((Node) obj).getProperty(ARGEO_USER_ID)
-       // .getString();
-       // String commandId = OpenArgeoUserEditor.COMMAND_ID;
-       // String paramName = OpenArgeoUserEditor.PARAM_USERNAME;
-       // CommandUtils.callCommand(commandId, paramName, username);
-       // } catch (RepositoryException e) {
-       // throw new ArgeoException("Cannot open user editor", e);
-       // }
-       // }
-       // }
-
-       /* DEPENDENCY INJECTION */
-       public void setWorkspaceName(String workspaceName) {
-               this.userWkspName = workspaceName;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-               userPage.setUserAdminService(userAdminService);
-       }
-
-       public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
-               // this.userDetailsManager = userDetailsManager;
-               // userPage.setUserDetailsManager(userDetailsManager);
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.cms/src/org/argeo/cms/users/UsersPage.java b/org.argeo.cms/src/org/argeo/cms/users/UsersPage.java
new file mode 100644 (file)
index 0000000..d5bfeb7
--- /dev/null
@@ -0,0 +1,274 @@
+package org.argeo.cms.users;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.cms.CmsUiProvider;
+import org.argeo.cms.maintenance.NonAdminPage;
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.eclipse.ui.parts.UsersTable;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+/**
+ * Simple page to manage users of a given repository. It relies on Argeo user
+ * model: user profile nodes are stored in the main workspace
+ */
+public class UsersPage implements CmsUiProvider {
+       private final static Log log = LogFactory.getLog(UsersPage.class);
+
+       /* DEPENDENCY INJECTION */
+       private UserAdminService userAdminService;
+       private String userWkspName;
+
+       // TODO use a constant
+       private final static String ROLE_USER_ADMIN = "ROLE_USER_ADMIN";
+
+       // Local UI Providers
+       private NonAdminPage nap = new NonAdminPage();
+       private UserPage userPage = new UserPage();
+
+       @Override
+       public Control createUi(Composite parent, Node context)
+                       throws RepositoryException {
+               // This page is only visible to user with role USER_ADMIN
+               if (isAdmin(context)) {
+                       Session session = context.getSession().getRepository()
+                                       .login(userWkspName);
+                       return createMainLayout(parent, session);
+               } else
+                       nap.createUi(parent, context);
+               return null;
+       }
+
+       // Main layout
+       // Left: User Table - Right User Details Edition
+       private Control createMainLayout(Composite parent, final Session session)
+                       throws RepositoryException {
+
+               Composite layoutCmp = new Composite(parent, SWT.NO_FOCUS);
+               layoutCmp.setLayoutData(CmsUtils.fillAll());
+               layoutCmp
+                               .setLayout(CmsUtils.noSpaceGridLayout(new GridLayout(2, true)));
+
+               Composite left = new Composite(layoutCmp, SWT.NO_FOCUS);
+               left.setLayoutData(CmsUtils.fillAll());
+               UsersTable table = createUsersTable(left, session);
+
+               final Composite right = new Composite(layoutCmp, SWT.NO_FOCUS);
+               right.setLayoutData(CmsUtils.fillAll());
+
+               final TableViewer viewer = table.getTableViewer();
+               viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+
+                       @Override
+                       public void selectionChanged(SelectionChangedEvent event) {
+                               IStructuredSelection selection = (IStructuredSelection) viewer
+                                               .getSelection();
+                               if (selection.isEmpty()) {
+                                       // Should we clean the right column?
+                                       CmsUtils.clear(right);
+                                       right.layout();
+                                       return;
+                               } else {
+                                       Node context = (Node) selection.getFirstElement();
+                                       try {
+                                               CmsUtils.clear(right);
+                                               userPage.createUi(right, context);
+                                               right.layout();
+                                               right.getParent().layout();
+                                       } catch (RepositoryException e) {
+                                               e.printStackTrace();
+                                               throw new ArgeoException("unable to create "
+                                                               + "editor for user " + context, e);
+                                       }
+                               }
+                       }
+               });
+               return left;
+       }
+
+       private UsersTable createUsersTable(Composite parent, final Session session)
+                       throws RepositoryException {
+               parent.setLayout(CmsUtils.noSpaceGridLayout());
+
+               // Add user CRUD buttons
+               Composite buttonCmp = new Composite(parent, SWT.NO_FOCUS);
+               buttonCmp.setLayoutData(CmsUtils.fillWidth());
+               buttonCmp.setLayout(new GridLayout(2, false));
+               // Delete
+               final Button deleteBtn = new Button(buttonCmp, SWT.PUSH);
+               deleteBtn.setText("Delete selected");
+               deleteBtn
+                               .setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
+
+               // Add
+               final Button addBtn = new Button(buttonCmp, SWT.PUSH);
+               addBtn.setText("Create");
+
+               // Create the composite that displays the list and a filter
+               final UsersTable userTableCmp = new UsersTable(parent, SWT.BORDER,
+                               session);
+               userTableCmp.populate(true, false);
+               userTableCmp.setLayoutData(CmsUtils.fillAll());
+
+               // The various listeners
+               userTableCmp.addDisposeListener(new DisposeListener() {
+                       private static final long serialVersionUID = -8854052549807709846L;
+
+                       @Override
+                       public void widgetDisposed(DisposeEvent event) {
+                               JcrUtils.logoutQuietly(session);
+                       }
+               });
+
+               deleteBtn.addSelectionListener(new SelectionAdapter() {
+                       private static final long serialVersionUID = -7340611909297995666L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+
+                               TableViewer viewer = userTableCmp.getTableViewer();
+                               ISelection selection = viewer.getSelection();
+                               if (selection.isEmpty())
+                                       return;
+
+                               Map<String, Node> toDelete = new TreeMap<String, Node>();
+                               @SuppressWarnings("unchecked")
+                               Iterator<Node> it = ((IStructuredSelection) selection)
+                                               .iterator();
+                               nodes: while (it.hasNext()) {
+                                       Node profileNode = it.next();
+                                       try {
+                                               String userName = profileNode.getProperty(
+                                                               ArgeoNames.ARGEO_USER_ID).getString();
+                                               if (userName.equals(profileNode.getSession()
+                                                               .getUserID())) {
+                                                       log.warn("Cannot delete its own user: " + userName);
+                                                       continue nodes;
+                                               }
+                                               toDelete.put(userName, profileNode);
+                                       } catch (RepositoryException re) {
+                                               log.warn("Cannot interpred user " + profileNode);
+                                       }
+                               }
+
+                               if (!MessageDialog.openQuestion(
+                                               userTableCmp.getShell(),
+                                               "Delete User",
+                                               "Are you sure that you want to delete users "
+                                                               + toDelete.keySet()
+                                                               + "?\n"
+                                                               + "This may lead to inconsistencies in the application."))
+                                       return;
+
+                               for (String username : toDelete.keySet()) {
+                                       Session session = null;
+                                       try {
+                                               Node profileNode = toDelete.get(username);
+                                               userAdminService.deleteUser(username);
+                                               profileNode.getParent().remove();
+                                               session = profileNode.getSession();
+                                               session.save();
+                                       } catch (RepositoryException re) {
+                                               JcrUtils.discardQuietly(session);
+                                               throw new ArgeoException("Cannot list users", re);
+                                       }
+                               }
+                               userTableCmp.refresh();
+                       }
+               });
+
+               addBtn.addSelectionListener(new SelectionAdapter() {
+                       private static final long serialVersionUID = 9214984636836267786L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               NewUserWizard newUserWizard = new NewUserWizard(session,
+                                               userAdminService);
+                               WizardDialog dialog = new WizardDialog(addBtn.getShell(),
+                                               newUserWizard);
+                               if (dialog.open() == Dialog.OK)
+                                       userTableCmp.refresh();
+                       }
+               });
+
+               // Configure
+               // userTableCmp.getTableViewer().addDoubleClickListener(
+               // new ViewDoubleClickListener());
+               // getViewSite().setSelectionProvider(userTableCmp.getTableViewer());
+
+               // Add listener to refresh the list when something changes
+               // userStructureListener = new JcrUserListener(getSite().getShell()
+               // .getDisplay());
+               // JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED
+               // | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null);
+               // userPropertiesListener = new JcrUserListener(getSite().getShell()
+               // .getDisplay());
+               // JcrUtils.addListener(session, userStructureListener,
+               // Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED
+               // | Event.PROPERTY_REMOVED,
+               // ArgeoJcrConstants.PEOPLE_BASE_PATH,
+               // ArgeoTypes.ARGEO_USER_PROFILE);
+
+               return userTableCmp;
+       }
+
+       private boolean isAdmin(Node node) throws RepositoryException {
+               return isUserInRole(ROLE_USER_ADMIN);
+       }
+
+       /**
+        * Returns true if the current user is in the specified role TODO factoize
+        * in the user admin service
+        */
+       private boolean isUserInRole(String role) {
+               Authentication authen = SecurityContextHolder.getContext()
+                               .getAuthentication();
+               for (GrantedAuthority ga : authen.getAuthorities()) {
+                       if (ga.getAuthority().equals(role))
+                               return true;
+               }
+               return false;
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setWorkspaceName(String workspaceName) {
+               this.userWkspName = workspaceName;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+               userPage.setUserAdminService(userAdminService);
+       }
+}
\ No newline at end of file
index c1b319fbe99f348e68e3813a102053917ebc3720..5d31e2c51f0d68639fe64234a69027249e82f5e2 100644 (file)
@@ -23,6 +23,7 @@ import org.eclipse.swt.layout.RowData;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.Widget;
 
 /** Static utilities for the CMS framework. */
@@ -72,6 +73,10 @@ public class CmsUtils implements CmsConstants {
                widget.setData(CmsConstants.MARKUP, true);
        }
 
+       public static void setItemHeight(Table table, int height) {
+               table.setData(CmsConstants.ITEM_HEIGHT, height);
+       }
+
        /** @return the path or null if not instrumented */
        public static String getDataPath(Widget widget) {
                // JCR item
index 3455577ceac63e7679071eb1acf994850b27e759..06f569dce7c216467543d3a4dbfe90fed8c9cf2e 100644 (file)
@@ -20,12 +20,48 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
 
 /** Utilities to simplify UI development. */
 public class EclipseUiUtils {
+       
+       
+       //
+       // Simplify grid layouts management
+       //
+       public static GridLayout noSpaceGridLayout() {
+               return noSpaceGridLayout(new GridLayout());
+       }
+
+       public static GridLayout noSpaceGridLayout(GridLayout layout) {
+               layout.horizontalSpacing = 0;
+               layout.verticalSpacing = 0;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+               return layout;
+       }
+
+       public static GridData fillWidth() {
+               return grabWidth(SWT.FILL, SWT.FILL);
+       }
+
+       public static GridData fillAll() {
+               return new GridData(SWT.FILL, SWT.FILL, true, true);
+       }
+
+       public static GridData grabWidth(int horizontalAlignment,
+                       int verticalAlignment) {
+               return new GridData(horizontalAlignment, horizontalAlignment, true,
+                               false);
+       }
+
+       
+       
+       
+       
        /**
         * Create a label and a text field for a grid layout, the text field grabbing
         * excess horizontal
index 0a7b8d1e055785aee9d49881b0efba3a6935d12d..41afb6a3a02f6ad95e8a859a538980b89ccbb733 100644 (file)
@@ -52,23 +52,21 @@ public class UsersTable extends Composite implements ArgeoNames {
 
        private static final long serialVersionUID = -7385959046279360420L;
 
+       private Session session;
+
+       private boolean hasFilter;
+       private boolean hasSelectionColumn;
+       private int tableStyle;
+
        private TableViewer usersViewer;
        private Text filterTxt;
-       private final static String FILTER_HELP_MSG = "Type filter criterion "
+       private String filterHelpMsg = "Type filter criterion "
                        + "separated by a space";
-       private Session session;
 
        private Font italic;
        private Font bold;
 
-       private boolean hasFilter;
-       private boolean hasSelectionColumn;
-
-       // private List<Node> selectedItems = new ArrayList<Node>();
-
-       /**
-        * Overwrite to display other columns
-        */
+       /** Overwrite to display other columns */
        public List<ColumnDefinition> getColumnsDef() {
                List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
 
@@ -91,7 +89,8 @@ public class UsersTable extends Composite implements ArgeoNames {
        }
 
        public UsersTable(Composite parent, int style, Session session) {
-               super(parent, style);
+               super(parent, SWT.NO_FOCUS);
+               this.tableStyle = style;
                this.session = session;
        }
 
@@ -112,7 +111,9 @@ public class UsersTable extends Composite implements ArgeoNames {
                hasSelectionColumn = addSelection;
 
                // Main Layout
-               this.setLayout(new GridLayout(1, false));
+               GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
+               layout.verticalSpacing = 5;
+               this.setLayout(layout);
                if (hasFilter)
                        createFilterPart(parent);
                usersViewer = createTableViewer(parent);
@@ -140,16 +141,14 @@ public class UsersTable extends Composite implements ArgeoNames {
        public TableViewer getTableViewer() {
                return usersViewer;
        }
-       
-       /** Returns filter String or null*/
+
+       /** Returns filter String or null */
        protected String getFilterString() {
                return hasFilter ? filterTxt.getText() : null;
        }
-       
-       
 
        private TableViewer createTableViewer(final Composite parent) {
-               int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
+               int style = tableStyle |  SWT.H_SCROLL | SWT.V_SCROLL;
                if (hasSelectionColumn)
                        style = style | SWT.CHECK;
 
@@ -164,9 +163,6 @@ public class UsersTable extends Composite implements ArgeoNames {
                table.setLinesVisible(true);
                table.setHeaderVisible(true);
 
-               // pass a mapping between col index and property name to the comparator.
-               // List<String> propertiesList = new ArrayList<String>();
-
                TableViewerColumn column;
                int offset = 0;
                if (hasSelectionColumn) {
@@ -239,11 +235,9 @@ public class UsersTable extends Composite implements ArgeoNames {
                        String username = getProperty(elem, ARGEO_USER_ID);
                        if (username.equals(session.getUserID()))
                                return bold;
-
                        // disabled
                        try {
                                Node userProfile = (Node) elem;
-                               // Node userProfile = userHome.getNode(ARGEO_PROFILE);
                                if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean())
                                        return italic;
                                else
@@ -298,7 +292,7 @@ public class UsersTable extends Composite implements ArgeoNames {
                // Text Area for the filter
                filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH
                                | SWT.ICON_CANCEL);
-               filterTxt.setMessage(FILTER_HELP_MSG);
+               filterTxt.setMessage(filterHelpMsg);
                filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
                                | GridData.HORIZONTAL_ALIGN_FILL));
                filterTxt.addModifyListener(new ModifyListener() {