Skip to content

Commit

Permalink
feat: add user tooltip for user links
Browse files Browse the repository at this point in the history
  • Loading branch information
drodil committed Nov 20, 2024
1 parent 16da6c7 commit 2f5a412
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ListItem from '@mui/material/ListItem';
import React from 'react';
import { useTranslation, useUserFollow } from '../../hooks';
import { RightList, RightListContainer } from '../Styled/RightList';
import { UserChip } from '../TagsAndEntities/UserChip';

export const FollowedUsersList = () => {
const users = useUserFollow();
const { t } = useTranslation();

if (users.users.length === 0 || users.loading) {
return null;
}

return (
<RightListContainer>
<RightList title={t('rightMenu.followedUsers')}>
<ListItem style={{ display: 'block' }} dense>
{users.users.map(user => (
<UserChip key={user} entityRef={user} />
))}
</ListItem>
</RightList>
</RightListContainer>
);
};
1 change: 1 addition & 0 deletions plugins/qeta-react/src/components/FollowedLists/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { FollowedEntitiesList } from './FollowedEntitiesList';
export { FollowedTagsList } from './FollowedTagsList';
export { FollowedCollectionsList } from './FollowedCollectionsList';
export { FollowedUsersList } from './FollowedUsersList';
14 changes: 11 additions & 3 deletions plugins/qeta-react/src/components/Links/Links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Link, LinkProps } from '@backstage/core-components';
import { userRouteRef } from '../../routes';
import { Answer, Comment, Post } from '@drodil/backstage-plugin-qeta-common';
import { useTranslation } from '../../hooks';
import { UserTooltip } from '../TagsAndEntities/UserChip';
import Tooltip from '@mui/material/Tooltip';

