First draft of a drag and drop implementation to manage group. Implement create group...
authorBruno Sinou <bsinou@argeo.org>
Mon, 14 Sep 2015 17:28:40 +0000 (17:28 +0000)
committerBruno Sinou <bsinou@argeo.org>
Mon, 14 Sep 2015 17:28:40 +0000 (17:28 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8392 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.security.ui.admin/META-INF/spring/commands.xml
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/NewGroup.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/UserMainPage.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserAdminConstants.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserDragListener.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/GroupsView.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/UsersView.java

index 23be58d8d959baec990782a95fd460fe95a28d6e..a2a25d7e844bf98fbaf40a14ecc309eae83a63fc 100644 (file)
                <property name="userTransaction" ref="userTransaction" />
        </bean>
 
+       <bean id="newGroup" class="org.argeo.security.ui.admin.commands.NewGroup"
+               scope="prototype">
+               <property name="userAdmin" ref="userAdmin" />
+               <property name="userTransaction" ref="userTransaction" />
+       </bean>
+
        <!-- <bean id="userBatchUpdate" class="org.argeo.security.ui.admin.commands.UserBatchUpdate" 
                scope="prototype"> <property name="repository" ref="nodeRepository" /> <property 
                name="userAdminService" ref="userAdminService" /> </bean> -->
index 41672d5b6498c9651b88775d5f67694690cd2f71..22780f27cf3bd0f625343591d7bce35d452e82df 100644 (file)
  */
 package org.argeo.security.ui.admin.commands;
 
+import java.util.Dictionary;
+
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
+import org.argeo.jcr.ArgeoNames;
 import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.argeo.security.ui.admin.internal.UiAdminUtils;
+import org.argeo.security.ui.admin.internal.UserAdminConstants;
+import org.argeo.security.ui.admin.views.GroupsView;
 import org.eclipse.core.commands.AbstractHandler;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.handlers.HandlerUtil;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.UserAdmin;
 
 /** Create a new group. */
@@ -28,53 +56,174 @@ public class NewGroup extends AbstractHandler {
        public final static String ID = SecurityAdminPlugin.PLUGIN_ID + ".newGroup";
 
        private UserAdmin userAdmin;
+       private UserTransaction userTransaction;
+
+       // TODO implement a dynamic choice of the base dn
+       private String getDn(String cn) {
+               return "cn=" + cn + ",dc=example,dc=com";
+       }
 
        public Object execute(ExecutionEvent event) throws ExecutionException {
+               NewGroupWizard newGroupWizard = new NewGroupWizard();
+               WizardDialog dialog = new WizardDialog(
+                               HandlerUtil.getActiveShell(event), newGroupWizard);
+               dialog.setTitle("Create a new group");
 
-               MessageDialog
-                               .openError(HandlerUtil.getActiveShell(event),
-                                               "Unimplemented method",
-                                               "Group creation is not yet implemented");
+               // Force refresh until the listener are implemented
+               if (Window.OK == dialog.open())
+                       forceRefresh(event);
                return null;
        }
 
+       private void forceRefresh(ExecutionEvent event) {
+               IWorkbenchWindow iww = HandlerUtil.getActiveWorkbenchWindow(event);
+               if (iww == null)
+                       return;
+               IWorkbenchPage activePage = iww.getActivePage();
+               IWorkbenchPart part = activePage.getActivePart();
+               if (part instanceof GroupsView)
+                       ((GroupsView) part).refresh();
+       }
+
+       private class NewGroupWizard extends Wizard {
+
+               // pages
+               private MainGroupInfoWizardPage mainGroupInfo;
+
+               // End user fields
+               private Text dNameTxt, commonNameTxt, descriptionTxt;
+
+               public NewGroupWizard() {
+               }
+
+               @Override
+               public void addPages() {
+                       mainGroupInfo = new MainGroupInfoWizardPage();
+                       addPage(mainGroupInfo);
+
+                       setWindowTitle("Create a new group");
+                       // mainGroupInfo.setMessage(message, WizardPage.WARNING);
+               }
+
+               @SuppressWarnings({ "rawtypes", "unchecked" })
+               @Override
+               public boolean performFinish() {
+                       if (!canFinish())
+                               return false;
+                       String commonName = commonNameTxt.getText();
+
+                       // Begin transaction if needed
+                       try {
+                               if (userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION)
+                                       userTransaction.begin();
+                       } catch (Exception e) {
+                               throw new ArgeoException("Unable to start "
+                                               + "transaction to create user " + commonName, e);
+                       }
+
+                       try {
+                               Group user = (Group) userAdmin.createRole(getDn(commonName),
+                                               Role.GROUP);
+                               Dictionary props = user.getProperties();
+                               String descStr = descriptionTxt.getText();
+                               if (UiAdminUtils.notNull(descStr))
+                                       props.put(UserAdminConstants.KEY_DESC, descStr);
+                               return true;
+                       } catch (Exception e) {
+                               ErrorFeedback.show("Cannot create new group " + commonName, e);
+                               return false;
+                       }
+               }
+
+               private class MainGroupInfoWizardPage extends WizardPage implements
+                               ModifyListener, ArgeoNames {
+                       private static final long serialVersionUID = -3150193365151601807L;
+
+                       public MainGroupInfoWizardPage() {
+                               super("Main");
+                               setTitle("General information");
+                               setMessage("Please provide a common name and a free description");
+                       }
+
+                       @Override
+                       public void createControl(Composite parent) {
+                               Composite bodyCmp = new Composite(parent, SWT.NONE);
+                               bodyCmp.setLayout(new GridLayout(2, false));
+                               dNameTxt = EclipseUiUtils.createGridLT(bodyCmp,
+                                               "Distinguished name", this);
+                               dNameTxt.setEnabled(false);
+                               commonNameTxt = EclipseUiUtils.createGridLT(bodyCmp,
+                                               "Common name", this);
+                               commonNameTxt.addModifyListener(new ModifyListener() {
+                                       private static final long serialVersionUID = -1435351236582736843L;
+
+                                       @Override
+                                       public void modifyText(ModifyEvent event) {
+                                               String name = commonNameTxt.getText();
+                                               if (name.trim().equals("")) {
+                                                       dNameTxt.setText("");
+                                               } else {
+                                                       dNameTxt.setText(getDn(name));
+                                               }
+                                       }
+                               });
+
+                               Label descLbl = new Label(bodyCmp, SWT.LEAD);
+                               descLbl.setText("Description");
+                               descLbl.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false,
+                                               false));
+                               descriptionTxt = new Text(bodyCmp, SWT.LEAD | SWT.MULTI
+                                               | SWT.WRAP | SWT.BORDER);
+                               descriptionTxt.setLayoutData(EclipseUiUtils.fillAll());
+                               descriptionTxt.addModifyListener(this);
+
+                               setControl(bodyCmp);
+
+                               // Initialize buttons
+                               setPageComplete(false);
+                               getContainer().updateButtons();
+                       }
+
+                       @Override
+                       public void modifyText(ModifyEvent event) {
+                               String message = checkComplete();
+                               if (message != null) {
+                                       setMessage(message, WizardPage.ERROR);
+                                       setPageComplete(false);
+                               } else {
+                                       setMessage("Complete", WizardPage.INFORMATION);
+                                       setPageComplete(true);
+                               }
+                               getContainer().updateButtons();
+                       }
+
+                       /** @return error message or null if complete */
+                       protected String checkComplete() {
+                               String name = commonNameTxt.getText();
+
+                               if (name.trim().equals(""))
+                                       return "Common name must not be empty";
+                               Role role = userAdmin.getRole(getDn(name));
+                               if (role != null)
+                                       return "Group " + name + " already exists";
+                               return null;
+                       }
+
+                       @Override
+                       public void setVisible(boolean visible) {
+                               super.setVisible(visible);
+                               if (visible)
+                                       commonNameTxt.setFocus();
+                       }
+               }
+       }
+
        /* DEPENDENCY INJECTION */
        public void setUserAdmin(UserAdmin userAdmin) {
                this.userAdmin = userAdmin;
        }
