Nest extensions and admin API section in side nav
Nest the extensions and the admin documentation under the service. Creates a shorter more organised side nav without duplicate sections covering identity and compute.
This commit is contained in:
parent
c34c4b4f5a
commit
d84fcb4e65
|
@ -22,6 +22,11 @@ body, h1, h2, h3, h4, h5, h6 {
|
|||
|
||||
}
|
||||
|
||||
.sidebar-nav > li > .sidebar-nav {
|
||||
margin-left: 10px;
|
||||
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
@ -94,12 +99,12 @@ a.accordion-toggle:focus, a.accordion-toggle:hover {
|
|||
color: #2a4e68;
|
||||
}
|
||||
|
||||
.sidebar .selected, .sidebar .selected a{
|
||||
.sidebar .selected > a, .sidebar .selected > a:hover, .sidebar .selected > a:focus{
|
||||
background: #496e8a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sidebar .li:hover {
|
||||
.sidebar a:hover {
|
||||
background: #bccfde;
|
||||
color: #2a4e68;
|
||||
}
|
||||
|
|
|
@ -31,14 +31,58 @@ angular.module('fairySlipper.index', [
|
|||
});
|
||||
}])
|
||||
|
||||
.controller('MenuCtrl', ['$scope', '$location', '$routeParams', '$timeout', 'APIs', 'snapRemote', function($scope, $location, $routeParams, $timeout, APIs, snapRemote) {
|
||||
if ($location.path().indexOf('/by-path/') == 0) {
|
||||
$scope.filterByModel = 'by-path';
|
||||
} else if ($location.path().indexOf('/by-tag/') == 0) {
|
||||
$scope.filterByModel = 'by-tag';
|
||||
} else {
|
||||
$scope.filterByModel = 'by-path';
|
||||
}
|
||||
.factory('navigation', ['APIs', function(APIs) {
|
||||
var nav_by_service = {};
|
||||
var extensions = [];
|
||||
var ends_with = function (string, substring) {
|
||||
return string.indexOf(substring, string.length - substring.length) !== -1;
|
||||
};
|
||||
|
||||
APIs.query().$promise.then(function (data) {
|
||||
data.forEach(function (value) {
|
||||
var service = value['service'];
|
||||
var api = null;
|
||||
|
||||
if (ends_with(service, '-extensions')) {
|
||||
// is an extension
|
||||
api = value.toJSON();
|
||||
api.title = 'Extensions';
|
||||
extensions.push(api);
|
||||
} else if (ends_with(service ,'-admin')) {
|
||||
// is an extension
|
||||
api = value.toJSON();
|
||||
api.title = 'Admin';
|
||||
extensions.push(api);
|
||||
} else {
|
||||
// is a normal service
|
||||
api = value.toJSON();
|
||||
api.section = [];
|
||||
if (!nav_by_service[service]) {
|
||||
nav_by_service[service] = {
|
||||
apis: [],
|
||||
title: value['title']};
|
||||
}
|
||||
nav_by_service[service]['apis'].push(api);
|
||||
}});
|
||||
|
||||
var nest_apis = function (name_suffix) {
|
||||
for (var i = 0; i < extensions.length; i++) {
|
||||
var extension = extensions[i];
|
||||
var service = extension['service'];
|
||||
if (ends_with(service, name_suffix)) {
|
||||
var service_name = service.substr(0, service.length - name_suffix.length);
|
||||
for (var j = 0; j < nav_by_service[service_name]['apis'].length; j++) {
|
||||
if (nav_by_service[service_name]['apis'][j]['version'] === extension.version) {
|
||||
nav_by_service[service_name]['apis'][j]['section'].push(extension);
|
||||
}}}}};
|
||||
nest_apis('-extensions');
|
||||
nest_apis('-admin');
|
||||
});
|
||||
return nav_by_service;
|
||||
}])
|
||||
|
||||
.controller('MenuCtrl', ['$scope', '$location', '$routeParams', '$timeout', 'navigation', 'snapRemote', function($scope, $location, $routeParams, $timeout, navigation, snapRemote) {
|
||||
$scope.filterByModel = 'by-tag';
|
||||
|
||||
// only show sidebar after hovering for 2 seconds
|
||||
var timer;
|
||||
|
@ -53,18 +97,6 @@ angular.module('fairySlipper.index', [
|
|||
|
||||
$scope.snapRemote = snapRemote;
|
||||
$scope.$routeParams = $routeParams;
|
||||
|
||||
APIs.query().$promise.then(function (data) {
|
||||
$scope.services = {};
|
||||
angular.forEach(data, function (value) {
|
||||
var service = value['service'];
|
||||
if (!$scope.services[service]) {
|
||||
$scope.services[service] = {
|
||||
apis: [],
|
||||
title: value['title']};
|
||||
}
|
||||
$scope.services[service]['apis'].push(value);
|
||||
});
|
||||
});
|
||||
$scope.services = navigation;
|
||||
|
||||
}]);
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
describe('Unit testing navigation creation', function() {
|
||||
var mock, navigation;
|
||||
beforeEach(module('fairySlipper.index'));
|
||||
beforeEach(module('browser/index.html'));
|
||||
|
||||
|
||||
beforeEach(inject(function(_$compile_, _$rootScope_, _$httpBackend_){
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
inject(function($injector) {
|
||||
navigation = $injector.get('navigation');
|
||||
});
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
$httpBackend.verifyNoOutstandingExpectation();
|
||||
$httpBackend.verifyNoOutstandingRequest();
|
||||
});
|
||||
|
||||
|
||||
it('It should return the navigation', function() {
|
||||
$httpBackend.when('GET', '/doc')
|
||||
.respond([
|
||||
{
|
||||
"version": "v2",
|
||||
"service": "identity",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Identity"
|
||||
},
|
||||
{
|
||||
"version": "v1",
|
||||
"service": "database",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Database Service"
|
||||
},
|
||||
{
|
||||
"version": "v3",
|
||||
"service": "identity",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Identity"
|
||||
}]);
|
||||
$httpBackend.flush();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(Object.keys(navigation).sort()).toEqual(['database', 'identity'].sort());
|
||||
|
||||
expect(navigation).toEqual(
|
||||
{
|
||||
identity: {
|
||||
apis: [{version: 'v2',
|
||||
service: 'identity',
|
||||
license: {url: 'http://www.apache.org/licenses/LICENSE-2.0.html', name: 'Apache 2.0'},
|
||||
section: [],
|
||||
title: 'Identity'},
|
||||
{version: 'v3',
|
||||
service: 'identity',
|
||||
license: {url: 'http://www.apache.org/licenses/LICENSE-2.0.html', name: 'Apache 2.0' },
|
||||
section: [],
|
||||
title: 'Identity' }],
|
||||
title: 'Identity' },
|
||||
database: {
|
||||
apis: [{version: 'v1',
|
||||
service: 'database',
|
||||
license: {url: 'http://www.apache.org/licenses/LICENSE-2.0.html', name: 'Apache 2.0'},
|
||||
section: [],
|
||||
title: 'Database Service' }],
|
||||
title: 'Database Service'}}
|
||||
);
|
||||
});
|
||||
|
||||
it('It should return the navigation', function() {
|
||||
$httpBackend.when('GET', '/doc')
|
||||
.respond([
|
||||
{
|
||||
"version": "v2",
|
||||
"service": "identity",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Identity"
|
||||
},
|
||||
{
|
||||
"version": "v1",
|
||||
"service": "database",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Database Service"
|
||||
},
|
||||
{
|
||||
"version": "v2",
|
||||
"service": "identity-extensions",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Identity"
|
||||
}]);
|
||||
$httpBackend.flush();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(Object.keys(navigation).sort()).toEqual(['database', 'identity'].sort());
|
||||
|
||||
expect(navigation).toEqual(
|
||||
{
|
||||
identity: {
|
||||
apis: [{version: 'v2',
|
||||
service: 'identity',
|
||||
license: {url: 'http://www.apache.org/licenses/LICENSE-2.0.html', name: 'Apache 2.0'},
|
||||
section: [{
|
||||
"version": "v2",
|
||||
"service": "identity-extensions",
|
||||
"license": {
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
"name": "Apache 2.0"
|
||||
},
|
||||
"title": "Extensions"
|
||||
}],
|
||||
title: 'Identity'}],
|
||||
title: 'Identity' },
|
||||
database: {
|
||||
apis: [{version: 'v1',
|
||||
service: 'database',
|
||||
license: {url: 'http://www.apache.org/licenses/LICENSE-2.0.html', name: 'Apache 2.0'},
|
||||
section: [],
|
||||
title: 'Database Service' }],
|
||||
title: 'Database Service'}}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -39,10 +39,6 @@
|
|||
<span class="glyphicon glyphicon-chevron-right"></span>
|
||||
</div>
|
||||
<div class="sidebar">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-primary" ng-model="filterByModel" btn-radio="'by-tag'">Tag</label>
|
||||
<label class="btn btn-primary" ng-model="filterByModel" btn-radio="'by-path'">Path</label>
|
||||
</div>
|
||||
<ul class="nav sidebar-nav">
|
||||
<li ng-repeat="service in services"
|
||||
class="">
|
||||
|
@ -53,6 +49,16 @@
|
|||
<a href="#/{{ filterByModel }}/{{ api.url }}">
|
||||
{{ api.version }}
|
||||
</a>
|
||||
|
||||
<ul class="nav sidebar-nav">
|
||||
<li ng-repeat="api in api.section"
|
||||
ng-class="{'selected': api.url == $routeParams.service + '/' + $routeParams.version + '/'}">
|
||||
<a href="#/{{ filterByModel }}/{{ api.url }}">
|
||||
{{ api.title }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue