diff --git a/horizon/static/framework/conf/resource-type-registry.service.js b/horizon/static/framework/conf/resource-type-registry.service.js
index c72b0bb818..eafecacc6d 100644
--- a/horizon/static/framework/conf/resource-type-registry.service.js
+++ b/horizon/static/framework/conf/resource-type-registry.service.js
@@ -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: {}});
}
diff --git a/horizon/static/framework/conf/resource-type-registry.service.spec.js b/horizon/static/framework/conf/resource-type-registry.service.spec.js
index 7488769ed5..5cb473621e 100644
--- a/horizon/static/framework/conf/resource-type-registry.service.spec.js
+++ b/horizon/static/framework/conf/resource-type-registry.service.spec.js
@@ -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);
+ });
});
});
})();
diff --git a/openstack_dashboard/contrib/developer/resource_browser/__init__.py b/openstack_dashboard/contrib/developer/resource_browser/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/openstack_dashboard/contrib/developer/resource_browser/panel.py b/openstack_dashboard/contrib/developer/resource_browser/panel.py
new file mode 100644
index 0000000000..c1977595d8
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/resource_browser/panel.py
@@ -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'
diff --git a/openstack_dashboard/contrib/developer/resource_browser/urls.py b/openstack_dashboard/contrib/developer/resource_browser/urls.py
new file mode 100644
index 0000000000..ca53f2852f
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/resource_browser/urls.py
@@ -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'),
+)
diff --git a/openstack_dashboard/contrib/developer/resource_browser/views.py b/openstack_dashboard/contrib/developer/resource_browser/views.py
new file mode 100644
index 0000000000..e072aeab92
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/resource_browser/views.py
@@ -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'
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js
index 70f5328746..6f280a81a9 100644
--- a/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js
@@ -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);
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.controller.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.controller.js
new file mode 100644
index 0000000000..3b6a7c2f6b
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.controller.js
@@ -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;
+ }
+ }
+
+})();
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.directive.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.directive.js
new file mode 100644
index 0000000000..2b739af3df
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.directive.js
@@ -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;
+ }
+})();
+
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.html b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.html
new file mode 100644
index 0000000000..186e779403
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/rb-resource-panel/rb-resource-panel.html
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.controller.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.controller.js
new file mode 100644
index 0000000000..7152b718d9
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.controller.js
@@ -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));
+ }
+ }
+ }
+
+})();
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.directive.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.directive.js
new file mode 100644
index 0000000000..961e2fb0d0
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.directive.js
@@ -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;
+ }
+})();
+
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.html b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.html
new file mode 100644
index 0000000000..d2afc1885f
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser-item.html
@@ -0,0 +1,191 @@
+
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.controller.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.controller.js
new file mode 100644
index 0000000000..40ad58f5cc
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.controller.js
@@ -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;
+ }
+
+})();
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.directive.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.directive.js
new file mode 100644
index 0000000000..661da16556
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.directive.js
@@ -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;
+ }
+})();
+
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.html b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.html
new file mode 100644
index 0000000000..529d4c47f6
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.html
@@ -0,0 +1,7 @@
+
+ Registered Resource Types
+
+
+
+
+
\ No newline at end of file
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.module.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.module.js
new file mode 100644
index 0000000000..106c80b5bf
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.module.js
@@ -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: ""
+ });
+ }
+
+})();
\ No newline at end of file
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.module.spec.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.module.spec.js
new file mode 100644
index 0000000000..c2cc1824a1
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resource-browser.module.spec.js
@@ -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();
+ });
+ });
+
+})();
diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resources.html b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resources.html
new file mode 100644
index 0000000000..15ff5948c3
--- /dev/null
+++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/resource-browser/resources.html
@@ -0,0 +1 @@
+
diff --git a/openstack_dashboard/enabled/_9020_resource_browser.py b/openstack_dashboard/enabled/_9020_resource_browser.py
new file mode 100644
index 0000000000..4acab132f4
--- /dev/null
+++ b/openstack_dashboard/enabled/_9020_resource_browser.py
@@ -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