Skip to content

Commit

Permalink
feat(hal browser): update to latest code
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed May 13, 2020
1 parent 3672237 commit a79ad29
Show file tree
Hide file tree
Showing 40 changed files with 540 additions and 90 deletions.
Empty file modified vendor/hal-browser/MIT-LICENSE.txt
100644 → 100755
Empty file.
169 changes: 169 additions & 0 deletions vendor/hal-browser/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
= HAL-browser

An API browser for the hal+json media type

== Example Usage

Here is an example of a hal+json API using the browser:

http://haltalk.herokuapp.com/explorer/browser.html[http://haltalk.herokuapp.com/explorer/browser.html]

== About HAL

HAL is a format based on json that establishes conventions for
representing links. For example:

[source,javascript]
----
{
"_links": {
"self": { "href": "/orders" },
"next": { "href": "/orders?page=2" }
}
}
----

More detail about HAL can be found at
http://stateless.co/hal_specification.html[http://stateless.co/hal_specification.html].

== Customizing the POST form

By default, the HAL Browser can't assume there is any metadata. When you click on the non-GET request button (to create a new resource), the user must enter the JSON document to submit. If your service includes metadata you can access, it's possible to plugin a custom view that makes use of it.

. Define your custom view.
+
Here is an example that leverages Spring Data REST's JSON Schema metadata found at */{entity}/schema*.
+
[source,javascript]
----
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',
createNewResource: function (e) {
e.preventDefault();
var self = this;
var data = {}
Object.keys(this.schema.properties).forEach(function(property) {
if (!("format" in self.schema.properties[property])) {
data[property] = self.$('input[name=' + property + ']').val();
}
});
var opts = {
url: this.$('.url').val(),
headers: HAL.parseHeaders(this.$('.headers').val()),
method: this.$('.method').val(),
data: JSON.stringify(data)
};
var request = HAL.client.request(opts);
request.done(function (response) {
self.vent.trigger('response', {resource: response, jqxhr: jqxhr});
}).fail(function (response) {
self.vent.trigger('fail-response', {jqxhr: jqxhr});
}).always(function () {
self.vent.trigger('response-headers', {jqxhr: jqxhr});
window.location.hash = 'NON-GET:' + opts.url;
});
this.$el.modal('hide');
},
render: function (opts) {
var headers = HAL.client.getHeaders();
var headersString = '';
_.each(headers, function (value, name) {
headersString += name + ': ' + value + '\n';
});
var request = HAL.client.request({
url: this.href + '/schema',
method: 'GET'
});
var self = this;
request.done(function (schema) {
self.schema = schema;
self.$el.html(self.template({
href: self.href,
schema: self.schema,
user_defined_headers: headersString}));
self.$el.modal();
});
return this;
},
template: _.template($('#dynamic-request-template').html())
});
----
+
. Register it by assigning to `HAL.customPostForm`
+
[source,javascript]
----
HAL.customPostForm = CustomPostForm;
----
+
. Load your custom JavaScript component and define your custom HTML template.
+
[source,html,indent=0]
----
<script id="dynamic-request-template" type="text/template">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>Make a non-GET request</h3>
</div>
<form class="non-safe" action="<%= href %>">
<div class="modal-body">
<p>Target URI</p>
<input name="url" type="text" class="url" value="<%= href %>" />
<p>Method:</p>
<input name="method" type="text" class="method" value="POST" />
<p>Headers:</p>
<textarea name="headers" class="headers" style="height: 100px">
Content-Type: application/json
<%= user_defined_headers %>
</textarea>
</div>
<% _.each(schema.properties, function(value, name) { %>
<% if (!("format" in value)) { %>
<input type="text" placeholder="<%= name %>" name="<%= name %>" />
<% } %>
<% }); %>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Make Request</button>
</div>
</form>
</script>
----

NOTE: To load a custom JavaScript module AND a custom HTML template, you will probably need to create a customized version of `browser.html`.

NOTE: The HAL Browser uses a global `HAL` object, so there is no need to deal with JavaScript packages.

== Usage Instructions

All you should need to do is copy the files into your webroot.
It is OK to put it in a subdirectory; it does not need to be in the root.

All the JS and CSS dependencies come included in the vendor directory.

== TODO

* Provide feedback to user when there are issues with response (missing
self link, wrong media type identifier)
* Give 'self' and 'curies' links special treatment
41 changes: 0 additions & 41 deletions vendor/hal-browser/README.md

This file was deleted.

