Skip to content

Commit a79ad29

Browse files
committed
feat(hal browser): update to latest code
1 parent 3672237 commit a79ad29

40 files changed

+540
-90
lines changed

vendor/hal-browser/MIT-LICENSE.txt

100644100755
File mode changed.

vendor/hal-browser/README.adoc

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
= HAL-browser
2+
3+
An API browser for the hal+json media type
4+
5+
== Example Usage
6+
7+
Here is an example of a hal+json API using the browser:
8+
9+
http://haltalk.herokuapp.com/explorer/browser.html[http://haltalk.herokuapp.com/explorer/browser.html]
10+
11+
== About HAL
12+
13+
HAL is a format based on json that establishes conventions for
14+
representing links. For example:
15+
16+
[source,javascript]
17+
----
18+
{
19+
"_links": {
20+
"self": { "href": "/orders" },
21+
"next": { "href": "/orders?page=2" }
22+
}
23+
}
24+
----
25+
26+
More detail about HAL can be found at
27+
http://stateless.co/hal_specification.html[http://stateless.co/hal_specification.html].
28+
29+
== Customizing the POST form
30+
31+
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.
32+
33+
. Define your custom view.
34+
+
35+
Here is an example that leverages Spring Data REST's JSON Schema metadata found at */{entity}/schema*.
36+
+
37+
[source,javascript]
38+
----
39+
var CustomPostForm = Backbone.View.extend({
40+
initialize: function (opts) {
41+
this.href = opts.href.split('{')[0];
42+
this.vent = opts.vent;
43+
_.bindAll(this, 'createNewResource');
44+
},
45+
46+
events: {
47+
'submit form': 'createNewResource'
48+
},
49+
50+
className: 'modal fade',
51+
52+
createNewResource: function (e) {
53+
e.preventDefault();
54+
55+
var self = this;
56+
57+
var data = {}
58+
Object.keys(this.schema.properties).forEach(function(property) {
59+
if (!("format" in self.schema.properties[property])) {
60+
data[property] = self.$('input[name=' + property + ']').val();
61+
}
62+
});
63+
64+
var opts = {
65+
url: this.$('.url').val(),
66+
headers: HAL.parseHeaders(this.$('.headers').val()),
67+
method: this.$('.method').val(),
68+
data: JSON.stringify(data)
69+
};
70+
71+
var request = HAL.client.request(opts);
72+
request.done(function (response) {
73+
self.vent.trigger('response', {resource: response, jqxhr: jqxhr});
74+
}).fail(function (response) {
75+
self.vent.trigger('fail-response', {jqxhr: jqxhr});
76+
}).always(function () {
77+
self.vent.trigger('response-headers', {jqxhr: jqxhr});
78+
window.location.hash = 'NON-GET:' + opts.url;
79+
});
80+
81+
this.$el.modal('hide');
82+
},
83+
84+
render: function (opts) {
85+
var headers = HAL.client.getHeaders();
86+
var headersString = '';
87+
88+
_.each(headers, function (value, name) {
89+
headersString += name + ': ' + value + '\n';
90+
});
91+
92+
var request = HAL.client.request({
93+
url: this.href + '/schema',
94+
method: 'GET'
95+
});
96+
97+
var self = this;
98+
request.done(function (schema) {
99+
self.schema = schema;
100+
self.$el.html(self.template({
101+
href: self.href,
102+
schema: self.schema,
103+
user_defined_headers: headersString}));
104+
self.$el.modal();
105+
});
106+
107+
return this;
108+
},
109+
template: _.template($('#dynamic-request-template').html())
110+
});
111+
----
112+
+
113+
. Register it by assigning to `HAL.customPostForm`
114+
+
115+
[source,javascript]
116+
----
117+
HAL.customPostForm = CustomPostForm;
118+
----
119+
+
120+
. Load your custom JavaScript component and define your custom HTML template.
121+
+
122+
[source,html,indent=0]
123+
----
124+
<script id="dynamic-request-template" type="text/template">
125+
<div class="modal-header">
126+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
127+
<h3>Make a non-GET request</h3>
128+
</div>
129+
130+
<form class="non-safe" action="<%= href %>">
131+
<div class="modal-body">
132+
<p>Target URI</p>
133+
<input name="url" type="text" class="url" value="<%= href %>" />
134+
<p>Method:</p>
135+
<input name="method" type="text" class="method" value="POST" />
136+
<p>Headers:</p>
137+
<textarea name="headers" class="headers" style="height: 100px">
138+
Content-Type: application/json
139+
<%= user_defined_headers %>
140+
</textarea>
141+
</div>
142+
<% _.each(schema.properties, function(value, name) { %>
143+
<% if (!("format" in value)) { %>
144+
<input type="text" placeholder="<%= name %>" name="<%= name %>" />
145+
<% } %>
146+
<% }); %>
147+
<div class="modal-footer">
148+
<button type="submit" class="btn btn-primary">Make Request</button>
149+
</div>
150+
</form>
151+
</script>
152+
----
153+
154+
NOTE: To load a custom JavaScript module AND a custom HTML template, you will probably need to create a customized version of `browser.html`.
155+
156+
NOTE: The HAL Browser uses a global `HAL` object, so there is no need to deal with JavaScript packages.
157+
158+
== Usage Instructions
159+
160+
All you should need to do is copy the files into your webroot.
161+
It is OK to put it in a subdirectory; it does not need to be in the root.
162+
163+
All the JS and CSS dependencies come included in the vendor directory.
164+
165+
== TODO
166+
167+
* Provide feedback to user when there are issues with response (missing
168+
self link, wrong media type identifier)
169+
* Give 'self' and 'curies' links special treatment

