Form for dataset metadata creation is almost complete and working. Custom fields must be checked

git-svn-id: http://svn.d4science-ii.research-infrastructures.eu/gcube/trunk/portlets/widgets/ckan-metadata-publisher-widget@128890 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-05-27 17:08:03 +00:00
parent eadc1b4e8f
commit 66fd421732
16 changed files with 918 additions and 135 deletions

38
pom.xml
View File

@ -128,6 +128,44 @@
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>home-library</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>asm-all</artifactId>
<groupId>asm</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>home-library-jcr</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.dvos</groupId>
<artifactId>usermanagement-core</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId>
<scope>runtime</scope>
<!-- put at provided for deploying -->
</dependency>
<dependency>
<groupId>org.gcube.portlets.user</groupId>
<artifactId>workspace-tree-widget</artifactId>
<version>[6.0.0-SNAPSHOT, 7.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.portlets.user</groupId>
<artifactId>gcube-widgets</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View File

@ -22,7 +22,9 @@ public class CKanMetadataPublisher implements EntryPoint {
private void startExample() {
RootPanel.get("ckan-metadata-publisher-div").add(new EditMetadataForm());
String idFolderWorkspace = "06bc1ca7-bf1b-4797-b0a4-cb8a55a9c189";
String owner = "costantino.perciante";
RootPanel.get("ckan-metadata-publisher-div").add(new EditMetadataForm(idFolderWorkspace, owner));
}
}

View File

@ -1,5 +1,6 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import com.google.gwt.user.client.rpc.RemoteService;
@ -14,5 +15,6 @@ import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
public interface CKanPublisherService extends RemoteService {
LicensesBean getLicenses();
DatasetMetadataBean getDatasetBean(String folderId, String owner);
}

View File

@ -1,5 +1,6 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import com.google.gwt.user.client.rpc.AsyncCallback;
@ -13,4 +14,7 @@ public interface CKanPublisherServiceAsync {
void getLicenses(AsyncCallback<LicensesBean> callback);
void getDatasetBean(String folderId, String owner,
AsyncCallback<DatasetMetadataBean> callback);
}

View File

@ -0,0 +1,29 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.events;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.CustomFieldEntry;
import com.google.gwt.event.shared.GwtEvent;
public class DeleteCustomFieldEvent extends GwtEvent<DeleteCustomFieldEventHandler> {
public static Type<DeleteCustomFieldEventHandler> TYPE = new Type<DeleteCustomFieldEventHandler>();
private CustomFieldEntry removedEntry;
public DeleteCustomFieldEvent(CustomFieldEntry removedEntry) {
this.removedEntry = removedEntry;
}
public CustomFieldEntry getRemovedEntry() {
return removedEntry;
}
@Override
public Type<DeleteCustomFieldEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(DeleteCustomFieldEventHandler handler) {
handler.onRemoveEntry(this);
}
}

View File

@ -0,0 +1,7 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.events;
import com.google.gwt.event.shared.EventHandler;
public interface DeleteCustomFieldEventHandler extends EventHandler {
void onRemoveEntry(DeleteCustomFieldEvent event);
}

View File

@ -1,9 +1,16 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEvent;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.InputAddOn;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
@ -15,31 +22,61 @@ public class CustomFieldEntry extends Composite {
interface CustomFieldEntryUiBinder extends
UiBinder<Widget, CustomFieldEntry> {
}
@UiField TextBox keyField;
@UiField TextBox valueField;
public CustomFieldEntry() {
@UiField InputAddOn keyFieldPrepend;
@UiField InputAddOn valueFieldPrepend;
@UiField Button removeCustomField;
// event bus
private HandlerManager eventBus;
public CustomFieldEntry(HandlerManager eventBus) {
initWidget(uiBinder.createAndBindUi(this));
this.eventBus = eventBus;
}
/**
* Get current key value
* @return string
* Check if it has been added by the user during form creation or comes from the workspace
* @return
*/
public String getCurrentKey(){
return keyField.getText();
private boolean isCreatedCustomField(){
return valueFieldPrepend.isAttached();
}
/**
* Get current value value
* @return string
* Retrieve the key value
* @return
*/
public String getCurrentValue(){
public String getKey(){
return valueField.getText();
if(isCreatedCustomField())
return ((TextBox)keyFieldPrepend.getWidget(1)).getValue();
else
return valueFieldPrepend.get
}
/**
* Retrieve the value
* @return
*/
public String getValue(){
if(isCreatedCustomField())
return ((TextBox)valueFieldPrepend.getWidget(1)).getValue();
else
return valueFieldPrepend.getWidgetIndex(1).get
}
@UiHandler("removeCustomField")
void onRemoveCustomField(ClickEvent e){
// fire event
eventBus.fireEvent(new DeleteCustomFieldEvent(this));
}
}

View File

@ -2,11 +2,12 @@
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<b:Controls>
<b:InputAddOn prependText="Key:">
<b:TextBox ui:field="keyField" />
<b:InputAddOn prependText="Key:" ui:field="keyFieldPrepend">
<b:TextBox />
</b:InputAddOn>
<b:InputAddOn prependText="Value:">
<b:TextBox ui:field="valueField"/>
<b:InputAddOn prependText="Value:" ui:field="valueFieldPrepend">
<b:TextBox />
</b:InputAddOn>
<b:Button icon="REMOVE_SIGN" title="Remove field" ui:field="removeCustomField"></b:Button>
</b:Controls>
</ui:UiBinder>

View File

@ -1,24 +1,41 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherServiceAsync;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEvent;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteCustomFieldEventHandler;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import org.gcube.portlets.widgets.workspacesharingwidget.client.view.sharing.multisuggest.Span;
import com.github.gwtbootstrap.client.ui.AlertBlock;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.ControlGroup;
import com.github.gwtbootstrap.client.ui.Label;
import com.github.gwtbootstrap.client.ui.ListBox;
import com.github.gwtbootstrap.client.ui.TextArea;
import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.base.ListItem;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
/**
@ -26,7 +43,7 @@ import com.google.gwt.user.client.ui.Widget;
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class EditMetadataForm extends Composite{
/**
* Create a remote service proxy to talk to the server-side ckan service.
*/
@ -40,13 +57,12 @@ public class EditMetadataForm extends Composite{
}
@UiField TextBox titleTextBox;
@UiField TextBox urlTextbox;
@UiField TextArea descriptionTextarea;
@UiField TextBox tagsTextbox;
@UiField TextBox tagsEnterTextBox;
@UiField FlowPanel tagsPanel;
@UiField ListBox licenseListbox;
@UiField ListBox visibilityListbox;
@UiField ListBox searchableListbox;
@UiField TextBox sourceTextbox;
@UiField TextBox versionTextbox;
@UiField TextBox authorTextbox;
@UiField TextBox authorEmailTextbox;
@ -56,52 +72,160 @@ public class EditMetadataForm extends Composite{
@UiField Button addCustomFieldButton;
@UiField Button createButton;
@UiField Button resetButton;
@UiField AlertBlock infoBlock;
// tags list
private List<String> tagsList = new ArrayList<String>();
// the licenses
private LicensesBean licenseBean;
// event bus
private final HandlerManager eventBus = new HandlerManager(null);
// added custom field entries
List<CustomFieldEntry> customFieldEntries = new ArrayList<CustomFieldEntry>();
// dataset metadata bean
private DatasetMetadataBean receivedBean;
public EditMetadataForm() {
public EditMetadataForm(String idFolderWorkspace, String owner) {
initWidget(uiBinder.createAndBindUi(this));
// bind on events
bind();
// get back the licenses
ckanServices.getLicenses(new AsyncCallback<LicensesBean>() {
// set info block
setAlertBlock("Retrieving information, please wait...", AlertType.INFO, true);
// disable create button
createButton.setEnabled(false);
// get back the licenses and the metadata information from the workspace
ckanServices.getDatasetBean(idFolderWorkspace, owner, new AsyncCallback<DatasetMetadataBean>() {
@Override
public void onSuccess(LicensesBean result) {
if(result != null && !result.getLicenses().isEmpty()){
public void onSuccess(DatasetMetadataBean bean) {
if(bean != null){
licenseBean = result;
// fill the listbox
for(String license: licenseBean.getLicenses()){
licenseListbox.addItem(license);
// save it
receivedBean = bean;
// fill the form
titleTextBox.setText(bean.getTitle());
descriptionTextarea.setText(bean.getDescription());
versionTextbox.setText(String.valueOf(bean.getVersion()));
authorTextbox.setText(bean.getAuthor());
authorEmailTextbox.setText(bean.getAuthorEmail());
maintainerTextbox.setText(bean.getMaintainer());
maintainerEmailTextbox.setText(bean.getMaintainerEmail());
// retrieve custom fields
Map<String, String> customFieldsMap = bean.getCustomFields();
if(customFields != null){
// get the keys and put them as tags
Iterator<Entry<String, String>> iteratorOverCustomField = customFieldsMap.entrySet().iterator();
while (iteratorOverCustomField.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) iteratorOverCustomField
.next();
// these are fixed key, variable value custom fields
CustomFieldEntry toAdd = new CustomFieldEntry(eventBus);
// remove the first appendbox
toAdd.valueFieldPrepend.removeFromParent();
toAdd.keyFieldPrepend.setPrependText(entry.getKey() + ":");
((TextBox)toAdd.keyFieldPrepend.getWidget(1)).setText(entry.getValue());
customFieldEntries.add(toAdd);
customFields.add(toAdd);
final ListItem item = new ListItem();
Label label = new Label(entry.getKey());
item.add(label);
}
}
}else
{
// TODO
// try to retrieve the licenses
setAlertBlock("Retrieving licenses, please wait...", AlertType.INFO, true);
ckanServices.getLicenses(new AsyncCallback<LicensesBean>() {
@Override
public void onSuccess(LicensesBean lBean) {
if(lBean != null && !lBean.getLicenses().isEmpty()){
licenseBean = lBean;
// fill the listbox
for(String license: licenseBean.getLicenses()){
licenseListbox.addItem(license);
}
// everything went ok
setAlertBlock("", AlertType.ERROR, false);
createButton.setEnabled(true);
}else{
setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true);
}
}
@Override
public void onFailure(Throwable caught) {
setAlertBlock("Error while retrieving licenses, try to refresh the page", AlertType.ERROR, true);
}
});
}else{
setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true);
}
}
@Override
public void onFailure(Throwable caught) {
// TODO
setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true);
}
});
}
/**
* Bind on events
*/
private void bind() {
// when a custom field is removed, remove it from the list
eventBus.addHandler(DeleteCustomFieldEvent.TYPE, new DeleteCustomFieldEventHandler() {
@Override
public void onRemoveEntry(DeleteCustomFieldEvent event) {
customFieldEntries.remove(event.getRemovedEntry());
customFields.remove(event.getRemovedEntry());
}
});
}
@UiHandler("addCustomFieldButton")
void addCustomFieldEvent(ClickEvent e){
CustomFieldEntry toAdd = new CustomFieldEntry();
CustomFieldEntry toAdd = new CustomFieldEntry(eventBus);
customFieldEntries.add(toAdd);
customFields.add(toAdd);
@ -109,9 +233,63 @@ public class EditMetadataForm extends Composite{
@UiHandler("createButton")
void createDatasetEvent(ClickEvent e){
// validate data TODO
boolean areDataValid = validateData();
// TODO
// Collect current data and send them to the server
if(areDataValid){
String title = titleTextBox.getValue();
String description = descriptionTextarea.getText();
String selectedLicense = licenseListbox.getSelectedItemText();
String visibility = visibilityListbox.getValue();
String searchable = searchableListbox.getValue();
long version = Long.valueOf(versionTextbox.getValue());
String author = authorTextbox.getValue();
String authorEmail = authorEmailTextbox.getValue();
String maintainer = maintainerTextbox.getValue();
String maintainerEmail = maintainerEmailTextbox.getValue();
// fill the bean
receivedBean.setAuthor(author);
receivedBean.setAuthorEmail(authorEmail);
receivedBean.setDescription(description);
receivedBean.setLicense(selectedLicense);
receivedBean.setMaintainer(maintainer);
receivedBean.setMaintainerEmail(maintainerEmail);
receivedBean.setVersion(version);
receivedBean.setVisibility(visibility.equals("Public"));
receivedBean.setTitle(title);
receivedBean.setSearchable(searchable.equals("Yes"));
receivedBean.setTags(tagsList);
Map<String, String> customFieldsMap = new HashMap<String, String>();
// prepare custom fields
for(CustomFieldEntry customEntry : customFieldEntries){
String key = customEntry.getKey();
String value = customEntry.getValue();
customFieldsMap.put(key, value);
}
receivedBean.setCustomFields(customFieldsMap);
// TODO invoke remote service
}
}
/**
* Validate data
* @return true on success
*/
private boolean validateData() {
// TODO Auto-generated method stub
return true;
}
@UiHandler("resetButton")
@ -119,21 +297,99 @@ public class EditMetadataForm extends Composite{
// reset main fields
titleTextBox.setText("");
urlTextbox.setText("");
descriptionTextarea.setText("");
tagsTextbox.setText("");
sourceTextbox.setText("");
versionTextbox.setText("");
authorTextbox.setText("");
authorEmailTextbox.setText("");
maintainerTextbox.setText("");
maintainerEmailTextbox.setText("");
removeTags();
// delete custom fields
for (CustomFieldEntry customField : customFieldEntries) {
customField.removeFromParent();
}
customFieldEntries.clear();
}
/**
* change alert block behavior.
* @param textToShow
* @param type
* @param visible
*/
private void setAlertBlock(String textToShow, AlertType type, boolean visible){
infoBlock.setText(textToShow);
infoBlock.setType(type);
infoBlock.setVisible(visible);
}
@UiHandler("tagsEnterTextBox")
void onAddTag(KeyDownEvent event){
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
if (!"".equals(tagsEnterTextBox.getValue().trim())) {
addTagElement(tagsEnterTextBox);
}
}
}
/**
* Add the tag as an element
*/
private void addTagElement(TextBox itemBox){
if (itemBox.getValue() != null && !"".equals(itemBox.getValue().trim())) {
if(tagsList.contains(itemBox.getValue()))
return;
final String value = itemBox.getValue();
final ListItem displayItem = new ListItem();
displayItem.setStyleName("tag-style");
Span p = new Span(itemBox.getValue());
Span span = new Span("x");
span.setTitle("Remove this tag");
span.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
removeListItem(displayItem, value);
}
});
span.setStyleName("tag-style-x");
displayItem.add(p);
displayItem.add(span);
itemBox.setValue("");
itemBox.setFocus(true);
tagsPanel.add(displayItem);
tagsList.add(value);
}
}
/**
* Remove a tag from the list
* @param displayItem
*/
private void removeListItem(ListItem displayItem, String value) {
GWT.log("Removing: " + displayItem.getWidget(0).getElement().getInnerHTML(), null);
tagsList.remove(value);
tagsPanel.remove(displayItem);
}
/**
* Remove all inserted tags
*/
private void removeTags(){
tagsList.clear();
tagsPanel.clear();
}
}

View File

@ -28,6 +28,11 @@
.block-alert-style {
margin-top: 10px;
padding: 10px;
margin-bottom: 10px;
}
.tagsPanelStyle {
display: inline-block;
}
</ui:style>
<g:HTMLPanel>
@ -37,9 +42,16 @@
<b:Legend styleName="{style.legend-style}">
Insert Dataset Metadata
<small>* is required</small>
<small>
<span style="color:red;">*</span>
is required
</small>
</b:Legend>
<!-- Alert blocks for info/errors -->
<b:AlertBlock type="INFO" close="false" animation="true"
visible="false" ui:field="infoBlock" styleName="{style.block-alert-style}"></b:AlertBlock>
<b:ControlGroup>
<b:ControlLabel for="title" title="Dataset title">
<font color="red">*</font>
@ -52,16 +64,16 @@
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="url" title="Dataset url">
<font color="red">*</font>
URL:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE" placeholder="Dataset URL"
b:id="url" title="Dataset URL" ui:field="urlTextbox" />
</b:Controls>
</b:ControlGroup>
<!-- <b:ControlGroup> -->
<!-- <b:ControlLabel for="url" title="Dataset url"> -->
<!-- <font color="red">*</font> -->
<!-- URL: -->
<!-- </b:ControlLabel> -->
<!-- <b:Controls> -->
<!-- <b:TextBox alternateSize="LARGE" placeholder="Dataset URL" -->
<!-- b:id="url" title="Dataset URL" ui:field="urlTextbox" /> -->
<!-- </b:Controls> -->
<!-- </b:ControlGroup> -->
<b:ControlGroup>
<b:ControlLabel for="description" title="Dataset description">
@ -74,14 +86,21 @@
</b:Controls>
</b:ControlGroup>
<!-- TAGS Panel -->
<b:ControlGroup>
<b:ControlLabel for="tags" title="Dataset tags">
Tags:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE"
placeholder="eg. economy, mental health, government" b:id="tags"
title="Dataset tags" ui:field="tagsTextbox" />
<b:TextBox alternateSize="LARGE" placeholder="Enter one or more tag for the dataset"
b:id="tags" ui:field="tagsEnterTextBox" />
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:Controls>
<g:FlowPanel ui:field="tagsPanel" styleName="{style.tagsPanelStyle}"></g:FlowPanel>
</b:Controls>
</b:ControlGroup>
@ -104,7 +123,7 @@
<b:Controls>
<b:ListBox b:id="visibility" title="Dataset visibility"
width="70%" ui:field="visibilityListbox">
<g:item title="private">Private</g:item>
<g:item title="private">Private</g:item>
<g:item enabled="true" title="public">Public</g:item>
</b:ListBox>
<span style="float:right; width:256px; color: #aaaaaa;">
@ -120,8 +139,8 @@
<b:Controls>
<b:ListBox b:id="searchable" title="Dataset searchable"
width="70%" ui:field="searchableListbox">
<g:item enabled="true" title="true">true</g:item>
<g:item title="false">false</g:item>
<g:item enabled="true" title="Yes">Yes</g:item>
<g:item title="No">No</g:item>
</b:ListBox>
<span style="float:right; width:256px;color: #aaaaaa;">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" />
@ -132,16 +151,16 @@
</b:Controls>
</b:ControlGroup>
<b:ControlGroup>
<b:ControlLabel for="source" title="Dataset source">
Source:
</b:ControlLabel>
<b:Controls>
<b:TextBox alternateSize="LARGE"
placeholder="http://example.com/dataset.json" b:id="source"
title="Dataset source" ui:field="sourceTextbox" />
</b:Controls>
</b:ControlGroup>
<!-- <b:ControlGroup> -->
<!-- <b:ControlLabel for="source" title="Dataset source"> -->
<!-- Source: -->
<!-- </b:ControlLabel> -->
<!-- <b:Controls> -->
<!-- <b:TextBox alternateSize="LARGE" -->
<!-- placeholder="http://example.com/dataset.json" b:id="source" -->
<!-- title="Dataset source" ui:field="sourceTextbox" /> -->
<!-- </b:Controls> -->
<!-- </b:ControlGroup> -->
<b:ControlGroup>
<b:ControlLabel for="version" title="Dataset version">
@ -155,6 +174,7 @@
<b:ControlGroup>
<b:ControlLabel for="author" title="Dataset author">
<font color="red">*</font>
Author:
</b:ControlLabel>
<b:Controls>
@ -165,6 +185,7 @@
<b:ControlGroup>
<b:ControlLabel for="email" title="Dataset author's email">
<font color="red">*</font>
Author Email:
</b:ControlLabel>
<b:Controls>
@ -195,19 +216,19 @@
<!-- Custom fields can be dinamically added -->
<b:ControlGroup ui:field="customFields">
<b:ControlLabel>Custom Field:</b:ControlLabel>
<b:Controls>
<b:InputAddOn prependText="Key:">
<b:TextBox ui:field="keyField" />
</b:InputAddOn>
<b:InputAddOn prependText="Value:">
<b:TextBox ui:field="valueField" />
</b:InputAddOn>
</b:Controls>
<b:ControlLabel>Custom Field(s):</b:ControlLabel>
</b:ControlGroup>
<b:ControlGroup>
<b:Controls>
<span style="float:right; width:256px; color: #aaaaaa;">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" />
Custom fields are customable metadata that will be added to the
dataset.
You have to choose a unique key for the field and a value
for this. You
can remove them at any time.
</span>
<b:Button icon="PLUS_SIGN" title="Add Custom Field"
ui:field="addCustomFieldButton"></b:Button>
</b:Controls>
@ -218,11 +239,6 @@
type="PRIMARY" block="true">Create</b:Button>
<b:Button title="Reset" ui:field="resetButton" block="true">Reset</b:Button>
<b:AlertBlock type="ERROR" close="false" animation="true"
visible="false" ui:field="errorBlock" styleName="{style.block-alert-style}"></b:AlertBlock>
<b:AlertBlock type="SUCCESS" close="false" animation="true"
visible="false" ui:field="successBlock" styleName="{style.block-alert-style}"></b:AlertBlock>
</b:Fieldset>
</b:Form>
</g:HTMLPanel>

View File

@ -1,20 +1,32 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.server;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.application.framework.core.session.ASLSession;
import org.gcube.application.framework.core.session.SessionManager;
import org.gcube.common.homelibrary.home.HomeLibrary;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.workspace.Workspace;
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.liferay.portal.service.UserLocalServiceUtil;
import eu.trentorise.opendata.jackan.CkanClient;
import eu.trentorise.opendata.jackan.CheckedCkanClient;
import eu.trentorise.opendata.jackan.model.CkanLicense;
/**
@ -24,9 +36,6 @@ import eu.trentorise.opendata.jackan.model.CkanLicense;
@SuppressWarnings("serial")
public class CKANPublisherServicesImpl extends RemoteServiceServlet implements CKanPublisherService{
public static final String HOSTNAME_CKAN = "https://ckan-d-d4s.d4science.org/";
public static final String API_KEY = "803ada7f-2080-493f-8a99-3e593e880d94";
// Logger
private static final Logger logger = LoggerFactory.getLogger(CKANPublisherServicesImpl.class);
@ -46,6 +55,28 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return user;
}
/**
* Retrieve the ckan portal url by querying the IS
* @return
*/
private String getCKANUrlFromIS(){
// TODO
return "https://ckan-d-d4s.d4science.org/";
}
/**
* Retrieve the API_KEY of the current user
* @return
*/
private String getCKANApikeyFromUser(String username){
// TODO
return "803ada7f-2080-493f-8a99-3e593e880d94";
}
/**
* the current ASLSession
* @return the session
@ -86,12 +117,16 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
logger.debug("Request for CKAN licenses");
// get the url and the api key of the user
String ckanPortalUrl = getCKANUrlFromIS();
String apiKey = getCKANApikeyFromUser(""); // TODO
List<String> result = new ArrayList<String>();
CkanClient cc = new CkanClient(HOSTNAME_CKAN);
CheckedCkanClient checkedClient = new CheckedCkanClient(ckanPortalUrl, apiKey);
//retrieve the list of available licenses
List<CkanLicense> licenses = cc.getLicenseList();
List<CkanLicense> licenses = checkedClient.getLicenseList();
for (CkanLicense ckanLicense : licenses) {
result.add(ckanLicense.getTitle());
@ -101,4 +136,99 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return new LicensesBean(result);
}
@Override
public DatasetMetadataBean getDatasetBean(String folderId, String owner){
DatasetMetadataBean bean = null;
ScopeProvider.instance.set("/gcube/devsec/devVRE");
if(isWithinPortal()){
try{
logger.debug("Request dataset metadata bean for folder with id " + folderId
+ " whose owner is " + owner);
Workspace ws = HomeLibrary
.getHomeManagerFactory()
.getHomeManager()
.getHome(owner).getWorkspace();
WorkspaceItem retrievedItem = ws.getItem(folderId);
// get usermanager (liferay)
UserManager liferUserManager = new LiferayUserManager();
GCubeUser userOwner = liferUserManager.getUserByUsername(owner);
// build bean
logger.debug("Building bean");
bean = new DatasetMetadataBean();
bean.setId(folderId);
bean.setDescription(retrievedItem.getDescription());
bean.setVersion(1);
bean.setTitle(retrievedItem.getName());
bean.setAuthor(userOwner.getFullname());
bean.setAuthorEmail(userOwner.getEmail());
bean.setMaintainer(userOwner.getFullname());
bean.setMaintainerEmail(userOwner.getEmail());
bean.setSource(retrievedItem.getPublicLink(true));
// retrieve gcube items of the folder
Map<String, String> folderItems = getGcubeItemProperties(retrievedItem);
bean.setCustomFields(folderItems);
}catch(Exception e){
logger.error("Error while retrieving folder information", e);
}
}else{
bean = new DatasetMetadataBean();
bean.setId(folderId);
bean.setDescription("This is a fantastic description");
bean.setVersion(1);
bean.setTitle("Dataset name");
bean.setAuthor("Costantino Perciante");
bean.setAuthorEmail("costantino.perciante@isti.cnr.it");
bean.setMaintainer("Costantino Perciante");
bean.setMaintainerEmail("costantino.perciante@isti.cnr.it");
bean.setSource("https://dev.d4science.org/group/data-e-infrastructure-gateway/workspace");
// retrieve gcube items of the folder
Map<String, String> folderItems = new HashMap<String, String>();
folderItems.put("tag1", "asds");
folderItems.put("tag2", "asdsdaxcxcs");
folderItems.put("tag3", "asasdads");
bean.setCustomFields(folderItems);
}
return bean;
}
/** Gets the gcube item properties.
*
* @param item the item
* @return the gcube item properties
*/
private Map<String, String> getGcubeItemProperties(WorkspaceItem item) {
if(item instanceof GCubeItem){
GCubeItem gItem = (GCubeItem) item;
try {
if(gItem.getProperties()!=null){
Map<String, String> map = gItem.getProperties().getProperties();
HashMap<String, String> properties = new HashMap<String, String>(map.size()); //TO PREVENT GWT SERIALIZATION ERROR
for (String key : map.keySet())
properties.put(key, map.get(key));
return properties;
}
} catch (InternalErrorException e) {
logger.error("Error in server getItemProperties: ", e);
return null;
}
}
return null;
}
}

View File

@ -0,0 +1,204 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.shared;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* This bean will contain during ckan metadata creation the following information
* (related to the workspace folder that represents a dataset)
* <ul>
* <li> id -> the id of the workspace folder
* <li> Title -> folder's name
* <li> Description -> folders' description
* <li> tags -> folder's custom fields keys' names
* <li> visibility -> as chosen by the creator (visible = true, not visible = false)
* <li> searchable -> as chosen by the creator
* <li> source -> url of the folder within the workspace
* <li> version -> during creation it is going to be 1.0
* <li> author, maintainer -> folder's owner
* <li> custom fields -> gcube items <key, value> couple
* </ul>
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
@SuppressWarnings("serial")
public class DatasetMetadataBean implements Serializable {
private String id;
private String title;
private String description;
private Map<String, String> customFields;
List<String> tags; // on retrieve, they are the keys of the custom fields
private String license; // chosen by the user
private boolean visibility; // Private (false) or Public(true)
private boolean searchable; // true or false
private String source; // url of the folder in the workspace
private long version; // version 1, 2 ...
private String author; // folder's owner
private String authorEmail; // folder's email owner
private String maintainer;
private String maintainerEmail;
public DatasetMetadataBean(){
super();
}
/** Create a metadata bean object.
* @param id
* @param title
* @param description
* @param tags
* @param license
* @param visibility
* @param searchable
* @param source
* @param version
* @param author
* @param authorEmail
* @param maintainer
* @param maintainerEmail
*/
public DatasetMetadataBean(String id, String title, String description,
Map<String, String> customFields, String license, boolean visibility,
boolean searchable, String source, long version, String author,
String authorEmail, String maintainer, String maintainerEmail) {
super();
this.id = id;
this.title = title;
this.description = description;
this.customFields = customFields;
this.license = license;
this.visibility = visibility;
this.searchable = searchable;
this.source = source;
this.version = version;
this.author = author;
this.authorEmail = authorEmail;
this.maintainer = maintainer;
this.maintainerEmail = maintainerEmail;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Map<String, String> getCustomFields() {
return customFields;
}
public void setCustomFields(Map<String, String> customFields) {
this.customFields = customFields;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public boolean getVisibility() {
return visibility;
}
public void setVisibility(boolean visibility) {
this.visibility = visibility;
}
public boolean isSearchable() {
return searchable;
}
public void setSearchable(boolean searchable) {
this.searchable = searchable;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getAuthorEmail() {
return authorEmail;
}
public void setAuthorEmail(String authorEmail) {
this.authorEmail = authorEmail;
}
public String getMaintainer() {
return maintainer;
}
public void setMaintainer(String maintainer) {
this.maintainer = maintainer;
}
public String getMaintainerEmail() {
return maintainerEmail;
}
public void setMaintainerEmail(String maintainerEmail) {
this.maintainerEmail = maintainerEmail;
}
@Override
public String toString() {
return "DatasetMetadataBean [id=" + id + ", title=" + title
+ ", description=" + description + ", customFields="
+ customFields + ", tags=" + tags + ", license=" + license
+ ", visibility=" + visibility + ", searchable=" + searchable
+ ", source=" + source + ", version=" + version + ", author="
+ author + ", authorEmail=" + authorEmail + ", maintainer="
+ maintainer + ", maintainerEmail=" + maintainerEmail + "]";
}
}

View File

@ -12,9 +12,6 @@ public class LicensesBean implements Serializable{
List<String> licenses;
/**
*
*/
public LicensesBean() {
super();
}

View File

@ -9,6 +9,9 @@
<!-- Responsive design -->
<set-property name="bootstrap.responsiveDesign" value="true" />
<inherits name='org.gcube.portlets.user.gcubewidgets.WidgetFactory' />
<inherits name="org.gcube.portlets.user.workspace.WorkspaceTree" />
<!-- Specify the app entry point class. -->
<entry-point
class='org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanMetadataPublisher' />

View File

@ -1,34 +1,24 @@
/** Add css rules here for your application. */
/** Example rules used by the template application (remove for your app) */
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
.tag-style {
color: #3a87ad;
background-color: #d9edf7;
border: 2px solid;
border-color: #bce8f1;
padding: 5px;
display: inline;
margin: 2px;
overflow: hidden;
height: auto !important;
font-size: 11px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
float: left;
font-size: 15px;
}
.sendButton {
display: block;
font-size: 16pt;
}
/** Most GWT widgets already have a style name defined */
.gwt-DialogBox {
width: 400px;
}
.dialogVPanel {
margin: 5px;
}
.serverResponseLabelError {
color: red;
}
/** Set ids using widget.getElement().setId("idOfElement") */
#closeButton {
margin: 15px 6px 6px;
}
.tag-style-x {
color: #a6b3cf !important;
margin-left: 5px !important;
font-weight: bold !important;
cursor: pointer !important;
}

View File

@ -0,0 +1,67 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.homelibrary.home.exceptions.HomeNotFoundException;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.exceptions.UserNotFoundException;
import org.gcube.common.homelibrary.home.workspace.exceptions.WorkspaceFolderNotFoundException;
import eu.trentorise.opendata.jackan.CheckedCkanClient;
import eu.trentorise.opendata.jackan.CkanClient;
import eu.trentorise.opendata.jackan.model.CkanUser;
public class Tests {
//@Test
public static void test() throws WorkspaceFolderNotFoundException, InternalErrorException, HomeNotFoundException, UserNotFoundException {
// String username ="costantino.perciante";
// ScopeProvider.instance.set("/gcube/devsec/devVRE");
//
// Workspace ws = HomeLibrary
// .getHomeManagerFactory()
// .getHomeManager()
// .getHome(username).getWorkspace();
//
// System.out.println("Created workspace reference");
//
// WorkspaceFolder rootFolder = ws.getRoot();
// System.out.println("Root folder has id " + rootFolder.getId());
//
// List<WorkspaceItem> children = rootFolder.getChildren();
//
// for (WorkspaceItem workspaceItem : children) {
// System.out.println("Children with name " + workspaceItem.getName() + " and id " + workspaceItem.getId());
// }
// get the url and the api key of the user
String ckanPortalUrl = "https://ckan-d-d4s.d4science.org/";
String apiKey = "803ada7f-2080-493f-8a99-3e593e880d94";
List<String> result = new ArrayList<String>();
CheckedCkanClient checkedClient = new CheckedCkanClient(ckanPortalUrl, apiKey);
CkanClient client = new CkanClient(ckanPortalUrl);
List<CkanUser> list = client.getUserList();
for (CkanUser ckanUser : list) {
System.out.println("User -> " + ckanUser.getId() + " with fullname " + ckanUser.getFullname() + " and name " + ckanUser.getName() + " password " + ckanUser.getPassword());
}
}
public static void main(String[] args) {
// try {
// test();
// } catch (WorkspaceFolderNotFoundException | InternalErrorException
// | HomeNotFoundException | UserNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}