CLOUDSTACK-9020: Implement collapsible columns and threshold colorings

Implements following in listView that generates tabular views;
- Collapsible columns in case of multi-header groupable columns
- Implements threshold coloring of cells in table
- Implements option to render a table that is scrollable in both x-y directions
- Support to only display status icon instead of label if compact is set to true
- Fixes quick-view alignment issue on Safari
- If a column was previously sorted, sorts after adding new rows
- If a supercolumn was collapsed, hides cell after adding new rows

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2015-11-05 12:39:42 +05:30
parent 106e9106c9
commit 0845edce1a

View File

@ -765,10 +765,12 @@
var createHeader = function(preFilter, fields, $table, actions, options) {
if (!options) options = {};
var $thead = $('<thead>').prependTo($table).append($('<tr>'));
var $tr = $('<tr>');
var $thead = $('<thead>').prependTo($table).append($tr);
var reorder = options.reorder;
var detailView = options.detailView;
var multiSelect = options.multiSelect;
var groupableColumns = options.groupableColumns;
var viewArgs = $table.closest('.list-view').data('view-args');
var uiCustom = viewArgs.uiCustom;
var hiddenFields = [];
@ -776,8 +778,110 @@
if (preFilter != null)
hiddenFields = preFilter();
var addColumnToTr = function($tr, key, colspan, label, needsCollapsibleColumn) {
var trText = _l(label);
var $th = $('<th>').addClass(key).attr('colspan', colspan).appendTo($tr);
if ($th.index()) $th.addClass('reduced-hide');
$th.css({'border-right': '1px solid #C6C3C3', 'border-left': '1px solid #C6C3C3'});
if (needsCollapsibleColumn) {
var karetLeft = $('<span>').css({'margin-right': '10px'});
karetLeft.attr('title', trText);
karetLeft.appendTo($th);
$('<span>').html('&laquo').css({'font-size': '15px', 'float': 'right'}).appendTo(karetLeft);
$('<span>').html(trText).appendTo(karetLeft);
$th.click(function(event) {
event.stopPropagation();
var $th = $(this);
var startIndex = 0;
$th.prevAll('th').each(function() {
startIndex += parseInt($(this).attr('colspan'));
});
var endIndex = startIndex + parseInt($th.attr('colspan'));
// Hide Column group
$th.hide();
$th.closest('table').find('tbody td').filter(function() {
return $(this).index() >= startIndex && $(this).index() < endIndex;
}).hide();
$th.closest('table').find('thead tr:last th').filter(function() {
return $(this).index() >= startIndex && $(this).index() < endIndex;
}).hide();
// Show collapsible column with blank cells
$th.next('th').show();
$th.closest('table').find('tbody td').filter(function() {
return $(this).index() == endIndex;
}).show();
$th.closest('table').find('thead tr:last th').filter(function() {
return $(this).index() == endIndex;
}).show();
// Refresh list view
$tr.closest('.list-view').find('.no-split').dataTable('refresh');
});
var karetRight = addColumnToTr($tr, 'collapsible-column', 1, '');
$('<span>').html(trText.substring(0,3)).appendTo(karetRight);
$('<span>').css({'font-size': '15px'}).html(' &raquo').appendTo(karetRight);
karetRight.attr('title', trText);
karetRight.css({'border-right': '1px solid #C6C3C3', 'border-left': '1px solid #C6C3C3', 'min-width': '10px', 'width': '10px', 'max-width': '45px', 'padding': '2px'});
karetRight.hide();
karetRight.click(function(event) {
event.stopPropagation();
var prevTh = $(this).prev('th');
var startIndex = 0;
prevTh.prevAll('th').each(function() {
startIndex += parseInt($(this).attr('colspan'));
});
var endIndex = startIndex + parseInt(prevTh.attr('colspan'));
prevTh.show();
prevTh.closest('table').find('tbody td').filter(function() {
return $(this).index() >= startIndex && $(this).index() < endIndex;
}).show();
prevTh.closest('table').find('thead tr:last th').filter(function() {
return $(this).index() >= startIndex && $(this).index() < endIndex;
}).show();
prevTh.next('th').hide();
prevTh.closest('table').find('tbody td').filter(function() {
return $(this).index() == endIndex;
}).hide();
prevTh.closest('table').find('thead tr:last th').filter(function() {
return $(this).index() == endIndex;
}).hide();
$tr.closest('.list-view').find('.no-split').dataTable('refresh');
});
} else {
$th.html(trText);
}
return $th;
};
if (groupableColumns) {
$tr.addClass('groupable-header-columns').addClass('groupable-header');
$.each(fields, function(key) {
var field = this;
if (field.columns) {
var colspan = Object.keys(field.columns).length;
addColumnToTr($tr, key, colspan, field.label, true);
} else {
var label = '';
if (key == 'name') {
label = 'label.resources';
}
addColumnToTr($tr, key, 1, label);
}
return true;
});
if (detailView && !$.isFunction(detailView) && !detailView.noCompact && !uiCustom) {
addColumnToTr($tr, 'quick-view', 1, '');
}
$tr = $('<tr>').appendTo($thead);
$tr.addClass('groupable-header');
}
if (multiSelect) {
var $th = $('<th>').addClass('multiselect').appendTo($thead.find('tr'));
var $th = $('<th>').addClass('multiselect').appendTo($tr);
var content = $('<input>')
.attr('type', 'checkbox')
.addClass('multiSelectMasterCheckbox')
@ -794,18 +898,24 @@
if ($.inArray(key, hiddenFields) != -1)
return true;
var field = this;
var $th = $('<th>').addClass(key).appendTo($thead.find('tr'));
if ($th.index()) $th.addClass('reduced-hide');
$th.html(_l(field.label));
if (field.columns) {
$.each(field.columns, function(idx) {
var subfield = this;
addColumnToTr($tr, key, 1, subfield.label);
return true;
});
var blankCell = addColumnToTr($tr, 'collapsible-column', 1, '');
blankCell.css({'min-width': '10px', 'width': '10px'});
blankCell.hide();
} else {
addColumnToTr($tr, key, 1, field.label);
}
return true;
});
// Re-order row buttons
if (reorder) {
$thead.find('tr').append(
$tr.append(
$('<th>').html(_l('label.order')).addClass('reorder-actions reduced-hide')
);
}
@ -826,7 +936,7 @@
);
if (actions && !options.noActionCol && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) {
$thead.find('tr').append(
$tr.append(
$('<th></th>')
.html(_l('label.actions'))
.addClass('actions reduced-hide')
@ -835,7 +945,7 @@
// Quick view
if (detailView && !$.isFunction(detailView) && !detailView.noCompact && !uiCustom) {
$thead.find('tr').append(
$tr.append(
$('<th></th>')
.html(_l('label.quickview'))
.addClass('quick-view reduced-hide')
@ -1033,6 +1143,7 @@
var listViewArgs = $listView.data('view-args');
var uiCustom = listViewArgs.uiCustom;
var subselect = uiCustom ? listViewArgs.listView.subselect : null;
var hasCollapsibleColumn = false;
if (!(data && data.length)) {
$listView.data('end-of-table', true);
@ -1088,8 +1199,25 @@
);
}
// Add field data
var reducedFields = {};
var idx = 0;
$.each(fields, function(key) {
var field = this;
if (field.columns) {
$.each(field.columns, function(innerKey) {
reducedFields[innerKey] = this;
});
reducedFields['blank-cell-' + idx] = {blankCell: true};
idx += 1;
hasCollapsibleColumn = true;
} else {
reducedFields[key] = this;
}
return true;
});
// Add field data
$.each(reducedFields, function(key) {
if ($.inArray(key, hiddenFields) != -1)
return true;
var field = this;
@ -1103,6 +1231,11 @@
$td.addClass('truncated');
}
if (field.blankCell) {
$td.css({'min-width': '10px', 'width': '10px'});
$td.hide();
}
if (field.indicator) {
$td.addClass('state').addClass(field.indicator[content]);
@ -1110,6 +1243,19 @@
//$tr.find('td:first').addClass('item-state-' + field.indicator[content]);
}
if (field.thresholdcolor && field.thresholds) {
if ((field.thresholds.disable in dataItem) && (field.thresholds.notification in dataItem)) {
var disableThreshold = parseFloat(dataItem[field.thresholds.disable]);
var notificationThreshold = parseFloat(dataItem[field.thresholds.notification]);
var value = parseFloat(content);
if (value >= disableThreshold) {
$td.addClass('alert-disable-threshold');
} else if (value >= notificationThreshold) {
$td.addClass('alert-notification-threshold');
}
}
}
if (field.id == true) id = field.id;
if ($td.index()) $td.addClass('reduced-hide');
if (field.action) {
@ -1140,9 +1286,12 @@
$('<pre>').html(_s(content))
);
} else {
$td.append(
$('<span>').html(_s(content))
);
var span = $('<span>').html(_s(content));
if (field.compact) {
span.addClass('compact');
span.html('');
}
$td.append(span);
}
}
@ -1380,8 +1529,8 @@
.appendTo($tr);
$quickView.mouseover(
// Show quick view
function() {
var $quickView = $(this);
var $quickViewTooltip = $('<div>').addClass('quick-view-tooltip hovered-elem');
var $tr = $quickView.closest('tr');
var $listView = $tr.closest('.list-view');
@ -1465,7 +1614,7 @@
});
$quickViewTooltip.css({
position: 'absolute',
left: $tr.offset().left + $tr.width() - $quickViewTooltip.width(),
left: $quickView.offset().left + $quickView.outerWidth() - $quickViewTooltip.width() - 2*(parseInt($quickView.css('border-left-width')) + parseInt($quickView.css('border-right-width'))),
top: $quickView.offset().top,
zIndex: $tr.closest('.panel').zIndex() + 1
});
@ -1480,6 +1629,14 @@
}
});
// Toggle collapsible column to fix alignment of hidden/shown cells
if (hasCollapsibleColumn) {
$tbody.closest('table').find('tr:first th.collapsible-column:visible').prev('th').click();
}
// Re-sort table if a column was previously sorted
$listView.find('thead tr:last th.sorted').click().click();
return rows;
};
@ -1798,8 +1955,19 @@
reorder: reorder,
detailView: listViewData.detailView,
'multiSelect': multiSelect,
noActionCol: listViewData.noActionCol
noActionCol: listViewData.noActionCol,
groupableColumns: listViewData.groupableColumns
});
if (listViewData.noSplit) {
$table.addClass('no-split');
}
if (listViewData.horizontalOverflow) {
$table.addClass('horizontal-overflow');
$table.parent().css({'overflow-x': 'auto'});
}
createFilters($toolbar, listViewData.filters);
if (listViewData.hideSearchBar != true) {