vendor/hal-browser/README.md

-41
This file was deleted.

vendor/hal-browser/browser.html

100644100755
+26-17
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<ul class="nav">
2727
<li><a href="#/" id="entryPointLink">Go To Entry Point</a></li>
2828
<li><a href="https://github.com/mikekelly/hal-browser">About The HAL Browser</a></li>
29-
<li><a href="/">Pact Broker Home</a></li>
29+
<li><a href="/">Pact Broker Home</a></li> <!-- pact_broker -->
3030
</ul>
3131
</div>
3232
</div>
@@ -38,7 +38,7 @@
3838
<script id="location-bar-template" type="text/template">
3939
<form>
4040
<div class="input-append span12 location-bar-container">
41-
<input class="span11" id="appendedInputButton" type="text" value="<%= url %>">
41+
<input class="span11" id="appendedInputButton" type="text" value="<%= _.escape(url) %>">
4242
<button class="btn" type="submit">Go!</button>
4343
<span class="ajax-loader"></span>
4444
</div>
@@ -63,24 +63,23 @@ <h2>Links</h2>
6363
<% if ($.isArray(obj)) { %>
6464
<% _.each(obj, function(link, i) { %>
6565
<tr>
66-
<% tdStyle = i > 0 ? "border-top:none" : "" %>
67-
<td style="<%= tdStyle %>"><strong><%= i === 0 ? HAL.truncateIfUrl(rel) : '' %></strong></td>
66+
<td><strong><%= HAL.truncateIfUrl(rel) %></strong></td>
6867
<td><%= link.title || '' %></td>
6968
<td><%= link.name ? 'name: ' + link.name : 'index: ' + i %></a></td>
7069
<td>
7170
<% if (HAL.isUrl(rel)) { %>
72-
<a class="dox" href="<%= HAL.buildUrl(rel) %>"><i class="icon-book"></i></a>
71+
<a class="dox" href="<%= HAL.normalizeUrl(HAL.buildUrl(rel)) %>"><i class="icon-book"></i></a>
7372
<% } %>
7473
</td>
7574
<td>
7675
<% if (link.templated === true) { %>
77-
<a class="query btn btn-success" href="<%= link.href %>" title="Query URI template"><i class="icon-question-sign"></i></a>
76+
<a class="query btn btn-success" href="<%= HAL.normalizeUrl(link.href) %>" title="Query URI template"><i class="icon-question-sign"></i></a>
7877
<% } else { %>
79-
<a class="follow btn btn-success" href="<%= link.href %>" title="Follow link"><i class="icon-arrow-right"></i></a>
78+
<a class="follow btn btn-success" href="<%= HAL.normalizeUrl(link.href) %>" title="Follow link"><i class="icon-arrow-right"></i></a>
8079
<% } %>
8180
</td>
8281
<td>
83-
<a class="non-get btn btn-warning" href="<%= link.href %>" title="Perform non-GET request">!</a>
82+
<a class="non-get btn btn-warning" href="<%= HAL.normalizeUrl(link.href) %>" title="Perform non-GET request">!</a>
8483
</td>
8584
</tr>
8685
<% }); %>
@@ -91,18 +90,18 @@ <h2>Links</h2>
9190
<td><%= obj.name || '' %></td>
9291
<td>
9392
<% if (HAL.isUrl(rel)) { %>
94-
<a class="dox" href="<%= HAL.buildUrl(rel) %>"><i class="icon-book"></i></a>
93+
<a class="dox" href="<%= HAL.normalizeUrl(HAL.buildUrl(rel)) %>"><i class="icon-book"></i></a>
9594
<% } %>
9695
</td>
9796
<td>
9897
<% if (obj.templated === true) { %>
99-
<a class="query btn btn-success" href="<%= obj.href %>" title="Query URI template"><i class="icon-question-sign"></i></a>
98+
<a class="query btn btn-success" href="<%= HAL.normalizeUrl(obj.href) %>" title="Query URI template"><i class="icon-question-sign"></i></a>
10099
<% } else { %>
101-
<a class="follow btn btn-success" href="<%= obj.href %>" title="Follow link"><i class="icon-arrow-right"></i></a>
100+
<a class="follow btn btn-success" href="<%= HAL.normalizeUrl(obj.href) %>" title="Follow link"><i class="icon-arrow-right"></i></a>
102101
<% } %>
103102
</td>
104103
<td>
105-
<a class="non-get btn btn-warning" href="<%= obj.href %>" title="Perform non-GET request">!</a>
104+
<a class="non-get btn btn-warning" href="<%= HAL.normalizeUrl(obj.href) %>" title="Perform non-GET request">!</a>
106105
</td>
107106
</tr>
108107
<% } %>
@@ -113,7 +112,7 @@ <h2>Links</h2>
113112

