summaryrefslogtreecommitdiff
path: root/horizon/static
diff options
context:
space:
mode:
authorwoodm1979 <woodm1979@gmail.com>2016-07-22 12:27:02 -0600
committerTyr Johanson <tyr@hp.com>2016-08-04 10:25:31 -0600
commit6ad296770a2401162e3aaf7daef3e64295c4aa39 (patch)
tree828bc279f9b872b960ecd7ee26350be050fcedbf /horizon/static
parent3864fd11a1864a850f9c2db5412647a17f44aa6a (diff)
downloadhorizon-6ad296770a2401162e3aaf7daef3e64295c4aa39.tar.gz
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
Diffstat (limited to 'horizon/static')
-rw-r--r--horizon/static/framework/conf/resource-type-registry.service.js36
-rw-r--r--horizon/static/framework/conf/resource-type-registry.service.spec.js12
-rw-r--r--horizon/static/framework/widgets/table/hz-cell.directive.js20
-rw-r--r--horizon/static/framework/widgets/table/hz-dynamic-table.directive.js6
-rw-r--r--horizon/static/framework/widgets/table/hz-dynamic-table.directive.spec.js82
-rw-r--r--horizon/static/framework/widgets/table/hz-dynamic-table.html3
-rw-r--r--horizon/static/framework/widgets/table/hz-resource-table.controller.js5
-rw-r--r--horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js11
-rw-r--r--horizon/static/framework/widgets/table/hz-resource-table.html1
-rw-r--r--horizon/static/framework/widgets/table/table.scss47
10 files changed, 207 insertions, 16 deletions
diff --git a/horizon/static/framework/conf/resource-type-registry.service.js b/horizon/static/framework/conf/resource-type-registry.service.js
index eafecacc6..00080fc61 100644
--- a/horizon/static/framework/conf/resource-type-registry.service.js
+++ b/horizon/static/framework/conf/resource-type-registry.service.js
@@ -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;
@@ -253,6 +255,40 @@
/**
* @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
* @description
* Provides the table columns for this type and generates a 'title'
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 5cb473621..b204bd4d6 100644
--- a/horizon/static/framework/conf/resource-type-registry.service.spec.js
+++ b/horizon/static/framework/conf/resource-type-registry.service.spec.js
@@ -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');
diff --git a/horizon/static/framework/widgets/table/hz-cell.directive.js b/horizon/static/framework/widgets/table/hz-cell.directive.js
index efd94d2c4..a4454dfe8 100644
--- a/horizon/static/framework/widgets/table/hz-cell.directive.js
+++ b/horizon/static/framework/widgets/table/hz-cell.directive.js
@@ -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);
}
diff --git a/horizon/static/framework/widgets/table/hz-dynamic-table.directive.js b/horizon/static/framework/widgets/table/hz-dynamic-table.directive.js
index 757d418a3..1846255c2 100644
--- a/horizon/static/framework/widgets/table/hz-dynamic-table.directive.js
+++ b/horizon/static/framework/widgets/table/hz-dynamic-table.directive.js
@@ -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'
diff --git a/horizon/static/framework/widgets/table/hz-dynamic-table.directive.spec.js b/horizon/static/framework/widgets/table/hz-dynamic-table.directive.spec.js
new file mode 100644
index 000000000..cbc278177
--- /dev/null
+++ b/horizon/static/framework/widgets/table/hz-dynamic-table.directive.spec.js
@@ -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);
+ });
+ });
+
+})();
diff --git a/horizon/static/framework/widgets/table/hz-dynamic-table.html b/horizon/static/framework/widgets/table/hz-dynamic-table.html
index a90b8a715..a6c8999e7 100644
--- a/horizon/static/framework/widgets/table/hz-dynamic-table.html
+++ b/horizon/static/framework/widgets/table/hz-dynamic-table.html
@@ -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">
diff --git a/horizon/static/framework/widgets/table/hz-resource-table.controller.js b/horizon/static/framework/widgets/table/hz-resource-table.controller.js
index 136466920..863eca9e2 100644
--- a/horizon/static/framework/widgets/table/hz-resource-table.controller.js
+++ b/horizon/static/framework/widgets/table/hz-resource-table.controller.js
@@ -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);
+ }
}
})();
diff --git a/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js b/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js
index 51da3b530..cfaff5db4 100644
--- a/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js
+++ b/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js
@@ -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);
+ });
+ });
+
});
})();
diff --git a/horizon/static/framework/widgets/table/hz-resource-table.html b/horizon/static/framework/widgets/table/hz-resource-table.html
index 2ca4e71e7..3ff5384b2 100644
--- a/horizon/static/framework/widgets/table/hz-resource-table.html
+++ b/horizon/static/framework/widgets/table/hz-resource-table.html
@@ -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>
diff --git a/horizon/static/framework/widgets/table/table.scss b/horizon/static/framework/widgets/table/table.scss
index 1af84e6a3..5539fdc22 100644
--- a/horizon/static/framework/widgets/table/table.scss
+++ b/horizon/static/framework/widgets/table/table.scss
@@ -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;
}
}