Merge "Modify hz-cell to use hz-field"
This commit is contained in:
commit
8850cdda24
131
horizon/static/framework/widgets/property/hz-field.directive.js
Normal file
131
horizon/static/framework/widgets/property/hz-field.directive.js
Normal file
@ -0,0 +1,131 @@
|
||||
/**
|
||||
* (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.framework.widgets.property')
|
||||
.directive('hzField', hzField);
|
||||
|
||||
hzField.$inject = ['$filter'];
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name hzField
|
||||
* @param config {Object} - The field definition object, described below
|
||||
* @param item {Object} - The object containing the property from config.id
|
||||
* @description
|
||||
* The `hzField` directive allows you to output an object's property using
|
||||
* formatting as provided by a field configuration.
|
||||
*
|
||||
* The config object describes a single field, and the config object's 'id'
|
||||
* property matches the name of a property in the 'item' parameter. For
|
||||
* example, if config.id is 'name' then there should be an item.name that
|
||||
* is evaluated for display using the logic described below.
|
||||
*
|
||||
* The field configuration may transform the data in the item's property
|
||||
* using either a set of single-argument filters or functions, specified by
|
||||
* the 'filters' property, or using the 'values' object in which the item
|
||||
* property is mapped via the keys to the values in the given object. Note
|
||||
* that a combination of 'filters' and 'values' may be used; in this case
|
||||
* the filters are evaluated first. This allows for translations that will
|
||||
* map to keys first (e.g. upper-casing a string with a filter so it matches
|
||||
* upper-case keys), and allows the values provided in the 'values' mapping
|
||||
* to be the final value produced. The 'urlFunction' option allows for a
|
||||
* a function to be given, where the item is the sole parameter and the result
|
||||
* should be a URL.
|
||||
*
|
||||
* @restrict E
|
||||
*
|
||||
* @scope
|
||||
* @example
|
||||
*
|
||||
* var config = {id: 'a', title: 'Header A', priority: 1};
|
||||
*
|
||||
* // Using urlFunction to create a link
|
||||
* var linked = {id: 'b', title: 'Header B', priority: 2, urlFunction: myUrlFunction},
|
||||
*
|
||||
* // Using defaultSort
|
||||
* var defaultSort = {id: 'c', title: 'Header C', priority: 1, sortDefault: true};
|
||||
*
|
||||
* // Using filters (can be combined with 'values')
|
||||
* var filtered = {id: 'd', title: 'Header D', priority: 2,
|
||||
* filters: [someFilterFunction, 'uppercase']};
|
||||
*
|
||||
* // Using value mappings
|
||||
* var mapped = {id: 'e', title: 'Header E', priority: 1,
|
||||
* values: {
|
||||
* 'a': 'apple',
|
||||
* 'j': 'jacks'
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* function myUrlFunction(item) {
|
||||
* return '/my/path/' + item.id;
|
||||
* }
|
||||
*
|
||||
* ```
|
||||
* <hz-field config="config" item="item"></hz-field>
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
function hzField($filter) {
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
config: "=",
|
||||
item: "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
return directive;
|
||||
|
||||
///////////////////
|
||||
|
||||
function link(scope, element) {
|
||||
var config = scope.config;
|
||||
var item = scope.item;
|
||||
var propValue = item[config.id];
|
||||
var output = propValue;
|
||||
if (config && config.filters) {
|
||||
for (var i = 0; i < config.filters.length; i++) {
|
||||
var filter = config.filters[i];
|
||||
// call horizon framework filter function if provided
|
||||
if (angular.isFunction(filter)) {
|
||||
output = filter(propValue);
|
||||
// call angular filters
|
||||
} else {
|
||||
output = $filter(filter)(propValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config && config.values) {
|
||||
// apply mapping values to the data if applicable
|
||||
output = config.values[output];
|
||||
}
|
||||
var url;
|
||||
if (config && config.urlFunction) {
|
||||
url = config.urlFunction(item);
|
||||
}
|
||||
if (url) {
|
||||
element.append(angular.element('<a>').attr('href', url).append(output));
|
||||
} else {
|
||||
element.append(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
28
horizon/static/framework/widgets/property/property.module.js
Normal file
28
horizon/static/framework/widgets/property/property.module.js
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* (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';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name horizon.framework.widgets.property
|
||||
* @description
|
||||
* This module provides support for displaying properties of registered resource
|
||||
* types.
|
||||
*/
|
||||
angular.module('horizon.framework.widgets.property', []);
|
||||
|
||||
})();
|
@ -20,26 +20,29 @@
|
||||
.module('horizon.framework.widgets.table')
|
||||
.directive('hzCell', hzCell);
|
||||
|
||||
hzCell.$inject = ['$compile', '$filter'];
|
||||
hzCell.$inject = ['$compile'];
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name horizon.framework.widgets.table.directive:hzCell
|
||||
* @param table {Object} - The table/controller context
|
||||
* @param column {Object} - The column definition object, described below
|
||||
* @param item {Object} - The object containing the property from column.id
|
||||
* @description
|
||||
* The `hzCell` directive allows you to customize your cell content.
|
||||
* When specifying your table configuration object, you may pass in a
|
||||
* template per each column.
|
||||
*
|
||||
* See the documentation on hz-field for details on how to specify formatting
|
||||
* based on the column configuration.
|
||||
*
|
||||
* You should define a template when you want to format data or show more
|
||||
* complex content (e.g conditionally show different icons or a link).
|
||||
* You should reference the cell's 'item' attribute in the template if
|
||||
* you need access to the cell's data. The attributes 'column' and 'item'
|
||||
* should be defined outside of this directive. See example below.
|
||||
* you need access to the cell's data. See example below.
|
||||
*
|
||||
* It should ideally be used within the context of the `hz-dynamic-table` directive.
|
||||
* The params passed into `hz-dynamic-table` can be used in the custom template,
|
||||
* including the 'table' scope. 'table' can be referenced if you want to pass in an
|
||||
* outside scope.
|
||||
* 'table' can be referenced in a template if you want to pass in an outside scope.
|
||||
*
|
||||
* @restrict E
|
||||
*
|
||||
@ -55,27 +58,37 @@
|
||||
* {id: 'c', title: 'Header C', priority: 1, sortDefault: true},
|
||||
* {id: 'd', title: 'Header D', priority: 2,
|
||||
* template: '<span class="fa fa-bolt">{$ item.id $}</span>',
|
||||
* filters: [someFilterFunction, 'uppercase']}
|
||||
* filters: [someFilterFunction, 'uppercase']},
|
||||
* {id: 'e', title: 'Header E', priority: 1,
|
||||
* values: {
|
||||
* 'a': 'apple',
|
||||
* 'j': 'jacks'
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* };
|
||||
*
|
||||
* ```
|
||||
* <tbody>
|
||||
* <tbody ng-controller="TableCtrl as table">
|
||||
* <tr ng-repeat="item in items track by $index">
|
||||
* <td ng-repeat="column in config.columns"
|
||||
* class="{$ column.classes $}">
|
||||
* <hz-cell></hz-cell>
|
||||
* <hz-cell table="table" column="column" item="item"></hz-cell>
|
||||
* </td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
function hzCell($compile, $filter) {
|
||||
function hzCell($compile) {
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
scope: false,
|
||||
scope: {
|
||||
table: '=',
|
||||
column: '=',
|
||||
item: '='
|
||||
},
|
||||
link: link
|
||||
};
|
||||
return directive;
|
||||
@ -84,26 +97,14 @@
|
||||
|
||||
function link(scope, element) {
|
||||
var column = scope.column;
|
||||
var item = scope.item;
|
||||
var html;
|
||||
// if template provided, render, and place into cell
|
||||
if (column && column.template) {
|
||||
// if template provided, render, and place into cell
|
||||
html = $compile(column.template)(scope);
|
||||
} else {
|
||||
// apply filters to cell data if applicable
|
||||
html = item[column.id];
|
||||
if (column && column.filters) {
|
||||
for (var i = 0; i < column.filters.length; i++) {
|
||||
var filter = column.filters[i];
|
||||
// call horizon framework filter function if provided
|
||||
if (angular.isFunction(filter)) {
|
||||
html = filter(item[column.id]);
|
||||
// call angular filters
|
||||
} else {
|
||||
html = $filter(filter)(item[column.id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: 'table' is not passed to hz-field as hz-field is intentionally
|
||||
// not cognizant of a 'table' context as hz-cell is.
|
||||
html = $compile('<hz-field config="column" item="item"></hz-field>')(scope);
|
||||
}
|
||||
element.append(html);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<span class="rsp-alt-p2">
|
||||
<dl class="col-sm-2" ng-repeat="column in config.columns">
|
||||
<dt translate>{$ column.title $}</dt>
|
||||
<dd translate><hz-cell></hz-cell></dd>
|
||||
<dd translate><hz-cell table="table" column="column" item="item"></hz-cell></dd>
|
||||
</dl>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -63,7 +63,7 @@
|
||||
</td>
|
||||
<td ng-repeat="column in config.columns"
|
||||
class="rsp-p{$ column.priority $}">
|
||||
<hz-cell></hz-cell>
|
||||
<hz-cell table="table" column="column" item="item"></hz-cell>
|
||||
</td>
|
||||
<td ng-if="itemActions" class="actions_column">
|
||||
<!--
|
||||
|
@ -222,6 +222,54 @@
|
||||
expect($element.find('tbody tr:eq(1) td:eq(3)').text()).toContain('reptile-ish');
|
||||
expect($element.find('tbody tr:eq(2) td:eq(3)').text()).toContain('bird-ish');
|
||||
});
|
||||
|
||||
it('properly maps the cell content given a mapping', function() {
|
||||
|
||||
$scope.config = {
|
||||
selectAll: true,
|
||||
expand: false,
|
||||
trackId: 'id',
|
||||
columns: [
|
||||
{id: 'animal', title: 'Animal', priority: 1,
|
||||
values: {
|
||||
cat: "Catamount",
|
||||
snake: "Serpent",
|
||||
sparrow: "CAPTAIN Jack Sparrow"
|
||||
}
|
||||
},
|
||||
{id: 'type', title: 'Type', priority: 2},
|
||||
{id: 'diet', title: 'Diet', priority: 1, sortDefault: true},
|
||||
{id: 'domestic', title: 'Domestic', priority: 2}
|
||||
]
|
||||
};
|
||||
var $element = digestMarkup($scope, $compile, markup);
|
||||
expect($element.find('tbody tr:eq(0) td:eq(2)').text()).toContain('Catamount');
|
||||
expect($element.find('tbody tr:eq(1) td:eq(2)').text()).toContain('Serpent');
|
||||
expect($element.find('tbody tr:eq(2) td:eq(2)').text()).toContain('CAPTAIN Jack Sparrow');
|
||||
});
|
||||
|
||||
it('properly adds a link with urlFunction', function() {
|
||||
$scope.config = {
|
||||
selectAll: true,
|
||||
expand: false,
|
||||
trackId: 'id',
|
||||
columns: [
|
||||
{id: 'animal', title: 'Animal', priority: 1,
|
||||
urlFunction: myFunction
|
||||
},
|
||||
{id: 'type', title: 'Type', priority: 2},
|
||||
{id: 'diet', title: 'Diet', priority: 1, sortDefault: true},
|
||||
{id: 'domestic', title: 'Domestic', priority: 2}
|
||||
]
|
||||
};
|
||||
var $element = digestMarkup($scope, $compile, markup);
|
||||
expect($element.find('tbody tr:eq(0) td:eq(2) a').attr('href')).toBe('/here/cat');
|
||||
expect($element.find('tbody tr:eq(1) td:eq(2) a').attr('href')).toBe('/here/snake');
|
||||
expect($element.find('tbody tr:eq(2) td:eq(2) a').attr('href')).toBe('/here/sparrow');
|
||||
function myFunction(item) {
|
||||
return '/here/' + item.animal;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -23,6 +23,7 @@
|
||||
'horizon.framework.widgets.details',
|
||||
'horizon.framework.widgets.help-panel',
|
||||
'horizon.framework.widgets.wizard',
|
||||
'horizon.framework.widgets.property',
|
||||
'horizon.framework.widgets.table',
|
||||
'horizon.framework.widgets.modal',
|
||||
'horizon.framework.widgets.modal-wait-spinner',
|
||||
|
@ -122,8 +122,7 @@
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
template: '<a ng-href="{$ \'project/ngdetails/OS::Glance::Image/\' + item.id $}">' +
|
||||
'{$ item.name $}</a>'
|
||||
urlFunction: urlFunction
|
||||
})
|
||||
.append({
|
||||
id: 'type',
|
||||
@ -228,6 +227,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function urlFunction(item) {
|
||||
return 'project/ngdetails/OS::Glance::Image/' + item.id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user