praxis 0.18.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -1
- data/Gemfile +2 -1
- data/README.md +21 -27
- data/lib/api_browser/app/index.html +3 -3
- data/lib/api_browser/app/js/app.js +23 -3
- data/lib/api_browser/app/js/controllers/action.js +33 -21
- data/lib/api_browser/app/js/controllers/controller.js +3 -25
- data/lib/api_browser/app/js/controllers/menu.js +61 -51
- data/lib/api_browser/app/js/controllers/trait.js +10 -0
- data/lib/api_browser/app/js/controllers/type.js +8 -5
- data/lib/api_browser/app/js/directives/fixed_if_fits.js +9 -2
- data/lib/api_browser/app/js/directives/menu_item.js +59 -0
- data/lib/api_browser/app/js/directives/readable_list.js +87 -0
- data/lib/api_browser/app/js/directives/url.js +16 -0
- data/lib/api_browser/app/js/factories/Configuration.js +1 -2
- data/lib/api_browser/app/js/factories/Documentation.js +49 -7
- data/lib/api_browser/app/js/factories/PageInfo.js +9 -0
- data/lib/api_browser/app/js/factories/normalize_attributes.js +1 -2
- data/lib/api_browser/app/js/factories/template_for.js +9 -4
- data/lib/api_browser/app/sass/modules/_sidebar.scss +54 -15
- data/lib/api_browser/app/sass/praxis.scss +4 -0
- data/lib/api_browser/app/views/action.html +72 -41
- data/lib/api_browser/app/views/builtin/field-selector.html +24 -0
- data/lib/api_browser/app/views/controller.html +9 -10
- data/lib/api_browser/app/views/directives/menu_item.html +8 -0
- data/lib/api_browser/app/views/directives/url.html +3 -0
- data/lib/api_browser/app/views/layout.html +2 -2
- data/lib/api_browser/app/views/menu.html +8 -14
- data/lib/api_browser/app/views/navbar.html +1 -1
- data/lib/api_browser/app/views/trait.html +13 -0
- data/lib/api_browser/app/views/type/details.html +1 -1
- data/lib/api_browser/app/views/type.html +1 -1
- data/lib/api_browser/app/views/types/embedded/field-selector.html +13 -0
- data/lib/api_browser/app/views/types/label/primitive.html +1 -1
- data/lib/api_browser/app/views/types/standalone/array.html +3 -0
- data/lib/praxis/action_definition.rb +15 -2
- data/lib/praxis/collection.rb +17 -5
- data/lib/praxis/controller.rb +12 -3
- data/lib/praxis/docs/generator.rb +11 -7
- data/lib/praxis/extensions/field_expansion.rb +59 -0
- data/lib/praxis/extensions/field_selection/field_selector.rb +125 -0
- data/lib/praxis/extensions/field_selection.rb +10 -0
- data/lib/praxis/extensions/mapper_selectors.rb +16 -0
- data/lib/praxis/extensions/rendering.rb +43 -0
- data/lib/praxis/links.rb +1 -0
- data/lib/praxis/media_type.rb +87 -3
- data/lib/praxis/media_type_collection.rb +1 -1
- data/lib/praxis/media_type_identifier.rb +6 -1
- data/lib/praxis/plugins/praxis_mapper_plugin.rb +29 -10
- data/lib/praxis/restful_doc_generator.rb +11 -8
- data/lib/praxis/tasks/api_docs.rb +6 -5
- data/lib/praxis/types/multipart_array.rb +1 -1
- data/lib/praxis/version.rb +1 -1
- data/lib/praxis.rb +5 -0
- data/praxis.gemspec +4 -3
- data/spec/api_browser/factories/configuration_spec.js +32 -0
- data/spec/api_browser/factories/documentation_spec.js +75 -25
- data/spec/api_browser/factories/normalize_attributes_spec.js +0 -5
- data/spec/praxis/{types/collection_spec.rb → collection_spec.rb} +36 -23
- data/spec/praxis/extensions/field_expansion_spec.rb +96 -0
- data/spec/praxis/extensions/field_selection/field_selector_spec.rb +92 -0
- data/spec/praxis/extensions/rendering_spec.rb +63 -0
- data/spec/praxis/links_spec.rb +6 -0
- data/spec/praxis/media_type_collection_spec.rb +0 -1
- data/spec/praxis/media_type_identifier_spec.rb +15 -1
- data/spec/praxis/media_type_spec.rb +101 -3
- data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +33 -24
- data/spec/praxis/request_stages/request_stage_spec.rb +1 -1
- data/spec/praxis/types/multipart_array_spec.rb +14 -4
- data/spec/spec_app/app/controllers/instances.rb +6 -1
- data/spec/spec_app/config/environment.rb +2 -1
- data/spec/spec_app/design/resources/instances.rb +1 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/support/spec_media_types.rb +224 -1
- metadata +50 -16
@@ -0,0 +1,87 @@
|
|
1
|
+
app.factory('Repeater', function() {
|
2
|
+
function Repeater(expression) {
|
3
|
+
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
|
4
|
+
|
5
|
+
var lhs = match[1];
|
6
|
+
this.rhs = match[2];
|
7
|
+
this.aliasAs = match[3];
|
8
|
+
this.trackByExp = match[4];
|
9
|
+
|
10
|
+
match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
|
11
|
+
|
12
|
+
this.valueIdentifier = match[3] || match[1];
|
13
|
+
this.keyIdentifier = match[2];
|
14
|
+
}
|
15
|
+
|
16
|
+
Repeater.prototype.$watch = function(fn) {
|
17
|
+
this.$scope.$watchCollection(this.rhs, fn);
|
18
|
+
};
|
19
|
+
|
20
|
+
Repeater.prototype.$transclude = function(length, value, key, index, fn) {
|
21
|
+
var self = this;
|
22
|
+
self._transclude(function(clone, scope) {
|
23
|
+
scope[self.valueIdentifier] = value;
|
24
|
+
if (self.keyIdentifier) scope[self.keyIdentifier] = key;
|
25
|
+
scope.$index = index;
|
26
|
+
scope.$first = (index === 0);
|
27
|
+
scope.$last = (index === (length - 1));
|
28
|
+
scope.$middle = !(scope.$first || scope.$last);
|
29
|
+
// jshint bitwise: false
|
30
|
+
scope.$odd = !(scope.$even = (index&1) === 0);
|
31
|
+
// jshint bitwise: true
|
32
|
+
fn(clone, scope);
|
33
|
+
});
|
34
|
+
};
|
35
|
+
|
36
|
+
return {
|
37
|
+
compile: function(repeatAttr, linkFn) {
|
38
|
+
return function(element, attrs) {
|
39
|
+
var expression = attrs[repeatAttr];
|
40
|
+
var repeater = new Repeater(expression);
|
41
|
+
return function($scope, $element, $attr, ctrl, $transclude) {
|
42
|
+
repeater._transclude = $transclude;
|
43
|
+
repeater.$scope = $scope;
|
44
|
+
linkFn($scope, $element, $attr, ctrl, repeater);
|
45
|
+
};
|
46
|
+
};
|
47
|
+
}
|
48
|
+
};
|
49
|
+
});
|
50
|
+
app.directive('readableList', function(Repeater) {
|
51
|
+
|
52
|
+
return {
|
53
|
+
restrict: 'E',
|
54
|
+
transclude: true,
|
55
|
+
compile: Repeater.compile('repeat', function($scope, $element, $attr, ctrl, $repeat) {
|
56
|
+
$repeat.$watch(function(inputList) {
|
57
|
+
$element.empty();
|
58
|
+
if (inputList.length == 1) {
|
59
|
+
$repeat.$transclude(1, inputList[0], null, 0, function(clone) {
|
60
|
+
$element.append(clone);
|
61
|
+
});
|
62
|
+
} else {
|
63
|
+
var finalJoin = ' and ';
|
64
|
+
|
65
|
+
var join = ', ',
|
66
|
+
arr = inputList.slice(0),
|
67
|
+
last = arr.pop(),
|
68
|
+
beforeLast = arr.pop();
|
69
|
+
|
70
|
+
_.each(arr, function(data, index) {
|
71
|
+
$repeat.$transclude(inputList.length, data, null, index, function(clone) {
|
72
|
+
$element.append(clone);
|
73
|
+
$element.append(document.createTextNode(join));
|
74
|
+
});
|
75
|
+
});
|
76
|
+
$repeat.$transclude(inputList.length, beforeLast, null, inputList.length - 2, function(clone) {
|
77
|
+
$element.append(clone);
|
78
|
+
$element.append(document.createTextNode(finalJoin));
|
79
|
+
});
|
80
|
+
$repeat.$transclude(inputList.length, last, null, inputList.length - 1, function(clone) {
|
81
|
+
$element.append(clone);
|
82
|
+
});
|
83
|
+
}
|
84
|
+
});
|
85
|
+
})
|
86
|
+
};
|
87
|
+
});
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/**
|
2
|
+
* This directive is responsible to render a URL for an action
|
3
|
+
*/
|
4
|
+
app.directive('url', function() {
|
5
|
+
return {
|
6
|
+
restrict: 'EA',
|
7
|
+
scope: {
|
8
|
+
action: '=',
|
9
|
+
example: '@'
|
10
|
+
},
|
11
|
+
templateUrl: 'views/directives/url.html',
|
12
|
+
link: function(scope, element, attrs) {
|
13
|
+
scope.showExample = scope.example == 'example' || scope.example == 'true' || 'example' in attrs;
|
14
|
+
}
|
15
|
+
};
|
16
|
+
});
|
@@ -7,7 +7,6 @@ app.provider('Configuration', function() {
|
|
7
7
|
this.$get = function() {
|
8
8
|
return this;
|
9
9
|
};
|
10
|
-
}).run(function(Configuration, $rootScope
|
10
|
+
}).run(function(Configuration, $rootScope) {
|
11
11
|
_.extend($rootScope, _.omit(Configuration, '$get'));
|
12
|
-
$document[0].title = Configuration.title;
|
13
12
|
});
|
@@ -1,13 +1,55 @@
|
|
1
|
-
|
1
|
+
/**
|
2
|
+
* This service gives access to the documentation metadata
|
3
|
+
*/
|
4
|
+
app.factory('Documentation', function($http, $q) {
|
5
|
+
var versions = $q.when($http.get('api/index-new.json', { cache: true }).then(function(data) {
|
6
|
+
return $q.all(_.map(data.data.versions, function(version) {
|
7
|
+
return $http.get('api/' + version + '.json', {cache: true}).then(function(versionData) {
|
8
|
+
return [version, versionData.data];
|
9
|
+
});
|
10
|
+
})).then(_.zipObject);
|
11
|
+
}));
|
12
|
+
|
2
13
|
return {
|
3
|
-
|
4
|
-
|
14
|
+
/**
|
15
|
+
* Returns an array of version strings
|
16
|
+
*/
|
17
|
+
versions: function() {
|
18
|
+
return versions.then(_.keys);
|
5
19
|
},
|
6
|
-
|
7
|
-
|
20
|
+
/**
|
21
|
+
* Returns a list of controllers and types, useful for generating navigation
|
22
|
+
*/
|
23
|
+
items: function(version) {
|
24
|
+
return versions.then(function(v) { return v[version]; });
|
8
25
|
},
|
9
|
-
|
10
|
-
|
26
|
+
/**
|
27
|
+
* Returns description of a controller
|
28
|
+
*/
|
29
|
+
controller: function(version, name) {
|
30
|
+
return this.items(version).then(function(v) {
|
31
|
+
var controller = v.resources[name];
|
32
|
+
controller.id = name;
|
33
|
+
return controller;
|
34
|
+
});
|
35
|
+
},
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Returns a description of a type
|
39
|
+
*/
|
40
|
+
type: function(version, name) {
|
41
|
+
return versions.then(function(v) {
|
42
|
+
return v[version].schemas[name];
|
43
|
+
});
|
44
|
+
},
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Returns a description of a trait
|
48
|
+
*/
|
49
|
+
trait: function(version, name) {
|
50
|
+
return versions.then(function(v) {
|
51
|
+
return v[version].traits[name];
|
52
|
+
});
|
11
53
|
}
|
12
54
|
};
|
13
55
|
});
|
@@ -2,11 +2,10 @@ app.factory('normalizeAttributes', function() {
|
|
2
2
|
function normalize(type, attributes, parent) {
|
3
3
|
_.forEach(attributes, function(attribute, name) {
|
4
4
|
var path = parent.concat([name]);
|
5
|
-
var example = JSON.stringify(_.get(type.example, path), null, 2);
|
6
5
|
if (!attribute.options) attribute.options = {};
|
7
|
-
if (example) attribute.options.example = example;
|
8
6
|
if (attribute.values != null) attribute.options.values = attribute.values;
|
9
7
|
if (attribute.default != null) attribute.options.default = attribute.default;
|
8
|
+
if (attribute.example != null) attribute.options.example = attribute.example;
|
10
9
|
if (attribute.type && attribute.type.attributes) {
|
11
10
|
normalize(type, attribute.type.attributes, path);
|
12
11
|
}
|
@@ -36,6 +36,8 @@ app.provider('templateFor', function() {
|
|
36
36
|
switch ($family) {
|
37
37
|
case 'hash':
|
38
38
|
return 'views/types/standalone/struct.html';
|
39
|
+
case 'array':
|
40
|
+
return 'views/types/standalone/array.html';
|
39
41
|
default:
|
40
42
|
return 'views/types/standalone/default.html';
|
41
43
|
}
|
@@ -48,6 +50,9 @@ app.provider('templateFor', function() {
|
|
48
50
|
if ($type === 'Links') {
|
49
51
|
return 'views/types/embedded/links.html';
|
50
52
|
}
|
53
|
+
if ($type === 'Praxis::Extensions::FieldSelection::FieldSelector') {
|
54
|
+
return 'views/types/embedded/field-selector.html';
|
55
|
+
}
|
51
56
|
switch ($family) {
|
52
57
|
case 'hash':
|
53
58
|
return 'views/types/embedded/struct.html';
|
@@ -60,14 +65,14 @@ app.provider('templateFor', function() {
|
|
60
65
|
this.register(function labelResolver($typeDefinition, $requestedTemplate, primitives) {
|
61
66
|
'ngInject';
|
62
67
|
if ($requestedTemplate === 'label') {
|
63
|
-
if (
|
64
|
-
|
65
|
-
} else if ( $typeDefinition.member_attribute !== undefined ) {
|
66
|
-
if ( _.contains(primitives, $typeDefinition.member_attribute.type.name)){
|
68
|
+
if ( $typeDefinition.member_attribute !== undefined) {
|
69
|
+
if ($typeDefinition.member_attribute.anonymous || _.contains(primitives, $typeDefinition.name)) {
|
67
70
|
return 'views/types/label/primitive_collection.html';
|
68
71
|
} else{
|
69
72
|
return 'views/types/label/type_collection.html';
|
70
73
|
}
|
74
|
+
} else if ($typeDefinition.anonymous || _.contains(primitives, $typeDefinition.name)) {
|
75
|
+
return 'views/types/label/primitive.html';
|
71
76
|
} else if ($typeDefinition.link_to) {
|
72
77
|
return 'views/types/label/link.html';
|
73
78
|
}
|
@@ -3,9 +3,6 @@
|
|
3
3
|
// ------------------------------
|
4
4
|
|
5
5
|
.sidebar {
|
6
|
-
@media (min-width: $screen-sm-min) {
|
7
|
-
width: 160px;
|
8
|
-
}
|
9
6
|
@media (min-width: $screen-lg-min) {
|
10
7
|
width: 250px;
|
11
8
|
}
|
@@ -20,25 +17,66 @@
|
|
20
17
|
}
|
21
18
|
|
22
19
|
.sidebar {
|
20
|
+
.open .dropdown-menu {
|
21
|
+
margin-left: 15px;
|
22
|
+
}
|
23
23
|
.list-group {
|
24
24
|
margin-bottom: 0;
|
25
25
|
margin-top: 0;
|
26
|
-
|
27
|
-
.list-group-item {
|
28
|
-
border-width: 1px 0;
|
29
|
-
word-break: break-word;
|
30
|
-
&:first-of-type {
|
26
|
+
& > menu-item:first-of-type > .menu-item {
|
31
27
|
border-radius: 0;
|
32
28
|
border-top: 0 none;
|
33
29
|
}
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
30
|
+
}
|
31
|
+
.action {
|
32
|
+
background: $table-bg-accent;
|
33
|
+
font-size: 11px;
|
34
|
+
font-weight: bolder;
|
35
|
+
}
|
36
|
+
.menu-item {
|
37
|
+
position: relative;
|
38
|
+
display: block;
|
39
|
+
// Place the border on the list items and negative margin up for better styling
|
40
|
+
margin-bottom: -1px;
|
41
|
+
background-color: $list-group-bg;
|
42
|
+
border: 1px solid $list-group-border;
|
43
|
+
border-width: 1px 0;
|
44
|
+
word-break: break-word;
|
45
|
+
a {
|
46
|
+
display: block;
|
47
|
+
padding: 10px 15px;
|
48
|
+
// Hover state
|
49
|
+
&:hover,
|
50
|
+
&:focus {
|
51
|
+
text-decoration: none;
|
52
|
+
background-color: $list-group-hover-bg;
|
53
|
+
}
|
54
|
+
|
55
|
+
// Active class on item itself, not parent
|
56
|
+
&.active,
|
57
|
+
&.active:hover,
|
58
|
+
&.active:focus {
|
59
|
+
z-index: 2; // Place active items above their siblings for proper border styling
|
60
|
+
color: $list-group-active-color;
|
61
|
+
background-color: $list-group-active-bg;
|
62
|
+
border-color: $list-group-active-border;
|
63
|
+
font-weight: bolder;
|
64
|
+
}
|
39
65
|
}
|
40
|
-
|
41
|
-
|
66
|
+
.menu-item {
|
67
|
+
a.action { padding: 10px 2.5rem; }
|
68
|
+
a.main { padding: 10px 2rem; }
|
69
|
+
a.main::before {
|
70
|
+
content: "↳"
|
71
|
+
}
|
72
|
+
.menu-item {
|
73
|
+
a.action { padding: 10px 3.5rem; }
|
74
|
+
a.main { padding: 10px 3rem; }
|
75
|
+
.menu-item {
|
76
|
+
a.action { padding: 10px 4.5rem; }
|
77
|
+
a.main { padding: 10px 4rem; }
|
78
|
+
}
|
79
|
+
}
|
42
80
|
}
|
43
81
|
}
|
44
82
|
}
|
@@ -73,6 +111,7 @@
|
|
73
111
|
a {
|
74
112
|
border-bottom: 0;
|
75
113
|
font-size: 12px;
|
114
|
+
padding: 10px 5px;
|
76
115
|
&:hover {
|
77
116
|
background-color: #fff;
|
78
117
|
border-color: transparent;
|
@@ -4,72 +4,103 @@
|
|
4
4
|
<div ng-if="action">
|
5
5
|
<div class="row">
|
6
6
|
<div class="col-lg-12">
|
7
|
-
<
|
8
|
-
{{ action.name }}
|
9
|
-
</
|
10
|
-
<
|
11
|
-
<span class="label label-default verb" ng-class="url.verb | lowercase">{{ url.verb }}</span> <b>{{ url.path }}</b>
|
12
|
-
</p>
|
7
|
+
<h1>
|
8
|
+
<a ui-sref="root.controller({version: apiVersion, controller: controller.id})">{{controller.display_name}}</a> » {{ action.name }}
|
9
|
+
</h1>
|
10
|
+
<url action="action"></url>
|
13
11
|
<p ng-bind-html="action.description | markdown"></p>
|
12
|
+
<p class="traits" ng-if="action.traits.length > 0">
|
13
|
+
This action is
|
14
|
+
<readable-list repeat="trait in action.traits"><a ui-sref="root.trait({version: apiVersion, trait: trait})">{{trait}}</a></readable-list>.
|
15
|
+
</p>
|
14
16
|
</div>
|
15
17
|
</div>
|
16
18
|
|
17
19
|
<div class="row" ng-if="action.headers.type.attributes">
|
18
20
|
<div class="col-lg-12">
|
19
|
-
<
|
21
|
+
<h2>Request Headers</h2>
|
20
22
|
<type-placeholder details="action.headers.type.attributes" type="action.headers.type" template="standalone"></type-placeholder>
|
21
23
|
</div>
|
22
24
|
</div>
|
23
25
|
|
24
26
|
<div class="row" ng-if="action.params.type.attributes">
|
25
27
|
<div class="col-lg-12">
|
26
|
-
<
|
28
|
+
<h2>Request Parameters</h2>
|
27
29
|
<type-placeholder details="action.params.type.attributes" type="action.params.type" template="standalone"></type-placeholder>
|
28
30
|
</div>
|
29
31
|
</div>
|
30
32
|
|
31
33
|
<div class="row" ng-if="action.payload.type">
|
32
34
|
<div class="col-lg-12">
|
33
|
-
<
|
35
|
+
<h2>Request Body</h2>
|
34
36
|
<type-placeholder type="action.payload.type" template="standalone" details="action.payload.type.attributes"></type-placeholder>
|
35
37
|
</div>
|
36
38
|
</div>
|
37
39
|
|
40
|
+
<div class="row">
|
41
|
+
<div class="col-lg-12">
|
42
|
+
<h2>Request Example</h2>
|
43
|
+
<div ng-if="!action.payload.examples">
|
44
|
+
<h4>URL</h4>
|
45
|
+
<url action="action" example></url>
|
46
|
+
<div ng-if="action.headers.example">
|
47
|
+
<h4>Headers</h4>
|
48
|
+
<pre><span ng-repeat="(header, value) in action.headers.example">{{header}}: {{value}}
|
49
|
+
</span></pre>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
<tabset ng-if="action.payload.examples">
|
53
|
+
<tab ng-repeat="(type, example) in action.payload.examples" heading="{{type}}">
|
54
|
+
<h4>URL</h4>
|
55
|
+
<url action="action" example></url>
|
56
|
+
<div ng-if="action.headers.example">
|
57
|
+
<h4>Headers</h4>
|
58
|
+
<pre><span ng-if="example.content_type">Content-Type: {{example.content_type}}
|
59
|
+
</span><span ng-repeat="(header, value) in action.headers.example">{{header}}: {{value}}
|
60
|
+
</span></pre>
|
61
|
+
</div>
|
62
|
+
<h4>Request body</h4>
|
63
|
+
<pre>{{ example.body }}</pre>
|
64
|
+
</tab>
|
65
|
+
</tabset>
|
66
|
+
</div>
|
67
|
+
</div>
|
68
|
+
|
38
69
|
<div class="row" ng-if="hasResponses()">
|
39
70
|
<div class="col-lg-12">
|
40
|
-
<
|
41
|
-
<div class="
|
42
|
-
<
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
<
|
47
|
-
<
|
48
|
-
<
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
<
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
+
<h2>Responses</h2>
|
72
|
+
<div class="panel panel-default" ng-repeat="response in responses">
|
73
|
+
<div class="panel-heading"><h4 class="panel-title">{{response.name}}</h4></div>
|
74
|
+
<div class="panel-body">
|
75
|
+
<div class="row">
|
76
|
+
<div class="col-md-4">
|
77
|
+
<h5>Status</h5>
|
78
|
+
<p>{{ response.status }}</p>
|
79
|
+
<div ng-if="response.examples.json">
|
80
|
+
<h5>Content-Type</h5>
|
81
|
+
<p>{{ response.examples.json.content_type }}</p>
|
82
|
+
</div>
|
83
|
+
<div ng-if="response.payload.id">
|
84
|
+
<h5>Media Type</h5>
|
85
|
+
<p><type-placeholder template="label" type="response.payload"></type-placeholder></p>
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
<div class="col-md-8">
|
89
|
+
<div ng-if="response.payload.examples">
|
90
|
+
<h5>Response Example</h5>
|
91
|
+
<tabset ng-if="numExamples > 1">
|
92
|
+
<tab ng-repeat="(type, example) in response.payload.examples" heading="{{type}}">
|
93
|
+
<pre>{{ example.body }}</pre>
|
94
|
+
</tab>
|
95
|
+
</tabset>
|
96
|
+
<div ng-if="response.numExamples == 1">
|
97
|
+
<pre ng-repeat="(type, example) in response.payload.examples">{{ example.body }}</pre>
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
</div>
|
71
103
|
</div>
|
72
104
|
</div>
|
73
105
|
</div>
|
74
106
|
</div>
|
75
|
-
<hr class="action-divider" />
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-lg-12">
|
3
|
+
<h1 class="page-header">FieldSelector</h1>
|
4
|
+
|
5
|
+
<p>Field Selectors allow you to specify in a request exactly what data you
|
6
|
+
wish to recieve in the response. This allows the client to get an efficient
|
7
|
+
response with only the fields required.</p>
|
8
|
+
<p>The fields can come from the endpointʼs associated Schema, or from an
|
9
|
+
attribute exposed in any of the views of the resource. Multiple fields are
|
10
|
+
separated by commas.</p>
|
11
|
+
<p>You can also select properties from nested schemas from parent schema
|
12
|
+
using curly braces. For example <code>title,user{name,email}</code> would lead to a
|
13
|
+
response like this:</p>
|
14
|
+
<pre>{
|
15
|
+
"title": "Nice Blog Post",
|
16
|
+
"user": {
|
17
|
+
"name": "John Appleseed",
|
18
|
+
"email": "john@example.com"
|
19
|
+
}
|
20
|
+
}</pre>
|
21
|
+
<p>If you do not specify attributes of nested properties, the <code>default</code>
|
22
|
+
view will be used to render them.</p>
|
23
|
+
</div>
|
24
|
+
</div>
|
@@ -7,7 +7,13 @@
|
|
7
7
|
<h1 class="page-header">
|
8
8
|
{{ controller.name | resourceName }}
|
9
9
|
</h1>
|
10
|
-
|
10
|
+
|
11
|
+
<p ng-bind-html="controller.description | markdown"></p>
|
12
|
+
|
13
|
+
<p class="traits" ng-if="controller.traits.length > 0">
|
14
|
+
This resource is
|
15
|
+
<readable-list repeat="trait in controller.traits"><a ui-sref="root.trait({version: apiVersion, trait: trait})">{{trait}}</a></readable-list>.
|
16
|
+
</p>
|
11
17
|
</div>
|
12
18
|
</div>
|
13
19
|
<div class="row" ng-if="controller.actions.length">
|
@@ -25,13 +31,10 @@
|
|
25
31
|
<tbody>
|
26
32
|
<tr ng-repeat="action in controller.actions">
|
27
33
|
<td>
|
28
|
-
<a ui-sref="root.
|
34
|
+
<a ui-sref="root.action({action: action.name, controller: controllerName, version: apiVersion})">{{ action.name }}</a>
|
29
35
|
</td>
|
30
36
|
<td>
|
31
|
-
<
|
32
|
-
<div class="label label-default verb" ng-class="url.verb | lowercase">{{ url.verb }}</div>
|
33
|
-
<strong>{{ url.path }}</strong>
|
34
|
-
</div>
|
37
|
+
<url action="action"></url>
|
35
38
|
</td>
|
36
39
|
<td style="font-size: 110%;">
|
37
40
|
<p ng-bind-html="action.description | markdown"></p>
|
@@ -49,8 +52,4 @@
|
|
49
52
|
<h2>Schema</h2>
|
50
53
|
<p ><b>Internet Media-type: {{ controller.media_type.identifier }}</b></p>
|
51
54
|
</div>
|
52
|
-
<h1>Actions</h1>
|
53
|
-
<div ng-controller="ActionCtrl" ng-repeat="action in controller.actions">
|
54
|
-
<div id="action-{{action.name}}" ng-include="'views/action.html'"></div>
|
55
|
-
</div>
|
56
55
|
</div>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<div class="menu-item" ng-if="shouldShow">
|
2
|
+
<a href="{{link.stateRef}}"
|
3
|
+
ng-class="{active: isActive, 'child-resource': link.parent, 'action': link.isAction, 'main': !link.isAction}">
|
4
|
+
{{ link.name }}
|
5
|
+
</a>
|
6
|
+
<menu-item ng-repeat="action in link.actions" link="action"></menu-item>
|
7
|
+
<menu-item ng-repeat="resource in link.childResources" link="resource"></menu-item>
|
8
|
+
</div>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
<div class="container" ng-cloak>
|
4
4
|
<div class="row">
|
5
|
-
<div class="col-sm-3" ng-controller="MenuCtrl" ng-include="'views/menu.html'"></div>
|
6
|
-
<div class="col-sm-9" ui-view=""></div>
|
5
|
+
<div class="col-sm-4 col-md-3" ng-controller="MenuCtrl" ng-include="'views/menu.html'"></div>
|
6
|
+
<div class="col-sm-8 col-md-9" ui-view="" autoscroll="true"></div>
|
7
7
|
</div>
|
8
8
|
</div>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<button type="button" class="btn btn-success" dropdown-toggle ng-disabled="disabled">
|
7
7
|
{{:: versionLabel}}: {{selectedVersion}} <span class="caret"></span>
|
8
8
|
</button>
|
9
|
-
<ul class="dropdown-menu
|
9
|
+
<ul class="dropdown-menu" role="menu">
|
10
10
|
<li ng-repeat="version in versions">
|
11
11
|
<a ng-click="select(version)" dropdown-toggle>{{version}}</a>
|
12
12
|
</li>
|
@@ -23,23 +23,17 @@
|
|
23
23
|
<tabset justified="true" class="tab-list-group">
|
24
24
|
<tab heading="Resources" active="active.resources">
|
25
25
|
<div class="list-group">
|
26
|
-
<
|
27
|
-
href="{{link.stateRef}}"
|
28
|
-
class="list-group-item"
|
29
|
-
ng-hide="expandChildren && link.parent && selectedGrandfatherType != link.grandfather"
|
30
|
-
ng-class="{active: link.typeName == currentType, 'child-resource': link.parent, 'group-selected': selectedGrandfatherType == link.grandfather}">
|
31
|
-
{{ link.name }}
|
32
|
-
</a>
|
26
|
+
<menu-item ng-repeat="link in availableResources() | orderBy: 'name'" link="link" toplevel="true"></menu-item>
|
33
27
|
</div>
|
34
28
|
</tab>
|
35
29
|
<tab heading="Schemas" active="active.schemas">
|
36
30
|
<div class="list-group">
|
37
|
-
<
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
31
|
+
<menu-item ng-repeat="link in availableSchemas() | orderBy: 'name'" link="link" toplevel="true"></menu-item>
|
32
|
+
</div>
|
33
|
+
</tab>
|
34
|
+
<tab heading="Traits" active="active.traits" ng-if="availableTraits().length > 0">
|
35
|
+
<div class="list-group">
|
36
|
+
<menu-item ng-repeat="link in availableTraits() | orderBy: 'name'" link="link" toplevel="true"></menu-item>
|
43
37
|
</div>
|
44
38
|
</tab>
|
45
39
|
</tabset>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div ng-if="error" class="alert alert-danger">
|
2
|
+
<p>The requested trait could not be found.</p>
|
3
|
+
</div>
|
4
|
+
<div ng-if="trait">
|
5
|
+
<div class="row">
|
6
|
+
<div class="col-lg-12">
|
7
|
+
<h1>
|
8
|
+
{{ traitName | resourceName }}
|
9
|
+
</h1>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
<div ng-if="trait.description" ng-bind-html="trait.description | markdown"></div>
|
13
|
+
</div>
|