ckan-metadata-publisher-widget/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java

674 lines
18 KiB
Java

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.user.gcubewidgets.client.elements.Span;
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 com.github.gwtbootstrap.client.ui.AlertBlock;
import com.github.gwtbootstrap.client.ui.Button;
import com.github.gwtbootstrap.client.ui.CheckBox;
import com.github.gwtbootstrap.client.ui.ControlGroup;
import com.github.gwtbootstrap.client.ui.ListBox;
import com.github.gwtbootstrap.client.ui.Tab;
import com.github.gwtbootstrap.client.ui.TabPanel;
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.github.gwtbootstrap.client.ui.resources.Bootstrap.Tabs;
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.Timer;
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.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* Edit metadata form for ckan dataset.
* @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.
*/
private final CKanPublisherServiceAsync ckanServices = GWT.create(CKanPublisherService.class);
private static EditMetadataFormUiBinder uiBinder = GWT
.create(EditMetadataFormUiBinder.class);
interface EditMetadataFormUiBinder extends
UiBinder<Widget, EditMetadataForm> {
}
@UiField TextBox titleTextBox;
@UiField TextArea descriptionTextarea;
@UiField TextBox tagsEnterTextBox;
@UiField FlowPanel tagsPanel;
@UiField ListBox licenseListbox;
@UiField ListBox visibilityListbox;
@UiField ListBox organizationsListbox;
@UiField TextBox versionTextbox;
@UiField TextBox authorTextbox;
@UiField TextBox authorEmailTextbox;
@UiField TextBox maintainerTextbox;
@UiField TextBox maintainerEmailTextbox;
@UiField ControlGroup customFields;
@UiField Button addCustomFieldButton;
@UiField CheckBox addResourcesCheckBox;
@UiField ControlGroup resourcesControlGroup;
@UiField Button createButton;
@UiField Button addResourcesButton;
@UiField Button resetButton;
@UiField AlertBlock infoBlock;
@UiField AlertBlock onCreateAlertBlock;
@UiField VerticalPanel resourcesPanel;
// tab panel
private TabPanel tabPanel;
// add resource form
AddResourceToDataset resourceForm;
// 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> customFieldEntriesList = new ArrayList<CustomFieldEntry>();
// dataset metadata bean
private DatasetMetadataBean receivedBean;
// the owner
private String owner;
/**
* Invoked in the most general case
* @param owner
*/
public EditMetadataForm(String owner) {
initWidget(uiBinder.createAndBindUi(this));
this.owner = owner;
// bind on events
bind();
// set info block
setAlertBlock("Retrieving information, please wait...", AlertType.INFO, true);
// disable create button
createButton.setEnabled(false);
resetButton.setEnabled(false);
// get back the licenses and the metadata information
ckanServices.getDatasetBean(null, owner, new AsyncCallback<DatasetMetadataBean>() {
@Override
public void onSuccess(DatasetMetadataBean bean) {
if(bean != null){
// save it
receivedBean = bean;
// fill the form
versionTextbox.setText(String.valueOf(bean.getVersion()));
authorTextbox.setText(bean.getAuthor());
authorEmailTextbox.setText(bean.getAuthorEmail());
maintainerTextbox.setText(bean.getMaintainer());
maintainerEmailTextbox.setText(bean.getMaintainerEmail());
// set organizations
List<String> organizations = bean.getOrganizationList();
for (String organization : organizations) {
organizationsListbox.addItem(organization);
}
// 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);
resetButton.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) {
setAlertBlock("Error while retrieving information, try to refresh the page", AlertType.ERROR, true);
}
});
// hide the Add resources checkbox
resourcesControlGroup.setVisible(false);
}
/**
* Invoked when the workspace is used.
* @param idFolderWorkspace
* @param owner
*/
public EditMetadataForm(String idFolderWorkspace, String owner) {
initWidget(uiBinder.createAndBindUi(this));
this.owner = owner;
// bind on events
bind();
// set info block
setAlertBlock("Retrieving information, please wait...", AlertType.INFO, true);
// disable create button
createButton.setEnabled(false);
resetButton.setEnabled(false);
// get back the licenses and the metadata information from the workspace
ckanServices.getDatasetBean(idFolderWorkspace, owner, new AsyncCallback<DatasetMetadataBean>() {
@Override
public void onSuccess(DatasetMetadataBean bean) {
if(bean != null){
// 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());
// set organizations
List<String> organizations = bean.getOrganizationList();
for (String organization : organizations) {
organizationsListbox.addItem(organization);
}
// retrieve custom fields
Map<String, String> customFieldsMap = bean.getCustomFields();
GWT.log("Custom fields is " + customFieldsMap);
if(customFieldsMap != 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, entry.getKey(), entry.getValue(), false);
customFieldEntriesList.add(toAdd);
customFields.add(toAdd);
// add as tag
addTagElement(entry.getKey());
}
}
// 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);
resetButton.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) {
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) {
customFieldEntriesList.remove(event.getRemovedEntry());
customFields.remove(event.getRemovedEntry());
}
});
}
@UiHandler("addCustomFieldButton")
void addCustomFieldEvent(ClickEvent e){
CustomFieldEntry toAdd = new CustomFieldEntry(eventBus, "", "", true);
customFieldEntriesList.add(toAdd);
customFields.add(toAdd);
}
@UiHandler("createButton")
void createDatasetEvent(ClickEvent e){
// validate data TODO
boolean areDataValid = validateData();
// 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.getSelectedItemText();
long version = Long.valueOf(versionTextbox.getValue());
String author = authorTextbox.getValue();
String authorEmail = authorEmailTextbox.getValue();
String maintainer = maintainerTextbox.getValue();
String maintainerEmail = maintainerEmailTextbox.getValue();
String chosenOrganization = organizationsListbox.getSelectedItemText();
boolean addResources = addResourcesCheckBox.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.setTags(tagsList);
receivedBean.setSelectedOrganization(chosenOrganization);
receivedBean.setAddResources(addResources);
Map<String, String> customFieldsMap = new HashMap<String, String>();
// prepare custom fields
for(CustomFieldEntry customEntry : customFieldEntriesList){
String key = customEntry.getKey();
String value = customEntry.getValue();
customFieldsMap.put(key, value);
}
receivedBean.setCustomFields(customFieldsMap);
// invoke the create method
createButton.setEnabled(false);
resetButton.setEnabled(false);
onCreateAlertBlock.setText("Trying to create dataset, please wait");
onCreateAlertBlock.setVisible(true);
ckanServices.createCKanDataset(receivedBean, new AsyncCallback<String>() {
@Override
public void onSuccess(final String datasetId) {
if(datasetId != null){
alertOnCreate("Dataset correctly created!", AlertType.SUCCESS);
// disable dataset fields
disableDatasetFields();
// if we are in the "general case" we need to show a form for adding resources
if(!resourcesControlGroup.isVisible()){
createButton.setVisible(false);
resetButton.setVisible(false);
// show the add resources button
addResourcesButton.setVisible(true);
addResourcesButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
// hide the button
addResourcesButton.setVisible(false);
// TabPanel
tabPanel = new TabPanel(Tabs.ABOVE);
tabPanel.setWidth("100%");
// add the form
resourceForm = new AddResourceToDataset(eventBus, datasetId, owner);
// tab for the form
Tab formContainer = new Tab();
formContainer.add(resourceForm);
formContainer.setHeading("Add New Resource");
tabPanel.add(formContainer);
// tab for the added resources
Tab addedResources = new Tab();
addedResources.add(new AddedResourcesSummary(eventBus));
addedResources.setHeading("Added Resource");
tabPanel.add(addedResources);
// add tabs to resources panel
tabPanel.selectTab(0);
resourcesPanel.add(tabPanel);
resourcesPanel.setVisible(true);
}
});
}
}else{
alertOnCreate("Unable to create this dataset, please retry later", AlertType.ERROR);
}
}
@Override
public void onFailure(Throwable caught) {
alertOnCreate("Unable to create this dataset, please retry later", AlertType.ERROR);
}
});
}
}
/**
* On create show alert box and enable buttons
* @param text
* @param type
*/
private void alertOnCreate(String text, AlertType type){
onCreateAlertBlock.setText(text);
onCreateAlertBlock.setType(type);
onCreateAlertBlock.setVisible(true);
createButton.setEnabled(true);
resetButton.setEnabled(true);
// hide after some seconds
Timer t = new Timer() {
@Override
public void run() {
onCreateAlertBlock.setVisible(false);
}
};
t.schedule(2000);
}
/**
* Validate data
* @return true on success
*/
private boolean validateData() {
// TODO
return true;
}
@UiHandler("resetButton")
void resetFormEvent(ClickEvent e){
// reset main fields
titleTextBox.setText("");
descriptionTextarea.setText("");
versionTextbox.setText("");
authorTextbox.setText("");
authorEmailTextbox.setText("");
maintainerTextbox.setText("");
maintainerEmailTextbox.setText("");
removeTags();
// delete custom fields
for (CustomFieldEntry customField : customFieldEntriesList) {
customField.removeFromParent();
}
customFieldEntriesList.clear();
}
/**
* Disable dataset editable fields
*/
protected void disableDatasetFields() {
titleTextBox.setEnabled(false);
descriptionTextarea.setEnabled(false);
versionTextbox.setEnabled(false);
authorTextbox.setEnabled(false);
authorEmailTextbox.setEnabled(false);
maintainerTextbox.setEnabled(false);
maintainerEmailTextbox.setEnabled(false);
visibilityListbox.setEnabled(false);
tagsEnterTextBox.setEnabled(false);
licenseListbox.setEnabled(false);
organizationsListbox.setEnabled(false);
addCustomFieldButton.setEnabled(false);
}
/**
* 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);
}
}
/**
* Add the tag as an element
*/
private void addTagElement(final String tag){
if(tagsList.contains(tag))
return;
final ListItem displayItem = new ListItem();
displayItem.setStyleName("tag-style");
Span p = new Span(tag);
Span span = new Span("x");
span.setTitle("Remove this tag");
span.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
removeListItem(displayItem, tag);
}
});
span.setStyleName("tag-style-x");
displayItem.add(p);
displayItem.add(span);
tagsPanel.add(displayItem);
tagsList.add(tag);
}
/**
* 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();
}
}