1window.angular && (function(angular) { 2 'use strict'; 3 4 /** 5 * 6 * bmcTable Component 7 * 8 * To use: 9 * 10 * The 'data' attribute should be an array of all row objects in the table. 11 * It will render each item as a <tr> in the table. 12 * Each row object in the data array should also have a 'uiData' 13 * property that should be an array of the properties that will render 14 * as each table cell <td>. 15 * Each row object in the data array can optionally have an 16 * 'actions' property that should be an array of actions to provide the 17 * <bmc-table-actions> component. 18 * 19 * data = [ 20 * { uiData: ['root', 'Admin', 'enabled' ] }, 21 * { uiData: ['user1', 'User', 'disabled' ] } 22 * ] 23 * 24 * The 'header' attribute should be an array of all header objects in the 25 * table. Each object in the header array should have a 'label' property 26 * that will render as a <th> in the table. 27 * If the table is sortable, can optionally add 'sortable' property to header 28 * row object. If a particular column is not sortable, set to false. 29 * 30 * header = [ 31 * { label: 'Username' }, 32 * { label: 'Privilege' } 33 * { label: 'Account Status', sortable: false } 34 * ] 35 * 36 * The 'sortable' attribute should be a boolean value. Defaults to false. 37 * The 'default-sort' attribute should be the index value of the header 38 * obejct that should be sorted on inital load. 39 * 40 * The 'row-actions-enabled' attribute, should be a boolean value 41 * Can be set to true to render table row actions. Defaults to false. 42 * Row actions are defined in data.actions. 43 * 44 * The 'size' attribute which can be set to 'small' which will 45 * render a smaller font size in the table. 46 * 47 */ 48 49 const TableController = function() { 50 this.sortAscending = true; 51 this.activeSort; 52 53 /** 54 * Sorts table data 55 */ 56 const sortData = () => { 57 this.data.sort((a, b) => { 58 const aProp = a.uiData[this.activeSort]; 59 const bProp = b.uiData[this.activeSort]; 60 if (aProp === bProp) { 61 return 0; 62 } else { 63 if (this.sortAscending) { 64 return aProp < bProp ? -1 : 1; 65 } 66 return aProp > bProp ? -1 : 1; 67 } 68 }) 69 }; 70 71 /** 72 * Callback when table row action clicked 73 * Emits user desired action and associated row data to 74 * parent controller 75 * @param {string} action : action type 76 * @param {any} row : user object 77 */ 78 this.onEmitTableAction = (action, row) => { 79 if (action !== undefined && row !== undefined) { 80 const value = {action, row}; 81 this.emitAction({value}); 82 } 83 }; 84 85 /** 86 * Callback when sortable table header clicked 87 * @param {number} index : index of header item 88 */ 89 this.onClickSort = (index) => { 90 if (index === this.activeSort) { 91 // If clicked header is already sorted, reverse 92 // the sort direction 93 this.sortAscending = !this.sortAscending; 94 this.data.reverse(); 95 } else { 96 this.sortAscending = true; 97 this.activeSort = index; 98 sortData(); 99 } 100 }; 101 102 /** 103 * onInit Component lifecycle hook 104 * Checking for undefined values 105 */ 106 this.$onInit = () => { 107 this.header = this.header === undefined ? [] : this.header; 108 this.data = this.data == undefined ? [] : this.data; 109 this.sortable = this.sortable === undefined ? false : this.sortable; 110 this.rowActionsEnabled = 111 this.rowActionsEnabled === undefined ? false : this.rowActionsEnabled; 112 this.size = this.size === undefined ? '' : this.size; 113 114 // Check for undefined 'uiData' property for each item in data array 115 this.data = this.data.map((row) => { 116 if (row.uiData === undefined) { 117 row.uiData = []; 118 } 119 return row; 120 }) 121 if (this.sortable) { 122 // If sort is enabled, check for undefined 'sortable' 123 // property for each item in header array 124 this.header = this.header.map((column) => { 125 column.sortable = 126 column.sortable === undefined ? true : column.sortable; 127 return column; 128 }) 129 } 130 if (this.rowActionsEnabled) { 131 // If table actions are enabled push an empty 132 // string to the header array to account for additional 133 // table actions cell 134 this.header.push({label: '', sortable: false}); 135 } 136 }; 137 138 /** 139 * onChanges Component lifecycle hook 140 * Check for changes in the data array and apply 141 * default or active sort if one is defined 142 */ 143 this.$onChanges = (onChangesObj) => { 144 const dataChange = onChangesObj.data; 145 if (dataChange) { 146 if (this.activeSort !== undefined || this.defaultSort !== undefined) { 147 this.activeSort = this.defaultSort !== undefined ? this.defaultSort : 148 this.activeSort; 149 sortData(); 150 } 151 } 152 } 153 }; 154 155 /** 156 * Register bmcTable component 157 */ 158 angular.module('app.common.components').component('bmcTable', { 159 template: require('./table.html'), 160 controller: TableController, 161 bindings: { 162 data: '<', // Array 163 header: '<', // Array 164 rowActionsEnabled: '<', // boolean 165 size: '<', // string 166 sortable: '<', // boolean 167 defaultSort: '<', // number (index of sort) 168 emitAction: '&' 169 } 170 }) 171})(window.angular); 172