groups association is now supported by the widget

git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/widgets/ckan-metadata-publisher-widget@134148 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-11-14 17:37:45 +00:00
parent 483dd77608
commit a40e25a3c4
12 changed files with 245 additions and 51 deletions

View File

@ -1,4 +1,9 @@
<ReleaseNotes>
<Changeset component="org.gcube.portlets-widgets.ckan-metadata-publisher-widget.1-2-0" date="2016-12-11">
<Change>A post is automatically created by the Product Catalogue user every time someone publishes</Change>
<Change>The user now can select all files in the hierarchy and publish them</Change>
<Change>The user can now associate the product to the avilable groups</Change>
</Changeset>
<Changeset component="org.gcube.portlets-widgets.ckan-metadata-publisher-widget.1-1-0" date="2016-10-11">
<Change>Creation of a group is now supported</Change>
<Change>Association of a dataset to a group is now supported</Change>

View File

@ -3,6 +3,7 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
import java.util.List;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetaDataProfileBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
@ -66,6 +67,12 @@ public interface CKanPublisherService extends RemoteService {
* @return true if it exists, false otherwise
*/
boolean datasetIdAlreadyExists(String title);
/**
* Retrieve the list of groups the user can choose to associate this product with.
* @return a list of groups' beans
*/
List<GroupBean> getUserGroups();
/**
* Return a tree object representing the whole folder hierarchy

View File

@ -3,6 +3,7 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
import java.util.List;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetaDataProfileBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceElementBean;
@ -11,8 +12,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* CKAN publisher services RPC.
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public interface CKanPublisherServiceAsync {
@ -76,4 +76,10 @@ public interface CKanPublisherServiceAsync {
void getTreeFolder(String folderId,
AsyncCallback<ResourceElementBean> callback);
/**
* Retrieve the list of groups the user can choose to associate this product with.
* @return a list of groups' beans
*/
void getUserGroups(AsyncCallback<List<GroupBean>> callback);
}

View File

