blob: 24aa0c91b93e967fbd2dda153c750a17439558a1 [file] [log] [blame]
Yoshie Muranakafa562732019-07-17 11:23:15 -05001window.angular && (function(angular) {
2 'use strict';
3
4 /**
5 *
Yoshie Muranakabb688792019-08-12 09:31:52 -05006 * bmcTable Component
Yoshie Muranakafa562732019-07-17 11:23:15 -05007 *
8 * To use:
Yoshie Muranakafa562732019-07-17 11:23:15 -05009 *
Yoshie Muranakab1f64242019-09-04 11:40:51 -070010 * 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'
Yoshie Muranakafa562732019-07-17 11:23:15 -050013 * property that should be an array of the properties that will render
14 * as each table cell <td>.
Yoshie Muranakab1f64242019-09-04 11:40:51 -070015 * Each row object in the data array can optionally have an
Yoshie Muranakabb688792019-08-12 09:31:52 -050016 * 'actions' property that should be an array of actions to provide the
17 * <bmc-table-actions> component.
Yoshie Muranakafa562732019-07-17 11:23:15 -050018 *
Yoshie Muranakab1f64242019-09-04 11:40:51 -070019 * 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.
Yoshie Muranakafa562732019-07-17 11:23:15 -050046 *
47 */
Yoshie Muranakabb688792019-08-12 09:31:52 -050048
Yoshie Muranakafa562732019-07-17 11:23:15 -050049 const TableController = function() {
Yoshie Muranakab1f64242019-09-04 11:40:51 -070050 this.sortAscending = true;
51 this.activeSort;
52
Yoshie Muranakafa562732019-07-17 11:23:15 -050053 /**
Yoshie Muranakab1f64242019-09-04 11:40:51 -070054 * Sorts table data
Yoshie Muranakafa562732019-07-17 11:23:15 -050055 */
Yoshie Muranakab1f64242019-09-04 11:40:51 -070056 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;
Yoshie Muranakafa562732019-07-17 11:23:15 -050067 }
Yoshie Muranakafa562732019-07-17 11:23:15 -050068 })
Yoshie Muranakafa562732019-07-17 11:23:15 -050069 };
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 */
Yoshie Muranakabb688792019-08-12 09:31:52 -050078 this.onEmitTableAction = (action, row) => {
Yoshie Muranakafa562732019-07-17 11:23:15 -050079 if (action !== undefined && row !== undefined) {
80 const value = {action, row};
81 this.emitAction({value});
82 }
83 };
84
85 /**
Yoshie Muranakab1f64242019-09-04 11:40:51 -070086 * 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
Yoshie Muranakafa562732019-07-17 11:23:15 -0500105 */
106 this.$onInit = () => {
Yoshie Muranakab1f64242019-09-04 11:40:51 -0700107 this.header = this.header === undefined ? [] : this.header;
108 this.data = this.data == undefined ? [] : this.data;
109 this.sortable = this.sortable === undefined ? false : this.sortable;
Yoshie Muranakabb688792019-08-12 09:31:52 -0500110 this.rowActionsEnabled =
Yoshie Muranakab1f64242019-09-04 11:40:51 -0700111 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 }
Yoshie Muranakabb688792019-08-12 09:31:52 -0500130 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
Yoshie Muranakab1f64242019-09-04 11:40:51 -0700134 this.header.push({label: '', sortable: false});
Yoshie Muranakabb688792019-08-12 09:31:52 -0500135 }
Yoshie Muranakafa562732019-07-17 11:23:15 -0500136 };
Yoshie Muranakab1f64242019-09-04 11:40:51 -0700137
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 }
Yoshie Muranakafa562732019-07-17 11:23:15 -0500153 };
154
155 /**
156 * Register bmcTable component
157 */
158 angular.module('app.common.components').component('bmcTable', {
159 template: require('./table.html'),
160 controller: TableController,
Yoshie Muranakab1f64242019-09-04 11:40:51 -0700161 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 }
Yoshie Muranakafa562732019-07-17 11:23:15 -0500170 })
171})(window.angular);