feat: Improve translations, fade inactive collection members

This commit is contained in:
Tom Moor
2022-09-13 08:47:41 +01:00
parent 6502aff4ef
commit 7d92b60e97
5 changed files with 73 additions and 12 deletions

View File

@@ -1,4 +1,6 @@
import { subMinutes } from "date-fns";
import { computed, observable } from "mobx";
import { now } from "mobx-utils";
import type { Role } from "@shared/types";
import ParanoidModel from "./ParanoidModel";
import Field from "./decorators/Field";
@@ -39,6 +41,17 @@ class User extends ParanoidModel {
return !this.lastActiveAt;
}
/**
* Whether the user has been recently active. Recently is currently defined
* as within the last 5 minutes.
*
* @returns true if the user has been active recently
*/
@computed
get isRecentlyActive(): boolean {
return new Date(this.lastActiveAt) > subMinutes(now(10000), 5);
}
@computed
get role(): Role {
if (this.isAdmin) {

View File

@@ -1,8 +1,12 @@
import { sortBy } from "lodash";
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import { PAGINATION_SYMBOL } from "~/stores/BaseStore";
import Collection from "~/models/Collection";
import User from "~/models/User";
import Avatar from "~/components/Avatar";
import Facepile from "~/components/Facepile";
import Fade from "~/components/Fade";
import NudeButton from "~/components/NudeButton";
@@ -17,7 +21,8 @@ type Props = {
const MembershipPreview = ({ collection, limit = 8 }: Props) => {
const [isLoading, setIsLoading] = React.useState(false);
const [totalMemberships, setTotalMemberships] = React.useState(0);
const [usersCount, setUsersCount] = React.useState(0);
const [groupsCount, setGroupsCount] = React.useState(0);
const { t } = useTranslation();
const { memberships, collectionGroupMemberships, users } = useStores();
const collectionUsers = users.inCollection(collection.id);
@@ -39,9 +44,8 @@ const MembershipPreview = ({ collection, limit = 8 }: Props) => {
memberships.fetchPage(options),
collectionGroupMemberships.fetchPage(options),
]);
setTotalMemberships(
users[PAGINATION_SYMBOL].total + groups[PAGINATION_SYMBOL].total
);
setUsersCount(users[PAGINATION_SYMBOL].total);
setGroupsCount(groups[PAGINATION_SYMBOL].total);
} finally {
setIsLoading(false);
}
@@ -60,24 +64,55 @@ const MembershipPreview = ({ collection, limit = 8 }: Props) => {
return null;
}
const overflow = totalMemberships - collectionUsers.length;
const overflow = usersCount - groupsCount - collectionUsers.length;
return (
<NudeButton
context={context}
action={editCollectionPermissions}
tooltip={{
tooltip: t("Users and groups with access"),
tooltip:
usersCount > 0
? groupsCount > 0
? groupsCount > 1
? t(
`{{ usersCount }} users and {{ groupsCount }} groups with access`,
{ usersCount, count: usersCount }
)
: t(`{{ usersCount }} users and a group have access`, {
usersCount,
count: usersCount,
})
: t(`{{ usersCount }} users with access`, {
usersCount,
count: usersCount,
})
: t(`{{ groupsCount }} groups with access`, {
groupsCount,
count: groupsCount,
}),
delay: 250,
}}
width="auto"
height="auto"
>
<Fade>
<Facepile users={collectionUsers} overflow={overflow} limit={limit} />
<Facepile
users={sortBy(collectionUsers, "lastActiveAt")}
overflow={overflow}
limit={limit}
renderAvatar={(user) => (
<StyledAvatar user={user} src={user.avatarUrl} size={32} />
)}
/>
</Fade>
</NudeButton>
);
};
const StyledAvatar = styled(Avatar)<{ user: User }>`
transition: opacity 250ms ease-in-out;
opacity: ${(props) => (props.user.isRecentlyActive ? 1 : 0.5)};
`;
export default observer(MembershipPreview);

View File

@@ -135,6 +135,7 @@
"mime-types": "^2.1.35",
"mobx": "^4.15.4",
"mobx-react": "^6.3.1",
"mobx-utils": "^6.0.5",
"natural-sort": "^1.0.0",
"node-fetch": "2.6.7",
"node-htmldiff": "^0.9.4",
@@ -351,4 +352,4 @@
"jpeg-js": "0.4.4"
},
"version": "0.66.0"
}
}

View File

@@ -347,7 +347,14 @@
"Get started by creating a new one!": "Get started by creating a new one!",
"Create a document": "Create a document",
"Manage permissions": "Manage permissions",
"Users and groups with access": "Users and groups with access",
"{{ usersCount }} users and {{ groupsCount }} groups with access": "{{ usersCount }} user and {{ groupsCount }} groups with access",
"{{ usersCount }} users and {{ groupsCount }} groups with access_plural": "{{ usersCount }} users and {{ groupsCount }} groups with access",
"{{ usersCount }} users and a group have access": "{{ usersCount }} user and a group have access",
"{{ usersCount }} users and a group have access_plural": "{{ usersCount }} users and a group have access",
"{{ usersCount }} users with access": "{{ usersCount }} user with access",
"{{ usersCount }} users with access_plural": "{{ usersCount }} users with access",
"{{ groupsCount }} groups with access": "{{ groupsCount }} group with access",
"{{ groupsCount }} groups with access_plural": "{{ groupsCount }} groups with access",
"The collection was updated": "The collection was updated",
"You can edit the name and other details at any time, however doing so often might confuse your team mates.": "You can edit the name and other details at any time, however doing so often might confuse your team mates.",
"Name": "Name",

View File

@@ -1043,7 +1043,7 @@
debug "^4.1.0"
globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.16.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
version "7.18.10"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.10.tgz#4908e81b6b339ca7c6b7a555a5fc29446f26dde6"
integrity sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==
@@ -8835,7 +8835,7 @@ is-ci@^2.0.0:
dependencies:
ci-info "^2.0.0"
is-core-module@^2.2.0, is-core-module@^2.8.0, is-core-module@^2.9.0:
is-core-module@^2.8.0, is-core-module@^2.9.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed"
integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==
@@ -10968,6 +10968,11 @@ mobx-react@^6.3.1:
dependencies:
mobx-react-lite "^2.2.0"
mobx-utils@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/mobx-utils/-/mobx-utils-6.0.5.tgz#0cce9afb07fbba1fb559f959f8cea1f44baa7252"
integrity sha512-QOduwicYedD4mwYZRl8+c3BalljFDcubg+PUGqBkn8tOuBoj2q7GhjXBP6JXM9J+Zh+2mePK8IoToeLfqr3Z/w==
mobx@^4.15.4:
version "4.15.7"
resolved "https://registry.yarnpkg.com/mobx/-/mobx-4.15.7.tgz#933281268c3b4658b6cf2526e872cf78ea48ab95"
@@ -11814,7 +11819,7 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-parse@^1.0.6, path-parse@^1.0.7:
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==