UNPKG

4.42 kBJavaScriptView Raw
1/**
2 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
3 */
4'use strict';
5
6const Base = require('../base/Base');
7
8module.exports = class Sort extends Base {
9
10 static getConstants () {
11 return {
12 ASC: 1,
13 DESC: -1
14 };
15 }
16
17 constructor (config) {
18 super({
19 attrs: {},
20 enableMultiSort: false,
21 sortParam: 'sort',
22 separator: ',',
23 // defaultOrder
24 // route
25 // params: 'attrName1,-attrName2',
26 ...config
27 });
28 this.initAttrs();
29 }
30
31 initAttrs () {
32 for (const name of Object.keys(this.attrs)) {
33 let attr = this.attrs[name];
34 if (typeof attr !== 'object') {
35 attr = {
36 asc: {[name]: this.ASC},
37 desc: {[name]: this.DESC}
38 }
39 } else {
40 if (!attr.asc) {
41 attr.asc = {[name]: this.ASC};
42 }
43 if (!attr.desc) {
44 attr.desc = {[name]: this.DESC};
45 }
46 }
47 this.attrs[name] = attr;
48 }
49 }
50
51 hasAttr (name) {
52 return Object.prototype.hasOwnProperty.call(this.attrs, name);
53 }
54
55 getOrders (recalculate) {
56 if (this._attrOrders && !recalculate) {
57 return this._attrOrders;
58 }
59 this._attrOrders = {};
60 let attrs = this.params || this.controller.getQueryParam(this.sortParam);
61 if (attrs) {
62 attrs = attrs.split(this.separator);
63 for (let attr of attrs) {
64 let desc = false;
65 if (attr.charAt(0) === '-') {
66 desc = true;
67 attr = attr.substring(1);
68 }
69 if (Object.prototype.hasOwnProperty.call(this.attrs, attr)) {
70 this._attrOrders[attr] = desc ? this.DESC : this.ASC;
71 if (!this.enableMultiSort) {
72 return this._attrOrders;
73 }
74 }
75 }
76 }
77 if (this.defaultOrder && !Object.values(this._attrOrders).length) {
78 this._attrOrders = this.defaultOrder;
79 }
80 return this._attrOrders;
81 }
82
83 getOrder (attr) {
84 const orders = this.getOrders();
85 return Object.prototype.hasOwnProperty.call(orders, attr) ? orders[attr] : null;
86 }
87
88 getLink (attr, options = {}) {
89 const direction = this.getOrder(attr);
90 if (direction) {
91 const className = direction === this.DESC ? 'desc' : 'asc';
92 options.class = options.class ? `${options.class} ${className}` : className;
93 }
94 const url = this.createUrl(attr);
95 options['data-sort'] = this.createSortParam(attr);
96 let label = options.label;
97 if (label) {
98 delete options.label;
99 } else if (this.attrs[attr].label) {
100 label = this.attrs[attr].label;
101 } else {
102 label = StringHelper.camelToWords(attr);
103 }
104 return {label, url, options}; // Html:a()
105 }
106
107 createUrl (attr) {
108 const params = this.params || {...this.controller.getQueryParams()};
109 params[this.sortParam] = this.createSortParam(attr);
110 const route = this.route || this.controller.getCurrentRoute();
111 return this.controller.createUrl([route, params]);
112 }
113
114 createSortParam (attr) {
115 let data = this.attrs[attr];
116 let directions = {...this.getOrders()}, direction;
117 if (Object.prototype.hasOwnProperty.call(directions, attr)) {
118 direction = directions[attr] === this.DESC ? this.ASC : this.DESC;
119 delete directions[attr];
120 } else {
121 direction = 'default' in data ? data.default : this.ASC;
122 }
123 directions = this.enableMultiSort
124 ? {[attr]: direction, ...directions}
125 : {[attr]: direction};
126 const sorts = [];
127 for (const attr in directions) {
128 sorts.push(directions[attr] === this.DESC ? `-${attr}` : attr);
129 }
130 return sorts.join(this.separator);
131 }
132};
133module.exports.init();
134
135const StringHelper = require('../helper/StringHelper');
\No newline at end of file