From 44ace169ec40767a3386809e1c910c02bf818891 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sun, 18 Aug 2019 12:53:15 +0200 Subject: [PATCH] Form for managing project members --- .../ui/SciProjectContactsTable.java | 75 ++-- .../contenttypes/ui/SciProjectController.java | 211 ++++++++++ .../ui/SciProjectMemberAddForm.java | 309 +++++++++++++++ .../ui/SciProjectMembersStep.java | 109 ++++++ .../ui/SciProjectMembersTable.java | 365 ++++++++++++++++++ .../ui/SciProjectUiConstants.java | 8 + .../contenttypes/sciproject/SciProject.java | 41 +- .../sciproject/SciProjectConfig.java | 16 +- 8 files changed, 1085 insertions(+), 49 deletions(-) create mode 100644 sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMemberAddForm.java create mode 100644 sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersStep.java create mode 100644 sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersTable.java diff --git a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectContactsTable.java b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectContactsTable.java index 6b897b7..dfaa243 100644 --- a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectContactsTable.java +++ b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectContactsTable.java @@ -53,12 +53,17 @@ public class SciProjectContactsTable .getLogger(SciProjectContactsTable.class); private final static String TABLE_COL_EDIT = "table_col_edit"; + private final static String TABLE_COL_EDIT_ASSOC = "table_col_edit_assoc"; + private final static String TABLE_COL_DEL = "table_col_del"; + private final static String TABLE_COL_UP = "table_col_up"; + private final static String TABLE_COL_DOWN = "table_col_down"; private final ItemSelectionModel itemModel; + private final SciProjectContactsStep editStep; public SciProjectContactsTable(final ItemSelectionModel itemModel, @@ -122,8 +127,8 @@ public class SciProjectContactsTable } @Override - public void cellSelected(final TableActionEvent event) throws - FormProcessException { + public void cellSelected(final TableActionEvent event) + throws FormProcessException { final PageState state = event.getPageState(); final SciProject selected = (SciProject) itemModel @@ -134,25 +139,25 @@ public class SciProjectContactsTable final Contact contact = controller.findContact(selected.getObjectId(), event.getRowKey()) .get(); - + final TableColumn column = getColumnModel() .get(event.getColumn().intValue()); - + if (TABLE_COL_EDIT_ASSOC.equals(column.getHeaderKey())) { editStep.setSelectedContact(contact.getContactable()); editStep.setSelectedContactType(contact.getContactType()); - + editStep.showComponent(state, SciProjectUiConstants.ADD_CONTACT_SHEET_NAME); - } else if(TABLE_COL_DEL.equals(column.getHeaderKey())) { + } else if (TABLE_COL_DEL.equals(column.getHeaderKey())) { controller.removeContact(selected.getObjectId(), - contact.getContactId()); - } else if(TABLE_COL_UP.equals(column.getHeaderKey())) { + contact.getContactId()); + } else if (TABLE_COL_UP.equals(column.getHeaderKey())) { controller.swapWithPreviousContact(selected.getObjectId(), - contact.getContactId()); - } else if(TABLE_COL_DOWN.equals(column.getHeaderKey())) { + contact.getContactId()); + } else if (TABLE_COL_DOWN.equals(column.getHeaderKey())) { controller.swapWithNextContact(selected.getObjectId(), - contact.getContactId()); + contact.getContactId()); } } @@ -189,8 +194,9 @@ public class SciProjectContactsTable private class SciProjectContactsTableModel implements TableModel { private final Table table; - private final List> data; + private final Iterator> iterator; + private Map currentRow; public SciProjectContactsTableModel(final Table table, @@ -202,8 +208,7 @@ public class SciProjectContactsTable final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final SciProjectController controller = cdiUtil .findBean(SciProjectController.class); - data = controller.getContacts(selected.getObjectId()); - iterator = data.iterator(); + iterator = controller.getContacts(selected.getObjectId()).iterator(); } @Override @@ -265,13 +270,13 @@ public class SciProjectContactsTable @Override public Component getComponent( - Table table, - PageState state, - Object value, - boolean isSelected, - Object key, - int row, - int col) { + final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int col) { // final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); // final PermissionChecker permissionChecker = cdiUtil @@ -331,13 +336,13 @@ public class SciProjectContactsTable @Override public Component getComponent( - Table table, - PageState state, - Object value, - boolean isSelected, - Object key, - int row, - int col) { + final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int col) { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final PermissionChecker permissionChecker = cdiUtil @@ -363,13 +368,13 @@ public class SciProjectContactsTable @Override public Component getComponent( - Table table, - PageState state, - Object value, - boolean isSelected, - Object key, - int row, - int col) { + final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int col) { final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final PermissionChecker permissionChecker = cdiUtil diff --git a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectController.java b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectController.java index 78d9a8d..41c7576 100644 --- a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectController.java +++ b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectController.java @@ -10,8 +10,12 @@ import org.libreccm.l10n.LocalizedString; import org.librecms.assets.ContactableEntity; import org.librecms.assets.ContactableEntityRepository; import org.librecms.assets.Organization; +import org.librecms.assets.Person; +import org.librecms.assets.PersonRepository; import org.librecms.contentsection.AssetRepository; import org.scientificcms.contenttypes.sciproject.Contact; +import org.scientificcms.contenttypes.sciproject.Membership; +import org.scientificcms.contenttypes.sciproject.MembershipStatus; import org.scientificcms.contenttypes.sciproject.SciProject; import org.scientificcms.contenttypes.sciproject.SciProjectConfig; import org.scientificcms.contenttypes.sciproject.SciProjectMananger; @@ -45,6 +49,14 @@ class SciProjectController { public static final String CONTACT_ID = "contactId"; + public static final String MEMBER_NAME = "memberName"; + + public static final String MEMBER_ROLE = "memberRole"; + + public static final String MEMBER_STATUS = "memberStatus"; + + public static final String MEMBERSHIP_ID = "membershipId"; + public static final String SPONSOR_ID = "sponsorId"; public static final String SPONSOR_NAME = "name"; @@ -60,6 +72,9 @@ class SciProjectController { @Inject private ContactableEntityRepository contactableRepository; + @Inject + private PersonRepository personRepository; + @Inject private SciProjectMananger projectMananger; @@ -74,6 +89,14 @@ class SciProjectController { return conf.getContactTypesBundleName(); } + public String getMemberRolesBundleName() { + + final SciProjectConfig conf = confManager + .findConfiguration(SciProjectConfig.class); + + return conf.getMemberRolesBundleName(); + } + @Transactional(Transactional.TxType.REQUIRED) public List> getContacts(final long forProjectId) { @@ -299,6 +322,186 @@ class SciProjectController { .anyMatch(current -> filterContact(current, project, contactable)); } + @Transactional(Transactional.TxType.REQUIRED) + public List> getMembers(final long projectId) { + + final SciProject project = projectRepository + .findById(projectId, SciProject.class) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No SciProject with ID %d found.", + projectId)) + ); + + return project + .getMembers() + .stream() + .map(this::buildMembershipEntry) + .collect(Collectors.toList()); + } + + private Map buildMembershipEntry( + final Membership membership) { + + Objects.requireNonNull(membership); + + final Map result = new HashMap<>(); + result.put(MEMBERSHIP_ID, membership.getMembershipId()); + result.put( + MEMBER_NAME, + String.format( + "%s, %s", + membership.getMember().getPersonName().getSurname(), + membership.getMember().getPersonName().getGivenName() + ) + ); + result.put(MEMBER_ROLE, membership.getRole()); + result.put(MEMBER_STATUS, membership.getStatus().toString()); + + return result; + + } + + @Transactional(Transactional.TxType.REQUIRED) + public Optional findMembership(final long projectId, + final Object key) { + + final SciProject project = projectRepository + .findById(projectId, SciProject.class) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No SciProject with ID %d found.", + projectId)) + ); + + final long membershipId = (long) key; + + return project + .getMembers() + .stream() + .filter(membership -> membership.getMembershipId() == membershipId) + .findAny(); + } + + @Transactional(Transactional.TxType.REQUIRED) + public void addMember(final long projectId, + final long memberId, + final String role, + final String status) { + + final SciProject project = projectRepository + .findById(projectId, SciProject.class) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No SciProject with ID %d found.", + projectId)) + ); + + final Person member = personRepository + .findById(memberId) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No Person with ID %d found.", + memberId) + ) + ); + + final MembershipStatus membershipStatus = MembershipStatus + .valueOf(status); + + projectMananger.addMember(member, project, role, membershipStatus); + } + + @Transactional(Transactional.TxType.REQUIRED) + public void updateMembership(final long projectId, + final long memberId, + final String role, + final String status) { + + final SciProject project = projectRepository + .findById(projectId, SciProject.class) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No SciProject with ID %d found.", + projectId)) + ); + + final Person member = personRepository + .findById(memberId) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No Person with ID %d found.", + memberId) + ) + ); + + final MembershipStatus membershipStatus = MembershipStatus + .valueOf(status); + + final Optional membership = project + .getMembers() + .stream() + .filter(current -> filterMembership(current, project, member)) + .findAny(); + + if (membership.isPresent()) { + + membership.get().setRole(role); + membership.get().setStatus(membershipStatus); + + projectRepository.save(project); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public void removeMember(final long projectId, final long membershipId) { + + final SciProject project = projectRepository + .findById(projectId, SciProject.class) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No SciProject with ID %d found.", + projectId)) + ); + + final Optional membership = project + .getMembers() + .stream() + .filter(current -> current.getMembershipId() == membershipId) + .findAny(); + + if (membership.isPresent()) { + projectMananger.removeMember(membership.get().getMember(), project); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public boolean hasMember(final long projectId, + final long memberId) { + + final SciProject project = projectRepository + .findById(projectId, SciProject.class) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No SciProject with ID %d found.", + projectId)) + ); + + final Person member = personRepository + .findById(memberId) + .orElseThrow( + () -> new IllegalArgumentException( + String.format("No Person with ID %d found.", + memberId) + ) + ); + + return project + .getMembers() + .stream() + .anyMatch(current -> filterMembership(current, project, member)); + } + @Transactional(Transactional.TxType.REQUIRED) public void updateDescription(final long projectId, final String descriptionText, @@ -600,4 +803,12 @@ class SciProjectController { && contact.getContactable().equals(contactable); } + private boolean filterMembership(final Membership membership, + final SciProject project, + final Person member) { + + return membership.getProject().equals(project) + && membership.getMember().equals(member); + } + } diff --git a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMemberAddForm.java b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMemberAddForm.java new file mode 100644 index 0000000..0779901 --- /dev/null +++ b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMemberAddForm.java @@ -0,0 +1,309 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.SingleSelect; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.assets.AssetSearchWidget; +import com.arsdigita.cms.ui.authoring.BasicItemForm; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.util.UncheckedWrapperException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.CmsConstants; +import org.librecms.assets.Person; +import org.scientificcms.contenttypes.sciproject.MembershipStatus; +import org.scientificcms.contenttypes.sciproject.SciProject; +import org.scientificcms.contenttypes.sciproject.SciProjectConstants; + +import java.util.ResourceBundle; +import java.util.TooManyListenersException; + +/** + * + * @author Jens Pelzetter + * @version $Id: SciProjectMemberAddForm.java 1170 2011-10-17 19:23:23Z jensp $ + */ +public class SciProjectMemberAddForm + extends BasicItemForm + implements FormProcessListener, FormInitListener, FormSubmissionListener { + + private static final Logger LOGGER = LogManager.getLogger( + SciProjectMemberAddForm.class); + + private final SciProjectMembersStep membersStep; + + private AssetSearchWidget personSearchWidget; + + private Text selectedPersonLabel; + + public SciProjectMemberAddForm( + final ItemSelectionModel itemModel, + final SciProjectMembersStep membersStep, + final StringParameter selectedLanguageParam) { + + super("SciProjectMemberAddForm", itemModel, selectedLanguageParam); + + this.membersStep = membersStep; + addSubmissionListener(this); + } + + @Override + public void addWidgets() { + + personSearchWidget = new AssetSearchWidget( + SciProjectUiConstants.MEMBER_SEARCH, + Person.class + ); + personSearchWidget.setLabel(new GlobalizedMessage( + "sciproject.ui.select_member", + SciProjectConstants.SCI_PROJECT_BUNDLE + )); + add(personSearchWidget); + + selectedPersonLabel = new Text(); + add(selectedPersonLabel); + + final ParameterModel roleParam = new StringParameter( + SciProjectUiConstants.MEMBER_ROLE + ); + final SingleSelect roleSelect = new SingleSelect(roleParam); + roleSelect.setLabel(new GlobalizedMessage( + "sciproject.ui.member.role", + SciProjectConstants.SCI_PROJECT_BUNDLE + )); + roleSelect.addValidationListener(new NotNullValidationListener()); + + try { + + roleSelect.addPrintListener(new PrintListener() { + + @Override + public void prepare(final PrintEvent event) { + final SingleSelect target = (SingleSelect) event.getTarget(); + target.clearOptions(); + + target.addOption(new Option("", + new Label(new GlobalizedMessage( + "cms.ui.select_one", + CmsConstants.CMS_BUNDLE)))); + + final String rolesBundleName = getController() + .getMemberRolesBundleName(); + final ResourceBundle rolesBundle = ResourceBundle + .getBundle(rolesBundleName); + for (final String key : rolesBundle.keySet()) { + + final Option option = new Option( + key, + new Label(new GlobalizedMessage(key, + rolesBundleName)) + ); + target.addOption(option); + } + } + + }); + + } catch (TooManyListenersException ex) { + throw new UncheckedWrapperException(ex); + } + add(roleSelect); + + final ParameterModel statusModel = new StringParameter( + SciProjectUiConstants.MEMBER_STATUS + ); + final SingleSelect statusSelect = new SingleSelect(statusModel); + statusSelect.setLabel(new GlobalizedMessage( + "sciproject.ui.member.status", + SciProjectConstants.SCI_PROJECT_BUNDLE + )); + statusSelect.addValidationListener(new NotNullValidationListener()); + try { + statusSelect.addPrintListener(new PrintListener() { + + @Override + public void prepare(final PrintEvent event) { + + final SingleSelect target = (SingleSelect) event.getTarget(); + target.clearOptions(); + + target.addOption(new Option("", + new Label(new GlobalizedMessage( + "cms.ui.select_one", + CmsConstants.CMS_BUNDLE)))); + + for (MembershipStatus status : MembershipStatus.values()) { + + final Option option = new Option( + status.toString(), + new Label(new GlobalizedMessage( + String.format("sciproject.membership.status.%s", + status.toString()), + SciProjectConstants.SCI_PROJECT_BUNDLE + )) + ); + target.addOption(option); + } + } + + }); + } catch (TooManyListenersException ex) { + throw new UncheckedWrapperException( + "Something has gone terribly wrong", ex); + } + add(statusSelect); + } + + @Override + public void init(final FormSectionEvent event) throws FormProcessException { + + final FormData formData = event.getFormData(); + final PageState state = event.getPageState(); + + final Person member = membersStep.getSelectedMember(state); + final String role = membersStep.getSelectedMemberRole(state); + final String status = membersStep.getSelectedMemberStatus(state); + + if (member == null) { + personSearchWidget.setVisible(state, true); + selectedPersonLabel.setVisible(state, false); + } else { + formData.put(SciProjectUiConstants.MEMBER_SEARCH, member); + formData.put(SciProjectUiConstants.MEMBER_ROLE, role); + formData.put(SciProjectUiConstants.MEMBER_STATUS, status); + + personSearchWidget.setVisible(state, false); + selectedPersonLabel.setVisible(state, true); + selectedPersonLabel.setText( + String.format( + "%s, %s", + member.getPersonName().getSurname(), + member.getPersonName().getGivenName() + ) + ); + } + setVisible(state, true); + } + + @Override + public void process(final FormSectionEvent event) + throws FormProcessException { + + final FormData formData = event.getFormData(); + final PageState state = event.getPageState(); + + final SciProject project = (SciProject) getItemSelectionModel() + .getSelectedItem(state); + + if (getSaveCancelSection().getSaveButton().isSelected(state)) { + + final Person selected = membersStep.getSelectedMember(state); + + if (selected == null) { + + final Person person = (Person) formData + .get(SciProjectUiConstants.MEMBER_SEARCH); + + final String role = (String) formData + .get(SciProjectUiConstants.MEMBER_ROLE); + final String status = (String) formData + .get(SciProjectUiConstants.MEMBER_STATUS); + + getController().addMember(project.getObjectId(), + person.getObjectId(), + role, + status); + + } else { + + final String role = (String) formData + .get(SciProjectUiConstants.MEMBER_ROLE); + final String status = (String) formData + .get(SciProjectUiConstants.MEMBER_STATUS); + + getController().updateMembership(project.getObjectId(), + selected.getObjectId(), + role, + status); + } + } + + init(event); + } + + @Override + public void submitted(final FormSectionEvent event) throws + FormProcessException { + + final PageState state = event.getPageState(); + if (getSaveCancelSection().getCancelButton().isSelected(state)) { + + membersStep.setSelectedMember(state, null); + membersStep.setSelectedMemberRole(state, null); + membersStep.setSelectedMemberStatus(state, null); + + init(event); + } + } + + @Override + public void validate(final FormSectionEvent event) + throws FormProcessException { + + final PageState state = event.getPageState(); + final FormData data = event.getFormData(); + + if (membersStep.getSelectedMember(state) == null + && data.get(SciProjectUiConstants.MEMBER_SEARCH) == null) { + + data.addError( + new GlobalizedMessage( + "sciproject.ui.member.no_person_selected", + SciProjectConstants.SCI_PROJECT_BUNDLE + ) + ); + return; + } + + if (membersStep.getSelectedMember(state) == null) { + + final SciProject project = (SciProject) getItemSelectionModel() + .getSelectedItem(state); + + final Person person = (Person) data + .get(SciProjectUiConstants.MEMBER_SEARCH); + + if (getController().hasMember(project.getObjectId(), + person.getObjectId())) { + + data.addError(new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.select_member.already_added", + SciProjectConstants.SCI_PROJECT_BUNDLE + )); + } + } + } + + private SciProjectController getController() { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + + return cdiUtil.findBean(SciProjectController.class); + } + +} diff --git a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersStep.java b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersStep.java new file mode 100644 index 0000000..43dd4c2 --- /dev/null +++ b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersStep.java @@ -0,0 +1,109 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ItemSelectionModel; + +import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; +import com.arsdigita.cms.ui.authoring.BasicItemForm; +import com.arsdigita.cms.ui.authoring.SimpleEditStep; + +import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.librecms.assets.Person; +import org.scientificcms.contenttypes.sciproject.SciProjectConstants; + +/** + * + * @author Jens Pelzetter + */ +public class SciProjectMembersStep extends SimpleEditStep { + + private static final String ADD_PROJECT_MEMBER_SHEET_NAME + = "SciProjectAddMember"; + + public static final String SELECTED_PERSON = "selected-person"; + +// private final AssetSelectionModel selectedPerson; + private Person selectedMember; + + private String selectedMembershipRole; + + private String selectedMembershipStatus; + + public SciProjectMembersStep( + final ItemSelectionModel itemModel, + final AuthoringKitWizard parent, + final StringParameter selectedLanguageParameter) { + + this(itemModel, parent, selectedLanguageParameter, null); + } + + public SciProjectMembersStep( + final ItemSelectionModel itemModel, + final AuthoringKitWizard parent, + final StringParameter selectedLanguageParameter, + final String prefix) { + super(itemModel, parent, selectedLanguageParameter, prefix); + + final BasicItemForm addMemberSheet = new SciProjectMemberAddForm( + itemModel, this, selectedLanguageParameter + ); + add(ADD_PROJECT_MEMBER_SHEET_NAME, + new GlobalizedMessage("sciproject.ui.members.add", + SciProjectConstants.SCI_PROJECT_BUNDLE), + new WorkflowLockedComponentAccess(addMemberSheet, itemModel), + addMemberSheet.getSaveCancelSection().getCancelButton()); + + final SciProjectMembersTable memberTable = new SciProjectMembersTable( + itemModel, this); + setDisplayComponent(memberTable); + +// selectedPerson = new ItemSelectionModel(SELECTED_PERSON); + } + + @Override + public void register(final Page page) { + super.register(page); + +// page.addGlobalStateParam(selectedPerson.getStateParameter()); + } + + public Person getSelectedMember(final PageState state) { + return selectedMember; + } + + public void setSelectedMember(final PageState state, + final Person selectedMember) { + this.selectedMember = selectedMember; + } + + public String getSelectedMemberRole(final PageState state) { + return selectedMembershipRole; + } + + public void setSelectedMemberRole(final PageState state, + final String selectedPersonRole) { + this.selectedMembershipRole = selectedPersonRole; + } + + public String getSelectedMemberStatus(final PageState state) { + return selectedMembershipStatus; + } + + public void setSelectedMemberStatus(final PageState state, + final String selectedPersonStatus) { + this.selectedMembershipStatus = selectedPersonStatus; + } + + public void showEditComponent(final PageState state) { + showComponent(state, ADD_PROJECT_MEMBER_SHEET_NAME); + } + +} diff --git a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersTable.java b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersTable.java new file mode 100644 index 0000000..19518d8 --- /dev/null +++ b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectMembersTable.java @@ -0,0 +1,365 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.util.LockableImpl; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.configuration.ConfigurationManager; +import org.libreccm.security.PermissionChecker; +import org.librecms.CmsConstants; +import org.librecms.contentsection.privileges.ItemPrivileges; +import org.scientificcms.contenttypes.sciproject.Membership; +import org.scientificcms.contenttypes.sciproject.SciProject; +import org.scientificcms.contenttypes.sciproject.SciProjectConfig; +import org.scientificcms.contenttypes.sciproject.SciProjectConstants; + +import java.util.Iterator; +import java.util.Map; + +/** + * + * @author Jens Pelzetter + * @version $Id: SciProjectMembersTable.java 1170 2011-10-17 19:23:23Z jensp $ + */ +public class SciProjectMembersTable + extends Table + implements TableActionListener { + + private static final Logger LOGGER = LogManager + .getLogger(SciProjectMembersTable.class); + + private static final String TABLE_COL_EDIT = "table_col_edit"; + + private static final String TABLE_COL_EDIT_LINK = "table_col_edit_link"; + + private static final String TABLE_COL_DEL = "table_col_del"; + + private final ItemSelectionModel itemModel; + + private final SciProjectMembersStep membersStep; + + public SciProjectMembersTable(final ItemSelectionModel itemModel, + final SciProjectMembersStep membersStep) { + + super(); + + this.itemModel = itemModel; + this.membersStep = membersStep; + + setEmptyView(new Label(new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.members.none", + SciProjectConstants.SCI_PROJECT_BUNDLE))); + + final TableColumnModel columnModel = getColumnModel(); + columnModel.add(new TableColumn( + 0, + new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.persons.name", + SciProjectConstants.SCI_PROJECT_BUNDLE + ), + TABLE_COL_EDIT)); + columnModel.add( + new TableColumn( + 1, + new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.persons.role", + SciProjectConstants.SCI_PROJECT_BUNDLE + ) + ) + ); + columnModel.add( + new TableColumn( + 2, + new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.persons.status", + SciProjectConstants.SCI_PROJECT_BUNDLE) + ) + ); + columnModel.add( + new TableColumn( + 3, + new GlobalizedMessage( + "cms.contenttypes.ui.genericorganunit.persons.edit", + SciProjectConstants.SCI_PROJECT_BUNDLE + ), + TABLE_COL_EDIT_LINK) + ); + columnModel.add( + new TableColumn( + 4, + new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.persons.delete", + SciProjectConstants.SCI_PROJECT_BUNDLE + ), + TABLE_COL_DEL) + ); + + setModelBuilder(new SciProjectMembersTableModelBuilder(itemModel)); + + columnModel.get(0).setCellRenderer(new EditCellRenderer()); + columnModel.get(3).setCellRenderer(new EditLinkCellRenderer()); + columnModel.get(4).setCellRenderer(new DeleteCellRenderer()); + + addTableActionListener(this); + } + + private class SciProjectMembersTableModelBuilder + extends LockableImpl + implements TableModelBuilder { + + private final ItemSelectionModel itemModel; + + public SciProjectMembersTableModelBuilder( + final ItemSelectionModel itemModel) { + + this.itemModel = itemModel; + } + + @Override + public TableModel makeModel(final Table table, final PageState state) { + + table.getRowSelectionModel().clearSelection(state); + final SciProject selected = (SciProject) itemModel + .getSelectedItem(state); + return new SciProjectMembersTableModel(table, state, selected); + } + + } + + private class SciProjectMembersTableModel implements TableModel { + + private final Table table; + + private final Iterator> iterator; + + private Map currentRow; + + public SciProjectMembersTableModel(final Table table, + final PageState state, + final SciProject selected) { + + this.table = table; + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final SciProjectController controller = cdiUtil + .findBean(SciProjectController.class); + iterator = controller.getMembers(selected.getObjectId()).iterator(); + } + + @Override + public int getColumnCount() { + return table.getColumnModel().size(); + } + + @Override + public boolean nextRow() { + + if (iterator.hasNext()) { + + currentRow = iterator.next(); + return true; + } else { + return false; + } + } + + @Override + public Object getElementAt(final int columnIndex) { + + switch (columnIndex) { + case 0: + return currentRow.get(SciProjectController.MEMBER_NAME); + case 1: + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ConfigurationManager confManager = cdiUtil + .findBean(ConfigurationManager.class); + final SciProjectConfig config = confManager + .findConfiguration(SciProjectConfig.class); + final String role = (String) currentRow + .get(SciProjectController.MEMBER_ROLE); + return new GlobalizedMessage(role, + config + .getMemberRolesBundleName()); + case 2: + return currentRow.get(SciProjectController.MEMBER_STATUS); + case 3: + return new Label(new GlobalizedMessage( + "cms.ui.edit_assoc", CmsConstants.CMS_BUNDLE)); + case 4: + return new Label(new GlobalizedMessage( + "cms.ui.delete", CmsConstants.CMS_BUNDLE)); + default: + return null; + } + } + + @Override + public Object getKeyAt(final int columnIndex) { + + return currentRow.get(SciProjectController.MEMBERSHIP_ID); + } + + } + + private class EditCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent( + final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int col) { + + final SciProject selected = (SciProject) itemModel + .getSelectedItem(state); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final SciProjectController controller = cdiUtil + .findBean(SciProjectController.class); + final Membership membership = controller + .findMembership(selected.getObjectId(), key) + .get(); + + return new Text(String.format( + "%s, %s", + membership.getMember().getPersonName().getSurname(), + membership.getMember().getPersonName().getGivenName() + )); + } + + } + + private class EditLinkCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent( + final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int col) { + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final PermissionChecker permissionChecker = cdiUtil + .findBean(PermissionChecker.class); + + final SciProject selected = (SciProject) itemModel + .getSelectedItem(state); + final boolean canEdit = permissionChecker + .isPermitted(ItemPrivileges.EDIT, selected); + + if (canEdit) { + return new ControlLink((Component) value); + } else { + return new Text(""); + } + + } + + } + + private class DeleteCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent( + final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int col) { + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final PermissionChecker permissionChecker = cdiUtil + .findBean(PermissionChecker.class); + + final SciProject selected = (SciProject) itemModel + .getSelectedItem(state); + final boolean canEdit = permissionChecker + .isPermitted(ItemPrivileges.EDIT, selected); + + if (canEdit) { + final ControlLink link = new ControlLink((Component) value); + link.setConfirmation(new GlobalizedMessage( + "cms.contenttypes.ui.sciproject.confirm_delete", + SciProjectConstants.SCI_PROJECT_BUNDLE + )); + return link; + } else { + return new Text(""); + } + } + + } + + @Override + public void cellSelected(final TableActionEvent event) + throws FormProcessException { + + final PageState state = event.getPageState(); + final SciProject selected = (SciProject) itemModel + .getSelectedItem(state); + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final SciProjectController controller = cdiUtil + .findBean(SciProjectController.class); + + final Membership membership = controller + .findMembership(selected.getObjectId(), event.getRowKey()) + .get(); + + final TableColumn column = getColumnModel() + .get(event.getColumn().intValue()); + + if (TABLE_COL_EDIT.equals(column.getHeaderKey())) { + // Nothing + } else if (TABLE_COL_EDIT_LINK.equals(column.getHeaderKey())) { + membersStep.setSelectedMember(state, membership.getMember()); + membersStep.setSelectedMemberRole(state, membership.getRole()); + membersStep.setSelectedMemberStatus( + state, + membership.getStatus().toString() + ); + membersStep + .showComponent(state, + SciProjectUiConstants.ADD_MEMBER_SHEET_NAME); + } else if (TABLE_COL_DEL.equals(column.getHeaderKey())) { + controller.removeMember(selected.getObjectId(), + membership.getMembershipId()); + } + } + + @Override + public void headSelected(final TableActionEvent event) { + + // Nothing + } + +} diff --git a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectUiConstants.java b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectUiConstants.java index 53fad95..0d88278 100644 --- a/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectUiConstants.java +++ b/sci-types-project/src/main/java/com/arsdigita/cms/contenttypes/ui/SciProjectUiConstants.java @@ -13,6 +13,8 @@ public final class SciProjectUiConstants { public static final String ADD_CONTACT_SHEET_NAME = "addContact"; + public static final String ADD_MEMBER_SHEET_NAME = "addMember"; + public static final String BEGIN = "begin"; public static final String EDIT_CONTACT_SHEET_NAME = "edit"; @@ -31,6 +33,12 @@ public final class SciProjectUiConstants { public static final String NAME = "name"; + public static final String MEMBER_ROLE = "memberRole"; + + public static final String MEMBER_SEARCH = "memberSearch"; + + public static final String MEMBER_STATUS = "memberStatus"; + public static final String PROJECT_SHORT_DESCRIPTION = "shortDescription"; public static final String PROJECT_DESCRIPTION = "description"; diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java index 438748f..178f931 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProject.java @@ -5,6 +5,8 @@ */ package org.scientificcms.contenttypes.sciproject; +import com.arsdigita.cms.contenttypes.ui.SciProjectDescriptionStep; +import com.arsdigita.cms.contenttypes.ui.SciProjectMembersStep; import com.arsdigita.cms.contenttypes.ui.SciProjectPropertiesStep; import com.arsdigita.cms.ui.authoring.PageCreateForm; @@ -58,7 +60,24 @@ import static org.scientificcms.contenttypes.sciproject.SciProjectConstants.*; descriptionBundle = SciProjectConstants.SCI_PROJECT_BUNDLE, descriptionKey = "cms.contenttypes.shared.basic_properties" + ".description", - order = 1) + order = 1 + ), + @AuthoringStep( + component = SciProjectMembersStep.class, + labelBundle = SciProjectConstants.SCI_PROJECT_BUNDLE, + labelKey = "sciproject.membersstep.label", + descriptionBundle = SciProjectConstants.SCI_PROJECT_BUNDLE, + descriptionKey = "sciproject.membersstep.description", + order = 2 + ), + @AuthoringStep( + component = SciProjectDescriptionStep.class, + labelBundle = SciProjectConstants.SCI_PROJECT_BUNDLE, + labelKey = "sciproject.descriptionstep.label", + descriptionBundle = SciProjectConstants.SCI_PROJECT_BUNDLE, + descriptionKey = "sciproject.descriptionstep.description", + order = 3 + ) }) @NamedQueries({ @NamedQuery( @@ -248,30 +267,30 @@ public class SciProject extends ContentItem implements Serializable { protected void setMembers(final List members) { this.members = new ArrayList<>(members); } - + public List getSponsoring() { - + if (sponsoring == null) { return null; } else { return Collections.unmodifiableList(sponsoring); } } - + protected void addSponsor(final Sponsoring sponsor) { - + sponsoring.add(sponsor); } - + protected void removeSponsor(final Sponsoring sponsor) { - + sponsoring.remove(sponsor); } - + protected void setSponsoring(final List sponsoring) { - + this.sponsoring = new ArrayList<>(sponsoring); - } + } @Override public int hashCode() { @@ -333,7 +352,7 @@ public class SciProject extends ContentItem implements Serializable { } if (!Objects.equals(members, other.getMembers())) { return false; - } + } return Objects.equals(sponsoring, other.getSponsoring()); } diff --git a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectConfig.java b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectConfig.java index 26b1084..733a819 100644 --- a/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectConfig.java +++ b/sci-types-project/src/main/java/org/scientificcms/contenttypes/sciproject/SciProjectConfig.java @@ -21,6 +21,10 @@ public class SciProjectConfig { private String contactTypesBundleName = "org.scientificcms.contenttypes.sciproject.DefaultContactTypes"; + @Setting + private String memberRolesBundleName + = "org.scientificcms.contenttypes.sciproject.MemberRoles"; + @Setting private boolean enableSponsor = true; @@ -32,7 +36,7 @@ public class SciProjectConfig { @Setting private boolean enableFundingVolume = true; - + @Setting private int fundingVolumeLength = 128; @@ -54,6 +58,14 @@ public class SciProjectConfig { this.contactTypesBundleName = contactTypesBundle; } + public String getMemberRolesBundleName() { + return memberRolesBundleName; + } + + public void setMemberRolesBundleName(final String memberRolesBundleName) { + this.memberRolesBundleName = memberRolesBundleName; + } + public boolean isEnableSponsor() { return enableSponsor; } @@ -93,7 +105,5 @@ public class SciProjectConfig { public void setFundingVolumeLength(final int fundingVolumeLength) { this.fundingVolumeLength = fundingVolumeLength; } - - }