43 changes: 26 additions & 17 deletions vendor/hal-browser/browser.html
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<ul class="nav">
<li><a href="#/" id="entryPointLink">Go To Entry Point</a></li>
<li><a href="https://github.com/mikekelly/hal-browser">About The HAL Browser</a></li>
<li><a href="/">Pact Broker Home</a></li>
<li><a href="/">Pact Broker Home</a></li> <!-- pact_broker -->
</ul>
</div>
</div>
Expand All @@ -38,7 +38,7 @@
<script id="location-bar-template" type="text/template">
<form>
<div class="input-append span12 location-bar-container">
<input class="span11" id="appendedInputButton" type="text" value="<%= url %>">
<input class="span11" id="appendedInputButton" type="text" value="<%= _.escape(url) %>">
<button class="btn" type="submit">Go!</button>
<span class="ajax-loader"></span>
</div>
Expand All @@ -63,24 +63,23 @@ <h2>Links</h2>
<% if ($.isArray(obj)) { %>
<% _.each(obj, function(link, i) { %>
<tr>
<% tdStyle = i > 0 ? "border-top:none" : "" %>
<td style="<%= tdStyle %>"><strong><%= i === 0 ? HAL.truncateIfUrl(rel) : '' %></strong></td>
<td><strong><%= HAL.truncateIfUrl(rel) %></strong></td>
<td><%= link.title || '' %></td>
<td><%= link.name ? 'name: ' + link.name : 'index: ' + i %></a></td>
<td>
<% if (HAL.isUrl(rel)) { %>
<a class="dox" href="<%= HAL.buildUrl(rel) %>"><i class="icon-book"></i></a>
<a class="dox" href="<%= HAL.normalizeUrl(HAL.buildUrl(rel)) %>"><i class="icon-book"></i></a>
<% } %>
</td>
<td>
<% if (link.templated === true) { %>
<a class="query btn btn-success" href="<%= link.href %>" title="Query URI template"><i class="icon-question-sign"></i></a>
<a class="query btn btn-success" href="<%= HAL.normalizeUrl(link.href) %>" title="Query URI template"><i class="icon-question-sign"></i></a>
<% } else { %>
<a class="follow btn btn-success" href="<%= link.href %>" title="Follow link"><i class="icon-arrow-right"></i></a>
<a class="follow btn btn-success" href="<%= HAL.normalizeUrl(link.href) %>" title="Follow link"><i class="icon-arrow-right"></i></a>
<% } %>
</td>
<td>
<a class="non-get btn btn-warning" href="<%= link.href %>" title="Perform non-GET request">!</a>
<a class="non-get btn btn-warning" href="<%= HAL.normalizeUrl(link.href) %>" title="Perform non-GET request">!</a>
</td>
</tr>
<% }); %>
Expand All @@ -91,18 +90,18 @@ <h2>Links</h2>
<td><%= obj.name || '' %></td>
<td>
<% if (HAL.isUrl(rel)) { %>
<a class="dox" href="<%= HAL.buildUrl(rel) %>"><i class="icon-book"></i></a>
<a class="dox" href="<%= HAL.normalizeUrl(HAL.buildUrl(rel)) %>"><i class="icon-book"></i></a>
<% } %>
</td>
<td>
<% if (obj.templated === true) { %>
<a class="query btn btn-success" href="<%= obj.href %>" title="Query URI template"><i class="icon-question-sign"></i></a>
<a class="query btn btn-success" href="<%= HAL.normalizeUrl(obj.href) %>" title="Query URI template"><i class="icon-question-sign"></i></a>
<% } else { %>
<a class="follow btn btn-success" href="<%= obj.href %>" title="Follow link"><i class="icon-arrow-right"></i></a>
<a class="follow btn btn-success" href="<%= HAL.normalizeUrl(obj.href) %>" title="Follow link"><i class="icon-arrow-right"></i></a>
<% } %>
</td>
<td>
<a class="non-get btn btn-warning" href="<%= obj.href %>" title="Perform non-GET request">!</a>
<a class="non-get btn btn-warning" href="<%= HAL.normalizeUrl(obj.href) %>" title="Perform non-GET request">!</a>
</td>
</tr>
<% } %>
Expand All @@ -113,7 +112,7 @@ <h2>Links</h2>

<script id="properties-template" type="text/template">
<h2>Properties</h2>
<pre><%= _.escape(JSON.stringify(properties, null, HAL.jsonIndent)) %></pre>
<pre><%= properties %></pre>
</script>

<script id="request-headers-template" type="text/template">
Expand All @@ -125,7 +124,16 @@ <h2>Custom Request Headers</h2>
<h2>Response Headers</h2>
<pre><%= status.code %> <%= status.text %>

<%= _.escape(headers) %></pre>
<% _.each(headers, function(value, name) {
%><%= _.escape(name) %>: <%
if(HAL.isFollowableHeader(name)) {
%><a href="<%= HAL.normalizeUrl(value) %>" class="follow"><%
}
%><%= _.escape(value)
%><% if(HAL.isFollowableHeader(name)) {
%></a><%
} %>
<% }) %></pre>
</script>

<script id="response-body-template" type="text/template">
Expand All @@ -142,7 +150,7 @@ <h3>Expand URI Template</h3>
<form id="query" action="<%= href %>">
<div class="modal-body">
<p>URI Template:</p>
<pre><%= href %></pre>
<pre><%- href %></pre>
<p>Input (JSON):</p>
<textarea><%= input %></textarea>
<p>Expanded URI:</p>
Expand Down Expand Up @@ -193,21 +201,22 @@ <h2>Embedded Resources</h2>

<script id="embedded-resource-template" type="text/template">
<div class="accordion-heading">
<!-- pact_broker -->
<a class="accordion-toggle" href="#"><%= resource.identifier %><% if (resource.name || resource.title) { %>: <span class="embedded-resource-title"><%- resource.name || resource.title %></span><% } %>
<% if (HAL.isUrl(resource.embed_rel)) { %>
<span class="dox pull-right" data-href="<%= HAL.buildUrl(resource.embed_rel) %>">
<span class="dox pull-right" data-href="<%= HAL.normalizeUrl(HAL.buildUrl(resource.embed_rel)) %>">
<i class="icon-book"></i>
</span>
<% } %>
</a>
</div>
</script>


<script src="vendor/js/jquery-1.10.2.min.js"></script>
<script src="vendor/js/underscore.js"></script>
<script src="vendor/js/backbone.js"></script>
<script src="vendor/js/uritemplates.js"></script>
<script src="vendor/js/URI.min.js"></script>
<script src="vendor/js/bootstrap.js"></script>

<script src="js/hal.js"></script>
Expand Down
Loading

0 comments on commit a79ad29

Please sign in to comment.