@ -21,6 +21,7 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.dataset.reso
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.dataset.resources.TagsPanel;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.utils.InfoIconsLabels;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetaDataProfileBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetadataFieldWrapper;
@ -112,6 +113,7 @@ public class CreateDatasetForm extends Composite{
@UiField Anchor licenseUrlAnchor;
@UiField Paragraph unavailableUrl;
@UiField TagsPanel tagsPanel;
@UiField ListBox groupsListbox;
// info panels
@UiField Icon infoIconLicenses;
@ -143,12 +145,16 @@ public class CreateDatasetForm extends Composite{
@UiField Popover popoverResources;
@UiField Icon infoIconTitle;
@UiField FocusPanel focusPanelTitle;
@UiField Popover popoverGroups;
@UiField Icon infoIconGroups;
@UiField FocusPanel focusPanelGroups;
@UiField Popover popoverTitle;
@UiField ControlGroup metadataProfilesControlGroup;
@UiField ControlGroup productTitleGroup;
@UiField ControlGroup maintainerControlGroup;
@UiField ControlGroup versionControlGroup;
@UiField ControlGroup organizationsGroup;
@UiField ControlGroup groupsControlGroup;
// Create a remote service proxy to talk to the server-side ckan service.
private final CKanPublisherServiceAsync ckanServices = GWT.create(CKanPublisherService.class);
@ -341,13 +347,10 @@ public class CreateDatasetForm extends Composite{
// if there are not resources, for now just checked it ( and hide so that the step will be skipped)
if(showAlertMissingResources){
alertNoResources.setType(AlertType.WARNING);
alertNoResources.setVisible(true);
}else
resourcesTwinPanel = new TwinColumnSelectionMainPanel(bean.getResources().get(0));
}
// set organizations
@ -368,7 +371,6 @@ public class CreateDatasetForm extends Composite{
public void onChange(ChangeEvent event) {
event.preventDefault();
organizationsListboxChangeHandlerBody();
}
});
@ -383,18 +385,14 @@ public class CreateDatasetForm extends Composite{
@Override
public void onFailure(Throwable caught) {
setAlertBlock("Error while retrieving profiles, try to refresh the page", AlertType.ERROR, true);
setAlertBlock("Error while retrieving profiles, try later", AlertType.ERROR, true);
}
@Override
public void onSuccess(List<MetaDataProfileBean> result) {
if(result == null){
setAlertBlock("Error while retrieving profiles, try to refresh the page", AlertType.ERROR, true);
setAlertBlock("Error while retrieving profiles, try later", AlertType.ERROR, true);
}
else{
@ -409,9 +407,7 @@ public class CreateDatasetForm extends Composite{
@Override
public void onFailure(Throwable caught){
setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true);
setAlertBlock("Error while retrieving licenses, try later", AlertType.ERROR, true);
}
@Override
@ -434,15 +430,38 @@ public class CreateDatasetForm extends Composite{
// set the url of the license, if any
showLicenseUrl();
// everything went ok
setAlertBlock("", AlertType.ERROR, false);
continueButton.setEnabled(true);
resetButton.setEnabled(true);
// request groups
ckanServices.getUserGroups(new AsyncCallback<List<GroupBean>>() {
@Override
public void onSuccess(List<GroupBean> result) {
if(result == null){
setAlertBlock("Error while retrieving groups, try later", AlertType.ERROR, true);
}else{
if(result.isEmpty())
return;
else{
for (GroupBean groups : result) {
groupsListbox.addItem(groups.getGroupTitle(), groups.getGroupName());
}
groupsControlGroup.setVisible(true);
}
// everything went ok
setAlertBlock("", AlertType.ERROR, false);
continueButton.setEnabled(true);
resetButton.setEnabled(true);
}
}
@Override
public void onFailure(Throwable caught) {
setAlertBlock("Error while retrieving groups, try later", AlertType.ERROR, true);
}
});
}else{
setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true);
setAlertBlock("Error while retrieving licenses, try later", AlertType.ERROR, true);
}
}
});
@ -749,6 +768,18 @@ public class CreateDatasetForm extends Composite{
break;
}
}
List<GroupBean> groups = new ArrayList<GroupBean>();
// get groups, if any
int items = groupsListbox.getItemCount();
for (int i = 0; i < items; i++) {
String groupTitle = groupsListbox.getItemText(i);
String groupName = groupsListbox.getValue(i);
if(groupsListbox.isItemSelected(i)){
groups.add(new GroupBean(groupTitle, groupName));
}
}
// fill the bean
receivedBean.setAuthorFullName(author);
@ -762,6 +793,7 @@ public class CreateDatasetForm extends Composite{
receivedBean.setTitle(title);
receivedBean.setTags(tagsPanel.getTags());
receivedBean.setSelectedOrganization(chosenOrganization);
receivedBean.setGroups(groups);
if(resourcesTwinPanel != null)
receivedBean.setResources(resourcesTwinPanel.getResourcesToPublish());
@ -1008,6 +1040,17 @@ public class CreateDatasetForm extends Composite{
focusPanelTitle,
popupOpenedIds
);
// groups
InfoIconsLabels.preparePopupPanelAndPopover(
InfoIconsLabels.GROUPS_INFO_ID_POPUP,
InfoIconsLabels.GROUPS_INFO_TEXT,
InfoIconsLabels.GROUPS_INFO_CAPTION,
infoIconGroups,
popoverGroups,
focusPanelGroups,
popupOpenedIds
);
}
/**

View File

@ -87,7 +87,7 @@
</b:ControlLabel>
<b:Controls>
<b:TextArea placeholder="eg. Some useful notes about the product"
width="95%" alternateSize="LARGE" b:id="description" title="Product description"
width="90%" alternateSize="LARGE" b:id="description" title="Product description"
ui:field="descriptionTextarea"></b:TextArea>
</b:Controls>
</b:ControlGroup>
@ -149,7 +149,7 @@
to publish the product">Publish in:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="organization" alternateSize="LARGE"
width="96%" title="Publish in this organization" ui:field="organizationsListbox">
width="91%" title="Publish in this organization" ui:field="organizationsListbox">
</b:ListBox>
</b:Controls>
</b:ControlGroup>
@ -263,6 +263,23 @@
</b:Controls>
</b:ControlGroup>
<b:ControlGroup ui:field="groupsControlGroup" visible="false">
<b:ControlLabel for="groups" title="The groups for this product">Product Groups:</b:ControlLabel>
<b:Controls>
<b:ListBox b:id="groups" alternateSize="LARGE" width="91%" multipleSelect="true"
title="The groups for this product (Hold CTRL or Command button for multiple selection)" ui:field="groupsListbox">
</b:ListBox>
<span style="float:right; width:5%; color: #aaaaaa;">
<b:Popover ui:field="popoverGroups" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelGroups">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIconGroups" />
</g:FocusPanel>
</b:Popover>
</span>
</b:Controls>
</b:ControlGroup>
<!-- Alert block on continue -->
<b:AlertBlock animation="true" visible="false"
ui:field="alertNoResources"

View File

@ -92,6 +92,7 @@ public class MetaDataFieldSkeleton extends Composite{
private static final String UPPER_RANGE_NOT_SPECIFIED = "Not specified";
// time range separator
public static final String RANGE_SEPARATOR = ",";
private static final String TOOLTIP_MULTISELECTION = "Hold down the Control (CTRL) or Command button to select multiple options";
public MetaDataFieldSkeleton(final MetadataFieldWrapper field, HandlerManager eventBus) throws Exception{
initWidget(uiBinder.createAndBindUi(this));
@ -224,25 +225,29 @@ public class MetaDataFieldSkeleton extends Composite{
}else{
// listbox
holder = new ListBox(field.isMultiSelection());
ListBox tempListBox;
holder = tempListBox = new ListBox(field.isMultiSelection());
if(field.isMultiSelection())
tempListBox.setTitle(TOOLTIP_MULTISELECTION);
// if it is not mandatory, add a disabled option
if(!field.getMandatory()){
((ListBox)holder).addItem("Select " + field.getFieldName());
((ListBox)holder).setSelectedValue("Select " + field.getFieldName());
((ListBox)holder).getElement().getElementsByTagName("option").getItem(0).setAttribute("disabled", "disabled");
tempListBox.addItem("Select " + field.getFieldName());
tempListBox.setSelectedValue("Select " + field.getFieldName());
tempListBox.getElement().getElementsByTagName("option").getItem(0).setAttribute("disabled", "disabled");
}
// get vocabulary fields
List<String> vocabulary = field.getVocabulary();
for (String term : vocabulary) {
((ListBox)holder).addItem(term);
tempListBox.addItem(term);
}
// set default value
if(field.getDefaultValue() != null)
((ListBox)holder).setSelectedValue(field.getDefaultValue());
tempListBox.setSelectedValue(field.getDefaultValue());
}
@ -390,7 +395,7 @@ public class MetaDataFieldSkeleton extends Composite{
if(rangeValue.contains(DataTimeBox.MISSING_RANGE_VALUE_START) && !rangeValue.equals(DataTimeBox.MISSING_RANGE_VALUE_START + DataTimeBox.RANGE_SEPARATOR_START_END + DataTimeBox.MISSING_RANGE_VALUE_END))
return INSERT_MISSING_VALUE;
return null;
case Times_ListOf:

View File

@ -72,19 +72,16 @@ public class ResourceInfoForm extends Composite{
@Override
public void onClick(ClickEvent event) {
removeError(controlName);
// check description
resourceBean.setDescription(resourceDescription.getText());
// check name
removeError(controlName);
String newName = resourceName.getText();
if(newName == null || newName.isEmpty()){
showError(controlName);
}else
}else{
resourceBean.setEditableName(newName);
valueUpdater.update(resourceBean);
valueUpdater.update(resourceBean);
}
}
});

View File

@ -80,6 +80,11 @@ public class InfoIconsLabels {
public static final String TITLE_INFO_ID_POPUP = "title-popup-panel-info";
public static final String TITLE_INFO_TEXT = "Product Title must contain only alphanumer characters, dots, underscore or hyphen minus. No others symbols are allowed.";
public static final String TITLE_INFO_CAPTION = "Product Title";
// GROUPS
public static final String GROUPS_INFO_ID_POPUP = "groups-popup-panel-info";
public static final String GROUPS_INFO_TEXT = "Associate this product to groups";
public static final String GROUPS_INFO_CAPTION = "Product Groups";
/**
* Prepare the popover and the gcube popup panel for information.

View File

@ -1,7 +1,10 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
import java.util.List;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -20,15 +23,18 @@ public class AssociationToGroupThread extends Thread {
private String username;
private DataCatalogue catalogue;
private String organization;
private List<GroupBean> groups;
/**
* @param list
* @param groupTitle
* @param datasetId
* @param username
* @param catalogue
*/
public AssociationToGroupThread(String groupTitle, String datasetId,
public AssociationToGroupThread(List<GroupBean> groups, String groupTitle, String datasetId,
String username, DataCatalogue catalogue, String organization) {
this.groups = groups;
this.groupTitle = groupTitle;
this.datasetId = datasetId;
this.username = username;
@ -39,7 +45,7 @@ public class AssociationToGroupThread extends Thread {
@Override
public void run() {
logger.info("Association thread started to put the dataset with id="+ datasetId + " into group with title " + groupTitle + " for user " + username);
logger.info("Association thread started to put the dataset with id = "+ datasetId + " into group with title " + groupTitle + " for user " + username);
// create the group
CkanGroup group = catalogue.createGroup(groupTitle, groupTitle, "");
@ -57,19 +63,25 @@ public class AssociationToGroupThread extends Thread {
if(!role.equals(RolesCkanGroupOrOrg.ADMIN))
role = RolesCkanGroupOrOrg.MEMBER; // decrease the role to member if it is not an admin
boolean assigned = catalogue.checkRoleIntoGroup(username, groupTitle, role);
if(assigned){
logger.debug("Admin/editor role was assigned for this group, going to associate the product to the group");
boolean putIntoGroup = catalogue.assignDatasetToGroup(groupTitle, datasetId, catalogue.getApiKeyFromUsername(username));
logger.info("Was product put into group? " + putIntoGroup);
}
}
logger.info("Other groups to which the product should be associate are " + groups);
for (GroupBean groupBean : groups) {
boolean putIntoGroup = catalogue.assignDatasetToGroup(groupBean.getGroupTitle(), datasetId, catalogue.getApiKeyFromUsername(username));
logger.info("Was product put into group" + groupBean + "? " + putIntoGroup);
}
}
}

View File

@ -2,6 +2,7 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
@ -23,6 +24,7 @@ import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherSe
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.Utils;
import org.gcube.portlets.widgets.ckandatapublisherwidget.server.utils.WorkspaceUtils;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.GroupBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.MetaDataProfileBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.OrganizationBean;
@ -35,6 +37,7 @@ import org.slf4j.LoggerFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.liferay.portal.service.UserLocalServiceUtil;
import eu.trentorise.opendata.jackan.model.CkanGroup;
import eu.trentorise.opendata.jackan.model.CkanLicense;
/**
@ -383,6 +386,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
AssociationToGroupThread threadAssociationToGroup =
new AssociationToGroupThread(
toCreate.getGroups(),
toCreate.getChosenProfile(),
datasetId,
userName,
@ -598,4 +602,41 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
.getHomeManager()
.getHome(getDevelopmentUser()).getWorkspace();
}
@Override
public List<GroupBean> getUserGroups() {
ASLSession session = getASLSession();
List<GroupBean> toReturn = new ArrayList<GroupBean>();
if(isWithinPortal()){
String username = session.getUsername();
if(username.equals(TEST_USER)){
logger.warn("Session expired");
return null;
}
logger.debug("Request for user " + username + " groups");
// get http session
HttpSession httpSession = getThreadLocalRequest().getSession();
String scope = (String)httpSession.getAttribute(SessionCatalogueAttributes.SCOPE_CLIENT_PORTLET_URL);
DataCatalogue catalogue = getCatalogue(scope);
List<CkanGroup> ckanGroups = catalogue.getGroups();
// TODO
for (CkanGroup ckanGroup : ckanGroups) {
toReturn.add(new GroupBean(ckanGroup.getTitle(), ckanGroup.getName()));
}
logger.debug("List of groups to return is " + toReturn);
}else{
logger.warn("Dev mode detected");
toReturn = Arrays.asList(new GroupBean("Group title", "aaa"));
}
return toReturn;
}
}

View File

@ -48,6 +48,7 @@ public class DatasetMetadataBean implements Serializable {
private List<MetaDataProfileBean> metadataList;
private List<String> tags; // on retrieve, they are the keys of the custom fields
private Map<String, String> customFields;
private List<GroupBean> groups;
public DatasetMetadataBean(){
super();
@ -81,7 +82,7 @@ public class DatasetMetadataBean implements Serializable {
String maintainerEmail, String ownerIdentifier,
List<OrganizationBean> organizationList, String selectedOrganization,
List<ResourceElementBean> resources,
List<MetaDataProfileBean> metadataList) {
List<MetaDataProfileBean> metadataList, List<GroupBean> groups) {
super();
this.id = id;
this.title = title;
@ -102,6 +103,7 @@ public class DatasetMetadataBean implements Serializable {
this.selectedOrganization = selectedOrganization;
this.resources = resources;
this.metadataList = metadataList;
this.groups = groups;
}
public List<MetaDataProfileBean> getMetadataList() {
@ -271,21 +273,30 @@ public class DatasetMetadataBean implements Serializable {
public void setChosenProfile(String chosenProfile) {
this.chosenProfile = chosenProfile;
}
public List<GroupBean> getGroups() {
return groups;
}
public void setGroups(List<GroupBean> groups) {
this.groups = groups;
}
@Override
public String toString() {
return "DatasetMetadataBean [id=" + id + ", title=" + title
+ ", description=" + description + ", customFields="
+ customFields + ", tags=" + tags + ", license=" + license
+ ", visibility=" + visibility + ", source=" + source
+ ", version=" + version + ", authorName=" + authorName
+ ", description=" + description + ", license=" + license
+ ", source=" + source + ", authorName=" + authorName
+ ", authorSurname=" + authorSurname + ", authorFullName="
+ authorFullName + ", authorEmail=" + authorEmail
+ ", maintainer=" + maintainer + ", maintainerEmail="
+ maintainerEmail + ", ownerIdentifier=" + ownerIdentifier
+ ", organizationList=" + organizationList
+ ", chosenProfile=" + chosenProfile
+ ", selectedOrganization=" + selectedOrganization
+ ", resources=" + resources + ", metadataList=" + metadataList
+ ", chosenProfile=" + chosenProfile + "]";
+ ", version=" + version + ", visibility=" + visibility
+ ", organizationList=" + organizationList + ", resources="
+ resources + ", metadataList=" + metadataList + ", tags="
+ tags + ", customFields=" + customFields + ", groups="
+ groups + "]";
}
}

View File

@ -0,0 +1,45 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.shared;
import java.io.Serializable;
/**
* A group bean.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class GroupBean implements Serializable {
private static final long serialVersionUID = -5529957814115387053L;
String groupTitle;
String groupName;
public GroupBean() {
super();
}
/**
* @param groupTitle
* @param groupName
*/
public GroupBean(String groupTitle, String groupName) {
super();
this.groupTitle = groupTitle;
this.groupName = groupName;
}
public String getGroupTitle() {
return groupTitle;
}
public void setGroupTitle(String groupTitle) {
this.groupTitle = groupTitle;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
}