feat(core): adjust member order (#5685)

close #5686

`Owner >> Unaccepted > Admin > Write > Read`

This algorithm contains two parts: firstly, it calculates the weight of the Member (calculateWeight), and then, it uses set weights to sort the Members (useMembers).

In the calculateWeight part, the computation of the weight involves three primary factors:

1. **Permission Level**: The `Owner` is given the highest weight of `4`, followed by `Admin` with a weight of `3`, then `Write` with a weight of `2`, and finally, `Read`, with a weight of `1`.
2. **Acceptance Status**: `Unaccepted` members have a higher weight, this weight is `1`.
3. The weight corresponding to the permission level, if the member does not exist, this weight is 0.

These three `factors` are stored in the factors array and then processed through the reduce function for weighted sum calculation. Among them, `factor * Math.pow(10, arr.length - 1 - index)` means the more significant weight factors (i.e., the earlier factors) will be assigned a higher value.

Sorting rules are primarily based on the weight values obtained from the calculateWeight function. If the weights are identical, it then sorts by name, here assuming the weight of the name being `null` is the highest. If the names are not `null`, they are sorted alphabetically.
This commit is contained in:
JimmFly
2024-01-24 12:44:01 +00:00
parent 0f67c683c9
commit ad1521fd81

View File

@@ -1,10 +1,31 @@
import {
type GetMembersByWorkspaceIdQuery,
getMembersByWorkspaceIdQuery,
Permission,
} from '@affine/graphql';
import { useMemo } from 'react';
import { useQuery } from '../use-query';
export function calculateWeight(member: Member) {
const permissionWeight = {
[Permission.Owner]: 4,
[Permission.Admin]: 3,
[Permission.Write]: 2,
[Permission.Read]: 1,
};
const factors = [
Number(member.permission === Permission.Owner), // Owner weight is the highest
Number(!member.accepted), // Unaccepted members are before accepted members
permissionWeight[member.permission] || 0,
];
return factors.reduce((ret, factor, index, arr) => {
return ret + factor * Math.pow(10, arr.length - 1 - index);
}, 0);
}
export type Member = Omit<
GetMembersByWorkspaceIdQuery['workspace']['members'][number],
'__typename'
@@ -22,5 +43,20 @@ export function useMembers(
take,
},
});
return data.workspace.members;
const members = data.workspace.members;
return useMemo(() => {
// sort members by weight
return members.sort((a, b) => {
const weightDifference = calculateWeight(b) - calculateWeight(a);
if (weightDifference !== 0) {
return weightDifference;
}
// if weight is the same, sort by name
if (a.name === null) return 1;
if (b.name === null) return -1;
return a.name.localeCompare(b.name);
});
}, [members]);
}