Skip to content

Commit

Permalink
code improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
DiogoSoaress committed Feb 15, 2024
1 parent 025ef40 commit 5390cb2
Show file tree
Hide file tree
Showing 15 changed files with 88 additions and 72 deletions.
3 changes: 2 additions & 1 deletion src/components/Blog/BannerForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Container, Grid, Typography } from '@mui/material'
import { MIRROR_SUBSCRIBE_LINK } from '@/config/constants'
import css from './styles.module.css'

const BannerForm = ({ title, subtitle }: { title: string; subtitle: string }) => {
Expand All @@ -13,7 +14,7 @@ const BannerForm = ({ title, subtitle }: { title: string; subtitle: string }) =>
</Typography>
</Grid>
<Grid item xs={12} md={6} className={css.centeredContent} mt={3}>
<iframe src="https://safe.mirror.xyz/subscribe/embed" />
<iframe src={MIRROR_SUBSCRIBE_LINK} />
</Grid>
<img src="/images/banner-lines.svg" className={css.image} />
</Grid>
Expand Down
6 changes: 2 additions & 4 deletions src/components/Blog/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import blogCss from '../styles.module.css'
import { calculateReadingTime } from '@/components/Blog/utils/calculateReadingTime'
import Tags from '@/components/Blog/Tags'
import CategoryIcon from '@/public/images/Blog/category-icon.svg'
import { isAsset, isEntryTypeTag } from '@/lib/typeGuards'
import { isAsset } from '@/lib/typeGuards'
import { type BlogPostEntry } from '@/components/Blog/Post'

const Card = (props: BlogPostEntry) => {
const { slug, title, content, coverImage, tags, category } = props.fields

const tagsList = tags?.filter(isEntryTypeTag)

return (
<div className={css.postCard}>
<Link key={slug} href={`/blog/${slug}`} className={css.link} />
Expand Down Expand Up @@ -44,7 +42,7 @@ const Card = (props: BlogPostEntry) => {
<span style={{ flexGrow: 1 }} />

<Box mt={2}>
<Tags tags={tagsList} />
<Tags tags={tags} />
</Box>
</div>
</div>
Expand Down
6 changes: 2 additions & 4 deletions src/components/Blog/FeaturedPost/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import blogCss from '../styles.module.css'
import { formatBlogDate } from '@/components/Blog/utils/formatBlogDate'
import { calculateReadingTime } from '@/components/Blog/utils/calculateReadingTime'
import { type BlogPostEntry } from '@/components/Blog/Post'
import { isAsset, isEntryTypeTag } from '@/lib/typeGuards'
import { isAsset } from '@/lib/typeGuards'
import CategoryIcon from '@/public/images/Blog/category-icon.svg'

const FeaturedPost = (props: BlogPostEntry) => {
const { slug, coverImage, category, date, title, excerpt, tags, content } = props.fields

const tagsList = tags?.filter(isEntryTypeTag)

return (
<Grid container columnSpacing="60px" rowGap={3} mt={10}>
<Grid item md={7}>
Expand Down Expand Up @@ -47,7 +45,7 @@ const FeaturedPost = (props: BlogPostEntry) => {
<Typography className={css.excerpt}>{excerpt}</Typography>

<Box mt={2}>
<Tags tags={tagsList} />
<Tags tags={tags} />
</Box>
</Grid>
</Grid>
Expand Down
5 changes: 2 additions & 3 deletions src/components/Blog/Post/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { type Entry } from 'contentful'
import type { TypeAuthorSkeleton, TypePostSkeleton } from '@/contentful/types'
import { formatBlogDate } from '@/components/Blog/utils/formatBlogDate'
import { calculateReadingTime } from '@/components/Blog/utils/calculateReadingTime'
import { isAsset, isEntryTypeAuthor, isEntryTypePost, isEntryTypeTag } from '@/lib/typeGuards'
import { isAsset, isEntryTypeAuthor, isEntryTypePost } from '@/lib/typeGuards'
import BlogLayout from '@/components/Blog/Layout'
import ProgressBar from '@/components/Blog/ProgressBar'
import BreadcrumbsNav from '@/components/Blog/BreadcrumbsNav'
Expand All @@ -24,7 +24,6 @@ const BlogPost = ({ blogPost }: { blogPost: BlogPostEntry }) => {
const { title, excerpt, content, coverImage, authors, tags, category, date, relatedPosts, metaTags } = blogPost.fields

const authorsList = authors.filter(isEntryTypeAuthor)
const tagsList = tags?.filter(isEntryTypeTag)
const relatedPostsList = relatedPosts?.filter(isEntryTypePost)

return (
Expand Down Expand Up @@ -53,7 +52,7 @@ const BlogPost = ({ blogPost }: { blogPost: BlogPostEntry }) => {
</Typography>

<Box mt={{ xs: 2, md: 3 }}>
<Tags tags={tagsList} />
<Tags tags={tags} />
</Box>

<Authors authors={authorsList} />
Expand Down
9 changes: 6 additions & 3 deletions src/components/Blog/Tags/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { Chip } from '@mui/material'
import css from '../styles.module.css'
import { type Entry } from 'contentful'
import type { UnresolvedLink, Entry } from 'contentful'
import { type TypeTagSkeleton } from '@/contentful/types'
import { isEntryTypeTag } from '@/lib/typeGuards'

const Tags = ({ tags }: { tags: Entry<TypeTagSkeleton, undefined, string>[] | undefined }) => {
type TagsType = (UnresolvedLink<'Entry'> | Entry<TypeTagSkeleton, undefined, string>)[] | undefined

const Tags = ({ tags }: { tags: TagsType }) => {
if (!tags || !tags.length) return null

return (
<div className={css.tagsWrapper}>
{tags.map((tag) => {
{tags.filter(isEntryTypeTag).map((tag) => {
const { name } = tag.fields

return <Chip key={name} label={name} className={css.chip} />
Expand Down
15 changes: 15 additions & 0 deletions src/components/Blog/Twitter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { extractLastPathname } from '@/lib/urlPatterns'
import { TwitterTweetEmbed } from 'react-twitter-embed'
import css from './styles.module.css'

const Twitter = ({ url }: { url: string }) => {
const tweetId = extractLastPathname(url)

return (
<div className={css.tweetContainer}>
<TwitterTweetEmbed tweetId={tweetId} />
</div>
)
}

export default Twitter
9 changes: 9 additions & 0 deletions src/components/Blog/Twitter/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.tweetContainer {
margin: 24px auto 0;
width: 80%;
}

.tweetContainer > * {
display: flex;
justify-content: center;
}
33 changes: 20 additions & 13 deletions src/components/Blog/Youtube/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { extractYouTubeVideoId } from '@/lib/urlPatterns'
import css from './styles.module.css'

const Youtube = ({ embedId }: { embedId: string }) => (
<div className={css.videoResponsive}>
<iframe
width="853"
height="480"
src={`https://www.youtube-nocookie.com/embed/${embedId}`}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen"
allowFullScreen
title="Embedded youtube"
/>
</div>
)
const YouTube = ({ url }: { url: string }) => {
const videoId = extractYouTubeVideoId(url)

export default Youtube
if (!videoId) return null

return (
<div className={css.videoResponsive}>
<iframe
width="853"
height="480"
src={`https://www.youtube-nocookie.com/embed/${videoId}`}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen"
allowFullScreen
title="Embedded YouTube"
/>
</div>
)
}

export default YouTube
25 changes: 8 additions & 17 deletions src/components/Campaign/RichText/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import css from './styles.module.css'
import { Typography } from '@mui/material'
import { isText } from '@/lib/typeGuards'
import kebabCase from 'lodash/kebabCase'
import { extractLastPathname, extractVideoId, isTwitterUrl, isYouTubeUrl } from '@/lib/urlPatterns'
import { TwitterTweetEmbed } from 'react-twitter-embed'
import Youtube from '@/components/Blog/Youtube'
import { isTwitterUrl, isYouTubeUrl } from '@/lib/urlPatterns'
import YouTube from '@/components/Blog/YouTube'
import Twitter from '@/components/Blog/Twitter'

const options: Options = {
renderNode: {
Expand Down Expand Up @@ -72,20 +72,11 @@ const options: Options = {
[BLOCKS.EMBEDDED_ENTRY]: (node: Node) => {
const entryUrl = node.data.target.fields.url

if (isYouTubeUrl(entryUrl)) {
const videoId = extractVideoId(entryUrl)
if (!videoId) return null

return <Youtube embedId={videoId} />
} else if (isTwitterUrl(entryUrl)) {
const tweetId = extractLastPathname(entryUrl)

return (
<div className={css.tweetContainer}>
<TwitterTweetEmbed tweetId={tweetId} />
</div>
)
}
return isYouTubeUrl(entryUrl) ? (
<YouTube url={entryUrl} />
) : isTwitterUrl(entryUrl) ? (
<Twitter url={entryUrl} />
) : null
},
},
} as unknown as RenderNode
Expand Down
10 changes: 0 additions & 10 deletions src/components/Campaign/RichText/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,3 @@
margin-top: 8px;
font-style: italic;
}

.tweetContainer {
margin: 24px auto 0;
width: 80%;
}

.tweetContainer > * {
display: flex;
justify-content: center;
}
1 change: 1 addition & 0 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const TWITTER_LINK = 'https://x.com/safe'
export const DISCORD_LINK = 'https://chat.safe.global'
export const YOUTUBE_LINK = 'https://www.youtube.com/@safeglobal'
export const MIRROR_LINK = 'https://safe.mirror.xyz'
export const MIRROR_SUBSCRIBE_LINK = 'https://safe.mirror.xyz/subscribe/embed'
export const GITHUB_LINK = 'https://github.com/safe-global'

export const PROTOCOL_KIT_LINK = 'https://docs.safe.global/safe-core-aa-sdk/protocol-kit'
Expand Down
2 changes: 1 addition & 1 deletion src/contentful/types/TypeTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface TypeTagFields {
| 'Events'
| 'Grants'
| 'NFT'
| 'New feature'
| 'New Feature'
| 'Safe{Core}'
| 'Safe{DAO}'
| 'Safe{Wallet}'
Expand Down
14 changes: 7 additions & 7 deletions src/lib/__test__/urlPatterns.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { extractLastPathname, extractVideoId, isTwitterUrl, isYouTubeUrl } from '@/lib/urlPatterns'
import { extractLastPathname, extractYouTubeVideoId, isTwitterUrl, isYouTubeUrl } from '@/lib/urlPatterns'

describe('urlPatterns', () => {
describe('isYouTubeUrl', () => {
Expand All @@ -13,15 +13,15 @@ describe('urlPatterns', () => {
})
})

describe('extractVideoId', () => {
describe('extractYouTubeVideoId', () => {
it('should extract video id from YouTube URLs', () => {
expect(extractVideoId('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
expect(extractVideoId('https://youtu.be/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
expect(extractYouTubeVideoId('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
expect(extractYouTubeVideoId('https://youtu.be/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ')
})

it('should return null for non-YouTube URLs', () => {
expect(extractVideoId('https://www.google.com')).toBe(null)
expect(extractVideoId('https://twitter.com')).toBe(null)
expect(extractYouTubeVideoId('https://www.google.com')).toBe(null)
expect(extractYouTubeVideoId('https://twitter.com')).toBe(null)
})
})

Expand All @@ -40,7 +40,7 @@ describe('urlPatterns', () => {
describe('extractLastPathname', () => {
it('should extract last pathname component from URL', () => {
expect(extractLastPathname('https://example.com/foo/bar')).toBe('bar')
expect(extractLastPathname('https://example.com/foo/bar/')).toBe('')
expect(extractLastPathname('https://example.com/foo/bar/')).toBe('bar')
expect(extractLastPathname('https://example.com/')).toBe('')
})
})
Expand Down
16 changes: 10 additions & 6 deletions src/lib/typeGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,32 @@ import type {
import type { Asset, Entry } from 'contentful'
import type { Text } from '@contentful/rich-text-types'

const getContentTypeSysId = (obj: any): string => {
return obj.sys.contentType && obj.sys.contentType.sys.id
}

export const isEntryTypeButton = (obj: any): obj is Entry<TypeButtonSkeleton, undefined, string> => {
return obj.sys.contentType.sys.id === 'button'
return getContentTypeSysId(obj) === 'button'
}

export const isEntryTypeCardGridItem = (obj: any): obj is Entry<TypeCardGridItemSkeleton, undefined, string> => {
return obj.sys.contentType.sys.id === 'cardGridItem'
return getContentTypeSysId(obj) === 'cardGridItem'
}

export const isEntryTypeFaqEntry = (obj: any): obj is Entry<TypeFaqEntrySkeleton, undefined, string> => {
return obj.sys.contentType.sys.id === 'faqEntry'
return getContentTypeSysId(obj) === 'faqEntry'
}

export const isEntryTypeTag = (obj: any): obj is Entry<TypeTagSkeleton, undefined, string> => {
return obj.sys.contentType && obj.sys.contentType.sys.id === 'tag'
return getContentTypeSysId(obj) === 'tag'
}

export const isEntryTypeAuthor = (obj: any): obj is Entry<TypeAuthorSkeleton, undefined, string> => {
return obj.sys.contentType && obj.sys.contentType.sys.id === 'author'
return getContentTypeSysId(obj) === 'author'
}

export const isEntryTypePost = (obj: any): obj is Entry<TypePostSkeleton, undefined, string> => {
return obj.sys.contentType && obj.sys.contentType.sys.id === 'post'
return getContentTypeSysId(obj) === 'post'
}

export const isEntryType = (obj: any): obj is Entry => {
Expand Down
6 changes: 3 additions & 3 deletions src/lib/urlPatterns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export function isYouTubeUrl(url: string) {
return youtubeRegex.test(url)
}

export function extractVideoId(url: string) {
export function extractYouTubeVideoId(url: string) {
// short form
if (url.includes('youtu.be')) return url.split('/').pop()

Expand All @@ -20,6 +20,6 @@ export function isTwitterUrl(url: string) {

export function extractLastPathname(url: string) {
const urlObj = new URL(url)
const pathnameParts = urlObj.pathname.split('/')
return pathnameParts[pathnameParts.length - 1]
const pathnameParts = urlObj.pathname.split('/').filter((part) => part !== '')
return pathnameParts[pathnameParts.length - 1] || ''
}

0 comments on commit 5390cb2

Please sign in to comment.