hz-resource-table handles transitional states
In the django tables, if a resource goes into a transitional-state (think building, deleting, shutting-down, ...) the table would highlight that behavior with 2 changes: A) the row would be highlighted B) a barber-pole would show up in the status column The new-ish registry-based hz-resource-table wasn't making either of those visual changes. But now it is! Hurray for fewer regressions! Change-Id: Ic84b1eabc2c32e7ba48bf9ce2279f69a4e9a95e0 Partially-Implements: blueprint angular-registry Co-Authored-By: Tyr Johanson tyr@hpe.com
This commit is contained in:
parent
3864fd11a1
commit
6ad296770a
@ -110,6 +110,8 @@
|
||||
self.list = defaultListFunction;
|
||||
self.setListFunction = setListFunction;
|
||||
self.isListFunctionSet = isListFunctionSet;
|
||||
self.itemInTransitionFunction = defaultItemInTransitionFunction;
|
||||
self.setItemInTransitionFunction = setItemInTransitionFunction;
|
||||
self.itemName = itemName;
|
||||
self.setItemNameFunction = setItemNameFunction;
|
||||
self.setPathParser = setPathParser;
|
||||
@ -251,6 +253,40 @@
|
||||
return Promise.reject({data: {items: []}});
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name defaultItemInTransitionFunction
|
||||
* @description
|
||||
* A default implementation for the "itemInTransitionFunction function-pointer" which
|
||||
* returns false every time.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function defaultItemInTransitionFunction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function that detects if an instance of this resource type is in a
|
||||
* "transition" state, such as an image with a "queued" status, or an instance
|
||||
* with an "in-progress" status. For example, this might be used to highlight
|
||||
* a particular item in a list, or to set a progress indicator when viewing that
|
||||
* items details.
|
||||
*
|
||||
* By default, a call to itemInTransitionFunction(item) will return false unless this
|
||||
* function is registered for the resource type;
|
||||
*
|
||||
* @ngdoc function
|
||||
* @param func - The callback-function to be used for determining if this
|
||||
* resource is in a transitional state. This callback-function will be passed
|
||||
* an object that is an instance of this resource (e.g. an image) and should
|
||||
* return a boolean. "true" indicates the item is in a "transition" state.
|
||||
* @returns {ResourceType} - returning self to facilitate call-chaining.
|
||||
*/
|
||||
function setItemInTransitionFunction(func) {
|
||||
self.itemInTransitionFunction = func;
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name getTableColumns
|
||||
|
@ -195,6 +195,18 @@
|
||||
expect(type.list()).toBe('this would be a promise');
|
||||
});
|
||||
|
||||
it("has a default isInTransition function that returns false", function() {
|
||||
expect(type.itemInTransitionFunction()).toBe(false);
|
||||
});
|
||||
|
||||
it("allows setting an isInTransition function", function() {
|
||||
function isInTransitionTest() {
|
||||
return "would return a boolean";
|
||||
}
|
||||
type.setItemInTransitionFunction(isInTransitionTest);
|
||||
expect(type.itemInTransitionFunction()).toBe("would return a boolean");
|
||||
});
|
||||
|
||||
it("allows setting of a summary template URL", function() {
|
||||
type.setSummaryTemplateUrl('/my/path.html');
|
||||
expect(type.summaryTemplateUrl).toBe('/my/path.html');
|
||||
|
@ -44,6 +44,10 @@
|
||||
* It should ideally be used within the context of the `hz-dynamic-table` directive.
|
||||
* 'table' can be referenced in a template if you want to pass in an outside scope.
|
||||
*
|
||||
* If the column has a itemInTransitionFunction property, that function will be
|
||||
* called with the row's item. If the function returns true, a progress bar will
|
||||
* be included in the cell.
|
||||
*
|
||||
* @restrict E
|
||||
*
|
||||
* @scope
|
||||
@ -64,7 +68,8 @@
|
||||
* 'a': 'apple',
|
||||
* 'j': 'jacks'
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* {id: 'f', title: 'Status', itemInTransitionFunction: myInTransitionFunc},
|
||||
* ]
|
||||
* };
|
||||
*
|
||||
@ -98,13 +103,24 @@
|
||||
function link(scope, element) {
|
||||
var column = scope.column;
|
||||
var html;
|
||||
var progressBarHtml = '';
|
||||
if (column && column.template) {
|
||||
// if template provided, render, and place into cell
|
||||
html = $compile(column.template)(scope);
|
||||
} else {
|
||||
// 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);
|
||||
if (column.itemInTransitionFunction && column.itemInTransitionFunction(scope.item)) {
|
||||
// NOTE(woodnt): It'd be nice to split this out into a template file,
|
||||
// but since we're inside a link function, that's complicated.
|
||||
progressBarHtml = '<div class="progress-text horizon-loading-bar">' +
|
||||
'<div class="progress progress-striped active">' +
|
||||
'<div class="progress-bar"></div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
html = $compile(progressBarHtml +
|
||||
'<hz-field config="column" item="item"></hz-field>')(scope);
|
||||
}
|
||||
element.append(html);
|
||||
}
|
||||
|
@ -39,6 +39,9 @@
|
||||
* searching. Filter will not be shown if this is not supplied (optional)
|
||||
* @param {function=} resultHandler function that is called with return value
|
||||
* from a clicked actions perform function passed into `actions` directive (optional)
|
||||
* @param {function=} itemInTransitionFunction function that is called with each item in
|
||||
* the table. If it returns true, the row is given the class "status_unknown" which by
|
||||
* default highlights the row with a warning color.
|
||||
*
|
||||
* @description
|
||||
* The `hzDynamicTable` directive generates all the HTML content for a table.
|
||||
@ -121,7 +124,8 @@
|
||||
batchActions: '=?',
|
||||
itemActions: '=?',
|
||||
filterFacets: '=?',
|
||||
resultHandler: '=?'
|
||||
resultHandler: '=?',
|
||||
itemInTransitionFunction: '=?'
|
||||
},
|
||||
controller: 'horizon.framework.widgets.table.HzDynamicTableController',
|
||||
templateUrl: basePath + 'table/hz-dynamic-table.html'
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* (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.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
describe('hz-dynamic-table directive', function() {
|
||||
var $compile, $rootScope, $scope;
|
||||
|
||||
beforeEach(module('templates'));
|
||||
beforeEach(module('smart-table'));
|
||||
beforeEach(module('horizon.framework'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.widgets.magic-search'));
|
||||
beforeEach(module('horizon.framework.widgets.table'));
|
||||
|
||||
beforeEach(inject(function(_$compile_, _$rootScope_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
$scope = $rootScope.$new();
|
||||
}));
|
||||
|
||||
it("sets class when item in transition", function() {
|
||||
var config = {
|
||||
selectAll: false,
|
||||
expand: false,
|
||||
trackId: 'id',
|
||||
columns: [
|
||||
{id: 'a', title: 'A', priority: 1},
|
||||
{id: 'b', title: 'B', priority: 2}
|
||||
]
|
||||
};
|
||||
$scope.config = config;
|
||||
$scope.tableConfig = config;
|
||||
$scope.items = [
|
||||
{
|
||||
id: 1,
|
||||
a: "a",
|
||||
b: "b"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
a: "a",
|
||||
b: "b"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
a: "a",
|
||||
b: "b"
|
||||
}
|
||||
];
|
||||
$scope.itemInTransitionFunc = function(item) {
|
||||
return item.id === 1;
|
||||
};
|
||||
var element = $compile(
|
||||
"<hz-dynamic-table" +
|
||||
" config='tableConfig'" +
|
||||
" items='items'" +
|
||||
" item-in-transition-function='itemInTransitionFunc'>" +
|
||||
"</hz-dynamic-table>")($scope);
|
||||
$scope.$digest();
|
||||
// 3 items in table, only one with ID that will return true from itemInTransitionFunc
|
||||
expect(element.find("tr.status_unknown").length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
@ -52,7 +52,8 @@
|
||||
classes rsp-p1 rsp-p2 are responsive priority as user resizes window.
|
||||
-->
|
||||
<tr ng-repeat-start="item in items track by item[config.trackId]"
|
||||
ng-class="{'st-selected': checked[item[config.trackId]]}">
|
||||
ng-class="{'st-selected': checked[item[config.trackId]],
|
||||
'status_unknown': itemInTransitionFunction(item)}">
|
||||
|
||||
<td ng-show="config.selectAll" class="multi_select_column">
|
||||
<div class="themable-checkbox">
|
||||
|
@ -40,6 +40,7 @@
|
||||
ctrl.batchActions = [];
|
||||
ctrl.items = [];
|
||||
ctrl.itemsSrc = [];
|
||||
ctrl.itemInTransitionFunction = itemInTransitionFunction;
|
||||
|
||||
// Watch for changes to search bar
|
||||
$scope.$on(events.SERVER_SEARCH_UPDATED, handleServerSearch);
|
||||
@ -187,6 +188,10 @@
|
||||
}).length === 0;
|
||||
}
|
||||
}
|
||||
|
||||
function itemInTransitionFunction(item) {
|
||||
return ctrl.resourceType.itemInTransitionFunction(item);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -31,7 +31,8 @@
|
||||
getTableColumns: angular.noop,
|
||||
list: angular.noop,
|
||||
globalActions: [],
|
||||
batchActions: []
|
||||
batchActions: [],
|
||||
itemInTransitionFunction: angular.noop
|
||||
};
|
||||
|
||||
beforeEach(inject(function($rootScope, $controller, $q) {
|
||||
@ -207,6 +208,14 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('item in transition function', function() {
|
||||
it('it calls resource type itemInTransitionFunction', function() {
|
||||
spyOn(resourceType, "itemInTransitionFunction");
|
||||
ctrl.itemInTransitionFunction();
|
||||
expect(resourceType.itemInTransitionFunction.calls.count()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -7,4 +7,5 @@
|
||||
batch-actions="ctrl.batchActions"
|
||||
filter-facets="ctrl.searchFacets"
|
||||
result-handler="ctrl.actionResultHandler"
|
||||
item-in-transition-function="ctrl.itemInTransitionFunction"
|
||||
></hz-dynamic-table>
|
||||
|
@ -87,8 +87,11 @@ $em-per-priority: floor($table-col-avg-width / $font-size-base) * 3;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:not(.st-sort-ascent):hover:after, &:not(.st-sort-descent):hover:after {
|
||||
opacity: 1;
|
||||
&:not(.st-sort-ascent),
|
||||
&:not(.st-sort-descent) {
|
||||
&:hover:after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,30 +152,52 @@ $em-per-priority: floor($table-col-avg-width / $font-size-base) * 3;
|
||||
&.table-striped {
|
||||
tbody {
|
||||
tr {
|
||||
&:nth-child(2n+1) > td, &:nth-child(2n+1) + .detail-row > td {
|
||||
background-color: $table-bg-accent;
|
||||
&:nth-child(2n+1) {
|
||||
|
||||
> td,
|
||||
+ .detail-row > td {
|
||||
background-color: $table-bg-accent;
|
||||
}
|
||||
|
||||
&.status_unknown td {
|
||||
background-color: lighten($brand-warning, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&,
|
||||
&.spacer-row > td, &.spacer-row:nth-child(6n+3) + tr + tr.detail-row td,
|
||||
&.detail-row:nth-child(4n+2) + tr:not(.spacer-row) td,
|
||||
&.detail-row:nth-child(4n+2) + tr:not(.spacer-row) + tr.detail-row td {
|
||||
&.spacer-row > td,
|
||||
&.spacer-row:nth-child(6n+3) + tr + tr.detail-row td {
|
||||
background-color: transparent;
|
||||
}
|
||||
&.detail-row:nth-child(4n+2) + tr:not(.spacer-row) {
|
||||
td,
|
||||
+ tr.detail-row td {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&.status_unknown td {
|
||||
background-color: lighten($brand-warning, 6%);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only all {
|
||||
.rsp-p1, .rsp-p2,
|
||||
.rsp-p3, .rsp-p4 {
|
||||
.rsp-p1,
|
||||
.rsp-p2,
|
||||
.rsp-p3,
|
||||
.rsp-p4 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
th,td {
|
||||
&.rsp-alt-p1, &.rsp-alt-p2,
|
||||
&.rsp-alt-p3, &.rsp-alt-p4 {
|
||||
&.rsp-alt-p1,
|
||||
&.rsp-alt-p2,
|
||||
&.rsp-alt-p3,
|
||||
&.rsp-alt-p4 {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user