-}
-
-// JcrRolesView rolesView = (JcrRolesView) HandlerUtil
-// .getActiveWorkbenchWindow(event).getActivePage()
-// .findView(JcrRolesView.ID);
-// String role = rolesView.getNewRole();
-// if (role.trim().equals(""))
-// return null;
-// if (role.equals(rolesView.getAddNewRoleText()))
-// return null;
-// role = role.trim().toUpperCase();
-// if (!role.startsWith(rolePrefix))
-// role = rolePrefix + role;
-// if (userAdminService.listEditableRoles().contains(role))
-// throw new ArgeoException("Role " + role + " already exists");
-// userAdminService.newRole(role);
-// rolesView.refresh();
-//
-// // refresh editors
-// IEditorReference[] refs = HandlerUtil.getActiveWorkbenchWindow(event)
-// .getActivePage()
-// .findEditors(null, JcrArgeoUserEditor.ID, IWorkbenchPage.MATCH_ID);
-// for (IEditorReference ref : refs) {
-// JcrArgeoUserEditor userEditor = (JcrArgeoUserEditor) ref.getEditor(false);
-// if (userEditor != null) {
-// userEditor.refresh();
-// }
-// }
-// return null;
-// }
-//
-// public void setUserAdminService(UserAdminService userAdminService) {
-// this.userAdminService = userAdminService;
-// }
-//
-// }
+
+       public void setUserTransaction(UserTransaction userTransaction) {
+               this.userTransaction = userTransaction;
+       }
+}
\ No newline at end of file
index df8e505af04b6fd382ef6115167168e739e72abc..41b21651f8b9acbaa74481a798ac183170a94c42 100644 (file)
@@ -30,7 +30,14 @@ import org.argeo.security.ui.admin.internal.UserNameLP;
 import org.argeo.security.ui.admin.internal.UserTableDefaultDClickListener;
 import org.argeo.security.ui.admin.internal.UserTableViewer;
 import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.layout.GridData;
