Developer Registry Resource Browser

Developer dashboard panel which shows:
- resource types currently in the resource registry browser
- the details that are set for each resource type
- links to generic table views (if available)
- available actions (with WIP mechanism to exercise the action)

To test:
- Open Developer -> Resources
- notice how Images item is green
- exercise some of the global actions (create image)
- enter an image id to exercise the item actions
- batch actions not currently testable
- click the images "Generic Table View" link

Partially-Implements: blueprint angular-registry
Change-Id: Ib931fac9917a50c268b2e63ff7a0de42052c62c8
This commit is contained in:
Tyr Johanson 2016-05-06 17:00:32 -06:00
parent 4aa405bc08
commit b507db7439
20 changed files with 861 additions and 6 deletions

View File

@ -104,10 +104,12 @@
self.getName = getName;
self.setNames = setNames;
self.label = label;
self.load = load;
self.load = defaultLoadFunction;
self.setLoadFunction = setLoadFunction;
self.list = list;
self.isLoadFunctionSet = isLoadFunctionSet;
self.list = defaultListFunction;
self.setListFunction = setListFunction;
self.isListFunctionSet = isListFunctionSet;
self.itemName = itemName;
self.setItemNameFunction = setItemNameFunction;
self.setPathParser = setPathParser;
@ -189,7 +191,10 @@
return self;
}
// Returns a copy of the properties.
/**
* Return a copy of any properties that have been registered.
* @returns {*}
*/
function getProperties() {
return angular.copy(properties);
}
@ -221,6 +226,14 @@
return self;
}
/**
* True if a list function for this resource has been registered.
* @returns {boolean}
*/
function isListFunctionSet() {
return self.list !== defaultListFunction;
}
/**
* @ngdoc function
* @name list
@ -233,7 +246,7 @@
var listPromise = resourceType.list();
```
*/
function list() {
function defaultListFunction() {
$log.error('No list function defined for', typeCode);
return Promise.reject({data: {items: []}});
}
@ -344,6 +357,14 @@
return self;
}
/**
* True if the load function for this resource has been registered
* @returns {boolean}
*/
function isLoadFunctionSet() {
return self.load !== defaultLoadFunction;
}
/**
* @ngdoc function
* @name load
@ -355,7 +376,7 @@
var loadPromise = resourceType.load('some-id');
```
*/
function load(spec) {
function defaultLoadFunction(spec) {
$log.error('No load function defined for', typeCode, 'with spec', spec);
return Promise.reject({data: {}});
}

View File

@ -257,6 +257,24 @@
type.setLoadFunction(api.loadMe);
expect(type.load()).toEqual({an: 'object'});
});
it('detects that a load function has not been set', function() {
expect(type.isLoadFunctionSet()).toEqual(false);
});
it('detects that a load function has been set', function() {
type.setLoadFunction(angular.noop);
expect(type.isLoadFunctionSet()).toEqual(true);
});
it('detects that a list function has not been set', function() {
expect(type.isListFunctionSet()).toEqual(false);
});
it('detects that a list function has been set', function() {
type.setListFunction(angular.noop);
expect(type.isListFunctionSet()).toEqual(true);
});
});
});
})();

View File

@ -0,0 +1,22 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.utils.translation import ugettext_lazy as _
import horizon
class ResourceBrowser(horizon.Panel):
name = _("Resources")
slug = 'resource_browser'

View File

@ -0,0 +1,24 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf.urls import patterns
from django.conf.urls import url
from openstack_dashboard.contrib.developer.resource_browser import views
urlpatterns = patterns(
'openstack_dashboard.contrib.developer.resource_browser.views',
url('', views.IndexView.as_view(), name='index'),
)

View File

@ -0,0 +1,19 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.views import generic
class IndexView(generic.TemplateView):
template_name = 'angular.html'

View File

@ -25,7 +25,8 @@
*/
angular
.module('horizon.dashboard.developer', [
'horizon.dashboard.developer.theme-preview'
'horizon.dashboard.developer.theme-preview',
'horizon.dashboard.developer.resource-browser'
])
.config(config);

View File

@ -0,0 +1,56 @@
/*
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.developer.resource-browser')
.controller('horizon.dashboard.developer.resource-browser.rbResourcePanelController', controller);
controller.$inject = [
'$routeParams',
'horizon.framework.conf.resource-type-registry.service',
];
/**
* @ngdoc controller
* @name horizon.dashboard.developer.resource-browser:rbResourcePanelController
* @description
* This controller allows the launching of any actions registered for resource types
*/
function controller($routeParams, registryService) {
var ctrl = this;
/**
* Private Data
*/
var resourceType = registryService.getResourceType($routeParams.resourceTypeName);
/**
* Public Interface
*/
ctrl.resourceTypeName = resourceTypeName();
/**
* Implementation
*/
function resourceTypeName() {
return resourceType.type;
}
}
})();

