Skip to content

Commit f9b6b35

Browse files
committed
Improvement - VueUiTableSparkline - Improve column filtering options
1 parent ae49e45 commit f9b6b35

File tree

1 file changed

+116
-23
lines changed

1 file changed

+116
-23
lines changed

src/components/vue-ui-table-sparkline.vue

Lines changed: 116 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -204,20 +204,31 @@ const currentSortOrder = ref(-1);
204204
function restoreOrder() {
205205
isSorting.value = false;
206206
currentSortingIndex.value = undefined;
207+
currentAdditionalSort.value = undefined;
207208
currentSortOrder.value = -1;
208209
mutableDataset.value = datasetWithOrders.value;
209210
}
210211
211-
function orderDatasetByIndex(index) {
212-
if (!hasSorting(index)) return;
212+
function orderDatasetByIndex(th, index) {
213213
214-
if (currentSortOrder.value === 1) {
215-
currentSortOrder.value = -1;
216-
currentSortingIndex.value = undefined;
217-
restoreOrder();
214+
if ((['name', 'sum', 'average', 'median'].includes(th.type))) {
215+
orderDatasetByAttribute(th.type);
218216
return;
219217
}
220218
219+
if (!hasSorting(index)) return;
220+
221+
selectedDataIndex.value = index;
222+
currentAdditionalSort.value = undefined;
223+
224+
// Maybe for later:
225+
// if (currentSortOrder.value === 1) {
226+
// currentSortOrder.value = -1;
227+
// currentSortingIndex.value = undefined;
228+
// restoreOrder();
229+
// return;
230+
// }
231+
221232
isSorting.value = true;
222233
currentSortingIndex.value = index;
223234
@@ -247,39 +258,78 @@ const maxSeriesLength = computed(() => {
247258
})
248259
249260
const colNames = computed(() => {
250-
let cn = usableColNames.value;
261+
let cn = usableColNames.value.map(c => {
262+
return {
263+
type: 'reg',
264+
value: c
265+
}
266+
});
251267
252268
if(!cn.length) {
253269
for(let i = 0; i < maxSeriesLength.value; i += 1) {
254-
cn.push(`col ${i+1}`)
270+
cn.push({type: 'reg', value: `col ${i+1}`})
255271
}
256272
}
257273
258274
if (FINAL_CONFIG.value.showTotal) {
259-
cn = [...cn, FINAL_CONFIG.value.translations.total];
275+
cn = [...cn, { type: 'sum', value: FINAL_CONFIG.value.translations.total}];
260276
}
261277
262278
let res;
263279
if (FINAL_CONFIG.value.showAverage && FINAL_CONFIG.value.showMedian) {
264280
res = [
265281
...cn,
266-
FINAL_CONFIG.value.translations.average,
267-
FINAL_CONFIG.value.translations.median,
282+
{ type: 'average', value: FINAL_CONFIG.value.translations.average},
283+
{ type: 'median', value: FINAL_CONFIG.value.translations.median}
268284
];
269285
} else if (FINAL_CONFIG.value.showAverage && !FINAL_CONFIG.value.showMedian) {
270-
res = [...cn, FINAL_CONFIG.value.translations.average];
286+
res = [...cn, { type: 'average', value: FINAL_CONFIG.value.translations.average}];
271287
} else if (!FINAL_CONFIG.value.showAverage && FINAL_CONFIG.value.showMedian) {
272-
res = [...cn, FINAL_CONFIG.value.translations.median];
288+
res = [...cn, { type: 'median', value: FINAL_CONFIG.value.translations.median}];
273289
} else {
274290
res = cn;
275291
}
276292
if (FINAL_CONFIG.value.showSparklines) {
277-
return [...res, FINAL_CONFIG.value.translations.chart];
293+
return [...res, { type: 'chart', value: FINAL_CONFIG.value.translations.chart}];
278294
} else {
279295
return res;
280296
}
281297
});
282298
299+
const sortOrders = ref({
300+
name: -1,
301+
sum: -1,
302+
average: -1,
303+
median: -1
304+
})
305+
306+
const currentAdditionalSort = ref(undefined);
307+
308+
function orderDatasetByAttribute(attribute) {
309+
if (!mutableDataset.value || mutableDataset.value.length === 0) return;
310+
if (!hasAdditionalSorting(attribute)) return;
311+
312+
currentAdditionalSort.value = attribute;
313+
currentSortingIndex.value = undefined;
314+
isSorting.value = true;
315+
316+
sortOrders.value[attribute] = sortOrders.value[attribute] === -1 ? 1 : -1;
317+
const sortOrder = sortOrders.value[attribute];
318+
319+
const sortedDataset = [...mutableDataset.value].sort((a, b) => {
320+
const aValue = a[attribute] ?? (typeof a[attribute] === 'number' ? 0 : '');
321+
const bValue = b[attribute] ?? (typeof b[attribute] === 'number' ? 0 : '');
322+
323+
if (typeof aValue === 'string' && typeof bValue === 'string') {
324+
return sortOrder === -1 ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
325+
} else if (typeof aValue === 'number' && typeof bValue === 'number') {
326+
return sortOrder === -1 ? aValue - bValue : bValue - aValue;
327+
}
328+
return 0;
329+
});
330+
mutableDataset.value = sortedDataset;
331+
}
332+
283333
const selectedDataIndex = ref(undefined);
284334
const selectedSerieIndex = ref(undefined);
285335
@@ -319,7 +369,31 @@ function generateCsv() {
319369
}
320370
321371
function hasSorting(index) {
322-
return FINAL_CONFIG.value.sortedColIndices.includes(index);
372+
return FINAL_CONFIG.value.sortedDataColumnIndices.includes(index);
373+
}
374+
375+
function hasAdditionalSorting(th) {
376+
if (th.type === 'name' || th === 'name') {
377+
return FINAL_CONFIG.value.sortedSeriesName;
378+
}
379+
if (th.type === 'sum' || th === 'sum') {
380+
return FINAL_CONFIG.value.sortedSum;
381+
}
382+
if (th.type === 'average' || th === 'average') {
383+
return FINAL_CONFIG.value.sortedAverage;
384+
}
385+
if (th.type === 'median' || th === 'median') {
386+
return FINAL_CONFIG.value.sortedMedian;
387+
}
388+
return false;
389+
}
390+
391+
function getArrowOpacity(index, th) {
392+
if (['sum', 'average', 'median'].includes(th.type)) {
393+
return currentAdditionalSort.value === th.type ? 1 : 0.3;
394+
} else {
395+
return index === currentSortingIndex.value ? 1 : 0.3;
396+
}
323397
}
324398
325399
defineExpose({
@@ -371,18 +445,38 @@ defineExpose({
371445
border: FINAL_CONFIG.thead.outline,
372446
textAlign: FINAL_CONFIG.thead.textAlign,
373447
fontWeight: FINAL_CONFIG.thead.bold ? 'bold' : 'normal',
374-
}" class="sticky-col-first" >
375-
{{ FINAL_CONFIG.translations.serie }}
448+
cursor: FINAL_CONFIG.sortedSeriesName ? 'pointer' : 'default'
449+
}" class="sticky-col-first" @click="orderDatasetByIndex({type: 'name'}, null)">
450+
<div
451+
:style="{
452+
display: 'flex',
453+
flexDirection: 'row',
454+
alignItems: 'center',
455+
gap: '6px',
456+
justifyContent: FINAL_CONFIG.thead.textAlign
457+
}">
458+
<span>{{ FINAL_CONFIG.translations.serie }}</span>
459+
460+
<BaseIcon
461+
:size="18"
462+
v-if="FINAL_CONFIG.sortedSeriesName"
463+
:name="'sort'"
464+
:stroke="FINAL_CONFIG.thead.color"
465+
:style="{
466+
opacity: currentAdditionalSort === 'name' ? 1 : 0.3
467+
}"
468+
/>
469+
</div>
376470
</th>
377471
<th role="cell" v-for="(th, i) in colNames" :style="{
378472
background: FINAL_CONFIG.thead.backgroundColor,
379473
border: FINAL_CONFIG.thead.outline,
380474
textAlign: FINAL_CONFIG.thead.textAlign,
381475
fontWeight: FINAL_CONFIG.thead.bold ? 'bold' : 'normal',
382476
minWidth: i === colNames.length - 1 ? `${FINAL_CONFIG.sparkline.dimensions.width}px` : '48px',
383-
cursor: hasSorting(i) ? 'pointer' : 'default',
477+
cursor: hasSorting(i) || hasAdditionalSorting(th) ? 'pointer' : 'default',
384478
paddingRight: i === colNames.length - 1 && FINAL_CONFIG.userOptions.show ? '36px' : '',
385-
}" @click="() => orderDatasetByIndex(i)" :class="{'sticky-col': i === colNames.length - 1 && FINAL_CONFIG.showSparklines}"
479+
}" @click="() => orderDatasetByIndex(th, i)" :class="{'sticky-col': i === colNames.length - 1 && FINAL_CONFIG.showSparklines}"
386480
>
387481
<div
388482
:style="{
@@ -392,16 +486,15 @@ defineExpose({
392486
gap: '6px',
393487
justifyContent: FINAL_CONFIG.thead.textAlign
394488
}">
395-
<span>{{ th }}</span>
489+
<span>{{ th.value }}</span>
396490
397-
<slot name="arrow" v-if="$slots.arrow && hasSorting(i)" v-bind="{ isSorted: i === currentSortingIndex }" />
398491
<BaseIcon
399492
:size="18"
400-
v-else-if="hasSorting(i)"
493+
v-if="hasSorting(i) || hasAdditionalSorting(th)"
401494
:name="'sort'"
402495
:stroke="FINAL_CONFIG.thead.color"
403496
:style="{
404-
opacity: i === currentSortingIndex ? 1 : 0.3
497+
opacity: getArrowOpacity(i, th)
405498
}"
406499
/>
407500
</div>

0 commit comments

Comments
 (0)