From: Bruno Sinou Date: Thu, 26 Mar 2015 14:31:40 +0000 (+0000) Subject: + Refactor Users Page X-Git-Tag: argeo-commons-2.1.30~287 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=60e8274d08b93c5dbb46a2fc2a4f8b1a0d18c0ed;p=lgpl%2Fargeo-commons.git + Refactor Users Page + 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 --- diff --git a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java index f722befeb..d6341e5b3 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java @@ -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) { diff --git a/org.argeo.cms/src/org/argeo/cms/CmsConstants.java b/org.argeo.cms/src/org/argeo/cms/CmsConstants.java index cae0167c8..df8c02fb8 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsConstants.java @@ -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 index 6b522f5d9..000000000 --- a/org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java +++ /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 index 2637ed4d9..000000000 --- a/org.argeo.cms/src/org/argeo/cms/users/Users.java +++ /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 toDelete = new TreeMap(); - @SuppressWarnings("unchecked") - Iterator 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 index 000000000..d5bfeb7cd --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/users/UsersPage.java @@ -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 toDelete = new TreeMap(); + @SuppressWarnings("unchecked") + Iterator 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 diff --git a/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java b/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java index c1b319fbe..5d31e2c51 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java @@ -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 diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java index 3455577ce..06f569dce 100644 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java +++ b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java @@ -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 diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java index 0a7b8d1e0..41afb6a3a 100644 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java +++ b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java @@ -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 selectedItems = new ArrayList(); - - /** - * Overwrite to display other columns - */ + /** Overwrite to display other columns */ public List getColumnsDef() { List columnDefs = new ArrayList(); @@ -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 propertiesList = new ArrayList(); - 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() {