未加星标

Dive deep into the Horizon framework

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二03 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

The Horizon framework has been evolving with each release since it began Angular development. Widgets now offer a lot of customization, but it can sometimes be difficult to keep up with the rapid changes, especially given the layers of abstraction. This post aims to cover some of the new standards and how everything fits together. It will use creating a new Angular panel to explain some new concepts.

Note: this may become out-of-date at some point because the framework is in a state of flux. Also, you may still create a panel as before, using the HTML template and defining a controller. This post presents a declarative approach that builds upon the existing Horizon framework.

Prerequisites:

Know how to create a Django dashboard/ panel Know how to create an Angular dashboard/ panel (using HTML template)

A quick recap before we dive into the new material… All Angular content should be placed under a static directory in order to be collected by Horizon automatically (when AUTO_DISCOVER_STATIC_FILES = True in your dashboard’s enabled file enabled/.py). For this tutorial, we create a panel called, Flavors.

As before, you should create these files to generate a blank panel.

openstack_dashboard/dashboards/admin/ngflavors/
├── __init__.py
├── panel.py
├── urls.py
└── views.py //Angular point of entry, angular.html picks up our panel.html content

core.module.js should be modified to add ‘horizon.dashboard.core.flavors’ and we should have an enabled file too.

This skeleton file structure should be placed under openstack_dashboard/static/app/core/flavors/

├── panel.html

├── flavors.module.js

└── flavors.module.spec.js

// panel.html (the starting point)

hzResourcePanel directive takes in a resource type name and creates the wrapper for the panel, including a header (using hzPageHeader directive) and content to be transcluded. For OpenStack Dashboard, we use HEAT type names for our resource type name, like “OS::Nova::Flavor” or “OS::Glance::Image” to associate with a single service API.

hzResourceTable directive produces a table and various other components for the specific resource type name. The resource type name is associated to a registry which contains all the relevant data for that type. More of that later. This data is then passed down from hzResourceTable into the hzDynamicTable directive. hzDynamicTable directive then generates all the HTML content for a table using a common template. hzResourceTable controller adds additional functionality including keeping track of changes/ updates to the registry, magic-search events, and actions, and handling them accordingly.

The registry is the backbone of panel generation. The registry pattern creates a container for objects that can be accessible from anywhere via a key. In our scenario, the application-level resourceTypeRegistry service collects all the data and details for generating a user interface and provides a single place for you to retrieve this information when you build tables, detail views, forms, modals, etc.

Some of the things you may put in the registry are:

Actions (e.g. “Create Image”) Detail views (when you click on an item for more information) Search filter facets Url to detail drawer template List function to retrieve API service promise Property information labels for table column headers or form elements formatting for property values

Some aspects use Horizon’s extensibility service allowing you to add, remove, replace existing items. These include:

Item actions Batch actions Global actions Detail views Table columns Filter facets

This makes it simple to create new table content and customize existing table content to your needs. For example, adding a new item action to an existing Angular table. You would simply add this new configuration to the registry and it would be picked up by the hzResourceTable directive.

To retrieve data from the registry, you would include the dependency, ‘ horizon.framework.conf.resource-type-registry.service ‘ and call ‘ registryService.getResourceType() ‘.

For our Flavors table example, we place our registry in flavors.module.js.

