table_view.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var filters = require('views/common/filter_view');
  20. var sort = require('views/common/sort_view');
  21. App.TableView = Em.View.extend({
  22. /**
  23. * Shows if all data is loaded and filtered
  24. */
  25. filteringComplete: false,
  26. /**
  27. * Loaded from local storage startIndex value
  28. */
  29. startIndexOnLoad: null,
  30. /**
  31. * Loaded from server persist value
  32. */
  33. displayLengthOnLoad: null,
  34. /**
  35. * Do filtering, using saved in the local storage filter conditions
  36. */
  37. willInsertElement:function () {
  38. var self = this;
  39. var name = this.get('controller.name');
  40. this.set('startIndexOnLoad', App.db.getStartIndex(name));
  41. if (App.db.getDisplayLength(name)) {
  42. this.set('displayLength', App.db.getDisplayLength(name));
  43. } else {
  44. self.dataLoading().done(function (initValue) {
  45. self.set('displayLength', initValue);
  46. });
  47. }
  48. var filterConditions = App.db.getFilterConditions(name);
  49. if (filterConditions) {
  50. this.set('filterConditions', filterConditions);
  51. var childViews = this.get('childViews');
  52. filterConditions.forEach(function(condition) {
  53. var view = childViews.findProperty('column', condition.iColumn);
  54. if (view) {
  55. view.set('value', condition.value);
  56. Em.run.next(function() {
  57. view.showClearFilter();
  58. });
  59. }
  60. });
  61. } else {
  62. this.clearFilters();
  63. }
  64. Em.run.next(function() {
  65. Em.run.next(function() {
  66. self.set('filteringComplete', true);
  67. });
  68. });
  69. },
  70. /**
  71. * Load user preference value on hosts page from server
  72. */
  73. dataLoading: function () {
  74. var dfd = $.Deferred();
  75. var self = this;
  76. this.getUserPref(this.displayLengthKey()).done(function () {
  77. var curLength = self.get('displayLengthOnLoad');
  78. self.set('displayLengthOnLoad', null);
  79. dfd.resolve(curLength);
  80. });
  81. return dfd.promise();
  82. },
  83. displayLengthKey: function (loginName) {
  84. if (!loginName)
  85. loginName = App.router.get('loginName');
  86. return 'hosts-pagination-displayLength-' + loginName;
  87. },
  88. /**
  89. * get display length persist value from server with displayLengthKey
  90. */
  91. getUserPref: function(key){
  92. return App.ajax.send({
  93. name: 'settings.get.user_pref',
  94. sender: this,
  95. data: {
  96. key: key
  97. },
  98. success: 'getDisplayLengthSuccessCallback',
  99. error: 'getDisplayLengthErrorCallback'
  100. });
  101. },
  102. getDisplayLengthSuccessCallback: function (response, request, data) {
  103. if (response != null) {
  104. console.log('Got DisplayLength value from server with key ' + data.key + '. Value is: ' + response);
  105. this.set('displayLengthOnLoad', response);
  106. return response;
  107. }
  108. },
  109. getDisplayLengthErrorCallback: function (request, ajaxOptions, error) {
  110. // this user is first time login
  111. if (request.status == 404) {
  112. console.log('Persist did NOT find the key');
  113. var displayLengthDefault = 10;
  114. this.set('displayLengthOnLoad', displayLengthDefault);
  115. this.postUserPref(this.displayLengthKey(), displayLengthDefault);
  116. return displayLengthDefault;
  117. }
  118. },
  119. /**
  120. * post display length persist key/value to server, value is object
  121. */
  122. postUserPref: function (key, value) {
  123. var keyValuePair = {};
  124. keyValuePair[key] = JSON.stringify(value);
  125. App.ajax.send({
  126. 'name': 'settings.post.user_pref',
  127. 'sender': this,
  128. 'beforeSend': 'postUserPrefBeforeSend',
  129. 'data': {
  130. 'keyValuePair': keyValuePair
  131. }
  132. });
  133. },
  134. postUserPrefBeforeSend: function(request, ajaxOptions, data){
  135. console.log('BeforeSend to persist: persistKeyValues', data.keyValuePair);
  136. },
  137. /**
  138. * Do pagination after filtering and sorting
  139. * Don't call this method! It's already used where it's need
  140. */
  141. showProperPage: function() {
  142. var self = this;
  143. Em.run.next(function() {
  144. Em.run.next(function() {
  145. if(self.get('startIndexOnLoad')) {
  146. self.set('startIndex', self.get('startIndexOnLoad'));
  147. }
  148. });
  149. });
  150. },
  151. /**
  152. * return filtered number of all content number information displayed on the page footer bar
  153. */
  154. filteredHostsInfo: function () {
  155. return this.t('apps.filters.filteredHostsInfo').format(this.get('filteredContent.length'), this.get('content').get('length'));
  156. }.property('content.length', 'filteredContent.length'),
  157. /**
  158. * return pagination information displayed on the page
  159. */
  160. paginationInfo: function () {
  161. return this.t('apps.filters.paginationInfo').format(this.get('startIndex'), this.get('endIndex'), this.get('filteredContent.length'));
  162. }.property('displayLength', 'filteredContent.length', 'startIndex', 'endIndex'),
  163. paginationLeft: Ember.View.extend({
  164. tagName: 'a',
  165. template: Ember.Handlebars.compile('<i class="icon-arrow-left"></i>'),
  166. classNameBindings: ['class'],
  167. class: function () {
  168. if (this.get("parentView.startIndex") > 1) {
  169. return "paginate_previous";
  170. }
  171. return "paginate_disabled_previous";
  172. }.property("parentView.startIndex", 'filteredContent.length'),
  173. click: function () {
  174. this.get('parentView').previousPage();
  175. }
  176. }),
  177. paginationRight: Ember.View.extend({
  178. tagName: 'a',
  179. template: Ember.Handlebars.compile('<i class="icon-arrow-right"></i>'),
  180. classNameBindings: ['class'],
  181. class: function () {
  182. if ((this.get("parentView.endIndex")) < this.get("parentView.filteredContent.length")) {
  183. return "paginate_next";
  184. }
  185. return "paginate_disabled_next";
  186. }.property("parentView.endIndex", 'filteredContent.length'),
  187. click: function () {
  188. this.get('parentView').nextPage();
  189. }
  190. }),
  191. rowsPerPageSelectView: Em.Select.extend({
  192. content: ['10', '25', '50'],
  193. change: function () {
  194. this.get('parentView').saveDisplayLength();
  195. }
  196. }),
  197. // start index for displayed content on the page
  198. startIndex: 1,
  199. // calculate end index for displayed content on the page
  200. endIndex: function () {
  201. return Math.min(this.get('filteredContent.length'), this.get('startIndex') + parseInt(this.get('displayLength')) - 1);
  202. }.property('startIndex', 'displayLength', 'filteredContent.length'),
  203. /**
  204. * onclick handler for previous page button on the page
  205. */
  206. previousPage: function () {
  207. var result = this.get('startIndex') - parseInt(this.get('displayLength'));
  208. if (result < 2) {
  209. result = 1;
  210. }
  211. this.set('startIndex', result);
  212. },
  213. /**
  214. * onclick handler for next page button on the page
  215. */
  216. nextPage: function () {
  217. var result = this.get('startIndex') + parseInt(this.get('displayLength'));
  218. if (result - 1 < this.get('filteredContent.length')) {
  219. this.set('startIndex', result);
  220. }
  221. },
  222. // the number of rows to show on every page
  223. displayLength: null,
  224. // calculates default value for startIndex property after applying filter or changing displayLength
  225. updatePaging: function () {
  226. this.set('startIndex', Math.min(1, this.get('filteredContent.length')));
  227. }.observes('displayLength', 'filteredContent.length'),
  228. /**
  229. * Apply each filter to each row
  230. *
  231. * @param iColumn number of column by which filter
  232. * @param value
  233. * @param type
  234. */
  235. updateFilter: function (iColumn, value, type) {
  236. var filterCondition = this.get('filterConditions').findProperty('iColumn', iColumn);
  237. if (filterCondition) {
  238. filterCondition.value = value;
  239. }
  240. else {
  241. filterCondition = {
  242. iColumn: iColumn,
  243. value: value,
  244. type: type
  245. };
  246. this.get('filterConditions').push(filterCondition);
  247. }
  248. this.saveFilterConditions();
  249. this.filtersUsedCalc();
  250. this.filter();
  251. },
  252. saveFilterConditions: function() {
  253. App.db.setFilterConditions(this.get('controller.name'), this.get('filterConditions'));
  254. },
  255. saveDisplayLength: function() {
  256. var self = this;
  257. Em.run.next(function() {
  258. App.db.setDisplayLength(self.get('controller.name'), self.get('displayLength'));
  259. if (!App.testMode) {
  260. self.postUserPref(self.displayLengthKey(), self.get('displayLength'));
  261. }
  262. });
  263. },
  264. saveStartIndex: function() {
  265. if (this.get('filteringComplete')) {
  266. App.db.setStartIndex(this.get('controller.name'), this.get('startIndex'));
  267. }
  268. }.observes('startIndex'),
  269. clearFilterCondition: function() {
  270. App.db.setFilterConditions(this.get('controller.name'), null);
  271. },
  272. clearStartIndex: function() {
  273. App.db.setStartIndex(this.get('controller.name'), null);
  274. },
  275. /**
  276. * contain filter conditions for each column
  277. */
  278. filterConditions: [],
  279. filteredContent: [],
  280. // contain content to show on the current page of data page view
  281. pageContent: function () {
  282. return this.get('filteredContent').slice(this.get('startIndex') - 1, this.get('endIndex'));
  283. }.property('filteredContent.length', 'startIndex', 'endIndex'),
  284. /**
  285. * filter table by filterConditions
  286. */
  287. filter: function () {
  288. var content = this.get('content');
  289. var filterConditions = this.get('filterConditions').filterProperty('value');
  290. var result;
  291. var assoc = this.get('colPropAssoc');
  292. if (filterConditions.length) {
  293. result = content.filter(function (item) {
  294. var match = true;
  295. filterConditions.forEach(function (condition) {
  296. var filterFunc = filters.getFilterByType(condition.type, false);
  297. if (match) {
  298. match = filterFunc(item.get(assoc[condition.iColumn]), condition.value);
  299. }
  300. });
  301. return match;
  302. });
  303. this.set('filteredContent', result);
  304. } else {
  305. this.set('filteredContent', content.toArray());
  306. }
  307. }.observes('content'),
  308. filtersUsed: false,
  309. filtersUsedCalc: function() {
  310. var filterConditions = this.get('filterConditions');
  311. if (!filterConditions.length) {
  312. this.set('filtersUsed', false);
  313. return;
  314. }
  315. var filtersUsed = false;
  316. filterConditions.forEach(function(filterCondition) {
  317. if (filterCondition.value.toString() !== '') {
  318. filtersUsed = true;
  319. }
  320. });
  321. this.set('filtersUsed', filtersUsed);
  322. },
  323. clearFilters: function() {
  324. this.set('filterConditions', []);
  325. this.get('_childViews').forEach(function(childView) {
  326. if (childView['clearFilter']) {
  327. childView.clearFilter();
  328. }
  329. });
  330. }
  331. });