View File

@ -0,0 +1,47 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.developer.resource-browser')
.directive('rbResourcePanel', directive);
directive.$inject = ['horizon.dashboard.developer.basePath'];
/**
* @ngdoc directive
* @name rb-resource-panel
* @description
* A simple directive that extracts a resource type name from the route
* and uses it to display a generic resource table
*/
function directive(path) {
var directive = {
restrict: 'E',
templateUrl: path + 'resource-browser/rb-resource-panel/rb-resource-panel.html',
scope: {
},
controller: 'horizon.dashboard.developer.resource-browser.rbResourcePanelController as ctrl'
};
return directive;
}
})();

View File

@ -0,0 +1,4 @@
<hz-resource-panel resource-type-name="{$ ctrl.resourceTypeName $}">
<hz-resource-table resource-type-name="{$ ctrl.resourceTypeName $}">
</hz-resource-table>
</hz-resource-panel>

View File

@ -0,0 +1,218 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.developer.resource-browser')
.controller('horizon.dashboard.developer.resource-browser.ResourceBrowserItemController', ResourceBrowserItemController);
ResourceBrowserItemController.$inject = [
'$scope',
'horizon.dashboard.developer.resource-browser.BASE_ROUTE'
];
/**
* @ngdoc controller
* @name horizon.dashboard.developer.resource-browser:ResourceBrowserItemController
* @description
* This controller allows the launching of any actions registered for resource types
*/
function ResourceBrowserItemController($scope, baseRoute) {
/**
* Directive data (Private)
*/
var ctrl = this;
var typeData = ctrl.registryResourceType;
var type = typeData.type;
/**
* View-specific model (Public)
*/
ctrl.collapsed = true;
ctrl.resourceId = undefined;
ctrl.fullySupported = fullySupported();
ctrl.typeLabel = type;
ctrl.nameLabel = typeData.getName();
ctrl.allNameLabels = [typeData.getName(1) || '', typeData.getName(2)];
ctrl.supportsGenericTableView = supportsGenericTableView();
ctrl.typeName = getName();
ctrl.hasListFunction = hasListFunction();
ctrl.listFunctionNameLabel = listFunctionNameLabel();
ctrl.hasProperties = hasProperties();
ctrl.hasTableColumns = hasTableColumns();
ctrl.hasSummaryView = hasSummaryView();
ctrl.summaryTemplateUrl = typeData.summaryTemplateUrl;
ctrl.tableUrl = getTableUrl(type);
ctrl.tableColumnLabels = getTableColumnLabels();
ctrl.propertyLabels = getProperties();
ctrl.supportsGenericDetailsView = supportsGenericDetailsView();
ctrl.hasLoadFunction = hasLoadFunction();
ctrl.loadFunctionNameLabel = loadFunctionNameLabel();
ctrl.hasDetailView = hasDetailView();
ctrl.detailViewLabels = getDetailViewLabels();
ctrl.hasGlobalActions = hasGlobalActions();
ctrl.globalActions = typeData.globalActions;
ctrl.hasBatchActions = hasBatchActions();
ctrl.batchActions = typeData.batchActions;
ctrl.hasItemActions = hasItemActions();
ctrl.itemActions = typeData.itemActions;
/**
* View-specific behavior (Public)
*/
ctrl.onActionSelected = onActionSelected;
//////////////
/**
* Implementation
*/
function fullySupported() {
return (supportsGenericDetailsView() &&
supportsGenericTableView() &&
hasSummaryView() &&
hasGlobalActions() &&
hasItemActions());
}
function getName() {
return typeData.getName();
}
function supportsGenericTableView() {
return (
getName() &&
hasListFunction() &&
hasProperties() &&
hasTableColumns() &&
hasSummaryView()
);
}
function hasListFunction() {
return typeData.isListFunctionSet();
}
function listFunctionNameLabel() {
var label = gettext("Not Set");
if ( hasListFunction() ) {
label = typeData.list.name;
}
return label;
}
function hasProperties() {
return getProperties().length > 0;
}
function hasTableColumns() {
return typeData.tableColumns.length > 0;
}
function getProperties() {
return Object.keys(typeData.getProperties());
}
function getProperties() {
var properties = typeData.getProperties();
var keys = Object.keys(properties);
return keys.map(getLabel);
function getLabel(item) {
return properties[item].label;
}
}
function getTableColumnLabels() {
return typeData.tableColumns.map(getColumnId);
function getColumnId(item) {
return item.id;
}
}
function getTableUrl(type) {
return baseRoute + type;
}
function supportsGenericDetailsView() {
return (hasDetailView() &&
hasLoadFunction());
}
function hasDetailView() {
return typeData.detailsViews.length > 0
}
function getDetailViewLabels() {
return typeData.detailsViews.map(getName);
function getName(item) {
return item.name;
}
}
function hasLoadFunction() {
return typeData.isLoadFunctionSet();
}
function loadFunctionNameLabel() {
var label = gettext("Not Set");
if ( hasLoadFunction() ) {
label = typeData.load.name
}
return label;
}
function hasGlobalActions() {
return typeData.globalActions.length != 0
}
function hasBatchActions() {
return typeData.batchActions.length != 0
}
function hasItemActions() {
return typeData.itemActions.length != 0;
}
function hasSummaryView() {
return typeData.summaryTemplateUrl;
}
function onActionSelected(action) {
// First, attempt to load the requested resource. Assume the user
// typed in an ID object that is compatible with the load function.
typeData.load(ctrl.resourceId).then(performAction, loadFailed);
function performAction(resource) {
if (action.service.initScope) {
action.service.initScope($scope.$new());
}
return action.service.perform(resource.data);
}
function loadFailed(reason) {
window.alert(gettext("resource load failed" + ":" + reason));
}
}
}
})();

