From 67480869d291a1e88781f48db301f84998a67fb5 Mon Sep 17 00:00:00 2001 From: Venryx Date: Mon, 20 May 2024 19:27:54 -0700 Subject: [PATCH] * Fixed that users table would not have its visual results change, even if the list of user-data changed (due to live-query update). [issue fixed by using useMemo, which re-applies the sorting+filtering when the base list changes] --- Packages/client/Source/UI/Database/Users.tsx | 135 ++++++++++--------- Packages/client/Source/UI/Debates.tsx | 64 ++++----- 2 files changed, 103 insertions(+), 96 deletions(-) diff --git a/Packages/client/Source/UI/Database/Users.tsx b/Packages/client/Source/UI/Database/Users.tsx index df1ac12f3..8e2f50a9d 100644 --- a/Packages/client/Source/UI/Database/Users.tsx +++ b/Packages/client/Source/UI/Database/Users.tsx @@ -2,7 +2,7 @@ import {BaseComponent, BaseComponentPlus, cssHelper} from "web-vcore/nm/react-ve import {Row, Column} from "web-vcore/nm/react-vcomponents.js"; import Moment from "web-vcore/nm/moment"; import {ScrollView} from "web-vcore/nm/react-vscrollview.js"; -import {Link, PageContainer, Observer, ES} from "web-vcore"; +import {Link, PageContainer, Observer, ES, AddNotificationMessage} from "web-vcore"; import {GetSelectedUser} from "Store/main/database"; import {ToNumber} from "web-vcore/nm/js-vextensions.js"; import {GetUsers, GetUser, User} from "dm_common"; @@ -46,7 +46,7 @@ const columns: ColumnData[] = [{ @Observer export class UsersUI extends BaseComponentPlus({} as {}, {}) { render() { - let users = GetUsers(); + const users = GetUsers(); // const userExtraInfoMap = GetUserExtraInfoMap(); const selectedUser = GetSelectedUser(); @@ -55,76 +55,19 @@ export class UsersUI extends BaseComponentPlus({} as {}, {}) { return ; } - users = users.filter(a=>a); - /* users = users.OrderBy((a) => (userExtraInfoMap[a.id] ? userExtraInfoMap[a.id].joinDate : Number.MAX_SAFE_INTEGER)); - users = users.OrderByDescending((a) => (userExtraInfoMap[a.id] ? (userExtraInfoMap[a.id].edits | 0) : Number.MIN_SAFE_INTEGER)); */ - users = users.OrderBy(a=>ToNumber(GetUser(a.id)?.joinDate, Number.MAX_SAFE_INTEGER)); - users = users.OrderByDescending(a=>ToNumber(GetUser(a.id)?.edits, 0)); - const [sortedAndFilteredUsers, setSortedAndFilteredUsers] = useState(users); - const onTableChange = (tableData:TableData)=>{ setTableData({ columnSort: tableData.columnSort, columnSortDirection: tableData.columnSortDirection, filters: [...tableData.filters], }); - let output: User[] = users; - - if (tableData.columnSort) { - switch (tableData.columnSort) { - case "displayName": { - output = users.OrderBy(a=>a.displayName); - break; - } - case "joined": { - output = users.OrderBy(a=>ToNumber(GetUser(a.id)?.joinDate, Number.MAX_SAFE_INTEGER)); - break; - } - case "edits": { - output = users.OrderByDescending(a=>ToNumber(GetUser(a.id)?.edits, 0)); - break; - } - case "lastEdit": { - output = users.OrderByDescending(a=>ToNumber(GetUser(a.id)?.lastEditAt, 0)); - break; - } - case "permissions": { - output = users.OrderBy(a=>{ - let nrOfPermissions = 0; - if (a.permissionGroups.basic) nrOfPermissions++; - if (a.permissionGroups.verified) nrOfPermissions++; - if (a.permissionGroups.mod) nrOfPermissions++; - if (a.permissionGroups.admin) nrOfPermissions++; - return nrOfPermissions; - }); - break; - } - default: { - console.warn(`Unknown columnSort: ${tableData.columnSort}`); - break; - } - } - } - if (tableData.columnSortDirection == "desc") { - output = output.reverse(); - } - - for (const filter of tableData.filters) { - output = output.filter(a=>{ - if (filter.key == "displayName") return a.displayName.toLowerCase().includes(filter.value.toLowerCase()); - if (filter.key == "joined") return Moment(a.joinDate).format("YYYY-MM-DD").includes(filter.value); - if (filter.key == "edits") return (a.edits || 0).toString().includes(filter.value); - if (filter.key == "lastEdit" && a.lastEditAt) return Moment(a.lastEditAt).format("YYYY-MM-DD").includes(filter.value); - if (filter.key == "permissions") return ["basic", "verified", "mod", "admin"].filter(b=>(a.permissionGroups || {})[b]).join(", ").toLowerCase().includes(filter.value.toLowerCase()); - console.error("Unknown filter key:", filter.key); - }); - } - - setSortedAndFilteredUsers([...output]); }; - const [tableData, setTableData] = useState({columnSort: "", columnSortDirection: "", filters: []} as TableData); + const sortedAndFilteredUsers = useMemo(()=>{ + return sortAndFilterUsers(users, tableData); + }, [users, tableData]); + return ( @@ -133,7 +76,7 @@ export class UsersUI extends BaseComponentPlus({} as {}, {}) { })}> {users.length == 0 &&
Loading...
} {sortedAndFilteredUsers.map((user, index)=>{ - return ; + return ; })}
@@ -141,6 +84,70 @@ export class UsersUI extends BaseComponentPlus({} as {}, {}) { } } +function sortAndFilterUsers(users: User[], tableData: TableData) { + let output: User[] = users.slice(); + + // start with the "default sorting" + /*output = output.OrderBy((a) => (userExtraInfoMap[a.id] ? userExtraInfoMap[a.id].joinDate : Number.MAX_SAFE_INTEGER)); + output = output.OrderByDescending((a) => (userExtraInfoMap[a.id] ? (userExtraInfoMap[a.id].edits | 0) : Number.MIN_SAFE_INTEGER));*/ + output = output.OrderBy(a=>ToNumber(GetUser(a.id)?.joinDate, Number.MAX_SAFE_INTEGER)); + output = output.OrderByDescending(a=>ToNumber(GetUser(a.id)?.edits, 0)); + + // then apply user's custom sorting + if (tableData.columnSort) { + switch (tableData.columnSort) { + case "displayName": { + output = output.OrderBy(a=>a.displayName); + break; + } + case "joined": { + output = output.OrderBy(a=>ToNumber(GetUser(a.id)?.joinDate, Number.MAX_SAFE_INTEGER)); + break; + } + case "edits": { + output = output.OrderByDescending(a=>ToNumber(GetUser(a.id)?.edits, 0)); + break; + } + case "lastEdit": { + output = output.OrderByDescending(a=>ToNumber(GetUser(a.id)?.lastEditAt, 0)); + break; + } + case "permissions": { + output = output.OrderBy(a=>{ + let nrOfPermissions = 0; + if (a.permissionGroups.basic) nrOfPermissions++; + if (a.permissionGroups.verified) nrOfPermissions++; + if (a.permissionGroups.mod) nrOfPermissions++; + if (a.permissionGroups.admin) nrOfPermissions++; + return nrOfPermissions; + }); + break; + } + default: { + console.warn(`Unknown columnSort: ${tableData.columnSort}`); + break; + } + } + } + if (tableData.columnSortDirection == "desc") { + output = output.reverse(); + } + + // then apply user's custom filtering + for (const filter of tableData.filters) { + output = output.filter(a=>{ + if (filter.key == "displayName") return a.displayName.toLowerCase().includes(filter.value.toLowerCase()); + if (filter.key == "joined") return Moment(a.joinDate).format("YYYY-MM-DD").includes(filter.value); + if (filter.key == "edits") return (a.edits || 0).toString().includes(filter.value); + if (filter.key == "lastEdit" && a.lastEditAt) return Moment(a.lastEditAt).format("YYYY-MM-DD").includes(filter.value); + if (filter.key == "permissions") return ["basic", "verified", "mod", "admin"].filter(b=>(a.permissionGroups || {})[b]).join(", ").toLowerCase().includes(filter.value.toLowerCase()); + console.error("Unknown filter key:", filter.key); + }); + } + + return output; +} + @Observer export class UserRow extends BaseComponent<{index: number, last: boolean, user: User}, {}> { render() { diff --git a/Packages/client/Source/UI/Debates.tsx b/Packages/client/Source/UI/Debates.tsx index 5e9d44b0a..53a813f51 100644 --- a/Packages/client/Source/UI/Debates.tsx +++ b/Packages/client/Source/UI/Debates.tsx @@ -100,38 +100,6 @@ export class MapListUI extends BaseComponentPlus({}, {}) { }; const [tableData, setTableData] = useState({columnSort: "", columnSortDirection: "", filters: []} as TableData); - const filterMaps = (maps: Map[], tableData: TableData)=>{ - let output = maps; - if (tableData.columnSort) { - switch (tableData.columnSort) { - case "name": output = output.OrderBy(a=>a.name); break; - case "edits": output = output.OrderByDescending(a=>ToNumber(a.edits, 0)); break; - case "lastEdit": output = output.OrderByDescending(a=>ToNumber(a.editedAt, 0)); break; - case "creator": output = output.OrderBy(a=>a.creator); break; - default: - console.warn("Unknown column key:", tableData.columnSort); - break; - } - - if (tableData.columnSortDirection == "desc") { - output = output.reverse(); - } - } - - for (const filter of tableData.filters) { - const filteringOn = key=>filter.key == "global" || filter.key == key; - output = output.filter(a=>{ - if (filteringOn("name") && a.name.toLowerCase().includes(filter.value.toLowerCase())) return true; - if (filteringOn("edits") && (a.edits || 0).toString().includes(filter.value)) return true; - if (filteringOn("lastEdit") && Moment(a.editedAt).format("YYYY-MM-DD").includes(filter.value)) return true; - if (filteringOn("creator") && GetUser(a.creator)?.displayName.toLowerCase().includes(filter.value)) return true; - return false; - }); - } - - return output; - }; - const maps_featured = maps.filter(a=>a.featured); let listType = uiState.listType; // if in sl-mode, some modes may not have any featured maps; in those cases, set/lock list-type to "all" so user doesn't see an empty list (since default list-type is "featured") @@ -198,4 +166,36 @@ export class MapListUI extends BaseComponentPlus({}, {}) { ); } +} + +function filterMaps(maps: Map[], tableData: TableData) { + let output = maps.slice(); + if (tableData.columnSort) { + switch (tableData.columnSort) { + case "name": output = output.OrderBy(a=>a.name); break; + case "edits": output = output.OrderByDescending(a=>ToNumber(a.edits, 0)); break; + case "lastEdit": output = output.OrderByDescending(a=>ToNumber(a.editedAt, 0)); break; + case "creator": output = output.OrderBy(a=>a.creator); break; + default: + console.warn("Unknown column key:", tableData.columnSort); + break; + } + + if (tableData.columnSortDirection == "desc") { + output = output.reverse(); + } + } + + for (const filter of tableData.filters) { + const filteringOn = key=>filter.key == "global" || filter.key == key; + output = output.filter(a=>{ + if (filteringOn("name") && a.name.toLowerCase().includes(filter.value.toLowerCase())) return true; + if (filteringOn("edits") && (a.edits || 0).toString().includes(filter.value)) return true; + if (filteringOn("lastEdit") && Moment(a.editedAt).format("YYYY-MM-DD").includes(filter.value)) return true; + if (filteringOn("creator") && GetUser(a.creator)?.displayName.toLowerCase().includes(filter.value)) return true; + return false; + }); + } + + return output; } \ No newline at end of file