Skip to content

Commit

Permalink
feat: navbar extra button from contentful (#565)
Browse files Browse the repository at this point in the history
* feat: load extra button from contentful

* feat: cache navbar button data using TTL in contentful

* chore: move contentful stuff to config

* chore: linted
  • Loading branch information
cazala authored Nov 13, 2024
1 parent 9d8f468 commit 80dff04
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 9 deletions.
30 changes: 28 additions & 2 deletions src/components/Navbar/MainMenu/MainMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react'
import React, { useEffect, useRef, useState } from 'react'
import classNames from 'classnames'

import { MenuItem } from '../MenuItem/MenuItem'
import { NavbarPages } from '../Navbar.types'
import { MainMenuProps } from './MainMenu.types'
import { getNavbarPagesUrls } from '../utils'
import { getExtraButton, getNavbarPagesUrls, NavbarExtraButton } from '../utils'

import './MainMenu.css'

Expand All @@ -13,6 +13,22 @@ export const MainMenu = (props: MainMenuProps) => {

const urls = getNavbarPagesUrls()

// load extra button
const isMounted = useRef(false)
const [extraButton, setExtraButton] = useState<NavbarExtraButton | null>(null)
useEffect(() => {
isMounted.current = true
if (!extraButton) {
getExtraButton().then((button) => {
if (!isMounted.current) return
setExtraButton(button)
})
}
return () => {
isMounted.current = false
}
}, [extraButton, isMounted, setExtraButton])

return (
<div
className={classNames(
Expand Down Expand Up @@ -51,6 +67,16 @@ export const MainMenu = (props: MainMenuProps) => {
title={i18n.explore}
mainUrl={urls[NavbarPages.EXPLORE]}
/>
{extraButton && extraButton.visible ? (
<MenuItem
{...menuItemProps}
section={NavbarPages.EXTRA}
title={extraButton.text}
mainUrl={extraButton.link}
textColor={extraButton.textColor}
backgroundColor={extraButton.backgroundColor}
/>
) : null}
</div>
)
}
21 changes: 21 additions & 0 deletions src/components/Navbar/MenuItem/MenuItem.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,27 @@
fill: var(--text);
}

.dui-navbar
.dui-navbar-wrapper
.item:not(.mobile).dui-menu-item.extra.has-background {
height: calc(100% - 24px);
padding: 12px;
margin-top: 12px;
}

.item.mobile.dui-menu-item.extra.has-background {
margin-top: 40px;
padding: 20px;
width: calc(100% - 50px - 40px);
border-radius: 8px;
justify-content: center;
border-bottom: none;
}

.item.mobile.dui-menu-item.extra.has-background .dui-icon-container.centered {
display: none;
}

@media (max-width: 991px) {
.item.dui-menu-item.mobile {
cursor: pointer;
Expand Down
20 changes: 17 additions & 3 deletions src/components/Navbar/MenuItem/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ import { MenuItemProps } from './MenuItem.types'
import './MenuItem.css'

export const MenuItem = (props: MenuItemProps) => {
const { activePage, section, title, onToggleShowSubMenu, isMobile, mainUrl } =
props
const {
activePage,
section,
title,
onToggleShowSubMenu,
isMobile,
mainUrl,
textColor,
backgroundColor
} = props

const mainRedirect = useCallback(() => {
mainUrl && window.open(mainUrl, '_self')
Expand All @@ -27,7 +35,13 @@ export const MenuItem = (props: MenuItemProps) => {
onMouseLeave={(e: React.MouseEvent) =>
!isMobile && onToggleShowSubMenu(e, false, section)
}
className={classNames('dui-menu-item', section, isMobile && 'mobile')}
className={classNames(
'dui-menu-item',
section,
isMobile && 'mobile',
backgroundColor && 'has-background'
)}
style={{ color: textColor, backgroundColor }}
>
{title}
{isMobile && <ArrowIcon />}
Expand Down
2 changes: 2 additions & 0 deletions src/components/Navbar/MenuItem/MenuItem.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export type MenuItemProps = {
) => void
mainUrl?: string
isMobile?: boolean
textColor?: string
backgroundColor?: string
}
3 changes: 2 additions & 1 deletion src/components/Navbar/Navbar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export enum NavbarPages {
CREATE = 'create',
EXPLORE = 'explore',
LEARN = 'learn',
GOVERNANCE = 'governance'
GOVERNANCE = 'governance',
EXTRA = 'extra'
}

export type NavbarMenuI18nProps = Record<NavbarPages, string>
Expand Down
49 changes: 49 additions & 0 deletions src/components/Navbar/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,52 @@ export const getNavbarPagesUrls = () => {
[NavbarPages.GOVERNANCE]: config.get('GOVERNANCE_URL')
}
}

export type NavbarExtraButton = {
text: string
link: string
visible: boolean
textColor?: `#${string}`
backgroundColor?: `#${string}`
id?: string
ttl: number
}

export type LocalStorageNavbarExtraButton = {
button: NavbarExtraButton
expiresAt: number
}

export const getExtraButton = async () => {
const cachedExtraButton = localStorage.getItem('navbarExtraButton')
if (cachedExtraButton) {
try {
const parsed = JSON.parse(
cachedExtraButton
) as LocalStorageNavbarExtraButton
if (parsed.expiresAt > Date.now()) {
return parsed.button
}
} catch (error) {
// error parsing cached data, ignore and fetch from Contentful
}
}
try {
const SPACE_ID = config.get('CONTENTFUL_SPACE_ID')
const ENV = config.get('CONTENTFUL_ENV')
const ACCESS_TOKEN = config.get('CONTENTFUL_NAVBAR_ACCESS_TOKEN')
const ENTRY_ID = config.get('CONTENTFUL_NAVBAR_ENTRY_ID')
const CONTENTFUL_URL = `https://cdn.contentful.com/spaces/${SPACE_ID}/environments/${ENV}/entries/${ENTRY_ID}?access_token=${ACCESS_TOKEN}`
const response = await fetch(CONTENTFUL_URL)
const entry = await response.json()
const button = entry.fields as NavbarExtraButton
localStorage.setItem(
'navbarExtraButton',
JSON.stringify({ button, expiresAt: Date.now() + button.ttl * 1000 })
)
return button
} catch (error) {
console.error(error)
return null
}
}
6 changes: 5 additions & 1 deletion src/config/env/dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@
"DOCS_DAO_URL": "https://docs.decentraland.org/player/general/dao/overview/what-is-the-dao/",
"BLOG_URL": "https://decentraland.zone/blog/",
"LANDING_CREATORS_URL": "https://decentraland.zone/create/",
"DOWNLOAD_URL": "https://decentraland.zone/download/"
"DOWNLOAD_URL": "https://decentraland.zone/download/",
"CONTENTFUL_SPACE_ID": "ea2ybdmmn1kv",
"CONTENTFUL_ENV": "master",
"CONTENTFUL_NAVBAR_ACCESS_TOKEN": "9dieh3AHS6uwb_YNMjxlO6FCibAFFJVdg2YzA5t6U-Y",
"CONTENTFUL_NAVBAR_ENTRY_ID": "18g1DzIyBxvu0steSwKyQr"
}
6 changes: 5 additions & 1 deletion src/config/env/prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@
"DOCS_DAO_URL": "https://docs.decentraland.org/player/general/dao/overview/what-is-the-dao/",
"BLOG_URL": "https://decentraland.org/blog/",
"LANDING_CREATORS_URL": "https://decentraland.org/create/",
"DOWNLOAD_URL": "https://decentraland.org/download/"
"DOWNLOAD_URL": "https://decentraland.org/download/",
"CONTENTFUL_SPACE_ID": "ea2ybdmmn1kv",
"CONTENTFUL_ENV": "master",
"CONTENTFUL_NAVBAR_ACCESS_TOKEN": "9dieh3AHS6uwb_YNMjxlO6FCibAFFJVdg2YzA5t6U-Y",
"CONTENTFUL_NAVBAR_ENTRY_ID": "18g1DzIyBxvu0steSwKyQr"
}
6 changes: 5 additions & 1 deletion src/config/env/stg.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@
"DOCS_DAO_URL": "https://docs.decentraland.org/player/general/dao/overview/what-is-the-dao/",
"BLOG_URL": "https://decentraland.today/blog/",
"LANDING_CREATORS_URL": "https://decentraland.today/create/",
"DOWNLOAD_URL": "https://decentraland.todat/download/"
"DOWNLOAD_URL": "https://decentraland.todat/download/",
"CONTENTFUL_SPACE_ID": "ea2ybdmmn1kv",
"CONTENTFUL_ENV": "master",
"CONTENTFUL_NAVBAR_ACCESS_TOKEN": "9dieh3AHS6uwb_YNMjxlO6FCibAFFJVdg2YzA5t6U-Y",
"CONTENTFUL_NAVBAR_ENTRY_ID": "18g1DzIyBxvu0steSwKyQr"
}

0 comments on commit 80dff04

Please sign in to comment.