|
@@ -0,0 +1,226 @@
|
|
|
+class Statistics {
|
|
|
+ static Modes = {
|
|
|
+ ALL: 'all',
|
|
|
+ USER: 'user',
|
|
|
+ CLASS: 'class'
|
|
|
+ };
|
|
|
+
|
|
|
+ static Response = {
|
|
|
+ COUNT: 'count',
|
|
|
+ RECORDS: 'records'
|
|
|
+ };
|
|
|
+
|
|
|
+ static RowFields = {
|
|
|
+ USER: 'user',
|
|
|
+ CLASS: 'class',
|
|
|
+ PROPERTY: 'property',
|
|
|
+ ACTION: 'action',
|
|
|
+ TIMESTAMP: 'timestamp',
|
|
|
+ CREATED: 'created',
|
|
|
+ UPDATED: 'updated',
|
|
|
+ REMOVED: 'removed',
|
|
|
+ TOTAL: 'total'
|
|
|
+ };
|
|
|
+
|
|
|
+ static TableHeaders = {
|
|
|
+ USER: 'User',
|
|
|
+ CLASS: 'Class',
|
|
|
+ PROPERTY: 'Property',
|
|
|
+ ACTION: 'Action',
|
|
|
+ TIME: 'Time',
|
|
|
+ CREATED: 'Created',
|
|
|
+ UPDATED: 'Updated',
|
|
|
+ REMOVED: 'Removed',
|
|
|
+ TOTAL: 'Total'
|
|
|
+ };
|
|
|
+
|
|
|
+ static DefaultPage = 1;
|
|
|
+ static DefaultPageSize = 50;
|
|
|
+
|
|
|
+ static init(container, mode, page, pageSize) {
|
|
|
+ return new Statistics(container, mode, page, pageSize).load();
|
|
|
+ }
|
|
|
+
|
|
|
+ constructor(container, mode, page, pageSize) {
|
|
|
+ this.mode = mode || Statistics.Modes.ALL;
|
|
|
+ this.page = page || Statistics.DefaultPage;
|
|
|
+ this.pageSize = pageSize || Statistics.DefaultPageSize;
|
|
|
+ this.container = DOM.create({ tag: DOM.Tags.Div, cls: 'statistics-module' }, container);
|
|
|
+ this.statistics = [];
|
|
|
+ this.pagers = [];
|
|
|
+ this.pagerPages = [];
|
|
|
+ this.pagerPageSizeSelectors = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ renderStatistics() {
|
|
|
+ if(this.statisticsTable)
|
|
|
+ this.statisticsTable.remove();
|
|
|
+
|
|
|
+ const table = this.statisticsTable = DOM.create({ tag: DOM.Tags.Table, cls: 'statistics-table' });
|
|
|
+ const headers = this.statisticsTableHeaders = DOM.create({ tag: DOM.Tags.Tr }, table);
|
|
|
+ const tbody = this.statisticsTableTbody = DOM.create({ tag: DOM.Tags.Tbody }, table);
|
|
|
+
|
|
|
+ if(!this.isAllMode()) {
|
|
|
+ if(this.isUserMode())
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.CLASS }, headers);
|
|
|
+ else
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.USER }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.PROPERTY }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.ACTION }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.TIME }, headers);
|
|
|
+
|
|
|
+ for(const statRow of this.statistics) {
|
|
|
+ const row = DOM.create({ tag: DOM.Tags.Tr }, tbody);
|
|
|
+ if(this.isUserMode()) {
|
|
|
+ const classLink = DOM.create({ tag: DOM.Tags.A, innerHTML: statRow[Statistics.RowFields.CLASS], attr: { 'href': `/class/${statRow[Statistics.RowFields.CLASS]}` } });
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, cn: [classLink] }, row);
|
|
|
+ } else {
|
|
|
+ const userLink = DOM.create({ tag: DOM.Tags.A, innerHTML: statRow[Statistics.RowFields.USER], attr: { 'href': `/statistics/${statRow[Statistics.RowFields.USER]}` } });
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, cn: [userLink] }, row);
|
|
|
+ }
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.PROPERTY] }, row);
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.ACTION] }, row);
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: CDUtils.dateFormatUTC(parseInt(statRow[Statistics.RowFields.TIMESTAMP]), 3, 'D.M.Y, H:I:S') }, row);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.USER }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.CREATED }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.UPDATED }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.REMOVED }, headers);
|
|
|
+ DOM.create({ tag: DOM.Tags.Th, innerHTML: Statistics.TableHeaders.TOTAL }, headers);
|
|
|
+
|
|
|
+ for(const statRow of this.statistics) {
|
|
|
+ const row = DOM.create({ tag: DOM.Tags.Tr }, tbody);
|
|
|
+ const userLink = DOM.create({ tag: DOM.Tags.A, innerHTML: statRow[Statistics.RowFields.USER], attr: { 'href': `/statistics/${statRow[Statistics.RowFields.USER]}` } });
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, cn: [userLink] }, row);
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.CREATED] }, row);
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.UPDATED] }, row);
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.REMOVED] }, row);
|
|
|
+ DOM.create({ tag: DOM.Tags.Td, innerHTML: statRow[Statistics.RowFields.TOTAL] }, row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.container.append(this.statisticsTable);
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ renderPager(pagerIndex) {
|
|
|
+ if(this.pagers[pagerIndex]) {
|
|
|
+
|
|
|
+ this.pagerPages[pagerIndex].forEach((page) => {
|
|
|
+ page.un(DOM.Events.Click, this.onPageClick.bind(this));
|
|
|
+ page.remove();
|
|
|
+ });
|
|
|
+
|
|
|
+ const selector = this.pagerPageSizeSelectors[pagerIndex];
|
|
|
+ selector.un(DOM.Events.Change, this.onPageSizeSelectChange.bind(this));
|
|
|
+ selector.remove();
|
|
|
+
|
|
|
+ this.pagers[pagerIndex].remove();
|
|
|
+ }
|
|
|
+
|
|
|
+ const page = this.page;
|
|
|
+ const pageCount = this.pageCount;
|
|
|
+
|
|
|
+ const pager = this.pagers[pagerIndex] = DOM.create({ tag: DOM.Tags.Div, cls: 'statistics-pager' });
|
|
|
+
|
|
|
+ const pagerPages = this.pagerPages[pagerIndex] = [];
|
|
|
+
|
|
|
+ pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: 'Page:', cls: 'pager-page-label' }));
|
|
|
+
|
|
|
+ const startPage = Math.max(1, page - 2);
|
|
|
+ const endPage = Math.min(pageCount > 0 ? pageCount : 1, page + 2);
|
|
|
+
|
|
|
+ if(startPage > 1) {
|
|
|
+ const firstPage = DOM.create({ tag: DOM.Tags.Span, innerHTML: 1, cls: 'pager-page' }).on(DOM.Events.Click, this.onPageClick.bind(this));
|
|
|
+ pagerPages.push(firstPage);
|
|
|
+ pager.append(firstPage);
|
|
|
+ pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: '..' }));
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let i = startPage; i <= endPage; i++) {
|
|
|
+ const pageElement = DOM.create({ tag: DOM.Tags.Span, innerHTML: i, cls: 'pager-page' });
|
|
|
+
|
|
|
+ if(page === i) {
|
|
|
+ pageElement.addClass('current');
|
|
|
+ } else {
|
|
|
+ pageElement.on(DOM.Events.Click, this.onPageClick.bind(this));
|
|
|
+ pagerPages.push(pageElement);
|
|
|
+ }
|
|
|
+
|
|
|
+ pager.append(pageElement);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(endPage < pageCount) {
|
|
|
+ pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: '..' }));
|
|
|
+
|
|
|
+ const lastPage = DOM.create({ tag: DOM.Tags.Span, innerHTML: pageCount, cls: 'pager-page' }).on(DOM.Events.Click, this.onPageClick.bind(this));
|
|
|
+ pager.append(lastPage);
|
|
|
+ pagerPages.push(lastPage);
|
|
|
+ }
|
|
|
+
|
|
|
+ const pageSizeSelector = DOM.create({ tag: DOM.Tags.Select, cls: 'pager-page-size-selector', cn: [
|
|
|
+ DOM.create({ tag: DOM.Tags.Option, innerHTML: '1', attr: { 'selected': (this.pageSize === 1 ? 'selected' : undefined) } }),
|
|
|
+ DOM.create({ tag: DOM.Tags.Option, innerHTML: '5', attr: { 'selected': (this.pageSize === 5 ? 'selected' : undefined) } }),
|
|
|
+ DOM.create({ tag: DOM.Tags.Option, innerHTML: '25', attr: { 'selected': (this.pageSize === 25 ? 'selected' : undefined) } }),
|
|
|
+ DOM.create({ tag: DOM.Tags.Option, innerHTML: '50', attr: { 'selected': (this.pageSize === 50 ? 'selected' : undefined) } }),
|
|
|
+ DOM.create({ tag: DOM.Tags.Option, innerHTML: '100', attr: { 'selected': (this.pageSize === 100 ? 'selected' : undefined) } }),
|
|
|
+ DOM.create({ tag: DOM.Tags.Option, innerHTML: '500', attr: { 'selected': (this.pageSize === 500 ? 'selected' : undefined) } })
|
|
|
+ ]});
|
|
|
+
|
|
|
+ pageSizeSelector.on(DOM.Events.Change, this.onPageSizeSelectChange.bind(this));
|
|
|
+
|
|
|
+ pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: '|' }));
|
|
|
+ pager.append(DOM.create({ tag: DOM.Tags.Span, innerHTML: 'Page size:', cls: 'pager-page-size-label' }));
|
|
|
+
|
|
|
+ pager.append(pageSizeSelector);
|
|
|
+
|
|
|
+ this.pagerPageSizeSelectors[pagerIndex] = pageSizeSelector;
|
|
|
+
|
|
|
+ this.container.append(pager);
|
|
|
+ }
|
|
|
+
|
|
|
+ onPageSizeSelectChange(e) {
|
|
|
+ this.page = Statistics.DefaultPage;
|
|
|
+ this.pageSize = parseInt(CDElement.get(e.target).getValue());
|
|
|
+ this.load();
|
|
|
+ }
|
|
|
+
|
|
|
+ onPageClick(e) {
|
|
|
+ this.page = parseInt(CDElement.get(e.target).getValue());
|
|
|
+ this.load();
|
|
|
+ }
|
|
|
+
|
|
|
+ isAllMode() {
|
|
|
+ return this.mode === Statistics.Modes.ALL;
|
|
|
+ }
|
|
|
+
|
|
|
+ isUserMode() {
|
|
|
+ return this.mode === Statistics.Modes.USER;
|
|
|
+ }
|
|
|
+
|
|
|
+ isClassMode() {
|
|
|
+ return this.mode === Statistics.Modes.CLASS;
|
|
|
+ }
|
|
|
+
|
|
|
+ load() {
|
|
|
+ let url = '/data/statistics';
|
|
|
+ if(this.isUserMode())
|
|
|
+ url = `/data/statistics/user/${StatisticsUser}`;
|
|
|
+ if(this.isClassMode())
|
|
|
+ url = `/data/statistics/class/${Class.name}`;
|
|
|
+
|
|
|
+ fetch(`${url}?page=${this.page}&pageSize=${this.pageSize}`, {
|
|
|
+ method: 'GET'
|
|
|
+ }).then(res => res.json()).then(res => {
|
|
|
+ this.statistics = res[Statistics.Response.RECORDS];
|
|
|
+ this.pageCount = Math.ceil(res[Statistics.Response.COUNT] / this.pageSize);
|
|
|
+ this.renderPager(0); // top
|
|
|
+ this.renderStatistics();
|
|
|
+ this.renderPager(1); // bottom
|
|
|
+ });
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+}
|