export const UserLink = (props: {
entityRef: string;
Expand All @@ -20,9 +22,15 @@ export const UserLink = (props: {
return <>{t('userLink.anonymous')}</>;
}
return (
<Link to={`${userRoute()}/${entityRef}`} {...linkProps}>
{userName}
</Link>
<Tooltip
arrow
title={<UserTooltip entityRef={entityRef} />}
enterDelay={400}
>
<Link to={`${userRoute()}/${entityRef}`} {...linkProps}>
{userName}
</Link>
</Tooltip>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@drodil/backstage-plugin-qeta-common';
import { TagsAndEntities } from '../TagsAndEntities/TagsAndEntities';
import { useRouteRef } from '@backstage/core-plugin-api';
import { articleRouteRef, questionRouteRef, userRouteRef } from '../../routes';
import { articleRouteRef, questionRouteRef } from '../../routes';
import { RelativeTimeWithTooltip } from '../RelativeTimeWithTooltip';
import { useSignal } from '@backstage/plugin-signals-react';
import { VoteButtons } from '../Buttons/VoteButtons';
Expand All @@ -25,6 +25,7 @@ import HelpOutlined from '@mui/icons-material/HelpOutlined';
import { useTranslation } from '../../hooks';
import { useEntityAuthor } from '../../hooks/useEntityAuthor';
import { VoteButtonContainer } from '../Styled/VoteButtonContainer';
import { UserLink } from '../Links';

export interface PostListItemProps {
post: PostResponse;
Expand Down Expand Up @@ -52,7 +53,6 @@ export const PostListItem = (props: PostListItemProps) => {

const questionRoute = useRouteRef(questionRouteRef);
const articleRoute = useRouteRef(articleRouteRef);
const userRoute = useRouteRef(userRouteRef);
const { name, initials, user } = useEntityAuthor(post);

const route = post.type === 'question' ? questionRoute : articleRoute;
Expand Down Expand Up @@ -168,11 +168,7 @@ export const PostListItem = (props: PostListItemProps) => {
>
{initials}
</Avatar>
{post.author === 'anonymous' ? (
t('common.anonymousAuthor')
) : (
<Link to={`${userRoute()}/${post.author}`}>{name}</Link>
)}{' '}
<UserLink entityRef={post.author} />{' '}
<Link to={href} className="qetaPostListItemQuestionBtn">
<RelativeTimeWithTooltip value={post.created} />
</Link>
Expand Down
10 changes: 3 additions & 7 deletions plugins/qeta-react/src/components/PostsGrid/PostsGridItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import React, { useEffect, useState } from 'react';
import { useSignal } from '@backstage/plugin-signals-react';
import { useApi, useRouteRef } from '@backstage/core-plugin-api';
import { articleRouteRef, questionRouteRef, userRouteRef } from '../../routes';
import { articleRouteRef, questionRouteRef } from '../../routes';
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import CardActionArea from '@mui/material/CardActionArea';
Expand All @@ -31,6 +31,7 @@ import VerticalAlignBottomIcon from '@mui/icons-material/VerticalAlignBottom';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import Stack from '@mui/material/Stack';
import { UserLink } from '../Links';

export interface PostsGridItemProps {
post: PostResponse;
Expand All @@ -57,7 +58,6 @@ export const PostsGridItem = (props: PostsGridItemProps) => {

const questionRoute = useRouteRef(questionRouteRef);
const articleRoute = useRouteRef(articleRouteRef);
const userRoute = useRouteRef(userRouteRef);
const { name, initials, user } = useEntityAuthor(post);
const navigate = useNavigate();

Expand Down Expand Up @@ -119,11 +119,7 @@ export const PostsGridItem = (props: PostsGridItemProps) => {
>
{initials}
</Avatar>
{post.author === 'anonymous' ? (
t('common.anonymousAuthor')
) : (
<Link to={`${userRoute()}/${post.author}`}>{name}</Link>
)}{' '}
<UserLink entityRef={post.author} />{' '}
<Link to={href} className="qetaPostListItemQuestionBtn">
<RelativeTimeWithTooltip value={post.created} />
</Link>
Expand Down
89 changes: 89 additions & 0 deletions plugins/qeta-react/src/components/TagsAndEntities/UserChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useRouteRef } from '@backstage/core-plugin-api';
import { userRouteRef } from '../../routes';
import { useTranslation, useUserFollow } from '../../hooks';
import { useEntityPresentation } from '@backstage/plugin-catalog-react';
import React from 'react';
import Chip from '@mui/material/Chip';
import { useNavigate } from 'react-router-dom';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';

export const UserTooltip = (props: { entityRef: string }) => {
const { entityRef } = props;
const { t } = useTranslation();
const {
primaryTitle: userName,
Icon,
secondaryTitle,
} = useEntityPresentation(
entityRef.startsWith('user:') ? entityRef : `user:${entityRef}`,
);
const users = useUserFollow();

return (
<Grid container style={{ padding: '0.5rem' }} spacing={1}>
<Grid item xs={12}>
<Typography variant="h6">
{Icon ? <Icon fontSize="small" /> : null}
{entityRef === 'anonymous' ? t('userLink.anonymous') : userName}
</Typography>
</Grid>
<Grid item xs={12}>
<Typography variant="subtitle2">{secondaryTitle}</Typography>
</Grid>
{!users.loading && (
<Grid item xs={12}>
<Button
size="small"
variant="outlined"
color={users.isFollowingUser(entityRef) ? 'secondary' : 'primary'}
onClick={() => {
if (users.isFollowingUser(entityRef)) {
users.unfollowUser(entityRef);
} else {
users.followUser(entityRef);
}
}}
>
{users.isFollowingUser(entityRef)
? t('userButton.unfollow')
: t('userButton.follow')}
</Button>
</Grid>
)}
</Grid>
);
};

export const UserChip = (props: { entityRef: string }) => {
const navigate = useNavigate();
const { entityRef } = props;
const userRoute = useRouteRef(userRouteRef);
const { t } = useTranslation();
const { primaryTitle: userName } = useEntityPresentation(
entityRef.startsWith('user:') ? entityRef : `user:${entityRef}`,
);
if (entityRef === 'anonymous') {
return <>{t('userLink.anonymous')}</>;
}
return (
<Tooltip
arrow
title={<UserTooltip entityRef={entityRef} />}
enterDelay={400}
>
<Chip
label={userName}
size="small"
className="qetaTagChip"
component="a"
onClick={() => {
navigate(`${userRoute()}/${entityRef}`);
}}
clickable
/>
</Tooltip>
);
};
1 change: 1 addition & 0 deletions plugins/qeta-react/src/translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export const qetaTranslationRef = createTranslationRef({
followedEntities: 'Followed entities',
followedTags: 'Followed tags',
followedCollections: 'Followed collections',
followedUsers: 'Followed users',
},
highlights: {
loadError: 'Failed to load questions',
Expand Down
20 changes: 15 additions & 5 deletions plugins/qeta/src/components/UsersPage/UsersPage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import React from 'react';
import { UsersGrid, useTranslation } from '@drodil/backstage-plugin-qeta-react';
import {
FollowedUsersList,
UsersGrid,
useTranslation,
} from '@drodil/backstage-plugin-qeta-react';
import { ContentHeader } from '@backstage/core-components';
import Grid from '@mui/material/Grid';

export const UsersPage = () => {
const { t } = useTranslation();

return (
<>
<ContentHeader title={t('usersPage.title')} />
<UsersGrid />
</>
<Grid container spacing={4}>
<Grid item md={12} lg={8} xl={9}>
<ContentHeader title={t('usersPage.title')} />
<UsersGrid />
</Grid>
<Grid item lg={4} xl={3}>
<FollowedUsersList />
</Grid>
</Grid>
);
};

0 comments on commit 2f5a412

Please sign in to comment.