114113
<script id="properties-template" type="text/template">
115114
<h2>Properties</h2>
116-
<pre><%= _.escape(JSON.stringify(properties, null, HAL.jsonIndent)) %></pre>
115+
<pre><%= properties %></pre>
117116
</script>
118117

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

128-
<%= _.escape(headers) %></pre>
127+
<% _.each(headers, function(value, name) {
128+
%><%= _.escape(name) %>: <%
129+
if(HAL.isFollowableHeader(name)) {
130+
%><a href="<%= HAL.normalizeUrl(value) %>" class="follow"><%
131+
}
132+
%><%= _.escape(value)
133+
%><% if(HAL.isFollowableHeader(name)) {
134+
%></a><%
135+
} %>
136+
<% }) %></pre>
129137
</script>
130138

131139
<script id="response-body-template" type="text/template">
@@ -142,7 +150,7 @@ <h3>Expand URI Template</h3>
142150
<form id="query" action="<%= href %>">
143151
<div class="modal-body">
144152
<p>URI Template:</p>
145-
<pre><%= href %></pre>
153+
<pre><%- href %></pre>
146154
<p>Input (JSON):</p>
147155
<textarea><%= input %></textarea>
148156
<p>Expanded URI:</p>
@@ -193,21 +201,22 @@ <h2>Embedded Resources</h2>
193201

194202
<script id="embedded-resource-template" type="text/template">
195203
<div class="accordion-heading">
204+
<!-- pact_broker -->
196205
<a class="accordion-toggle" href="#"><%= resource.identifier %><% if (resource.name || resource.title) { %>: <span class="embedded-resource-title"><%- resource.name || resource.title %></span><% } %>
197206
<% if (HAL.isUrl(resource.embed_rel)) { %>
198-
<span class="dox pull-right" data-href="<%= HAL.buildUrl(resource.embed_rel) %>">
207+
<span class="dox pull-right" data-href="<%= HAL.normalizeUrl(HAL.buildUrl(resource.embed_rel)) %>">
199208
<i class="icon-book"></i>
200209
</span>
201210
<% } %>
202211
</a>
203212
</div>
204213
</script>
205214

206-
207215
<script src="vendor/js/jquery-1.10.2.min.js"></script>
208216
<script src="vendor/js/underscore.js"></script>
209217
<script src="vendor/js/backbone.js"></script>
210218
<script src="vendor/js/uritemplates.js"></script>
219+
<script src="vendor/js/URI.min.js"></script>
211220
<script src="vendor/js/bootstrap.js"></script>
212221

213222
<script src="js/hal.js"></script>

0 commit comments

Comments
 (0)