From 449ad5f06b8f392a7eb54a31ff7393ab2c8bf0e4 Mon Sep 17 00:00:00 2001 From: Maxime GRANDCOLAS Date: Wed, 13 Nov 2024 08:54:25 +0100 Subject: [PATCH] [MS] Handle user status frozen --- client/src/components/users/UserCard.vue | 9 +++-- .../components/users/UserFilterPopover.vue | 15 +++++++ client/src/components/users/UserListItem.vue | 7 +++- client/src/components/users/UserStatusTag.vue | 40 +++++++++++++++++-- client/src/components/users/types.ts | 38 +++++++++++++----- client/src/locales/en-US.json | 8 +++- client/src/locales/fr-FR.json | 8 +++- client/src/parsec/types.ts | 1 + client/src/parsec/user.ts | 14 ++++++- 9 files changed, 118 insertions(+), 22 deletions(-) diff --git a/client/src/components/users/UserCard.vue b/client/src/components/users/UserCard.vue index 2ebdcd063aa..9d45f083504 100644 --- a/client/src/components/users/UserCard.vue +++ b/client/src/components/users/UserCard.vue @@ -8,7 +8,6 @@ selected: user.isSelected, 'no-padding-end': !user.isSelected, revoked: user.isRevoked(), - frozen: user.isFrozen(), 'user-hovered': !user.isSelected && (menuOpened || isHovered), }" @click="$emit('click', $event, user)" @@ -30,10 +29,14 @@
- +
+ + + + - +
diff --git a/client/src/components/users/UserStatusTag.vue b/client/src/components/users/UserStatusTag.vue index db48c9a75e6..44a353bf2c4 100644 --- a/client/src/components/users/UserStatusTag.vue +++ b/client/src/components/users/UserStatusTag.vue @@ -1,22 +1,49 @@ diff --git a/client/src/components/users/types.ts b/client/src/components/users/types.ts index 7e8977b7a8b..1d854350317 100644 --- a/client/src/components/users/types.ts +++ b/client/src/components/users/types.ts @@ -33,6 +33,7 @@ function compareUserProfiles(profile1: UserProfile, profile2: UserProfile): numb export interface UserFilterLabels { statusActive?: boolean; statusRevoked?: boolean; + statusFrozen?: boolean; profileAdmin?: boolean; profileStandard?: boolean; profileOutsider?: boolean; @@ -51,6 +52,7 @@ export class UserCollection { this.filters = { statusActive: true, statusRevoked: true, + statusFrozen: true, profileAdmin: true, profileStandard: true, profileOutsider: true, @@ -99,7 +101,11 @@ export class UserCollection { ) { return false; } - if ((!this.filters.statusRevoked && user.isRevoked()) || (!this.filters.statusActive && !user.isRevoked())) { + if ( + (!this.filters.statusRevoked && user.isRevoked()) || + (!this.filters.statusActive && user.isActive()) || + (!this.filters.statusFrozen && user.isFrozen()) + ) { return false; } return true; @@ -117,6 +123,15 @@ export class UserCollection { return this.getSelectedUsers().length; } + private statusDiff(user1: UserModel, user2: UserModel): number { + return ( + Number(user2.isActive()) * 4 + + Number(user2.isRevoked()) * 2 + + Number(user2.isFrozen()) - + (Number(user1.isActive()) * 4 + Number(user1.isRevoked()) * 2 + Number(user1.isFrozen())) + ); + } + sort(property: SortProperty, ascending: boolean): void { this.users.sort((user1, user2) => { // Arbitrary value to keep the current user always at the top of the list @@ -144,18 +159,21 @@ export class UserCollection { } case SortProperty.Profile: if (profile1 === profile2) { - return user2.isRevoked() && !user1.isRevoked() ? -1 : 0; + // return user2.isRevoked() && !user1.isRevoked() ? -1 : 0; + return this.statusDiff(user1, user2); } return diff; case SortProperty.Status: - if (user2.isRevoked() === user1.isRevoked()) { - return ascending ? diff : -diff; - } - if (ascending) { - return user2.isRevoked() && !user1.isRevoked() ? -1 : 0; - } else { - return user1.isRevoked() && !user2.isRevoked() ? -1 : 0; - } + return ascending ? this.statusDiff(user1, user2) : this.statusDiff(user2, user1); + + // if (user2.isRevoked() === user1.isRevoked()) { + // return ascending ? diff : -diff; + // } + // if (ascending) { + // return user2.isRevoked() && !user1.isRevoked() ? -1 : 0; + // } else { + // return user1.isRevoked() && !user2.isRevoked() ? -1 : 0; + // } default: return 0; } diff --git a/client/src/locales/en-US.json b/client/src/locales/en-US.json index e0257629b66..7f2077dac2f 100644 --- a/client/src/locales/en-US.json +++ b/client/src/locales/en-US.json @@ -955,7 +955,13 @@ }, "status": { "active": "Active", - "revoked": "Revoked" + "revoked": "Revoked", + "frozen": "Suspended" + }, + "statusDescriptions": { + "active": "User is active.", + "revoked": "User has been revoked and can no longer access this organization.", + "frozen": "User is suspended and cannot access this organization." }, "success": { "email": "Email address:", diff --git a/client/src/locales/fr-FR.json b/client/src/locales/fr-FR.json index ddea86606bf..af628533a97 100644 --- a/client/src/locales/fr-FR.json +++ b/client/src/locales/fr-FR.json @@ -955,7 +955,13 @@ }, "status": { "active": "Actif", - "revoked": "Révoqué" + "revoked": "Révoqué", + "frozen": "Suspendu" + }, + "statusDescriptions": { + "active": "L'utilisateur est actif.", + "revoked": "L'utilisateur a été révoqué et ne peux plus accéder à cette organisation.", + "frozen": "L'utilisateur a été suspendu et ne peut pas accéder à cette organisation." }, "success": { "email": "Adresse email :", diff --git a/client/src/parsec/types.ts b/client/src/parsec/types.ts index 83e255f9777..5aead54fe07 100644 --- a/client/src/parsec/types.ts +++ b/client/src/parsec/types.ts @@ -198,6 +198,7 @@ type SystemPath = Path; interface UserInfo extends ParsecUserInfo { isRevoked: () => boolean; isFrozen: () => boolean; + isActive: () => boolean; } interface OwnDeviceInfo extends DeviceInfo { diff --git a/client/src/parsec/user.ts b/client/src/parsec/user.ts index 4dd520de44c..8778b49d281 100644 --- a/client/src/parsec/user.ts +++ b/client/src/parsec/user.ts @@ -20,6 +20,8 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise = frozenResult.ok ? frozenResult.value : []; if (pattern.length > 0) { // Won't be using dates or `isRevoked` so the cast is fine result.value = filterUserList(result.value as Array, pattern); @@ -30,7 +32,9 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise item.revokedOn !== null; - (item as UserInfo).isFrozen = (): boolean => false; + (item as UserInfo).isFrozen = (): boolean => + !(item as UserInfo).isRevoked() && frozen.find((userId) => userId === item.id) !== undefined; + (item as UserInfo).isActive = (): boolean => !(item as UserInfo).isRevoked() && !(item as UserInfo).isFrozen(); return item; }); } @@ -50,6 +54,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise false, isFrozen: (): boolean => false, + isActive: (): boolean => true, }, { id: 'id1', @@ -62,6 +67,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise false, isFrozen: (): boolean => false, + isActive: (): boolean => true, }, { id: 'id2', @@ -74,6 +80,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise false, isFrozen: (): boolean => false, + isActive: (): boolean => true, }, { id: 'id3', @@ -86,6 +93,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise false, isFrozen: (): boolean => true, + isActive: (): boolean => false, }, { id: 'id4', @@ -98,6 +106,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise false, isFrozen: (): boolean => false, + isActive: (): boolean => true, }, ]; if (!skipRevoked) { @@ -113,6 +122,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise true, isFrozen: (): boolean => false, + isActive: (): boolean => false, }, { id: 'id6', @@ -125,6 +135,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise true, isFrozen: (): boolean => false, + isActive: (): boolean => false, }, { id: 'id7', @@ -137,6 +148,7 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise true, isFrozen: (): boolean => false, + isActive: (): boolean => false, }, ); }