@doyosi/laraisy 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/package.json +1 -1
- package/src/CodeInput.js +48 -48
- package/src/DSAlert.js +352 -352
- package/src/DSAvatar.js +207 -207
- package/src/DSDelete.js +274 -274
- package/src/DSForm.js +568 -568
- package/src/DSGridOrTable.js +453 -453
- package/src/DSLocaleSwitcher.js +239 -239
- package/src/DSLogout.js +293 -293
- package/src/DSNotifications.js +365 -365
- package/src/DSRestore.js +181 -181
- package/src/DSSelect.js +1071 -1071
- package/src/DSSelectBox.js +563 -563
- package/src/DSSimpleSlider.js +517 -517
- package/src/DSSvgFetch.js +69 -69
- package/src/DSTable/DSTableExport.js +68 -68
- package/src/DSTable/DSTableFilter.js +224 -224
- package/src/DSTable/DSTablePagination.js +136 -136
- package/src/DSTable/DSTableSearch.js +40 -40
- package/src/DSTable/DSTableSelection.js +192 -192
- package/src/DSTable/DSTableSort.js +58 -58
- package/src/DSTable.js +353 -353
- package/src/DSTabs.js +488 -488
- package/src/DSUpload.js +887 -887
- package/dist/CodeInput.d.ts +0 -10
- package/dist/DSAlert.d.ts +0 -112
- package/dist/DSAvatar.d.ts +0 -45
- package/dist/DSDelete.d.ts +0 -61
- package/dist/DSForm.d.ts +0 -151
- package/dist/DSGridOrTable/DSGOTRenderer.d.ts +0 -60
- package/dist/DSGridOrTable/DSGOTViewToggle.d.ts +0 -26
- package/dist/DSGridOrTable.d.ts +0 -296
- package/dist/DSLocaleSwitcher.d.ts +0 -71
- package/dist/DSLogout.d.ts +0 -76
- package/dist/DSNotifications.d.ts +0 -54
- package/dist/DSRestore.d.ts +0 -56
- package/dist/DSSelect.d.ts +0 -221
- package/dist/DSSelectBox.d.ts +0 -123
- package/dist/DSSimpleSlider.d.ts +0 -136
- package/dist/DSSvgFetch.d.ts +0 -17
- package/dist/DSTable/DSTableExport.d.ts +0 -11
- package/dist/DSTable/DSTableFilter.d.ts +0 -40
- package/dist/DSTable/DSTablePagination.d.ts +0 -12
- package/dist/DSTable/DSTableSearch.d.ts +0 -8
- package/dist/DSTable/DSTableSelection.d.ts +0 -46
- package/dist/DSTable/DSTableSort.d.ts +0 -8
- package/dist/DSTable.d.ts +0 -116
- package/dist/DSTabs.d.ts +0 -156
- package/dist/DSUpload.d.ts +0 -220
- package/dist/index.d.ts +0 -17
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
export class DSTableSelection {
|
|
2
|
-
constructor(tableInstance) {
|
|
3
|
-
this.table = tableInstance;
|
|
4
|
-
this.table.registerModule('selection', this);
|
|
5
|
-
|
|
6
|
-
// Configuration for persistence
|
|
7
|
-
this.persist = this.table.config.selection_persist ?? false;
|
|
8
|
-
this.storageType = this.table.config.selection_storage ?? 'localStorage'; // 'localStorage' or 'sessionStorage'
|
|
9
|
-
this.storageKey = this.table.config.selection_storage_key ?? `dstable_selection_${this._getTableIdentifier()}`;
|
|
10
|
-
|
|
11
|
-
this.selectedIds = new Set();
|
|
12
|
-
|
|
13
|
-
// Load persisted selection if enabled
|
|
14
|
-
if (this.persist) {
|
|
15
|
-
this._loadFromStorage();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
this._init();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate a unique identifier for this table instance
|
|
23
|
-
*/
|
|
24
|
-
_getTableIdentifier() {
|
|
25
|
-
// Use wrapper id, data-url, or fallback to path
|
|
26
|
-
return this.table.wrapper.id ||
|
|
27
|
-
this.table.config.ajax_url ||
|
|
28
|
-
window.location.pathname.replace(/\//g, '_');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
_init() {
|
|
32
|
-
// We need to re-bind on render
|
|
33
|
-
this.table.on('render', () => this.update());
|
|
34
|
-
|
|
35
|
-
// Check all toggle
|
|
36
|
-
const checkAll = this.table.table.querySelector('thead input[type="checkbox"].select-all');
|
|
37
|
-
if (checkAll) {
|
|
38
|
-
checkAll.addEventListener('change', (e) => {
|
|
39
|
-
this.toggleAll(e.target.checked);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
update() {
|
|
45
|
-
// Determine indentifier key, default 'id'
|
|
46
|
-
const key = 'id';
|
|
47
|
-
|
|
48
|
-
// Find checkboxes in tbody
|
|
49
|
-
const checkboxes = this.table.tbody.querySelectorAll('input[type="checkbox"].select-row');
|
|
50
|
-
|
|
51
|
-
checkboxes.forEach(chk => {
|
|
52
|
-
const rowId = chk.value; // Assuming value holds the ID
|
|
53
|
-
|
|
54
|
-
// Restore state from selectedIds (which may have been loaded from storage)
|
|
55
|
-
chk.checked = this.selectedIds.has(rowId);
|
|
56
|
-
|
|
57
|
-
// Bind click
|
|
58
|
-
chk.onchange = (e) => {
|
|
59
|
-
this._toggleId(rowId, e.target.checked);
|
|
60
|
-
};
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
this._updateCheckAllState();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
_toggleId(id, checked) {
|
|
67
|
-
if (checked) this.selectedIds.add(id);
|
|
68
|
-
else this.selectedIds.delete(id);
|
|
69
|
-
|
|
70
|
-
this._updateCheckAllState();
|
|
71
|
-
this._saveToStorage();
|
|
72
|
-
this.table._emit('selectionChange', { selected: Array.from(this.selectedIds) });
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
toggleAll(checked) {
|
|
76
|
-
const checkboxes = this.table.tbody.querySelectorAll('input[type="checkbox"].select-row');
|
|
77
|
-
checkboxes.forEach(chk => {
|
|
78
|
-
chk.checked = checked;
|
|
79
|
-
const rowId = chk.value;
|
|
80
|
-
if (checked) this.selectedIds.add(rowId);
|
|
81
|
-
else this.selectedIds.delete(rowId);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
this._saveToStorage();
|
|
85
|
-
this.table._emit('selectionChange', { selected: Array.from(this.selectedIds) });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
_updateCheckAllState() {
|
|
89
|
-
const checkAll = this.table.table.querySelector('thead input[type="checkbox"].select-all');
|
|
90
|
-
if (!checkAll) return;
|
|
91
|
-
|
|
92
|
-
const checkboxes = Array.from(this.table.tbody.querySelectorAll('input[type="checkbox"].select-row'));
|
|
93
|
-
if (checkboxes.length === 0) {
|
|
94
|
-
checkAll.checked = false;
|
|
95
|
-
checkAll.indeterminate = false;
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const allChecked = checkboxes.every(c => c.checked);
|
|
100
|
-
const someChecked = checkboxes.some(c => c.checked);
|
|
101
|
-
|
|
102
|
-
checkAll.checked = allChecked;
|
|
103
|
-
checkAll.indeterminate = someChecked && !allChecked;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ==================== STORAGE ====================
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Save selection to storage
|
|
110
|
-
*/
|
|
111
|
-
_saveToStorage() {
|
|
112
|
-
if (!this.persist) return;
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
const storage = this.storageType === 'sessionStorage' ? sessionStorage : localStorage;
|
|
116
|
-
storage.setItem(this.storageKey, JSON.stringify(Array.from(this.selectedIds)));
|
|
117
|
-
} catch (e) {
|
|
118
|
-
console.warn('DSTableSelection: Failed to save to storage', e);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Load selection from storage
|
|
124
|
-
*/
|
|
125
|
-
_loadFromStorage() {
|
|
126
|
-
try {
|
|
127
|
-
const storage = this.storageType === 'sessionStorage' ? sessionStorage : localStorage;
|
|
128
|
-
const saved = storage.getItem(this.storageKey);
|
|
129
|
-
|
|
130
|
-
if (saved) {
|
|
131
|
-
const ids = JSON.parse(saved);
|
|
132
|
-
if (Array.isArray(ids)) {
|
|
133
|
-
this.selectedIds = new Set(ids.map(String));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
} catch (e) {
|
|
137
|
-
console.warn('DSTableSelection: Failed to load from storage', e);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Clear storage
|
|
143
|
-
*/
|
|
144
|
-
_clearStorage() {
|
|
145
|
-
if (!this.persist) return;
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
const storage = this.storageType === 'sessionStorage' ? sessionStorage : localStorage;
|
|
149
|
-
storage.removeItem(this.storageKey);
|
|
150
|
-
} catch (e) {
|
|
151
|
-
console.warn('DSTableSelection: Failed to clear storage', e);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// ==================== PUBLIC API ====================
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Get all selected IDs
|
|
159
|
-
*/
|
|
160
|
-
getSelected() {
|
|
161
|
-
return Array.from(this.selectedIds);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Set selected IDs programmatically
|
|
166
|
-
*/
|
|
167
|
-
setSelected(ids) {
|
|
168
|
-
this.selectedIds = new Set(ids.map(String));
|
|
169
|
-
this._saveToStorage();
|
|
170
|
-
this.update();
|
|
171
|
-
this.table._emit('selectionChange', { selected: Array.from(this.selectedIds) });
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Clear all selections
|
|
176
|
-
*/
|
|
177
|
-
clearAll() {
|
|
178
|
-
this.selectedIds.clear();
|
|
179
|
-
this._clearStorage();
|
|
180
|
-
this.update();
|
|
181
|
-
this.table._emit('selectionChange', { selected: [] });
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Check if an ID is selected
|
|
186
|
-
*/
|
|
187
|
-
isSelected(id) {
|
|
188
|
-
return this.selectedIds.has(String(id));
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
export default DSTableSelection;
|
|
192
|
-
|
|
1
|
+
export class DSTableSelection {
|
|
2
|
+
constructor(tableInstance) {
|
|
3
|
+
this.table = tableInstance;
|
|
4
|
+
this.table.registerModule('selection', this);
|
|
5
|
+
|
|
6
|
+
// Configuration for persistence
|
|
7
|
+
this.persist = this.table.config.selection_persist ?? false;
|
|
8
|
+
this.storageType = this.table.config.selection_storage ?? 'localStorage'; // 'localStorage' or 'sessionStorage'
|
|
9
|
+
this.storageKey = this.table.config.selection_storage_key ?? `dstable_selection_${this._getTableIdentifier()}`;
|
|
10
|
+
|
|
11
|
+
this.selectedIds = new Set();
|
|
12
|
+
|
|
13
|
+
// Load persisted selection if enabled
|
|
14
|
+
if (this.persist) {
|
|
15
|
+
this._loadFromStorage();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this._init();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate a unique identifier for this table instance
|
|
23
|
+
*/
|
|
24
|
+
_getTableIdentifier() {
|
|
25
|
+
// Use wrapper id, data-url, or fallback to path
|
|
26
|
+
return this.table.wrapper.id ||
|
|
27
|
+
this.table.config.ajax_url ||
|
|
28
|
+
window.location.pathname.replace(/\//g, '_');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_init() {
|
|
32
|
+
// We need to re-bind on render
|
|
33
|
+
this.table.on('render', () => this.update());
|
|
34
|
+
|
|
35
|
+
// Check all toggle
|
|
36
|
+
const checkAll = this.table.table.querySelector('thead input[type="checkbox"].select-all');
|
|
37
|
+
if (checkAll) {
|
|
38
|
+
checkAll.addEventListener('change', (e) => {
|
|
39
|
+
this.toggleAll(e.target.checked);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
update() {
|
|
45
|
+
// Determine indentifier key, default 'id'
|
|
46
|
+
const key = 'id';
|
|
47
|
+
|
|
48
|
+
// Find checkboxes in tbody
|
|
49
|
+
const checkboxes = this.table.tbody.querySelectorAll('input[type="checkbox"].select-row');
|
|
50
|
+
|
|
51
|
+
checkboxes.forEach(chk => {
|
|
52
|
+
const rowId = chk.value; // Assuming value holds the ID
|
|
53
|
+
|
|
54
|
+
// Restore state from selectedIds (which may have been loaded from storage)
|
|
55
|
+
chk.checked = this.selectedIds.has(rowId);
|
|
56
|
+
|
|
57
|
+
// Bind click
|
|
58
|
+
chk.onchange = (e) => {
|
|
59
|
+
this._toggleId(rowId, e.target.checked);
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this._updateCheckAllState();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_toggleId(id, checked) {
|
|
67
|
+
if (checked) this.selectedIds.add(id);
|
|
68
|
+
else this.selectedIds.delete(id);
|
|
69
|
+
|
|
70
|
+
this._updateCheckAllState();
|
|
71
|
+
this._saveToStorage();
|
|
72
|
+
this.table._emit('selectionChange', { selected: Array.from(this.selectedIds) });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
toggleAll(checked) {
|
|
76
|
+
const checkboxes = this.table.tbody.querySelectorAll('input[type="checkbox"].select-row');
|
|
77
|
+
checkboxes.forEach(chk => {
|
|
78
|
+
chk.checked = checked;
|
|
79
|
+
const rowId = chk.value;
|
|
80
|
+
if (checked) this.selectedIds.add(rowId);
|
|
81
|
+
else this.selectedIds.delete(rowId);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
this._saveToStorage();
|
|
85
|
+
this.table._emit('selectionChange', { selected: Array.from(this.selectedIds) });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_updateCheckAllState() {
|
|
89
|
+
const checkAll = this.table.table.querySelector('thead input[type="checkbox"].select-all');
|
|
90
|
+
if (!checkAll) return;
|
|
91
|
+
|
|
92
|
+
const checkboxes = Array.from(this.table.tbody.querySelectorAll('input[type="checkbox"].select-row'));
|
|
93
|
+
if (checkboxes.length === 0) {
|
|
94
|
+
checkAll.checked = false;
|
|
95
|
+
checkAll.indeterminate = false;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const allChecked = checkboxes.every(c => c.checked);
|
|
100
|
+
const someChecked = checkboxes.some(c => c.checked);
|
|
101
|
+
|
|
102
|
+
checkAll.checked = allChecked;
|
|
103
|
+
checkAll.indeterminate = someChecked && !allChecked;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ==================== STORAGE ====================
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Save selection to storage
|
|
110
|
+
*/
|
|
111
|
+
_saveToStorage() {
|
|
112
|
+
if (!this.persist) return;
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const storage = this.storageType === 'sessionStorage' ? sessionStorage : localStorage;
|
|
116
|
+
storage.setItem(this.storageKey, JSON.stringify(Array.from(this.selectedIds)));
|
|
117
|
+
} catch (e) {
|
|
118
|
+
console.warn('DSTableSelection: Failed to save to storage', e);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Load selection from storage
|
|
124
|
+
*/
|
|
125
|
+
_loadFromStorage() {
|
|
126
|
+
try {
|
|
127
|
+
const storage = this.storageType === 'sessionStorage' ? sessionStorage : localStorage;
|
|
128
|
+
const saved = storage.getItem(this.storageKey);
|
|
129
|
+
|
|
130
|
+
if (saved) {
|
|
131
|
+
const ids = JSON.parse(saved);
|
|
132
|
+
if (Array.isArray(ids)) {
|
|
133
|
+
this.selectedIds = new Set(ids.map(String));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch (e) {
|
|
137
|
+
console.warn('DSTableSelection: Failed to load from storage', e);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Clear storage
|
|
143
|
+
*/
|
|
144
|
+
_clearStorage() {
|
|
145
|
+
if (!this.persist) return;
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const storage = this.storageType === 'sessionStorage' ? sessionStorage : localStorage;
|
|
149
|
+
storage.removeItem(this.storageKey);
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.warn('DSTableSelection: Failed to clear storage', e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ==================== PUBLIC API ====================
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get all selected IDs
|
|
159
|
+
*/
|
|
160
|
+
getSelected() {
|
|
161
|
+
return Array.from(this.selectedIds);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Set selected IDs programmatically
|
|
166
|
+
*/
|
|
167
|
+
setSelected(ids) {
|
|
168
|
+
this.selectedIds = new Set(ids.map(String));
|
|
169
|
+
this._saveToStorage();
|
|
170
|
+
this.update();
|
|
171
|
+
this.table._emit('selectionChange', { selected: Array.from(this.selectedIds) });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Clear all selections
|
|
176
|
+
*/
|
|
177
|
+
clearAll() {
|
|
178
|
+
this.selectedIds.clear();
|
|
179
|
+
this._clearStorage();
|
|
180
|
+
this.update();
|
|
181
|
+
this.table._emit('selectionChange', { selected: [] });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Check if an ID is selected
|
|
186
|
+
*/
|
|
187
|
+
isSelected(id) {
|
|
188
|
+
return this.selectedIds.has(String(id));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
export default DSTableSelection;
|
|
192
|
+
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
export class DSTableSort {
|
|
2
|
-
constructor(tableInstance) {
|
|
3
|
-
this.table = tableInstance;
|
|
4
|
-
this.table.registerModule('sort', this);
|
|
5
|
-
|
|
6
|
-
// We need to attach listeners to table headers row
|
|
7
|
-
this.headers = this.table.wrapper.querySelectorAll('thead th[data-sort]');
|
|
8
|
-
|
|
9
|
-
if (this.headers.length > 0) {
|
|
10
|
-
this._init();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
_init() {
|
|
15
|
-
this.headers.forEach(th => {
|
|
16
|
-
th.classList.add('cursor-pointer', 'hover:bg-base-200'); // Add UI hint
|
|
17
|
-
th.addEventListener('click', () => {
|
|
18
|
-
const sortKey = th.dataset.sort;
|
|
19
|
-
let currentDir = this.table.getParam('sort_order') || 'asc';
|
|
20
|
-
let currentSort = this.table.getParam('sort_by');
|
|
21
|
-
|
|
22
|
-
// Toggle if clicking same header, else default asc
|
|
23
|
-
if (currentSort === sortKey) {
|
|
24
|
-
currentDir = currentDir === 'asc' ? 'desc' : 'asc';
|
|
25
|
-
} else {
|
|
26
|
-
currentDir = 'asc';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Reset page to 1 when sorting changes
|
|
30
|
-
this.table.setParam('page', 1);
|
|
31
|
-
this.table.setParam('sort_by', sortKey);
|
|
32
|
-
this.table.setParam('sort_order', currentDir);
|
|
33
|
-
|
|
34
|
-
this._updateIcons(th, currentDir);
|
|
35
|
-
this.table.loadData();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
_updateIcons(activeTh, dir) {
|
|
41
|
-
this.headers.forEach(th => {
|
|
42
|
-
// Remove existing icons
|
|
43
|
-
const icon = th.querySelector('.sort-icon');
|
|
44
|
-
if (icon) icon.remove();
|
|
45
|
-
th.classList.remove('text-primary'); // Remove active color
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// Add icon to active
|
|
49
|
-
// Simple text arrow for now, can be SVG
|
|
50
|
-
const arrow = dir === 'asc' ? '↑' : '↓';
|
|
51
|
-
const span = document.createElement('span');
|
|
52
|
-
span.className = 'sort-icon ml-1';
|
|
53
|
-
span.textContent = arrow;
|
|
54
|
-
activeTh.appendChild(span);
|
|
55
|
-
activeTh.classList.add('text-primary');
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
export default DSTableSort;
|
|
1
|
+
export class DSTableSort {
|
|
2
|
+
constructor(tableInstance) {
|
|
3
|
+
this.table = tableInstance;
|
|
4
|
+
this.table.registerModule('sort', this);
|
|
5
|
+
|
|
6
|
+
// We need to attach listeners to table headers row
|
|
7
|
+
this.headers = this.table.wrapper.querySelectorAll('thead th[data-sort]');
|
|
8
|
+
|
|
9
|
+
if (this.headers.length > 0) {
|
|
10
|
+
this._init();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_init() {
|
|
15
|
+
this.headers.forEach(th => {
|
|
16
|
+
th.classList.add('cursor-pointer', 'hover:bg-base-200'); // Add UI hint
|
|
17
|
+
th.addEventListener('click', () => {
|
|
18
|
+
const sortKey = th.dataset.sort;
|
|
19
|
+
let currentDir = this.table.getParam('sort_order') || 'asc';
|
|
20
|
+
let currentSort = this.table.getParam('sort_by');
|
|
21
|
+
|
|
22
|
+
// Toggle if clicking same header, else default asc
|
|
23
|
+
if (currentSort === sortKey) {
|
|
24
|
+
currentDir = currentDir === 'asc' ? 'desc' : 'asc';
|
|
25
|
+
} else {
|
|
26
|
+
currentDir = 'asc';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Reset page to 1 when sorting changes
|
|
30
|
+
this.table.setParam('page', 1);
|
|
31
|
+
this.table.setParam('sort_by', sortKey);
|
|
32
|
+
this.table.setParam('sort_order', currentDir);
|
|
33
|
+
|
|
34
|
+
this._updateIcons(th, currentDir);
|
|
35
|
+
this.table.loadData();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_updateIcons(activeTh, dir) {
|
|
41
|
+
this.headers.forEach(th => {
|
|
42
|
+
// Remove existing icons
|
|
43
|
+
const icon = th.querySelector('.sort-icon');
|
|
44
|
+
if (icon) icon.remove();
|
|
45
|
+
th.classList.remove('text-primary'); // Remove active color
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Add icon to active
|
|
49
|
+
// Simple text arrow for now, can be SVG
|
|
50
|
+
const arrow = dir === 'asc' ? '↑' : '↓';
|
|
51
|
+
const span = document.createElement('span');
|
|
52
|
+
span.className = 'sort-icon ml-1';
|
|
53
|
+
span.textContent = arrow;
|
|
54
|
+
activeTh.appendChild(span);
|
|
55
|
+
activeTh.classList.add('text-primary');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export default DSTableSort;
|