View File

@ -0,0 +1,47 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.developer.resource-browser')
.directive('resourceBrowserItem', resourceBrowserItem);
resourceBrowserItem.$inject = ['horizon.dashboard.developer.basePath'];
/**
* @ngdoc directive
* @name resource-browser-item
* @description
* A detailed view of resource registration data
*/
function resourceBrowserItem(path) {
var directive = {
restrict: 'E',
templateUrl: path + 'resource-browser/resource-browser-item.html',
scope: {
registryResourceType: '='
},
controller: 'horizon.dashboard.developer.resource-browser.ResourceBrowserItemController as ctrl',
bindToController: true
};
return directive;
}
})();

View File

@ -0,0 +1,191 @@
<div class="container">
<div class="panel panel-default">
<div class="panel-heading" ng-click="ctrl.collapsed=!ctrl.collapsed">
<div class="panel-title">
<span class="fa" ng-class="ctrl.fullySupported ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
{$ ctrl.nameLabel $} ( {$ ctrl.typeLabel $} )
<span class="fa pull-right" ng-class="ctrl.collapsed ? 'fa-plus' : 'fa-minus'"></span>
</div>
</div>
<div>
<div class="panel-body" collapse="ctrl.collapsed">
<!-- Has generic table view -->
<div class="row"><label>
<div class="col-xs-12">
<h4>
<span class="fa" ng-class="ctrl.supportsGenericTableView ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<a ng-href="{$ ctrl.tableUrl $}">
<label>Generic Table View:</label>
</a>
</h4>
</div>
</div>
<!-- Name(s) is set -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.nameLabel ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Names:</label>
<ul ng-repeat="label in ctrl.allNameLabels">
<li>{$ label $}</li>
</ul>
</div>
</div>
<!-- Has List function -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.hasListFunction ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>List Function:</label> {$ ctrl.listFunctionNameLabel $}
</div>
</div>
<!-- Has Properties -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.hasProperties ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Properties:</label>
<ul ng-repeat="label in ctrl.propertyLabels">
<li>{$ label $}</li>
</ul>
</div>
</div>
<!-- Has default table columns -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.hasTableColumns > 0 ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Table Columns:</label>
<ul ng-repeat="label in ctrl.tableColumnLabels">
<li>{$ label $}</li>
</ul>
</div>
</div>
<!-- Has drawer view -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.hasSummaryView ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Summary Template URL:</label> {$ ctrl.summaryTemplateUrl $}
</div>
</div>
<!-- Has generic details view -->
<div class="row">
<div class="col-xs-12">
<h4>
<span class="fa" ng-class="ctrl.supportsGenericDetailsView ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Supports Details View:</label>
</h4>
</div>
</div>
<!-- Has Load function -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.hasLoadFunction ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Load Function:</label> {$ ctrl.loadFunctionNameLabel $}
</div>
</div>
<!-- Has 1 or more details views -->
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<span class="fa" ng-class="ctrl.hasDetailView ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Details Views:</label>
<ul ng-repeat="label in ctrl.detailViewLabels">
<li>{$ label $}</li>
</ul>{$ ctrl.detailsViewsLabel $}
</div>
</div>
<!-- Has global actions -->
<div class="row">
<div class="col-xs-12">
<h4>
<span class="fa" ng-class="ctrl.hasGlobalActions ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Global Actions:</label>
</h4>
</div>
</div>
<div ng-if="ctrl.hasGlobalActions != 0">
<div ng-repeat="action in ctrl.globalActions">
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
{$ action.template.text $}
</div>
<div class="col-xs-4">
</div>
<div class="col-xs-4">
<input type="button"
value="{$ action.template.text $}"
ng-click="ctrl.onActionSelected(action)"/>
</div>
</div>
</div>
</div>
<!-- Has batch actions -->
<div class="row">
<div class="col-xs-12">
<h4>
<span class="fa" ng-class="ctrl.hasBatchActions ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Batch Actions:</label>
</h4>
</div>
</div>
<div ng-if="ctrl.hasBatchActions != 0">
<div ng-repeat="action in ctrl.batchActions">
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
{$ action.template.text $}
</div>
<div class="col-xs-4">
</div>
<div class="col-xs-4">
<input type="button"
value="{$ action.template.text $}"
ng-click="ctrl.onActionSelected(action)"/>
</div>
</div>
</div>
</div>
<!-- Has item actions -->
<div class="row">
<div class="col-xs-12">
<h4>
<span class="fa" ng-class="ctrl.hasItemActions ? 'text-success fa-check' : 'text-warning fa-warning'"></span>
<label>Item Actions:</label>
</h4>
</div>
</div>
<div ng-if="ctrl.hasItemActions">
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
<div ng-repeat="action in ctrl.itemActions">
{$ action.template.text $}
</div>
</div>
<div class="col-xs-4">
<form name="resourceIdForm">
<input ng-model="ctrl.resourceId"
type="text"
placeholder="Resource ID(s)"/>
</form>
</div>
<div class="col-xs-4">
<div ng-repeat="action in ctrl.itemActions">
<input
type="button"
value="{$ action.template.text $}"
ng-click="ctrl.onActionSelected(action)"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,41 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.developer.resource-browser')
.controller('horizon.dashboard.developer.resource-browser.ResourceBrowserController', ResourceBrowserController);
ResourceBrowserController.$inject = [
'$location',
'$scope',
'horizon.framework.conf.resource-type-registry.service',
];
/**
* @ngdoc controller
* @name horizon.dashboard.developer.resource-browser:ResourceBrowserController
* @description
* This controller allows the launching of any actions registered for resource types
*/
function ResourceBrowserController($location, $scope, registryService) {
var ctrl = this;
ctrl.resourceTypes = registryService.resourceTypes;
}
})();