@@ -46,6 +53,8 @@ import org.eclipse.ui.forms.editor.FormPage;
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.ScrolledForm;
 import org.eclipse.ui.forms.widgets.Section;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
@@ -208,7 +217,7 @@ public class UserMainPage extends FormPage implements ArgeoNames {
        private UserTableViewer userTableViewerCmp;
        private TableViewer userViewer;
 
-       public void appendMemberOfPart(Composite parent) {
+       private void appendMemberOfPart(Composite parent) {
                FormToolkit tk = getManagedForm().getToolkit();
                Composite body = addSection(tk, parent, "Roles");
                body.setLayout(EclipseUiUtils.noSpaceGridLayout());
@@ -236,6 +245,13 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                userViewer.addDoubleClickListener(new UserTableDefaultDClickListener());
                // Really?
                userTableViewerCmp.refresh();
+
+               // Drag and drop
+               int operations = DND.DROP_COPY | DND.DROP_MOVE;
+               Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
+               userViewer.addDropSupport(operations, tt, new ItemDropListener(
+                               userViewer, userAdmin, editor.getDisplayedUser()));
+
        }
 
        private class MyUserTableViewer extends UserTableViewer {
@@ -252,6 +268,53 @@ public class UserMainPage extends FormPage implements ArgeoNames {
                }
        }
 
+       // DRAG & DROP MANAGEMENT
+
+       private class ItemDropListener extends ViewerDropAdapter {
+               private static final long serialVersionUID = 2893468717831451621L;
+
+               private final UserAdmin myUserAdmin;
+               private final User myUser;
+
+               public ItemDropListener(Viewer viewer, UserAdmin userAdmin, User user) {
+                       super(viewer);
+                       this.myUserAdmin = userAdmin;
+                       this.myUser = user;
+               }
+
+               @Override
+               public boolean validateDrop(Object target, int operation,
+                               TransferData transferType) {
+                       // Target is always OK in a list only view
+                       // TODO check if not a string
+                       boolean validDrop = true;
+                       return validDrop;
+               }
+
+               @Override
+               public void drop(DropTargetEvent event) {
+                       String name = (String) event.data;
+                       Role role = myUserAdmin.getRole(name);
+                       // TODO this check should be done before.
+                       if (role.getType() == Role.GROUP) {
+                               // TODO check if the user is already member of this group
+                               // we expect here that there is already a begun transaction
+                               // TODO implement the dirty state
+                               Group group = (Group) role;
+                               group.addMember(myUser);
+                       }
+                       super.drop(event);
+               }
+
+               @Override
+               public boolean performDrop(Object data) {
+                       userTableViewerCmp.refresh();
+                       return true;
+               }
+       }
+
+       // LOCAL HELPERS
+       /** Appends a section with a title */
        private Composite addSection(FormToolkit tk, Composite parent, String title) {
                Section section = tk.createSection(parent, Section.TITLE_BAR);
                GridData gd = EclipseUiUtils.fillWidth();
index ab9f0fbe27d97e656b3b6802e3683c11662096ab..4dbb358f0963088c2628151b692ecb58a8289b33 100644 (file)
@@ -9,4 +9,6 @@ public interface UserAdminConstants {
        public final static String KEY_FIRSTNAME = "givenname";
        public final static String KEY_LASTNAME = "sn";
        public final static String KEY_MAIL = "mail";
+       public final static String KEY_DESC  = "description";
+
 }
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserDragListener.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/internal/UserDragListener.java
new file mode 100644 (file)
index 0000000..abaab33
--- /dev/null
@@ -0,0 +1,39 @@
+package org.argeo.security.ui.admin.internal;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.osgi.service.useradmin.User;
+
+public class UserDragListener implements DragSourceListener {
+       private static final long serialVersionUID = -2074337775033781454L;
+       private final Viewer viewer;
+
+       public UserDragListener(Viewer viewer) {
+               this.viewer = viewer;
+       }
+
+       public void dragStart(DragSourceEvent event) {
+               // TODO implement finer checks
+               IStructuredSelection selection = (IStructuredSelection) viewer
+                               .getSelection();
+               if (selection.isEmpty() || selection.size() > 1)
+                       event.doit = false;
+               else
+                       event.doit = true;
+       }
+
+       public void dragSetData(DragSourceEvent event) {
+               // TODO Support multiple selection
+               Object obj = ((IStructuredSelection) viewer.getSelection())
+                               .getFirstElement();
+               if (obj != null) {
+                       User user = (User) obj;
+                       event.data = user.getName();
+               }
+       }
+
+       public void dragFinished(DragSourceEvent event) {
+       }
+}
\ No newline at end of file
index faf0e8025d3c07e0985493b299e1e87111bbc64b..74d2c995dfc9da95b9ea024b467bd3cccb0e3444 100644 (file)
@@ -26,11 +26,15 @@ import org.argeo.security.ui.admin.internal.ColumnDefinition;
 import org.argeo.security.ui.admin.internal.CommonNameLP;
 import org.argeo.security.ui.admin.internal.UiAdminUtils;
 import org.argeo.security.ui.admin.internal.UserAdminConstants;
+import org.argeo.security.ui.admin.internal.UserDragListener;
 import org.argeo.security.ui.admin.internal.UserNameLP;
 import org.argeo.security.ui.admin.internal.UserTableDefaultDClickListener;
 import org.argeo.security.ui.admin.internal.UserTableViewer;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.widgets.Composite;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.useradmin.Role;
@@ -74,6 +78,12 @@ public class GroupsView extends UsersView implements ArgeoNames {
 
                // Really?
                groupTableViewerCmp.refresh();
+
+               // Drag and drop
+               int operations = DND.DROP_COPY | DND.DROP_MOVE;
+               Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
+               userViewer.addDragSupport(operations, tt, new UserDragListener(
+                               userViewer));
        }
 
        private class MyUserTableViewer extends UserTableViewer {
index 3438d85b0ddb3eaec676127db611441dc68e0cb9..538329559a1ef3284754990f4691baddae8a01a8 100644 (file)
@@ -27,11 +27,15 @@ import org.argeo.security.ui.admin.internal.CommonNameLP;
 import org.argeo.security.ui.admin.internal.MailLP;
 import org.argeo.security.ui.admin.internal.UiAdminUtils;
 import org.argeo.security.ui.admin.internal.UserAdminConstants;
+import org.argeo.security.ui.admin.internal.UserDragListener;
 import org.argeo.security.ui.admin.internal.UserNameLP;
 import org.argeo.security.ui.admin.internal.UserTableDefaultDClickListener;
 import org.argeo.security.ui.admin.internal.UserTableViewer;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.ui.part.ViewPart;
 import org.osgi.framework.InvalidSyntaxException;
@@ -79,12 +83,11 @@ public class UsersView extends ViewPart implements ArgeoNames {
                // Really?
                userTableViewerCmp.refresh();
 
-               // try {
-               // if (userTransaction != null)
-               // userTransaction.begin();
-               // } catch (Exception e) {
-               // throw new ArgeoException("Cannot begin transaction", e);
-               // }
+               // Drag and drop
+               int operations = DND.DROP_COPY | DND.DROP_MOVE;
+               Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
+               userViewer.addDragSupport(operations, tt, new UserDragListener(
+                               userViewer));
        }
 
        private class MyUserTableViewer extends UserTableViewer {