statistics.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. class Statistics {
  2. static Modes = {
  3. ALL: 'all',
  4. USER: 'user',
  5. CLASS: 'class'
  6. };
  7. static Response = {
  8. COUNT: 'count',
  9. RECORDS: 'records'
  10. };
  11. static RowFields = {
  12. USER: 'user',
  13. CLASS: 'class',
  14. PROPERTY: 'property',
  15. ACTION: 'action',
  16. TIMESTAMP: 'timestamp',
  17. CREATED: 'created',
  18. UPDATED: 'updated',
  19. REMOVED: 'removed',
  20. TOTAL: 'total'
  21. };
  22. static TableHeaders = {
  23. USER: 'User',
  24. CLASS: 'Class',
  25. PROPERTY: 'Property',
  26. ACTION: 'Action',
  27. TIME: 'Time',
  28. CREATED: 'Created',
  29. UPDATED: 'Updated',
  30. REMOVED: 'Removed',
  31. TOTAL: 'Total'
  32. };
  33. static DefaultPage = 1;
  34. static DefaultPageSize = 50;
  35. static init(container, mode, page, pageSize) {
  36. return new Statistics(container, mode, page, pageSize).load();
  37. }
  38. constructor(container, mode, page, pageSize) {
  39. this.mode = mode || Statistics.Modes.ALL;
  40. this.page = page || Statistics.DefaultPage;
  41. this.pageSize = pageSize || Statistics.DefaultPageSize;
  42. this.container = DOM.create({ tag: DOM.Tags.Div, cls: 'statistics-module' }, container);
  43. this.statistics = [];
  44. this.pagers = [];
  45. this.pagerPages = [];
  46. this.pagerPageSizeSelectors = [];
  47. }
  48. renderStatistics() {
  49. if(this.statisticsTable)
  50. this.statisticsTable.remove();
  51. const table = this.statisticsTable = DOM.create({ tag: DOM.Tags.Table, cls: 'statistics-table' });
  52. const headers = this.statisticsTableHeaders = DOM.create({ tag: DOM.Tags.Tr }, table);
  53. const tbody = this.statisticsTableTbody = DOM.create({ tag: DOM.Tags.Tbody }, table);
  54. if(!this.isAllMode()) {
  55. if(this.isUserMode())
  56. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.CLASS }, headers);
  57. else
  58. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.USER }, headers);
  59. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.PROPERTY }, headers);
  60. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.ACTION }, headers);
  61. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.TIME }, headers);
  62. for(const statRow of this.statistics) {
  63. const row = DOM.create({ tag: DOM.Tags.Tr }, tbody);
  64. if(this.isUserMode()) {
  65. const classLink = DOM.create({ tag: DOM.Tags.A, innerHTML: statRow[Statistics.RowFields.CLASS], attr: { 'href': `/class/${statRow[Statistics.RowFields.CLASS]}` } });
  66. DOM.create({ tag: DOM.Tags.Td, cn: [classLink] }, row);
  67. } else {
  68. const userLink = DOM.create({ tag: DOM.Tags.A, innerHTML: statRow[Statistics.RowFields.USER], attr: { 'href': `/statistics/${statRow[Statistics.RowFields.USER]}` } });
  69. DOM.create({ tag: DOM.Tags.Td, cn: [userLink] }, row);
  70. }
  71. DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.PROPERTY] }, row);
  72. DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.ACTION] }, row);
  73. DOM.create({ tag: DOM.Tags.Td, innerHTML: CDUtils.dateFormatUTC(parseInt(statRow[Statistics.RowFields.TIMESTAMP]), 3, 'D.M.Y, H:I:S') }, row);
  74. }
  75. } else {
  76. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.USER }, headers);
  77. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.CREATED }, headers);
  78. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.UPDATED }, headers);
  79. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.REMOVED }, headers);
  80. DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.TOTAL }, headers);
  81. for(const statRow of this.statistics) {
  82. const row = DOM.create({ tag: DOM.Tags.Tr }, tbody);
  83. const userLink = DOM.create({ tag: DOM.Tags.A, innerHTML: statRow[Statistics.RowFields.USER], attr: { 'href': `/statistics/${statRow[Statistics.RowFields.USER]}` } });
  84. DOM.create({ tag: DOM.Tags.Td, cn: [userLink] }, row);
  85. DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.CREATED] }, row);
  86. DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.UPDATED] }, row);
  87. DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.REMOVED] }, row);
  88. DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.TOTAL] }, row);
  89. }
  90. }
  91. this.container.append(this.statisticsTable);
  92. return this;
  93. }
  94. renderPager(pagerIndex) {
  95. if(this.pagers[pagerIndex]) {
  96. this.pagerPages[pagerIndex].forEach((page) => {
  97. page.un(DOM.Events.Click, this.onPageClick.bind(this));
  98. page.remove();
  99. });
  100. const selector = this.pagerPageSizeSelectors[pagerIndex];
  101. selector.un(DOM.Events.Change, this.onPageSizeSelectChange.bind(this));
  102. selector.remove();
  103. this.pagers[pagerIndex].remove();
  104. }
  105. const page = this.page;
  106. const pageCount = this.pageCount;
  107. const pager = this.pagers[pagerIndex] = DOM.create({ tag: DOM.Tags.Div, cls: 'statistics-pager' });
  108. const pagerPages = this.pagerPages[pagerIndex] = [];
  109. pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: 'Page:', cls: 'pager-page-label' }));
  110. const startPage = Math.max(1, page - 2);
  111. const endPage = Math.min(pageCount > 0 ? pageCount : 1, page + 2);
  112. if(startPage > 1) {
  113. const firstPage = DOM.create({ tag: DOM.Tags.Span, innerHTML: 1, cls: 'pager-page' }).on(DOM.Events.Click, this.onPageClick.bind(this));
  114. pagerPages.push(firstPage);
  115. pager.append(firstPage);
  116. pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: '..' }));
  117. }
  118. for (let i = startPage; i <= endPage; i++) {
  119. const pageElement = DOM.create({ tag: DOM.Tags.Span, innerHTML: i, cls: 'pager-page' });
  120. if(page === i) {
  121. pageElement.addClass('current');
  122. } else {
  123. pageElement.on(DOM.Events.Click, this.onPageClick.bind(this));
  124. pagerPages.push(pageElement);
  125. }
  126. pager.append(pageElement);
  127. }
  128. if(endPage < pageCount) {
  129. pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: '..' }));
  130. const lastPage = DOM.create({ tag: DOM.Tags.Span, innerHTML: pageCount, cls: 'pager-page' }).on(DOM.Events.Click, this.onPageClick.bind(this));
  131. pager.append(lastPage);
  132. pagerPages.push(lastPage);
  133. }
  134. const pageSizeSelector = DOM.create({ tag: DOM.Tags.Select, cls: 'pager-page-size-selector', cn: [
  135. DOM.create({ tag: DOM.Tags.Option, innerHTML: '1', attr: { 'selected': (this.pageSize === 1 ? 'selected' : undefined) } }),
  136. DOM.create({ tag: DOM.Tags.Option, innerHTML: '5', attr: { 'selected': (this.pageSize === 5 ? 'selected' : undefined) } }),
  137. DOM.create({ tag: DOM.Tags.Option, innerHTML: '25', attr: { 'selected': (this.pageSize === 25 ? 'selected' : undefined) } }),
  138. DOM.create({ tag: DOM.Tags.Option, innerHTML: '50', attr: { 'selected': (this.pageSize === 50 ? 'selected' : undefined) } }),
  139. DOM.create({ tag: DOM.Tags.Option, innerHTML: '100', attr: { 'selected': (this.pageSize === 100 ? 'selected' : undefined) } }),
  140. DOM.create({ tag: DOM.Tags.Option, innerHTML: '500', attr: { 'selected': (this.pageSize === 500 ? 'selected' : undefined) } })
  141. ]});
  142. pageSizeSelector.on(DOM.Events.Change, this.onPageSizeSelectChange.bind(this));
  143. pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: '|' }));
  144. pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: 'Page size:', cls: 'pager-page-size-label' }));
  145. pager.append(pageSizeSelector);
  146. this.pagerPageSizeSelectors[pagerIndex] = pageSizeSelector;
  147. this.container.append(pager);
  148. }
  149. onPageSizeSelectChange(e) {
  150. this.page = Statistics.DefaultPage;
  151. this.pageSize = parseInt(CDElement.get(e.target).getValue());
  152. this.load();
  153. }
  154. onPageClick(e) {
  155. this.page = parseInt(CDElement.get(e.target).getValue());
  156. this.load();
  157. }
  158. isAllMode() {
  159. return this.mode === Statistics.Modes.ALL;
  160. }
  161. isUserMode() {
  162. return this.mode === Statistics.Modes.USER;
  163. }
  164. isClassMode() {
  165. return this.mode === Statistics.Modes.CLASS;
  166. }
  167. load() {
  168. let url = '/data/statistics';
  169. if(this.isUserMode())
  170. url = `/data/statistics/user/${StatisticsUser}`;
  171. if(this.isClassMode())
  172. url = `/data/statistics/class/${Class.name}`;
  173. fetch(`${url}?page=${this.page}&pageSize=${this.pageSize}`, {
  174. method: 'GET'
  175. }).then(res => res.json()).then(res => {
  176. this.statistics = res[Statistics.Response.RECORDS];
  177. this.pageCount = Math.ceil(res[Statistics.Response.COUNT] / this.pageSize);
  178. this.renderPager(0); // top
  179. this.renderStatistics();
  180. this.renderPager(1); // bottom
  181. });
  182. return this;
  183. }
  184. }