Skip to content

Commit

Permalink
* Fixed that users table would not have its visual results change, ev…
Browse files Browse the repository at this point in the history
…en 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]
  • Loading branch information
Venryx committed May 21, 2024
1 parent 1cb6b67 commit 6748086
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 96 deletions.
135 changes: 71 additions & 64 deletions Packages/client/Source/UI/Database/Users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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();

Expand All @@ -55,76 +55,19 @@ export class UsersUI extends BaseComponentPlus({} as {}, {}) {
return <UserProfileUI user={selectedUser}/>;
}

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 (
<PageContainer style={{padding: 0, background: null}}>
<TableHeader columns={columns} onTableChange={onTableChange} tableData={tableData}/>
Expand All @@ -133,14 +76,78 @@ export class UsersUI extends BaseComponentPlus({} as {}, {}) {
})}>
{users.length == 0 && <div style={{textAlign: "center", fontSize: 18}}>Loading...</div>}
{sortedAndFilteredUsers.map((user, index)=>{
return <UserRow key={user.id} index={index} last={index == users.length - 1} user={user}/>;
return <UserRow key={user.id} index={index} last={index == sortedAndFilteredUsers.length - 1} user={user}/>;
})}
</ScrollView>
</PageContainer>
);
}
}

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() {
Expand Down
64 changes: 32 additions & 32 deletions Packages/client/Source/UI/Debates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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;
}

0 comments on commit 6748086

Please sign in to comment.