diff --git a/pom.xml b/pom.xml
index 3ea0936..3b0fe63 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,14 +93,10 @@
org.slf4j
slf4j-log4j12
- 1.6.4
- provided
org.slf4j
slf4j-api
- 1.6.4
- provided
org.gcube.common.portal
@@ -176,6 +172,11 @@
gcube-widgets
provided
+
+ net.htmlparser.jericho
+ jericho-html
+ 3.3
+
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java
index 4ca55fe..d0d9a56 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanMetadataPublisher.java
@@ -1,6 +1,6 @@
package org.gcube.portlets.widgets.ckandatapublisherwidget.client;
-import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.EditMetadataForm;
+import org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui.CreateDatasetForm;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
@@ -24,7 +24,7 @@ public class CKanMetadataPublisher implements EntryPoint {
String idFolderWorkspace = "8b67fc1f-940d-4512-b783-105fba11c270";
String owner = "costantino.perciante";
- RootPanel.get("ckan-metadata-publisher-div").add(new EditMetadataForm(owner));
+ RootPanel.get("ckan-metadata-publisher-div").add(new CreateDatasetForm(owner));
}
}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java
index 94d62d9..493a315 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherService.java
@@ -32,17 +32,26 @@ public interface CKanPublisherService extends RemoteService {
/**
* Try to create such dataset starting from the information contained into the toCreate bean.
* @param toCreate
+ * @param isWorkspaceRequest if the call comes from the workspace
* @return the identifier of the created dataset or null on error
*/
- String createCKanDataset(DatasetMetadataBean toCreate);
+ String createCKanDataset(DatasetMetadataBean toCreate, boolean isWorkspaceRequest);
/**
* Add this resource to the dataset whose id is datasetId
* @param resource
* @param datasetId
* @param owner of the dataset
- * @param callback
*/
- boolean addResourceToDataset(ResourceBean resource, String datasetId, String owner);
+ ResourceBean addResourceToDataset(ResourceBean resource, String datasetId, String owner);
+
+ /**
+ * Delete this resource from the dataset with id datasetId
+ * @param resource
+ * @param datasetId
+ * @param owner of the dataset
+ * @return true on success, false otherwise
+ */
+ boolean deleteResourceFromDataset(ResourceBean resource, String owner);
}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java
index a2eb722..d07202b 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/CKanPublisherServiceAsync.java
@@ -31,9 +31,10 @@ public interface CKanPublisherServiceAsync {
/**
* Try to create such dataset starting from the information contained into the toCreate bean.
* @param toCreate
+ * @param isWorkspaceRequest if the call comes from the workspace
* @return true on success, false otherwise
*/
- void createCKanDataset(DatasetMetadataBean toCreate,
+ void createCKanDataset(DatasetMetadataBean toCreate, boolean isWorkspaceRequest,
AsyncCallback callback);
/**
@@ -44,6 +45,15 @@ public interface CKanPublisherServiceAsync {
* @param callback
*/
void addResourceToDataset(ResourceBean resource, String datasetId, String owner,
- AsyncCallback callback);
+ AsyncCallback callback);
+
+ /**
+ * Delete this resource from the dataset with id datasetId
+ * @param resource
+ * @param owner of the dataset
+ * @return true on success, false otherwise
+ */
+ void deleteResourceFromDataset(ResourceBean resource,
+ String owner, AsyncCallback callback);
}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/events/DeleteResourceEvent.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/events/DeleteResourceEvent.java
new file mode 100644
index 0000000..63178a5
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/events/DeleteResourceEvent.java
@@ -0,0 +1,34 @@
+package org.gcube.portlets.widgets.ckandatapublisherwidget.client.events;
+
+import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceBean;
+
+import com.google.gwt.event.shared.GwtEvent;
+
+/**
+ * Deleted resource event.
+ * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
+ */
+public class DeleteResourceEvent extends GwtEvent {
+ public static Type TYPE = new Type();
+
+ private ResourceBean resource;
+
+ public DeleteResourceEvent(ResourceBean resource) {
+ this.resource = resource;
+ }
+
+ public ResourceBean getResource() {
+ return resource;
+ }
+
+ @Override
+ public Type getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(DeleteResourceEventHandler handler) {
+ handler.onDeletedResource(this);
+ }
+
+}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/events/DeleteResourceEventHandler.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/events/DeleteResourceEventHandler.java
new file mode 100644
index 0000000..02f6f95
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/events/DeleteResourceEventHandler.java
@@ -0,0 +1,11 @@
+package org.gcube.portlets.widgets.ckandatapublisherwidget.client.events;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * The delete event handler
+ * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
+ */
+public interface DeleteResourceEventHandler extends EventHandler{
+ void onDeletedResource(DeleteResourceEvent deleteResourceEvent);
+}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.java
index 453b12e..61a7d9b 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.java
@@ -36,10 +36,10 @@ public class AddResourceToDataset extends Composite{
// bus to alert the dataset form about this new resource
private HandlerManager eventBus;
-
+
// the dataset id
private String datasetId;
-
+
// the owner
private String owner;
@@ -57,10 +57,10 @@ public class AddResourceToDataset extends Composite{
// save bus
this.eventBus = eventBus;
-
+
// save dataset id (it is needed when we will add resources)
this.datasetId = datasetId;
-
+
// the owner of the dataset/files
this.owner = owner;
}
@@ -71,44 +71,45 @@ public class AddResourceToDataset extends Composite{
infoBlock.setVisible(false);
// validation
- if(resourceUrlTextBox.getText().isEmpty()){
+ if(resourceUrlTextBox.getText().isEmpty() || resourceNameTextBox.getText().isEmpty()){
- infoBlock.setType(AlertType.ERROR);
- infoBlock.setText("URL cannot be empty");
- infoBlock.setVisible(true);
+ showAlert("Url and name fields cannot be empty", AlertType.ERROR);
return;
}
-
- // remove html tags into description
- //String description = convert(resourceDescriptionTextArea.getText()); TODO
-
+
// collect data and build up the bean
final ResourceBean resource = new ResourceBean(resourceUrlTextBox.getText(), resourceNameTextBox.getText(), resourceDescriptionTextArea.getText());
// disable add button
addResourceButton.setEnabled(false);
-
+
// try to create
- ckanServices.addResourceToDataset(resource, datasetId, owner, new AsyncCallback() {
-
+ ckanServices.addResourceToDataset(resource, datasetId, owner, new AsyncCallback() {
+
@Override
- public void onSuccess(Boolean result) {
-
- if(result){
+ public void onSuccess(ResourceBean result) {
+
+ if(result != null){
showAlert("Resource created correctly", AlertType.SUCCESS);
- eventBus.fireEvent(new AddResourceEvent(resource));
+ eventBus.fireEvent(new AddResourceEvent(result));
+
+ // remove data
+ resourceUrlTextBox.setText("");
+ resourceNameTextBox.setText("");
+ resourceDescriptionTextArea.setText("");
+
}
else
- showAlert("Unable to add this resource. Check the url is correct", AlertType.ERROR);
-
+ showAlert("Unable to add this resource. Check that the url is correct", AlertType.ERROR);
+
}
-
+
@Override
public void onFailure(Throwable caught) {
-
+
showAlert("Unable to add this resource, sorry", AlertType.ERROR);
-
+
}
});
@@ -120,7 +121,7 @@ public class AddResourceToDataset extends Composite{
* @param type
*/
protected void showAlert(String text, AlertType type) {
-
+
infoBlock.setText(text);
infoBlock.setType(type);
infoBlock.setVisible(true);
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.ui.xml
index 15eb527..59a13e8 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.ui.xml
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddResourceToDataset.ui.xml
@@ -37,15 +37,6 @@
.add-resource-button {
float: right;
}
-
- .info-markdown {
- width: 95%;
- background-color: #ebebeb;
- border-bottom: 1px thin;
- border-left: 1px thin;
- border-right: 1px thin;
- padding: 3px;
- }
+ *
Name:
@@ -89,34 +81,16 @@
-
- You can use
-
- Markdown formatting
-
-
-
- Add
+ Add
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.java
index b338e85..e52ff7b 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.java
@@ -3,24 +3,31 @@ package org.gcube.portlets.widgets.ckandatapublisherwidget.client.ui;
import java.util.ArrayList;
import java.util.List;
+import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService;
+import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherServiceAsync;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.AddResourceEvent;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.AddResourceEventHandler;
+import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteResourceEvent;
+import org.gcube.portlets.widgets.ckandatapublisherwidget.client.events.DeleteResourceEventHandler;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.ResourceBean;
+import com.github.gwtbootstrap.client.ui.Accordion;
+import com.github.gwtbootstrap.client.ui.AccordionGroup;
import com.github.gwtbootstrap.client.ui.Button;
-import com.github.gwtbootstrap.client.ui.constants.ButtonType;
+import com.github.gwtbootstrap.client.ui.Paragraph;
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.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
- * A summary of the added resources by the user.
+ * A summary of the resources added by the user.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class AddedResourcesSummary extends Composite{
@@ -32,20 +39,29 @@ public class AddedResourcesSummary extends Composite{
UiBinder {
}
+ //Create a remote service proxy to talk to the server-side ckan service.
+ private final CKanPublisherServiceAsync ckanServices = GWT.create(CKanPublisherService.class);
+
// Event bus
private HandlerManager eventBus;
- // list of added resources
+ // list of added resources (beans)
List addedResources;
+ // the owner
+ private String owner;
+
@UiField VerticalPanel addResourcesPanel;
- public AddedResourcesSummary(HandlerManager eventBus) {
+ public AddedResourcesSummary(HandlerManager eventBus, String owner) {
initWidget(uiBinder.createAndBindUi(this));
// save bus
this.eventBus = eventBus;
+ // save owner
+ this.owner = owner;
+
// bind on add resource event
bind();
@@ -53,6 +69,9 @@ public class AddedResourcesSummary extends Composite{
addedResources = new ArrayList();
}
+ /**
+ * Bind on add/delete resource event
+ */
private void bind() {
// when a new resource is added
@@ -64,71 +83,84 @@ public class AddedResourcesSummary extends Composite{
// get the resource
final ResourceBean justAddedResource = addResourceEvent.getResource();
- // check if a resource with this id already exists
- for (ResourceBean resource : addedResources){
+ // Build an accordion to show resource info
+ Accordion accordion = new Accordion();
+ AccordionGroup accordionGroup = new AccordionGroup();
+ accordionGroup.setHeading("- " + justAddedResource.getName());
+ accordion.add(accordionGroup);
- if(resource.getId().equals(justAddedResource.getId())){
+ // add sub-info such as url and description
+ Paragraph pUrl = new Paragraph();
+ pUrl.setText("Url : " + justAddedResource.getUrl());
+ Paragraph pDescription = new Paragraph();
+ pDescription.setText("Description : " + justAddedResource.getDescription());
+
+ // button to delete the resource
+ Button deleteButton = new Button();
+ deleteButton.setText("Delete");
+ deleteButton.addClickHandler(new ClickHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+
+ eventBus.fireEvent(new DeleteResourceEvent(justAddedResource));
- // clear list and rebuild
- rebuildSummary();
- return;
}
- }
+ });
- Button associatedButton = new Button();
- associatedButton.setType(ButtonType.LINK);
- associatedButton.setText("-" + justAddedResource.getName());
+ // fill accordion
+ accordionGroup.add(pUrl);
+ accordionGroup.add(pDescription);
+ accordionGroup.add(deleteButton);
// add to the list
addedResources.add(justAddedResource);
// add to the panel
- addResourcesPanel.add(associatedButton);
-
- // add handler to swap tab on click
- associatedButton.addClickHandler(new ClickHandler() {
+ addResourcesPanel.add(accordion);
+ }
+ });
- @Override
- public void onClick(ClickEvent event) {
+ // when the user wants to delete a resource
+ eventBus.addHandler(DeleteResourceEvent.TYPE, new DeleteResourceEventHandler() {
- // TODO show information below this link and swap panel
+ @Override
+ public void onDeletedResource(DeleteResourceEvent deleteResourceEvent) {
+ // to delete
+ ResourceBean toDelete = deleteResourceEvent.getResource();
+
+ // find it
+ for(int i = 0; i < addedResources.size(); i++){
+
+ if(addedResources.get(i).getId().equals(toDelete.getId())){
+
+ // get the associated widget and remove it
+ final Widget widget = addResourcesPanel.getWidget(i);
+
+ // remote call to remove it from the dataset
+ ckanServices.deleteResourceFromDataset(toDelete, owner, new AsyncCallback() {
+
+ @Override
+ public void onSuccess(Boolean result) {
+
+ if(result)
+ widget.removeFromParent();
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+
+ }
+ });
+
+ break;
}
- });
-
+ }
+
+ // remove from the list
+ addedResources.remove(toDelete);
}
});
}
-
- /**
- * Rebuild the summary list
- */
- protected void rebuildSummary() {
-
- addResourcesPanel.clear();
-
- for (final ResourceBean resource : addedResources){
-
- Button associatedButton = new Button();
- associatedButton.setType(ButtonType.LINK);
- associatedButton.setText("-" + resource.getName());
-
- // add to the list
- addedResources.add(resource);
-
- // add to the panel
- addResourcesPanel.add(associatedButton);
-
- // add handler to swap tab on click
- associatedButton.addClickHandler(new ClickHandler() {
-
- @Override
- public void onClick(ClickEvent event) {
-
- // TODO show information below this link and swap panel
-
- }
- });
- }
- }
}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.ui.xml
index 79ee8b8..3311d54 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.ui.xml
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/AddedResourcesSummary.ui.xml
@@ -1,11 +1,8 @@
-
-
-
- Added Resources
-
+ Added Resources
+
\ No newline at end of file
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java
similarity index 85%
rename from src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java
rename to src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java
index dc7e066..d0af196 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.java
@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import org.gcube.datacatalogue.ckanutillibrary.models.MetaDataBean;
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;
@@ -33,6 +34,8 @@ 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.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
@@ -47,7 +50,7 @@ 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{
+public class CreateDatasetForm extends Composite{
/**
* Create a remote service proxy to talk to the server-side ckan service.
@@ -58,7 +61,7 @@ public class EditMetadataForm extends Composite{
.create(EditMetadataFormUiBinder.class);
interface EditMetadataFormUiBinder extends
- UiBinder {
+ UiBinder {
}
@UiField TextBox titleTextBox;
@@ -83,12 +86,14 @@ public class EditMetadataForm extends Composite{
@UiField AlertBlock infoBlock;
@UiField AlertBlock onCreateAlertBlock;
@UiField VerticalPanel resourcesPanel;
+ @UiField VerticalPanel metadataPanel;
+ @UiField ListBox metadataFormatListbox;
// tab panel
private TabPanel tabPanel;
// add resource form
- AddResourceToDataset resourceForm;
+ private AddResourceToDataset resourceForm;
// tags list
private List tagsList = new ArrayList();
@@ -108,11 +113,14 @@ public class EditMetadataForm extends Composite{
// the owner
private String owner;
+ // workspace request?
+ private boolean isWorkspaceRequest = false;
+
/**
* Invoked in the most general case
* @param owner
*/
- public EditMetadataForm(String owner) {
+ public CreateDatasetForm(String owner) {
initWidget(uiBinder.createAndBindUi(this));
this.owner = owner;
@@ -144,6 +152,7 @@ public class EditMetadataForm extends Composite{
authorEmailTextbox.setText(bean.getAuthorEmail());
maintainerTextbox.setText(bean.getMaintainer());
maintainerEmailTextbox.setText(bean.getMaintainerEmail());
+ prepareMetadataList(receivedBean);
// set organizations
List organizations = bean.getOrganizationList();
@@ -206,16 +215,35 @@ public class EditMetadataForm extends Composite{
}
+ /**
+ * Add the items to the listbox and put data into the metadataPanel
+ * @param receivedBean
+ */
+ protected void prepareMetadataList(DatasetMetadataBean receivedBean) {
+
+ List beans = receivedBean.getMetadataList();
+
+ for(MetaDataBean metadataBean: beans){
+
+ //metadataFormatListbox.addItem(metadataBean.getType().getName());
+
+ }
+
+ }
+
/**
* Invoked when the workspace is used.
* @param idFolderWorkspace
* @param owner
*/
- public EditMetadataForm(String idFolderWorkspace, String owner) {
+ public CreateDatasetForm(String idFolderWorkspace, String owner) {
initWidget(uiBinder.createAndBindUi(this));
this.owner = owner;
+ // workspace request
+ isWorkspaceRequest = true;
+
// bind on events
bind();
@@ -245,6 +273,7 @@ public class EditMetadataForm extends Composite{
authorEmailTextbox.setText(bean.getAuthorEmail());
maintainerTextbox.setText(bean.getMaintainer());
maintainerEmailTextbox.setText(bean.getMaintainerEmail());
+ prepareMetadataList(receivedBean);
// set organizations
List organizations = bean.getOrganizationList();
@@ -364,11 +393,16 @@ public class EditMetadataForm extends Composite{
@UiHandler("createButton")
void createDatasetEvent(ClickEvent e){
- // validate data TODO
+ // validate data
boolean areDataValid = validateData();
// Collect current data and send them to the server
- if(areDataValid){
+ if(!areDataValid){
+
+ alertOnCreate("Please check inserted data ", AlertType.ERROR);
+
+ }
+ else{
String title = titleTextBox.getValue();
String description = descriptionTextarea.getText();
@@ -413,10 +447,9 @@ public class EditMetadataForm extends Composite{
createButton.setEnabled(false);
resetButton.setEnabled(false);
- onCreateAlertBlock.setText("Trying to create dataset, please wait");
- onCreateAlertBlock.setVisible(true);
+ alertOnCreate("Trying to create dataset, please wait", AlertType.INFO);
- ckanServices.createCKanDataset(receivedBean, new AsyncCallback() {
+ ckanServices.createCKanDataset(receivedBean, isWorkspaceRequest, new AsyncCallback() {
@Override
public void onSuccess(final String datasetId) {
@@ -459,10 +492,10 @@ public class EditMetadataForm extends Composite{
// tab for the added resources
Tab addedResources = new Tab();
- addedResources.add(new AddedResourcesSummary(eventBus));
+ addedResources.add(new AddedResourcesSummary(eventBus, owner));
addedResources.setHeading("Added Resource");
tabPanel.add(addedResources);
-
+
// add tabs to resources panel
tabPanel.selectTab(0);
resourcesPanel.add(tabPanel);
@@ -518,14 +551,38 @@ public class EditMetadataForm extends Composite{
/**
* Validate data
- * @return true on success
+ * @return true on success, false otherwise
*/
private boolean validateData() {
+
+ boolean correct = true;
- // TODO
- return true;
+ if(titleTextBox.getText().isEmpty())
+ correct = false;
+
+ // email reg expression
+ String regexMail = "\\b[\\w.%-]+@[-.\\w]+\\.[A-Za-z]{2,4}\\b";
+
+ correct &= validateByRegExpression(maintainerEmailTextbox.getText(), regexMail);
+
+ // name reg expression
+ String regexName = "^[a-zA-Z\\s]+";
+
+ correct &= validateByRegExpression(maintainerTextbox.getText(), regexName);
+
+ return correct;
}
+ private boolean validateByRegExpression(String textToValidate, String regex){
+
+ RegExp pattern = RegExp.compile(regex);
+ MatchResult matcher = pattern.exec(textToValidate);
+
+ GWT.log("Matcher is " + matcher);
+
+ return (matcher != null);
+ }
+
@UiHandler("resetButton")
void resetFormEvent(ClickEvent e){
@@ -533,8 +590,6 @@ public class EditMetadataForm extends Composite{
titleTextBox.setText("");
descriptionTextarea.setText("");
versionTextbox.setText("");
- authorTextbox.setText("");
- authorEmailTextbox.setText("");
maintainerTextbox.setText("");
maintainerEmailTextbox.setText("");
removeTags();
@@ -548,14 +603,14 @@ public class EditMetadataForm extends Composite{
}
/**
- * Disable dataset editable fields
+ * Disable dataset editable fields once the dataset has been
+ * Successfully created.
*/
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);
@@ -563,6 +618,17 @@ public class EditMetadataForm extends Composite{
licenseListbox.setEnabled(false);
organizationsListbox.setEnabled(false);
addCustomFieldButton.setEnabled(false);
+
+ // freeze tags
+ for(int i = 0; i < tagsList.size(); i++){
+
+ // get tag widget
+ ListItem tagWidget = (ListItem)tagsPanel.getWidget(i);
+
+ // get the "x" span
+ tagWidget.getWidget(1).removeFromParent();
+
+ }
}
/**
@@ -604,19 +670,19 @@ public class EditMetadataForm extends Composite{
final String value = itemBox.getValue();
final ListItem displayItem = new ListItem();
displayItem.setStyleName("tag-style");
- Span p = new Span(itemBox.getValue());
+ Span tagText = new Span(itemBox.getValue());
- Span span = new Span("x");
- span.setTitle("Remove this tag");
- span.addClickHandler(new ClickHandler() {
+ Span tagRemove = new Span("x");
+ tagRemove.setTitle("Remove this tag");
+ tagRemove.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
- removeListItem(displayItem, value);
+ removeTag(displayItem, value);
}
});
- span.setStyleName("tag-style-x");
- displayItem.add(p);
- displayItem.add(span);
+ tagRemove.setStyleName("tag-style-x");
+ displayItem.add(tagText);
+ displayItem.add(tagRemove);
itemBox.setValue("");
itemBox.setFocus(true);
tagsPanel.add(displayItem);
@@ -640,7 +706,7 @@ public class EditMetadataForm extends Composite{
span.setTitle("Remove this tag");
span.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
- removeListItem(displayItem, tag);
+ removeTag(displayItem, tag);
}
});
@@ -655,10 +721,11 @@ public class EditMetadataForm extends Composite{
* Remove a tag from the list
* @param displayItem
*/
- private void removeListItem(ListItem displayItem, String value) {
- GWT.log("Removing: " + displayItem.getWidget(0).getElement().getInnerHTML(), null);
+ private void removeTag(ListItem displayItem, String value) {
+
tagsList.remove(value);
tagsPanel.remove(displayItem);
+
}
/**
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml
similarity index 87%
rename from src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml
rename to src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml
index 66d0cb7..dfdbcf0 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/EditMetadataForm.ui.xml
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/client/ui/CreateDatasetForm.ui.xml
@@ -33,15 +33,6 @@
.tagsPanelStyle {
display: inline-block;
}
-
- .info-markdown {
- width: 95%;
- background-color: #ebebeb;
- border-bottom: 1px thin;
- border-left: 1px thin;
- border-right: 1px thin;
- padding: 3px;
- }
-
- You can use
-
- Markdown formatting
-
-
@@ -188,7 +160,7 @@
+ enabled="false" b:id="author" title="Dataset author" ui:field="authorTextbox" />
@@ -199,7 +171,7 @@
+ enabled="false" b:id="email" title="Dataset author" ui:field="authorEmailTextbox" />
@@ -223,6 +195,20 @@
+
+ Metadata
+ Format:
+
+
+
+
+
+
+
+
+
Custom Field(s):
@@ -236,7 +222,8 @@
dataset.
You have to choose a unique key for the field and a value
for this. You
- can remove them at any time.
+ can remove them at any time until you create the
+ dataset.
@@ -261,12 +248,13 @@
-
- Add Resources
+
+ Add Resources
-
+
Create
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java
index a41f983..107cd1e 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/server/CKANPublisherServicesImpl.java
@@ -10,6 +10,10 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import net.htmlparser.jericho.Renderer;
+import net.htmlparser.jericho.Segment;
+import net.htmlparser.jericho.Source;
+
import org.gcube.common.homelibrary.home.HomeLibrary;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.workspace.Workspace;
@@ -18,6 +22,7 @@ import org.gcube.common.homelibrary.home.workspace.folder.FolderItem;
import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.CKanUtilsFactory;
+import org.gcube.datacatalogue.ckanutillibrary.models.MetaDataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.client.CKanPublisherService;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.DatasetMetadataBean;
import org.gcube.portlets.widgets.ckandatapublisherwidget.shared.LicensesBean;
@@ -149,6 +154,27 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
return null;
}
+
+ /**
+ * Retrieve the list of metadata beans
+ * @return
+ */
+ private List getMetaDataBeanList(){
+
+ logger.debug("Request for metadata beans list");
+
+ try{
+
+ String currentScope = getCurrentScope();
+ return CKanUtilsFactory.getInstance().getCkanUtilsForScope(currentScope).getMetadataList();
+
+ }catch(Exception e){
+ logger.error("Unable to retrieve metadata", e);
+ }
+
+ return null;
+
+ }
@Override
public LicensesBean getLicenses() {
@@ -187,7 +213,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
bean = new DatasetMetadataBean();
bean.setId(folderId);
- bean.setOwnerFolderInWorkspace(owner);
+ bean.setOwnerIdentifier(owner);
bean.setVersion(1);
bean.setAuthor(userOwner.getFullname());
bean.setAuthorEmail(userOwner.getEmail());
@@ -195,6 +221,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
bean.setMaintainerEmail(userOwner.getEmail());
bean.setOrganizationList(getUserOrganizationsList(owner));
+ // if the request comes from the workspace
if(folderId != null && !folderId.isEmpty()){
@@ -222,6 +249,11 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
bean.setResourcesIds(childrenIds);
+
+ // retrieve the metadata
+ List metadataBeans = getMetaDataBeanList();
+ bean.setMetadataList(metadataBeans);
+
}
}catch(Exception e){
@@ -241,7 +273,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
bean.setMaintainer("Costantino Perciante");
bean.setMaintainerEmail("costantino.perciante@isti.cnr.it");
bean.setOrganizationList(getUserOrganizationsList(owner));
- bean.setOwnerFolderInWorkspace(owner);
+ bean.setOwnerIdentifier(owner);
if(folderId != null && !folderId.isEmpty()){
ScopeProvider.instance.set("/gcube");
@@ -267,6 +299,11 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
bean.setResourcesIds(childrenIds);
}
+
+ // retrieve the metadata
+ List metadataBeans = getMetaDataBeanList();
+ bean.setMetadataList(metadataBeans);
+
}catch(Exception e){
logger.error("Error while building bean into dev mode", e);
}
@@ -302,13 +339,13 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
@Override
- public String createCKanDataset(DatasetMetadataBean toCreate) {
+ public String createCKanDataset(DatasetMetadataBean toCreate, boolean isWorkspaceRequest) {
// retrieve ckan's catalog url
String ckanPortalUrl = getCatalogueUrl();
- // retrieve the owner of the original folder into the workspace
- String owner = toCreate.getOwnerFolderInWorkspace();
+ // retrieve the owner identifier
+ String owner = toCreate.getOwnerIdentifier();
// retrieve the api key for this user
String apiKey = getCKANApikeyFromUser(owner);
@@ -335,7 +372,16 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
dataset.setMaintainer(toCreate.getMaintainer());
dataset.setMaintainerEmail(toCreate.getMaintainerEmail());
dataset.setVersion(String.valueOf(toCreate.getVersion()));
- dataset.setNotes(toCreate.getDescription());
+
+ // description must be escaped
+ Source description = new Source(toCreate.getDescription());
+ Segment htmlSeg = new Segment(description, 0, description.length());
+ Renderer htmlRend = new Renderer(htmlSeg);
+ dataset.setNotes(htmlRend.toString());
+
+ logger.debug("Description (escaped is ) " + htmlRend.toString());
+
+ // visibility TODO
dataset.setOpen(toCreate.getVisibility());
// iterate over the licenses to find the id of the chosen one
@@ -374,7 +420,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
// check if we need to add the resources
- if(toCreate.isAddResources()){
+ if(toCreate.isAddResources() && isWorkspaceRequest){
logger.debug("We need to add resources to the dataset");
@@ -384,7 +430,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
Workspace ws = HomeLibrary
.getHomeManagerFactory()
.getHomeManager()
- .getHome(toCreate.getOwnerFolderInWorkspace()).getWorkspace();
+ .getHome(toCreate.getOwnerIdentifier()).getWorkspace();
List resources = new ArrayList();
@@ -420,8 +466,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}catch(Exception e){
// try to update
- logger.error("Error while creating the dataset, probably it already exists. Trying to update it..", e);
- res = client.updateDataset(dataset);
+ logger.error("Error while creating the dataset, probably it already exists.", e);
}
@@ -459,7 +504,7 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
HttpURLConnection.setFollowRedirects(true);
HttpURLConnection con = (HttpURLConnection) new URL(URLName).openConnection();
con.setRequestMethod("HEAD");
- logger.info("Return code is " + con.getResponseCode());
+ logger.debug("Return code is " + con.getResponseCode());
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
@@ -469,45 +514,81 @@ public class CKANPublisherServicesImpl extends RemoteServiceServlet implements C
}
@Override
- public boolean addResourceToDataset(ResourceBean resourceBean, String datasetId, String owner) {
-
- logger.info("Incoming request for creating new resource for dataset with id " + datasetId);
- logger.info("Owner is " + owner + " and resource is " + resourceBean);
-
+ public ResourceBean addResourceToDataset(ResourceBean resourceBean, String datasetId, String owner) {
+
+ logger.debug("Incoming request for creating new resource for dataset with id " + datasetId);
+ logger.debug("Owner is " + owner + " and resource is " + resourceBean);
+
// of course, if it exists
if(exists(resourceBean.getUrl())){
-
+
try{
- // retrieve ckan's catalog url
- String ckanPortalUrl = getCatalogueUrl();
-
- // retrieve the api key for this user
- String apiKey = getCKANApikeyFromUser(owner);
-
- CkanResource resource = new CkanResource(ckanPortalUrl, datasetId);
- resource.setName(resourceBean.getName());
- resource.setDescription(resourceBean.getDescription());
- resource.setUrl(resourceBean.getUrl());
- resource.setOwner(owner);
-
- // Checked client
- CheckedCkanClient client = new CheckedCkanClient(ckanPortalUrl, apiKey);
- CkanResource createdRes = client.createResource(resource);
-
- if(createdRes != null){
-
- logger.info("Resource " + createdRes.getName() + " is now available");
- return true;
-
- }
-
+ // retrieve ckan's catalog url
+ String ckanPortalUrl = getCatalogueUrl();
+
+ // retrieve the api key for this user
+ String apiKey = getCKANApikeyFromUser(owner);
+
+ CkanResource resource = new CkanResource(ckanPortalUrl, datasetId);
+ resource.setName(resourceBean.getName());
+
+ // escape description
+ Source description = new Source(resourceBean.getDescription());
+ Segment htmlSeg = new Segment(description, 0, description.length());
+ Renderer htmlRend = new Renderer(htmlSeg);
+
+ resource.setDescription(htmlRend.toString());
+ resource.setUrl(resourceBean.getUrl());
+ resource.setOwner(owner);
+
+ // Checked client
+ CheckedCkanClient client = new CheckedCkanClient(ckanPortalUrl, apiKey);
+ CkanResource createdRes = client.createResource(resource);
+
+ if(createdRes != null){
+
+ logger.debug("Resource " + createdRes.getName() + " is now available");
+
+ // set its id and turn it to the client
+ resourceBean.setId(createdRes.getId());
+ return resourceBean;
+
+ }
+
}catch(Exception e){
logger.error("Unable to create new resource", e);
}
}
-
- logger.info("No resource created");
-
+
+ logger.debug("No resource created");
+
+ return null;
+ }
+
+ @Override
+ public boolean deleteResourceFromDataset(ResourceBean resource,
+ String owner) {
+ logger.debug("Request for deleting resource " + resource);
+
+ try{
+
+ // retrieve ckan's catalog url
+ String ckanPortalUrl = getCatalogueUrl();
+
+ // retrieve the api key for this user
+ String apiKey = getCKANApikeyFromUser(owner);
+
+ // Checked client
+ CheckedCkanClient client = new CheckedCkanClient(ckanPortalUrl, apiKey);
+ client.deleteResource(resource.getId());
+
+ return true;
+
+ }catch(Exception e){
+ logger.error("Unable to delete such resource", e);
+ }
+
return false;
}
+
}
diff --git a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java
index 66084fb..98e5268 100644
--- a/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java
+++ b/src/main/java/org/gcube/portlets/widgets/ckandatapublisherwidget/shared/DatasetMetadataBean.java
@@ -4,6 +4,8 @@ import java.io.Serializable;
import java.util.List;
import java.util.Map;
+import org.gcube.datacatalogue.ckanutillibrary.models.MetaDataBean;
+
/**
* This bean will contain during ckan metadata creation the following information
* (related to the workspace folder that represents a dataset)
@@ -19,6 +21,7 @@ import java.util.Map;
* custom fields -> gcube items couple
* organizationsList -> list of organizations to which the user belong (and in which
* he wants to publish)
+ * list of metadata, that is custom fields per vre
*
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
@@ -39,11 +42,12 @@ public class DatasetMetadataBean implements Serializable {
private String authorEmail; // folder's email owner
private String maintainer;
private String maintainerEmail;
- private String ownerFolderInWorkspace; // owner of the folder into the workspace
+ private String ownerIdentifier; // owner of the folder into the workspace (e.g., andrea.rossi)
private List organizationList; // list of organization in which the user is present and could create the dataset
private String selectedOrganization;
private List resourcesIds; // in case of workspace, this is the list of children's ids
private boolean addResources; // if true, add these files as resources to the dataset
+ private List metadataList;
public DatasetMetadataBean(){
super();
@@ -63,17 +67,21 @@ public class DatasetMetadataBean implements Serializable {
* @param authorEmail
* @param maintainer
* @param maintainerEmail
- * @param ownerFolderInWorkspace
+ * @param ownerIdentifier
* @param organizationList
* @param selectedOrganization
+ * @param resourcesIds
+ * @param addResources
+ * @param metadataList
*/
public DatasetMetadataBean(String id, String title, String description,
Map customFields, List tags,
- String license, boolean visibility,
- String source, long version, String author, String authorEmail,
- String maintainer, String maintainerEmail,
- String ownerFolderInWorkspace, List organizationList,
- String selectedOrganization) {
+ String license, boolean visibility, String source, long version,
+ String author, String authorEmail, String maintainer,
+ String maintainerEmail, String ownerIdentifier,
+ List organizationList, String selectedOrganization,
+ List resourcesIds, boolean addResources,
+ List metadataList) {
super();
this.id = id;
this.title = title;
@@ -88,9 +96,20 @@ public class DatasetMetadataBean implements Serializable {
this.authorEmail = authorEmail;
this.maintainer = maintainer;
this.maintainerEmail = maintainerEmail;
- this.ownerFolderInWorkspace = ownerFolderInWorkspace;
+ this.ownerIdentifier = ownerIdentifier;
this.organizationList = organizationList;
this.selectedOrganization = selectedOrganization;
+ this.resourcesIds = resourcesIds;
+ this.addResources = addResources;
+ this.metadataList = metadataList;
+ }
+
+ public List getMetadataList() {
+ return metadataList;
+ }
+
+ public void setMetadataList(List metadataList) {
+ this.metadataList = metadataList;
}
public String getId() {
@@ -101,12 +120,12 @@ public class DatasetMetadataBean implements Serializable {
this.id = id;
}
- public void setOwnerFolderInWorkspace(String ownerFolderInWorkspace) {
- this.ownerFolderInWorkspace = ownerFolderInWorkspace;
+ public String getOwnerIdentifier() {
+ return ownerIdentifier;
}
- public String getOwnerFolderInWorkspace(){
- return ownerFolderInWorkspace;
+ public void setOwnerIdentifier(String ownerIdentifier) {
+ this.ownerIdentifier = ownerIdentifier;
}
public String getTitle() {
@@ -242,14 +261,14 @@ public class DatasetMetadataBean implements Serializable {
return "DatasetMetadataBean [id=" + id + ", title=" + title
+ ", description=" + description + ", customFields="
+ customFields + ", tags=" + tags + ", license=" + license
- + ", visibility=" + visibility
- + ", source=" + source + ", version=" + version + ", author="
- + author + ", authorEmail=" + authorEmail + ", maintainer="
- + maintainer + ", maintainerEmail=" + maintainerEmail
- + ", ownerFolderInWorkspace=" + ownerFolderInWorkspace
- + ", organizationList=" + organizationList
+ + ", visibility=" + visibility + ", source=" + source
+ + ", version=" + version + ", author=" + author
+ + ", authorEmail=" + authorEmail + ", maintainer=" + maintainer
+ + ", maintainerEmail=" + maintainerEmail + ", ownerIdentifier="
+ + ownerIdentifier + ", organizationList=" + organizationList
+ ", selectedOrganization=" + selectedOrganization
+ ", resourcesIds=" + resourcesIds + ", addResources="
- + addResources + "]";
+ + addResources + ", metadataList=" + metadataList + "]";
}
+
}
diff --git a/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml b/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml
index fa37e4f..f36e359 100644
--- a/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml
+++ b/src/main/resources/org/gcube/portlets/widgets/ckandatapublisherwidget/CKanMetadataPublisher.gwt.xml
@@ -10,7 +10,7 @@
-
+
diff --git a/src/main/webapp/CKanMetadataPublisher.html b/src/main/webapp/CKanMetadataPublisher.html
index 7fa2fb4..f0b17e1 100644
--- a/src/main/webapp/CKanMetadataPublisher.html
+++ b/src/main/webapp/CKanMetadataPublisher.html
@@ -5,8 +5,6 @@
-
diff --git a/src/main/webapp/js/showdown.js b/src/main/webapp/js/showdown.js
deleted file mode 100644
index 7f8d073..0000000
--- a/src/main/webapp/js/showdown.js
+++ /dev/null
@@ -1,325 +0,0 @@
-/**
- * Created by Tivie on 06-01-2015.
- */
-
-// Private properties
-var showdown = {},
- parsers = {},
- extensions = {},
- globalOptions = getDefaultOpts(true),
- flavor = {
- github: {
- omitExtraWLInCodeBlocks: true,
- prefixHeaderId: 'user-content-',
- simplifiedAutoLink: true,
- literalMidWordUnderscores: true,
- strikethrough: true,
- tables: true,
- tablesHeaderId: true,
- ghCodeBlocks: true,
- tasklists: true
- },
- vanilla: getDefaultOpts(true)
- };
-
-/**
- * helper namespace
- * @type {{}}
- */
-showdown.helper = {};
-
-/**
- * TODO LEGACY SUPPORT CODE
- * @type {{}}
- */
-showdown.extensions = {};
-
-/**
- * Set a global option
- * @static
- * @param {string} key
- * @param {*} value
- * @returns {showdown}
- */
-showdown.setOption = function (key, value) {
- 'use strict';
- globalOptions[key] = value;
- return this;
-};
-
-/**
- * Get a global option
- * @static
- * @param {string} key
- * @returns {*}
- */
-showdown.getOption = function (key) {
- 'use strict';
- return globalOptions[key];
-};
-
-/**
- * Get the global options
- * @static
- * @returns {{}}
- */
-showdown.getOptions = function () {
- 'use strict';
- return globalOptions;
-};
-
-/**
- * Reset global options to the default values
- * @static
- */
-showdown.resetOptions = function () {
- 'use strict';
- globalOptions = getDefaultOpts(true);
-};
-
-/**
- * Set the flavor showdown should use as default
- * @param {string} name
- */
-showdown.setFlavor = function (name) {
- 'use strict';
- if (flavor.hasOwnProperty(name)) {
- var preset = flavor[name];
- for (var option in preset) {
- if (preset.hasOwnProperty(option)) {
- globalOptions[option] = preset[option];
- }
- }
- }
-};
-
-/**
- * Get the default options
- * @static
- * @param {boolean} [simple=true]
- * @returns {{}}
- */
-showdown.getDefaultOptions = function (simple) {
- 'use strict';
- return getDefaultOpts(simple);
-};
-
-/**
- * Get or set a subParser
- *
- * subParser(name) - Get a registered subParser
- * subParser(name, func) - Register a subParser
- * @static
- * @param {string} name
- * @param {function} [func]
- * @returns {*}
- */
-showdown.subParser = function (name, func) {
- 'use strict';
- if (showdown.helper.isString(name)) {
- if (typeof func !== 'undefined') {
- parsers[name] = func;
- } else {
- if (parsers.hasOwnProperty(name)) {
- return parsers[name];
- } else {
- throw Error('SubParser named ' + name + ' not registered!');
- }
- }
- }
-};
-
-/**
- * Gets or registers an extension
- * @static
- * @param {string} name
- * @param {object|function=} ext
- * @returns {*}
- */
-showdown.extension = function (name, ext) {
- 'use strict';
-
- if (!showdown.helper.isString(name)) {
- throw Error('Extension \'name\' must be a string');
- }
-
- name = showdown.helper.stdExtName(name);
-
- // Getter
- if (showdown.helper.isUndefined(ext)) {
- if (!extensions.hasOwnProperty(name)) {
- throw Error('Extension named ' + name + ' is not registered!');
- }
- return extensions[name];
-
- // Setter
- } else {
- // Expand extension if it's wrapped in a function
- if (typeof ext === 'function') {
- ext = ext();
- }
-
- // Ensure extension is an array
- if (!showdown.helper.isArray(ext)) {
- ext = [ext];
- }
-
- var validExtension = validate(ext, name);
-
- if (validExtension.valid) {
- extensions[name] = ext;
- } else {
- throw Error(validExtension.error);
- }
- }
-};
-
-/**
- * Gets all extensions registered
- * @returns {{}}
- */
-showdown.getAllExtensions = function () {
- 'use strict';
- return extensions;
-};
-
-/**
- * Remove an extension
- * @param {string} name
- */
-showdown.removeExtension = function (name) {
- 'use strict';
- delete extensions[name];
-};
-
-/**
- * Removes all extensions
- */
-showdown.resetExtensions = function () {
- 'use strict';
- extensions = {};
-};
-
-/**
- * Validate extension
- * @param {array} extension
- * @param {string} name
- * @returns {{valid: boolean, error: string}}
- */
-function validate(extension, name) {
- 'use strict';
-
- var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
- ret = {
- valid: true,
- error: ''
- };
-
- if (!showdown.helper.isArray(extension)) {
- extension = [extension];
- }
-
- for (var i = 0; i < extension.length; ++i) {
- var baseMsg = errMsg + ' sub-extension ' + i + ': ',
- ext = extension[i];
- if (typeof ext !== 'object') {
- ret.valid = false;
- ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
- return ret;
- }
-
- if (!showdown.helper.isString(ext.type)) {
- ret.valid = false;
- ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
- return ret;
- }
-
- var type = ext.type = ext.type.toLowerCase();
-
- // normalize extension type
- if (type === 'language') {
- type = ext.type = 'lang';
- }
-
- if (type === 'html') {
- type = ext.type = 'output';
- }
-
- if (type !== 'lang' && type !== 'output' && type !== 'listener') {
- ret.valid = false;
- ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
- return ret;
- }
-
- if (type === 'listener') {
- if (showdown.helper.isUndefined(ext.listeners)) {
- ret.valid = false;
- ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
- return ret;
- }
- } else {
- if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
- ret.valid = false;
- ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
- return ret;
- }
- }
-
- if (ext.listeners) {
- if (typeof ext.listeners !== 'object') {
- ret.valid = false;
- ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
- return ret;
- }
- for (var ln in ext.listeners) {
- if (ext.listeners.hasOwnProperty(ln)) {
- if (typeof ext.listeners[ln] !== 'function') {
- ret.valid = false;
- ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
- ' must be a function but ' + typeof ext.listeners[ln] + ' given';
- return ret;
- }
- }
- }
- }
-
- if (ext.filter) {
- if (typeof ext.filter !== 'function') {
- ret.valid = false;
- ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
- return ret;
- }
- } else if (ext.regex) {
- if (showdown.helper.isString(ext.regex)) {
- ext.regex = new RegExp(ext.regex, 'g');
- }
- if (!ext.regex instanceof RegExp) {
- ret.valid = false;
- ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
- return ret;
- }
- if (showdown.helper.isUndefined(ext.replace)) {
- ret.valid = false;
- ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
- return ret;
- }
- }
- }
- return ret;
-}
-
-/**
- * Validate extension
- * @param {object} ext
- * @returns {boolean}
- */
-showdown.validateExtension = function (ext) {
- 'use strict';
-
- var validateExtension = validate(ext, null);
- if (!validateExtension.valid) {
- console.warn(validateExtension.error);
- return false;
- }
- return true;
-};