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:
Russell Sim 2015-09-27 09:35:07 +10:00
parent c34c4b4f5a
commit d84fcb4e65
4 changed files with 213 additions and 27 deletions

View File

@ -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;
}

View File

@ -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;
}]);

View File

@ -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'}}
);
});
});

View File

@ -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>