(function() {
'use strict';
angular
.module('horizon.app.core.flavors', [
'ngRoute',
'horizon.framework.conf',
'horizon.app.core'
])
.constant('horizon.app.core.flavors.resourceType', 'OS::Nova::Flavor')
.run(run)
.config(config);
run.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'horizon.app.core.flavors.basePath',
'horizon.app.core.flavors.service',
'horizon.app.core.flavors.resourceType'
];
function run(registry, basePath, flavorsService, flavorResourceType) {
registry.getResourceType(flavorResourceType)
.setNames(gettext('Flavor'), gettext('Flavors'))
.setSummaryTemplateUrl(basePath + 'summary.html')
.setProperty('name', {
label: gettext('Flavor Name')
})
.setProperty('vcpus', {
label: gettext('VCPUs')
})
.setProperty('ram', {
label: gettext('RAM'),
filters: ['mb']
})
.setProperty('disk', {
label: gettext('Root Disk'),
filters: ['gb']
})
.setProperty('OS-FLV-EXT-DATA:ephemeral', {
label: gettext('Ephemeral Disk'),
filters: ['gb']
})
.setProperty('swap', {
label: gettext('Swap Disk'),
filters: ['gb']
})
.setProperty('rxtx_factor', {
label: gettext('RX/TX Factor')
})
.setProperty('id', {
label: gettext('ID')
})
.setProperty('os-flavor-access:is_public', {
label: gettext('Public'),
filters: ['yesno']
})
.setProperty('metadata', {
label: gettext('Metadata')
})
.setListFunction(flavorsService.getFlavorsPromise)
.tableColumns
.append({
id: 'name',
priority: 1
})
.append({
id: 'vcpus',
priority: 2
})
.append({
id: 'ram',
priority: 1,
sortDefault: true
})
.append({
id: 'disk',
priority: 2
})
.append({
id: 'id',
priority: 1
})
.append({
id: 'os-flavor-access:is_public',
priority: 2
});
}
config.$inject = [
'$provide',
'$windowProvider',
'$routeProvider'
];
/**
* @name config
* @param {Object} $provide
* @param {Object} $windowProvider
* @param {Object} $routeProvider
* @description Routes used by this module.
* @returns {undefined} Returns nothing
*/
function config($provide, $windowProvider, $routeProvider) {
var path = $windowProvider.$get().STATIC_URL + 'app/core/flavors/';
$provide.constant('horizon.app.core.flavors.basePath', path);
$routeProvider.when('/admin/flavors/', {
templateUrl: path + 'panel.html'
});
}
})();

Then you can access the registry like:

var resourceType = registryService.getResourceType('OS::Glance::Image');
resourceType.getTableColumns();

More details on resource-type-registry service.

//

hzDynamicTable directive is built off the AngularJS Smart-Table module and requires config and items . The config object contains an array of objects that describes each column. The items object contains the data to want to show (probably from an API call). You may also pass in batch actions, item actions, filter facets into the directive for more complex use case.

If you take a look at hz-dynamic-table.html, it is essentially what you would write to generate an Angular table prior to Newton release. We packaged that up so that you don’t need to rewrite the same boilerplate code for a new table. Instead, pass in a registry and ‘Voila!’ a table is created!

hzDynamicTable uses other Horizon framework components:

hz-magic-search-context st-table hz-table actions hz-select-all hz-select hz-magic-search-bar hz-cell (uses hz-field) hz-no-items hz-detail-row hz-expand-detail hz-table-footer

More details on hz-dynamic-table.

For each row, you can also have an expandable detail drawer defined by summaryTemplateUrl() in registry and passed into hzDynamicTable’s config as detailsTemplateUrl.

Inside the detail_drawer.html, you may use hzResourcePropertyList directive.

This displays set of properties registered to a particular resource type grouped by label/values. It is built off a 12-column system. In the example above, it will generate 4 columns.

Name VCPUs Root Disk RX/TX Factor
m1.tiny 1 1GB 1
ID RAM Ephemeral Disk
123 512MB 0GB
Swap Disk
0GB

The directive also uses the permissions service to check whether or not to show the column. It will check that certain policies pass, certain settings are enabled, or certain services are enabled. In addition, you can set a generic allowed function on the column config.

//


Dive deep into the Horizon framework
Fig 1: This shows the layers of directives/ dependency chain. Red shows external modules we’ve modified.

A summary of the topics covered in this post include:

Horizon framework directives and how they work together Resource type registry service Extensibility service

Also, please check out Images Panel for the most up-to-date reference.

Til next time,

Cindy

This post first appeared on the IBM OpenTech blog . Superuser is always interested in community content, email:[emailprotected]

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: HTMLCPUDjangoAngularJSOpenStackTIUTAUAUTLV
分页:12
转载请注明
本文标题:Dive deep into the Horizon framework
本站链接:http://www.codesec.net/view/482932.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(34)