View File

@ -0,0 +1,47 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.developer.resource-browser')
.directive('resourceBrowser', resourceBrowser);
resourceBrowser.$inject = ['horizon.dashboard.developer.basePath'];
/**
* @ngdoc directive
* @name resource-browser
* @description
* A page that shows all resource types and associated actions available
* from the resource registry
*/
function resourceBrowser(path) {
var directive = {
restrict: 'E',
templateUrl: path + 'resource-browser/resource-browser.html',
scope: {
},
controller: 'horizon.dashboard.developer.resource-browser.ResourceBrowserController as ctrl'
};
return directive;
}
})();

View File

@ -0,0 +1,7 @@
<h2>
Registered Resource Types
</h2>
<div ng-repeat="(type, typeData) in ctrl.resourceTypes">
<a name="{$ type $}"></a>
<resource-browser-item registry-resource-type="typeData"></resource-browser-item>
</div>

View File

@ -0,0 +1,46 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
/**
* @ngdoc module
* @ngname horizon.dashboard.developer.resource-browser
* @description
* Dashboard module for the resource-browser panel.
*/
angular
.module('horizon.dashboard.developer.resource-browser', [], config)
.constant('horizon.dashboard.developer.resource-browser.BASE_ROUTE', '/developer/resource_browser/');
config.$inject = [
'$windowProvider',
'$routeProvider',
'horizon.dashboard.developer.resource-browser.BASE_ROUTE'];
function config($windowProvider, $routeProvider, baseRoute) {
$routeProvider
.when(baseRoute, {
templateUrl: $windowProvider.$get().STATIC_URL +
'dashboard/developer/resource-browser/resources.html'
})
.when(baseRoute + ':resourceTypeName', {
template: "<rb-resource-panel></rb-resource-panel>"
});
}
})();

View File

@ -0,0 +1,25 @@
/*
* (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
describe('horizon.dashboard.developer.resource-browser', function () {
it('should be defined', function () {
expect(angular.module('horizon.dashboard.developer.resource-browser')).toBeDefined();
});
});
})();

View File

@ -0,0 +1 @@
<resource-browser></resource-browser>

View File

@ -0,0 +1,20 @@
# (c) Copyright 2015 Hewlett Packard Enterprise Development Company LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
PANEL = 'resource_browser'
PANEL_GROUP = 'default'
PANEL_DASHBOARD = 'developer'
ADD_PANEL = 'openstack_dashboard.contrib.developer.resource_browser.panel.ResourceBrowser' # noqa