From a7c8d681470584fdaa067fe0027a87c73f48a2af Mon Sep 17 00:00:00 2001 From: Francesco Menghi <53121061+menghif@users.noreply.github.com> Date: Sat, 15 Jan 2022 14:15:35 -0500 Subject: [PATCH] - Initial work from @irenejoeunpark with PR #2491 - Changed repos display to row, added border bottom for header, added hint icon for accordion - Fixed clicking on expand icon copies link to blog post - Added expand icons in the bottom of the github info - Added function to auto close accordion when scroll pass post - Added css for mobile device < 375 px width --- src/web/src/components/Posts/ExpandIcon.tsx | 49 +++++ src/web/src/components/Posts/GitHubInfo.tsx | 2 +- .../src/components/Posts/GitHubInfoMobile.tsx | 51 +++++ src/web/src/components/Posts/Post.tsx | 187 ++++++++++++------ src/web/src/components/Posts/PostAvatar.tsx | 7 +- src/web/src/components/Posts/Repos.tsx | 2 +- src/web/src/components/Posts/ShareButton.tsx | 7 +- 7 files changed, 242 insertions(+), 63 deletions(-) create mode 100644 src/web/src/components/Posts/ExpandIcon.tsx create mode 100644 src/web/src/components/Posts/GitHubInfoMobile.tsx diff --git a/src/web/src/components/Posts/ExpandIcon.tsx b/src/web/src/components/Posts/ExpandIcon.tsx new file mode 100644 index 0000000000..1057bd0003 --- /dev/null +++ b/src/web/src/components/Posts/ExpandIcon.tsx @@ -0,0 +1,49 @@ +import { IconButton, createStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import ExpandLessIcon from '@material-ui/icons/ExpandLess'; + +type Props = { + small: Boolean; + expandHeader: Boolean; + setExpandHeader: Function; +}; + +const useStyles = makeStyles(() => + createStyles({ + container: { + display: 'flex', + justifyContent: 'center', + }, + smallIcon: { + padding: 0, + fill: '#cccccc', + }, + bigIcon: { + fontSize: '5rem', + fill: '#cccccc', + }, + iconBtn: { + padding: '5px', + }, + }) +); +const ExpandIcon = ({ small, expandHeader, setExpandHeader }: Props) => { + const classes = useStyles(); + return small ? ( + setExpandHeader(!expandHeader)} className={classes.iconBtn}> + {expandHeader ? ( + + ) : ( + + )} + + ) : ( +
+ setExpandHeader(!expandHeader)} className={classes.iconBtn}> + + +
+ ); +}; +export default ExpandIcon; diff --git a/src/web/src/components/Posts/GitHubInfo.tsx b/src/web/src/components/Posts/GitHubInfo.tsx index fb869a82af..9e9693c0f7 100644 --- a/src/web/src/components/Posts/GitHubInfo.tsx +++ b/src/web/src/components/Posts/GitHubInfo.tsx @@ -39,7 +39,7 @@ const parseGitHubUrl = (url: string): URL | null => { } }; -const filterGitHubUrls = (urls: string[]) => { +export const filterGitHubUrls = (urls: string[]) => { const issues: Set = new Set(); const pullRequests: Set = new Set(); const repos: Set = new Set(); diff --git a/src/web/src/components/Posts/GitHubInfoMobile.tsx b/src/web/src/components/Posts/GitHubInfoMobile.tsx new file mode 100644 index 0000000000..1f8e3d5d6c --- /dev/null +++ b/src/web/src/components/Posts/GitHubInfoMobile.tsx @@ -0,0 +1,51 @@ +import { createStyles, makeStyles, Theme, ListSubheader } from '@material-ui/core'; +import Repos from './Repos'; +import Issues from './Issues'; +import PullRequests from './PullRequests'; +import Commits from './Commits'; +import Users from './Users'; +import { filterGitHubUrls } from './GitHubInfo'; + +type Props = { + ghUrls: string[]; +}; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + padding: '0', + display: 'flex', + flexDirection: 'column', + marginTop: '0', + lineHeight: '1', + [theme.breakpoints.up('lg')]: { + width: '21rem', + }, + color: theme.palette.text.secondary, + }, + GitHubInfoContainer: { + margin: '0 0 0 1rem', + }, + }) +); + +const GitHubInfoMobile = ({ ghUrls }: Props) => { + const classes = useStyles(); + const { repos, issues, pullRequests, commits, users } = filterGitHubUrls(ghUrls); + + return ( +
+ +
+ {!!repos.length && } + {!!issues.length && } + {!!pullRequests.length && } + {!!commits.length && } + {!!users.length && } +
+
+
+ ); +}; + +export default GitHubInfoMobile; diff --git a/src/web/src/components/Posts/Post.tsx b/src/web/src/components/Posts/Post.tsx index 2a47b7c87d..24b4f67d4c 100644 --- a/src/web/src/components/Posts/Post.tsx +++ b/src/web/src/components/Posts/Post.tsx @@ -1,4 +1,4 @@ -import { useRef, useState, useMemo } from 'react'; +import { useRef, useState, useMemo, useEffect } from 'react'; import useSWR from 'swr'; import clsx from 'clsx'; import { makeStyles, Theme, useTheme } from '@material-ui/core/styles'; @@ -9,6 +9,9 @@ import { ListSubheader, createStyles, useMediaQuery, + Accordion, + AccordionSummary, + AccordionDetails, Chip, } from '@material-ui/core'; import ErrorRoundedIcon from '@material-ui/icons/ErrorRounded'; @@ -19,7 +22,9 @@ import Spinner from '../Spinner'; import PostDesktopInfo from './PostInfo'; import PostAvatar from './PostAvatar'; import GitHubInfo from './GitHubInfo'; +import GitHubInfoMobile from './GitHubInfoMobile'; import ShareButton from './ShareButton'; +import ExpandIcon from './ExpandIcon'; import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'; @@ -61,7 +66,8 @@ const useStyles = makeStyles((theme: Theme) => gridTemplateColumns: 'auto auto auto auto', justifyContent: 'left', width: '100%', - padding: '1em 0 1em 0', + padding: '1em 0 0 0', + marginBottom: '0', }, }, video: { @@ -104,6 +110,7 @@ const useStyles = makeStyles((theme: Theme) => fontSize: 'clamp(2.5em, 4vw, 3em)', [theme.breakpoints.down(1205)]: { textAlign: 'start', + fontSize: '2em', marginLeft: '.3em', }, [theme.breakpoints.down(1024)]: { @@ -183,7 +190,7 @@ const useStyles = makeStyles((theme: Theme) => [theme.breakpoints.down(1024)]: { fontSize: '1.1em', height: '5px', - margin: '-1.6em 1em -1em .5px', + margin: '-1.6em -.5em .5px', }, }, authorAvatarContainer: { @@ -215,6 +222,30 @@ const useStyles = makeStyles((theme: Theme) => width: 'auto', }, }, + accordionSummary: { + marginTop: '0', + paddingRight: '0', + justifyContent: 'flex-end', + overflow: 'hidden', + textOverflow: 'ellipsis', + paddingBottom: '0', + '& .MuiAccordionSummary-content': { + marginBottom: '0.2em', + }, + }, + accordion: { + backgroundColor: 'inherit', + borderBottom: '1.5px solid #cccccc', + boxShadow: 'none', + top: '0', + zIndex: 1, + position: 'sticky', + }, + expandIcon: { + alignSelf: 'center', + borderLeft: '1px solid #cccccc', + paddingLeft: '5px', + }, }) ); @@ -271,6 +302,7 @@ const PostComponent = ({ postUrl, currentPost, totalPosts }: Props) => { const desktop = useMediaQuery(theme.breakpoints.up(1205)); // We need a ref to our post content, which we inject into a
below. const sectionEl = useRef(null); + // Grab the post data from our backend so we can render it const { data: post, error } = useSWR(postUrl); const isMedia = post?.type === 'video'; @@ -281,6 +313,23 @@ const PostComponent = ({ postUrl, currentPost, totalPosts }: Props) => { [post?.html] ); + useEffect(() => { + const onScroll = () => { + // get the distance between the bottom of the blog post and + // the top of the web page + const bottom = sectionEl?.current?.getBoundingClientRect().bottom; + if (bottom && bottom < 1) { + // if bottom reaches top => close header and remove event listener + setExpandHeader(false); + window.removeEventListener('scroll', onScroll); + } + }; + // only if header is open, we attach the onScroll function to scroll event + if (expandHeader) { + window.addEventListener('scroll', onScroll); + } + }, [expandHeader]); + if (error) { console.error(`Error loading post at ${postUrl}`, error); return ( @@ -331,63 +380,89 @@ const PostComponent = ({ postUrl, currentPost, totalPosts }: Props) => { )} - -
- - setExpandHeader(!expandHeader)} - onKeyDown={() => setExpandHeader(!expandHeader)} - > - {post.title} - - -
- {!desktop && ( - <> -
- -
-
-

- - {post.feed.author} - -

+ {desktop ? ( + <> + +
+ + setExpandHeader(!expandHeader)} + onKeyDown={() => setExpandHeader(!expandHeader)} + > + {post.title} + +
-
-

- - - - - -

+ + + + {!!extractedGitHubUrls.length && } + + + ) : ( + setExpandHeader(!expandHeader)} + expanded={expandHeader} + className={classes.accordion} + > + + +
+ + + {post.title} + + +
+
+ +
+ + - - )} -
- {desktop && ( - - - {!!extractedGitHubUrls.length && } - + +
+ + {!!extractedGitHubUrls.length && } + + +
)} +
{isMedia && ( height: '2.5em', [theme.breakpoints.down(1200)]: { fontSize: '2.5em', - width: '2.5em', - height: '2.5em', }, [theme.breakpoints.down(1024)]: { fontSize: '2em', - width: '2.5em', - height: '2.5em', + }, + [theme.breakpoints.down(375)]: { + fontSize: '1.7em', }, }, text: { diff --git a/src/web/src/components/Posts/Repos.tsx b/src/web/src/components/Posts/Repos.tsx index 55a15d3e54..8706b5f516 100644 --- a/src/web/src/components/Posts/Repos.tsx +++ b/src/web/src/components/Posts/Repos.tsx @@ -28,7 +28,7 @@ const useStyles = makeStyles((theme: Theme) => repos: { paddingLeft: 0, display: 'flex', - flexDirection: 'column', + flexWrap: 'wrap', gap: '1.5rem', }, repo: { diff --git a/src/web/src/components/Posts/ShareButton.tsx b/src/web/src/components/Posts/ShareButton.tsx index 497fcba821..14e6954c48 100644 --- a/src/web/src/components/Posts/ShareButton.tsx +++ b/src/web/src/components/Posts/ShareButton.tsx @@ -24,6 +24,10 @@ const useStyles = makeStyles((theme: Theme) => check: { fill: '#3fb950', }, + + iconBtn: { + padding: '5px', + }, }) ); @@ -44,6 +48,7 @@ const ShareButton = ({ url }: Props) => { return !isCopiedToClipboard ? ( { copyToClipboardEvent(); }} @@ -53,7 +58,7 @@ const ShareButton = ({ url }: Props) => { ) : ( - +