diff --git a/spring-data-rest-hal-browser/pom.xml b/spring-data-rest-hal-browser/pom.xml
index 835576b4b..9171b9f37 100644
--- a/spring-data-rest-hal-browser/pom.xml
+++ b/spring-data-rest-hal-browser/pom.xml
@@ -12,7 +12,8 @@
Spring Data REST - HAL Browser
- b7669f1-1
+ 9f96c74
+ 0.7.21
@@ -33,7 +34,14 @@
org.webjars
hal-browser
- b7669f1-1
+ ${browser.version}
+ provided
+
+
+
+ org.webjars
+ json-editor
+ ${json-editor.version}
provided
@@ -49,7 +57,7 @@
2.10
- unpack
+ unpack-hal-browser
process-resources
unpack
@@ -64,6 +72,22 @@
${project.build.directory}/hal-browser
+
+ unpack-json-editor
+ process-resources
+
+ unpack
+
+
+
+
+ org.webjars
+ json-editor
+
+
+ ${project.build.directory}/json-editor
+
+
@@ -82,7 +106,10 @@
-
+
+
+
+
diff --git a/spring-data-rest-hal-browser/src/main/resources/META-INF/spring-data-rest/hal-browser/index.html b/spring-data-rest-hal-browser/src/main/resources/META-INF/spring-data-rest/hal-browser/index.html
new file mode 100644
index 000000000..80a752427
--- /dev/null
+++ b/spring-data-rest-hal-browser/src/main/resources/META-INF/spring-data-rest/hal-browser/index.html
@@ -0,0 +1,288 @@
+
+
+
+ The HAL Browser (customized for Spring Data REST)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-data-rest-hal-browser/src/main/resources/META-INF/spring-data-rest/hal-browser/js/CustomPostForm.js b/spring-data-rest-hal-browser/src/main/resources/META-INF/spring-data-rest/hal-browser/js/CustomPostForm.js
new file mode 100644
index 000000000..9c03b57a6
--- /dev/null
+++ b/spring-data-rest-hal-browser/src/main/resources/META-INF/spring-data-rest/hal-browser/js/CustomPostForm.js
@@ -0,0 +1,201 @@
+/**
+ * Custom Backbone view that uses JSON Schema metadata to create pop-up dialog with actual field names instead of
+ * asking user to input raw JSON.
+ *
+ * NOTE: Because JSON Schema lists all properties, including those that are links, they have to be filtered out.
+ * Links have to be set via a PUT operation with the proper media type.
+ *
+ * @author Greg Turnquist
+ * @since 2.4
+ * @see DATAREST-627
+ */
+/* jshint strict: true */
+/* globals HAL, Backbone, _, $, window, jqxhr */
+
+'use strict';
+
+var CustomPostForm = Backbone.View.extend({
+ initialize: function (opts) {
+ this.href = opts.href.split('{')[0];
+ this.vent = opts.vent;
+ _.bindAll(this, 'createNewResource');
+ },
+
+ events: {
+ 'submit form': 'createNewResource'
+ },
+
+ className: 'modal fade',
+
+ /**
+ * Perform a POST/PUT operation on the resource.
+ *
+ * @param e
+ */
+ createNewResource: function (e) {
+ e.preventDefault();
+
+ var self = this;
+
+ var opts = {
+ url: this.$('.url').val(),
+ headers: {'Content-Type': 'application/json'},
+ method: this.$('.method').val(),
+ data: this.getNewResourceData()
+ };
+
+ HAL.client.request(opts).done(function (response) {
+ self.vent.trigger('response', {resource: response, jqxhr: jqxhr});
+ }).fail(function (e) {
+ self.vent.trigger('fail-response', {jqxhr: jqxhr});
+ }).always(function (e) {
+ self.vent.trigger('response-headers', {jqxhr: jqxhr});
+ window.location.hash = 'NON-GET:' + opts.url;
+ });
+
+ this.$el.modal('hide');
+ },
+
+ /**
+ * Draw the dialog after fetching the resource's JSON Schema metadata. If no metadata is available, use the
+ * fallback editor.
+ *
+ * @param opts
+ * @returns {CustomPostForm}
+ */
+ render: function (opts) {
+ var self = this;
+
+ try {
+ HAL.client.request({
+ method: 'HEAD',
+ url: this.href
+ }).done(function (message, text, jqXHR) {
+ self.$el.html(self.template({href: self.href}));
+
+ try {
+ var hal = self.w3cLinksToHalLinks(jqXHR.getResponseHeader('Link'));
+
+ HAL.client.request({
+ method: 'GET',
+ url: hal._links.profile.href,
+ headers: {'Accept': 'application/schema+json'}
+ }).done(function (schema) {
+ self.loadJsonEditor(schema);
+ });
+ } catch (e) {
+ self.loadFallbackEditor();
+ }
+
+ self.$el.modal();
+ });
+ } catch (e) {
+ self.loadFallbackEditor();
+ self.$el.modal();
+ }
+
+
+ return this;
+ },
+
+ /**
+ * Load the JSON Schema-driven editor.
+ *
+ * @see https://github.com/jdorn/json-editor
+ */
+ loadJsonEditor: function (schema) {
+ var self = this;
+
+ /**
+ * Remove URI-based fields since this dialog doesn't handle relationships.
+ */
+ Object.keys(schema.properties).forEach(function (property) {
+ if (schema.properties[property].hasOwnProperty('format') &&
+ schema.properties[property].format === 'uri') {
+ delete schema.properties[property];
+ }
+ });
+
+ /**
+ * See https://github.com/jdorn/json-editor#options for more customizing options.
+ */
+ this.editor = new window.JSONEditor(this.$('#jsoneditor')[0], {
+ theme: 'bootstrap2',
+ schema: schema,
+ disable_collapse: true,
+ disable_edit_json: true,
+ disable_properties: true
+ });
+
+ this.getNewResourceData = function() {
+ return JSON.stringify(self.editor.getValue());
+ }
+ },
+
+ /**
+ * Load fallback editor that doesn't depend on any form of metadata.
+ */
+ loadFallbackEditor: function () {
+ var editor = this.$('#jsoneditor');
+
+ editor.append($('' + this.href + '
'));
+
+ var inputBox = $('');
+ editor.append(inputBox);
+
+ this.getNewResourceData = function() {
+ return inputBox.val();
+ }
+ },
+
+ /**
+ * Convert a W3C link header into a HAL-based set of _links.
+ *
+ * e.g.
+ * ; rel="persons",; rel="profile"
+ * to
+ * {
+ * _links: {
+ * persons: {
+ * href: http://localhost:8080/persons
+ * },
+ * profile: {
+ * href: http://localhost:8080/profile/persons
+ * }
+ * }
+ * }
+ *
+ * @param linkHeader - HTTP Response header containing a list of W3C compliant links with rels.
+ * @see http://www.w3.org/wiki/LinkHeader
+ */
+ w3cLinksToHalLinks: function (linkHeader) {
+ var w3cLinks = linkHeader.split(',');
+
+ var halLinks = {_links: {}};
+
+ w3cLinks.forEach(function (w3cLink) {
+ var parts = w3cLink.split(';');
+
+ var hrefWrappedWithBrackets = parts[0];
+ var href = hrefWrappedWithBrackets.slice(1, parts[0].length - 1);
+
+ var w3cRel = parts[1];
+ var relWrappedWithQuotes = w3cRel.split('=')[1];
+ var rel = relWrappedWithQuotes.slice(1, relWrappedWithQuotes.length - 1);
+
+ halLinks._links[rel] = { "href": href };
+ });
+
+ return halLinks;
+ },
+
+ /**
+ * Look up the HTML template.
+ */
+ template: _.template($('#dynamic-request-template').html())
+});
+
+/**
+ * Inject the form into the HAL Browser.
+ */
+HAL.customPostForm = CustomPostForm;
\ No newline at end of file
diff --git a/src/main/asciidoc/images/hal-browser-2.png b/src/main/asciidoc/images/hal-browser-2.png
index e1fbe1f3d..6d9cac274 100644
Binary files a/src/main/asciidoc/images/hal-browser-2.png and b/src/main/asciidoc/images/hal-browser-2.png differ