diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue
index ada3e450..8c9f8cca 100644
--- a/src/components/DataTable.vue
+++ b/src/components/DataTable.vue
@@ -6,7 +6,8 @@
v-bind="mergedTableProps"
:stripe="false"
:default-sort="resolvedDefaultSort"
- @row-click="handleRowClick">
+ @row-click="handleRowClick"
+ @sort-change="handleSortChange">
@@ -63,7 +64,7 @@
}
});
- const emit = defineEmits(['row-click']);
+ const emit = defineEmits(['row-click', 'sort-change']);
const appearanceSettingsStore = useAppearanceSettingsStore();
const vrcxStore = useVrcxStore();
@@ -169,6 +170,10 @@
emit('row-click', row, column, event);
};
+ const handleSortChange = (data) => {
+ emit('sort-change', data);
+ };
+
const handleSizeChange = (size) => {
if (props.pageSizeLinked) {
appearanceSettingsStore.setTablePageSize(size);
diff --git a/src/views/FriendList/FriendList.vue b/src/views/FriendList/FriendList.vue
index 870577d7..16ea8316 100644
--- a/src/views/FriendList/FriendList.vue
+++ b/src/views/FriendList/FriendList.vue
@@ -52,6 +52,7 @@
@@ -67,7 +68,7 @@
:label="t('table.friendList.no')"
width="100"
prop="$friendNumber"
- :sortable="true"
+ :sortable="'custom'"
fixed="left">
{{ row.$friendNumber ? row.$friendNumber : '' }}
@@ -84,8 +85,7 @@
:label="t('table.friendList.displayName')"
min-width="200"
prop="displayName"
- sortable
- :sort-method="(a, b) => sortAlphabetically(a, b, 'displayName')"
+ sortable="'custom'"
fixed="left">
{{
@@ -93,7 +93,7 @@
}}
-
+
+ sortable="'custom'">
+ sortable="'custom'">
@@ -163,13 +161,13 @@
:label="t('table.friendList.joinCount')"
width="120"
prop="$joinCount"
- sortable
+ sortable="'custom'"
align="right">
{{ timeToText(row.$timeSpent) }}
@@ -179,8 +177,7 @@
:label="t('table.friendList.lastSeen')"
width="170"
prop="$lastSeen"
- sortable
- :sort-method="(a, b) => sortAlphabetically(a, b, '$lastSeen')">
+ sortable="'custom'">
{{
formatDateFilter(row.$lastSeen, 'long') === '-'
@@ -193,7 +190,7 @@
:label="t('table.friendList.mutualFriends')"
width="120"
prop="$mutualCount"
- sortable
+ sortable="'custom'"
align="right">
{{ row.$mutualCount }}
@@ -203,8 +200,7 @@
:label="t('table.friendList.lastActivity')"
width="200"
prop="last_activity"
- sortable
- :sort-method="(a, b) => sortAlphabetically(a, b, 'last_activity')">
+ sortable="'custom'">
{{ formatDateFilter(row.last_activity, 'long') }}
@@ -213,8 +209,7 @@
:label="t('table.friendList.lastLogin')"
width="200"
prop="last_login"
- sortable
- :sort-method="(a, b) => sortAlphabetically(a, b, 'last_login')">
+ sortable="'custom'">
{{ formatDateFilter(row.last_login, 'long') }}
@@ -223,8 +218,7 @@
:label="t('table.friendList.dateJoined')"
width="120"
prop="date_joined"
- sortable
- :sort-method="(a, b) => sortAlphabetically(a, b, 'date_joined')">
+ sortable="'custom'">
{
if (!friendsListLoadingTotal.value) return 0;
@@ -375,10 +370,11 @@
}
results.push(ctx.ref);
}
+ allFilteredData.value = results;
getAllUserStats();
getAllUserMutualCount();
+ applySortAndPagination(friendsListTable.tableProps.defaultSort.prop, friendsListTable.tableProps.defaultSort.order);
nextTick(() => {
- friendsListTable.data = results;
friendsListLoading.value = false;
});
}
@@ -486,20 +482,81 @@
else showUserDialog(val.id);
}
- function sortAlphabetically(a, b, field) {
- if (!a[field] || !b[field]) return 0;
- return a[field].toLowerCase().localeCompare(b[field].toLowerCase());
+ function compareWithFriendNumber(a, b, primaryComparison, primarySelector = (x) => x) {
+ const primaryComparisonResult = primaryComparison(primarySelector(a), primarySelector(b));
+ if (primaryComparisonResult === 0) {
+ return (a.$friendNumber || 0) - (b.$friendNumber || 0);
+ }
+ return primaryComparisonResult;
+ }
+
+ function sortAlphabetically(a, b) {
+ if (!a || !b) {
+ if (!a && !b) return 0;
+ return !a ? -1 : 1;
+ }
+ return a.toLowerCase().localeCompare(b.toLowerCase());
}
function sortLanguages(a, b) {
- const as = a.$languages.map((i) => i.value).sort();
- const bs = b.$languages.map((i) => i.value).sort();
+ const as = a.map((i) => i.value).sort();
+ const bs = b.map((i) => i.value).sort();
return JSON.stringify(as).localeCompare(JSON.stringify(bs));
}
function openChartsTab() {
router.push({ name: 'charts' });
}
+
+ function handleSortChange({ prop, order }) {
+ applySortAndPagination(prop, order);
+ }
+
+ function resolveSortFunction(prop) {
+ const numberComparison = (a, b) => (a || 0) - (b || 0);
+ switch (prop) {
+ case '$friendNumber':
+ return [numberComparison, (item) => item.$friendNumber || 0];
+ case 'displayName':
+ return [sortAlphabetically, (item) => item.displayName || ''];
+ case '$trustSortNum':
+ return [numberComparison, (item) => item.$trustSortNum || 0];
+ case 'status':
+ return [sortStatus, (item) => item.status || 'offline'];
+ case '$languages':
+ return [sortLanguages, (item) => item.$languages || []];
+ case '$joinCount':
+ return [numberComparison, (item) => item.$joinCount || 0];
+ case '$timeSpent':
+ return [numberComparison, (item) => item.$timeSpent || 0];
+ case '$lastSeen':
+ return [sortAlphabetically, (item) => item.$lastSeen || ''];
+ case '$mutualCount':
+ return [numberComparison, (item) => item.$mutualCount || 0];
+ case 'last_activity':
+ return [sortAlphabetically, (item) => item.last_activity || ''];
+ case 'last_login':
+ return [sortAlphabetically, (item) => item.last_login || ''];
+ case 'date_joined':
+ return [sortAlphabetically, (item) => item.date_joined || ''];
+ default:
+ return [sortAlphabetically, (item) => item[prop] || ''];
+ }
+ }
+
+ function applySortAndPagination(prop, order) {
+ let sortedData = [...allFilteredData.value];
+
+ if (prop && order !== null) {
+ const [comparison, selector] = resolveSortFunction(prop);
+ sortedData.sort((a, b) => {
+ const result = compareWithFriendNumber(a, b, comparison, selector);
+ return order === 'ascending' ? result : -result;
+ });
+ }
+
+ friendsListTable.data = sortedData;
+ }