wip(lab): Work on v3 lab
This commit is contained in:
parent
bee8f8b2fd
commit
2dcf46befa
40 changed files with 411 additions and 185 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -123,6 +123,7 @@ sites/*/out
|
|||
sites/*/public/mdx
|
||||
sites/*/prebuild
|
||||
!sites/shared/prebuild
|
||||
sites/shared/prebuild/data
|
||||
sites/dev/public/og
|
||||
|
||||
# misc
|
||||
|
|
|
@ -84,7 +84,7 @@ lab:
|
|||
develop: *nextDev
|
||||
e2e: &e2e 'yarn playwright test'
|
||||
lint: *nextLint
|
||||
prebuild: 'node --experimental-json-modules ../shared/prebuild/index.mjs'
|
||||
prebuild: 'SITE=lab node --experimental-json-modules ../shared/prebuild/index.mjs'
|
||||
start: *nextStart
|
||||
|
||||
org:
|
||||
|
|
|
@ -4,4 +4,4 @@ import { build } from '../src/prebuild.mjs'
|
|||
export const denyList = ['uk']
|
||||
|
||||
// call this here instead of in the src/prebuild.mjs so that build isn't called by other files importing that build function
|
||||
build((loc) => denyList.indexOf(loc) === -1)
|
||||
//build((loc) => denyList.indexOf(loc) === -1)
|
||||
|
|
6
sites/lab/components/feeds.mjs
Normal file
6
sites/lab/components/feeds.mjs
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Placeholder feeds component that does nothing
|
||||
* but allows us to re-use code that expects this
|
||||
* to be here
|
||||
*/
|
||||
export const Feeds = () => null
|
|
@ -1,70 +0,0 @@
|
|||
// Hooks
|
||||
import { useState, useEffect } from 'react'
|
||||
// Components
|
||||
import { ThemePicker } from 'shared/components/theme-picker/index.mjs'
|
||||
import { LocalePicker } from 'shared/components/locale-picker/index.mjs'
|
||||
import { DesignPicker } from 'site/components/design-picker.mjs'
|
||||
import { CloseIcon, MenuIcon } from 'shared/components/icons.mjs'
|
||||
import { Ribbon } from 'shared/components/ribbon.mjs'
|
||||
import { WordMark } from 'shared/components/wordmark.mjs'
|
||||
|
||||
export const Header = ({ app }) => {
|
||||
const [prevScrollPos, setPrevScrollPos] = useState(0)
|
||||
const [show, setShow] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const handleScroll = () => {
|
||||
const curScrollPos = typeof window !== 'undefined' ? window.pageYOffset : 0
|
||||
if (curScrollPos >= prevScrollPos) {
|
||||
if (show && curScrollPos > 20) setShow(false)
|
||||
} else setShow(true)
|
||||
setPrevScrollPos(curScrollPos)
|
||||
}
|
||||
window.addEventListener('scroll', handleScroll)
|
||||
return () => window.removeEventListener('scroll', handleScroll)
|
||||
}
|
||||
}, [prevScrollPos, show])
|
||||
|
||||
return (
|
||||
<header
|
||||
className={`
|
||||
fixed top-0 left-0
|
||||
bg-neutral
|
||||
w-full
|
||||
z-30
|
||||
transition-transform
|
||||
${show ? '' : 'fixed top-0 left-0 -translate-y-20'}
|
||||
`}
|
||||
>
|
||||
<div>
|
||||
<div className="p-2 flex flex-row justify-between text-neutral-content">
|
||||
<div className="flex flex-row items-center">
|
||||
<button
|
||||
className={`
|
||||
btn btn-sm btn-ghost
|
||||
text-neutral-content bg-transparent
|
||||
hover:text-secondary-focus
|
||||
lg:hidden
|
||||
`}
|
||||
onClick={app.togglePrimaryMenu}
|
||||
>
|
||||
{app.primaryMenu ? <CloseIcon /> : <MenuIcon />}
|
||||
</button>
|
||||
<WordMark />
|
||||
</div>
|
||||
{!app.standalone && (
|
||||
<div className="hidden md:flex flex-row items-center gap-2 grow">
|
||||
<DesignPicker app={app} />
|
||||
</div>
|
||||
)}
|
||||
<div className="hidden md:flex flex-row items-center gap-2">
|
||||
<ThemePicker app={app} />
|
||||
<LocalePicker app={app} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Ribbon loading={app.loading} theme={app.theme} />
|
||||
</header>
|
||||
)
|
||||
}
|
13
sites/lab/components/header/header.en.yaml
Normal file
13
sites/lab/components/header/header.en.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
menu: Menu
|
||||
designs: Designs
|
||||
showcase: Showcase
|
||||
docs: Documentation
|
||||
blog: Blog
|
||||
community: Community
|
||||
account: Account
|
||||
theme: Theme
|
||||
language: Language
|
||||
search: Search
|
||||
sets: Measurements
|
||||
patterns: Patterns
|
||||
|
|
@ -2,6 +2,8 @@ import { useRouter } from 'next/router'
|
|||
import { AsideNavigation } from 'shared/components/navigation/aside.mjs'
|
||||
import { BeforeNav } from './lab.mjs'
|
||||
|
||||
export const ns = ['']
|
||||
|
||||
export const BareLayout = ({ app, children = [] }) => {
|
||||
const router = useRouter()
|
||||
const slug = router.asPath.slice(1)
|
||||
|
|
26
sites/lab/components/layouts/docs.mjs
Normal file
26
sites/lab/components/layouts/docs.mjs
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { useContext } from 'react'
|
||||
// Components
|
||||
import { AsideNavigation, ns as navNs } from 'shared/components/navigation/aside.mjs'
|
||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
||||
import { NavigationContext } from 'shared/context/navigation-context.mjs'
|
||||
|
||||
export const ns = navNs
|
||||
|
||||
export const DocsLayout = ({ children = [], pageTitle = false }) => {
|
||||
const { title, crumbs } = useContext(NavigationContext)
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-4 m-auto justify-center place-items-stretch lg:mt-16">
|
||||
<AsideNavigation />
|
||||
<section className="col-span-4 lg:col-span-3 py-24 px-4 lg:pl-8 bg-base-50">
|
||||
{title && (
|
||||
<div className="xl:pl-4">
|
||||
<Breadcrumbs crumbs={crumbs} title={pageTitle ? pageTitle : title} />
|
||||
<h1 className="break-words">{pageTitle ? pageTitle : title}</h1>
|
||||
</div>
|
||||
)}
|
||||
<div className="xl:pl-4">{children}</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { ThemePicker } from 'shared/components/theme-picker/index.mjs'
|
||||
import { LocalePicker } from 'shared/components/locale-picker/index.mjs'
|
||||
|
||||
export const ns = ['']
|
||||
|
||||
export const BeforeNav = ({ app }) => (
|
||||
<>
|
||||
<div className="md:hidden flex flex-row flex-wrap sm:flex-nowrap gap-2 mb-2">
|
||||
|
|
33
sites/lab/components/navigation/modal-menu.mjs
Normal file
33
sites/lab/components/navigation/modal-menu.mjs
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { SectionsMenu } from 'site/components/navigation/sections-menu.mjs'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ActiveSection, ns as primaryNs } from 'shared/components/navigation/primary.mjs'
|
||||
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
||||
|
||||
export const ns = primaryNs
|
||||
|
||||
export const ModalMenu = () => {
|
||||
const { t } = useTranslation(ns)
|
||||
|
||||
return (
|
||||
<ModalWrapper flex="col" justify="top lg:justify-center" slideFrom="left">
|
||||
<div className="max-w-full">
|
||||
<div
|
||||
className={`
|
||||
py-4 lg:py-16 w-full m-auto
|
||||
flex flex-col-reverse gap-0 flex-wrap justify-between
|
||||
lg:max-w-6xl lg:flex-nowrap lg:gap-8 lg:flex-row
|
||||
`}
|
||||
>
|
||||
<div className="w-full lg:w-1/2">
|
||||
<h3>{t('mainSections')}</h3>
|
||||
<SectionsMenu />
|
||||
</div>
|
||||
<div className="w-full lg:w-1/2">
|
||||
<h3>{t('currentSection')}</h3>
|
||||
<ActiveSection bare />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
46
sites/lab/components/navigation/sections-menu.mjs
Normal file
46
sites/lab/components/navigation/sections-menu.mjs
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { useContext } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { icons, ns as sectionsNs } from 'shared/components/navigation/primary.mjs'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import orderBy from 'lodash.orderby'
|
||||
import { colors } from 'site/components/header/index.mjs'
|
||||
import { NavigationContext } from 'shared/context/navigation-context.mjs'
|
||||
import { HelpIcon } from 'shared/components/icons.mjs'
|
||||
|
||||
export const ns = sectionsNs
|
||||
|
||||
export const SectionsMenu = () => {
|
||||
const { t } = useTranslation(ns)
|
||||
const { sections = false } = useContext(NavigationContext)
|
||||
if (!sections) return null
|
||||
|
||||
// Ensure each page as an `o` key so we can put them in order
|
||||
const sortableSections = sections.map((s) => ({ ...s, o: s.o ? s.o : s.t }))
|
||||
const output = []
|
||||
for (const page of orderBy(sortableSections, ['o', 't'])) {
|
||||
const item = (
|
||||
<Link
|
||||
key={page.s}
|
||||
className={`bg-${
|
||||
colors[page.s]
|
||||
}-400 p-0 rounded shadow hover:shadow-lg w-full bg-opacity-70 hover:bg-opacity-100 text-neutral-900
|
||||
`}
|
||||
href={`/${page.s}`}
|
||||
title={page.t}
|
||||
>
|
||||
<div className="flex flex-col rounded">
|
||||
<div className={`flex flex-row items-center justify-between pt-2 px-4`}>
|
||||
<h4 className="text-neutral-900">{page.t}</h4>
|
||||
{icons[page.s] ? icons[page.s]('w-10 h-10') : <HelpIcon />}
|
||||
</div>
|
||||
<div className={`font-medium text-base leading-5 text-left rounded-b py-4 px-4 `}>
|
||||
{t(page.s + 'About')}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
output.push(item)
|
||||
}
|
||||
|
||||
return <div className="flex flex-col gap-2">{output}</div>
|
||||
}
|
|
@ -1,19 +1,11 @@
|
|||
// Hooks
|
||||
import { useRouter } from 'next/router'
|
||||
// Components
|
||||
import { Header } from 'site/components/header.mjs'
|
||||
import { Footer } from 'site/components/footer.mjs'
|
||||
import Head from 'next/head'
|
||||
import { Header, ns as headerNs } from 'site/components/header/index.mjs'
|
||||
import { Footer, ns as footerNs } from 'shared/components/footer/index.mjs'
|
||||
|
||||
export const LayoutWrapper = ({ app, children = [] }) => {
|
||||
const startNavigation = () => {
|
||||
app.startLoading()
|
||||
// Force close of menu on mobile if it is open
|
||||
if (app.primaryMenu) app.setPrimaryMenu(false)
|
||||
}
|
||||
export const ns = [...new Set([...headerNs, ...footerNs])]
|
||||
|
||||
const router = useRouter()
|
||||
router.events?.on('routeChangeStart', startNavigation)
|
||||
router.events?.on('routeChangeComplete', app.stopLoading)
|
||||
export const LayoutWrapper = ({ children = [], header = false }) => {
|
||||
const ChosenHeader = header ? header : Header
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -23,9 +15,12 @@ export const LayoutWrapper = ({ app, children = [] }) => {
|
|||
bg-base-100
|
||||
`}
|
||||
>
|
||||
<Header app={app} />
|
||||
<Head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</Head>
|
||||
<ChosenHeader />
|
||||
<main className="grow">{children}</main>
|
||||
<Footer app={app} />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
151
sites/lab/hooks/use-navigation.mjs
Normal file
151
sites/lab/hooks/use-navigation.mjs
Normal file
|
@ -0,0 +1,151 @@
|
|||
import { useContext, useEffect } from 'react'
|
||||
import { NavigationContext } from 'shared/context/navigation-context.mjs'
|
||||
import get from 'lodash.get'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import orderBy from 'lodash.orderby'
|
||||
import { freeSewingConfig as conf } from 'shared/config/freesewing.config.mjs'
|
||||
import { useAccount } from 'shared/hooks/use-account.mjs'
|
||||
import { designs, tags } from 'shared/config/designs.mjs'
|
||||
|
||||
/*
|
||||
* prebuildNavvigation[locale] holds the navigation structure based on MDX content.
|
||||
* The entire website only has a few pages that are now MDX-based:
|
||||
* - 404 => no navigation shown
|
||||
* - home page => no navvigation shown
|
||||
* - /contact => Added below
|
||||
*
|
||||
* Note: Set 'h' to truthy to not show a top-level entry as a section
|
||||
* Note: Set 'c' to set the control level to hide things from users
|
||||
*/
|
||||
|
||||
const ns = ['account', 'sections', 'design', 'tags']
|
||||
|
||||
const sitePages = (t = false, control = 99) => {
|
||||
// Handle t not being present
|
||||
if (!t) t = (string) => string
|
||||
const pages = {
|
||||
// Top-level pages that are the sections menu
|
||||
designs: {
|
||||
t: t('sections:designs'),
|
||||
s: 'designs',
|
||||
o: 10,
|
||||
},
|
||||
patterns: {
|
||||
t: t('sections:patterns'),
|
||||
s: 'patterns',
|
||||
o: 20,
|
||||
},
|
||||
sets: {
|
||||
t: t('sections:sets'),
|
||||
s: 'sets',
|
||||
o: 30,
|
||||
},
|
||||
docs: {
|
||||
t: t('sections:docs'),
|
||||
s: 'docs',
|
||||
o: 40,
|
||||
},
|
||||
code: {
|
||||
t: t('sections:code'),
|
||||
s: 'blog',
|
||||
o: 50,
|
||||
},
|
||||
account: {
|
||||
t: t('sections:account'),
|
||||
s: 'account',
|
||||
o: 99,
|
||||
},
|
||||
// Top-level pages that are not in the sections menu
|
||||
new: {
|
||||
t: t('new'),
|
||||
s: 'new',
|
||||
h: 1,
|
||||
pattern: {
|
||||
t: t('patternNew'),
|
||||
s: 'new/pattern',
|
||||
o: 10,
|
||||
},
|
||||
set: {
|
||||
t: t('newSet'),
|
||||
s: 'new/set',
|
||||
0: 20,
|
||||
},
|
||||
},
|
||||
profile: {
|
||||
t: t('yourProfile'),
|
||||
s: 'profile',
|
||||
h: 1,
|
||||
},
|
||||
}
|
||||
for (const section in conf.account.fields) {
|
||||
for (const [field, controlScore] of Object.entries(conf.account.fields[section])) {
|
||||
if (Number(control) >= controlScore)
|
||||
pages.account[field] = {
|
||||
t: t(`account:${field}`),
|
||||
s: `account/${field}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Number(control) >= conf.account.fields.developer.apikeys)
|
||||
pages.new.apikey = {
|
||||
t: t('newApikey'),
|
||||
s: 'new/apikey',
|
||||
o: 30,
|
||||
}
|
||||
pages.account.reload = {
|
||||
t: t(`account:reload`),
|
||||
s: `account/reload`,
|
||||
}
|
||||
for (const design in designs) {
|
||||
pages.designs[design] = {
|
||||
t: t(`designs:${design}.t`),
|
||||
s: `designs/${design}`,
|
||||
}
|
||||
pages.new.pattern[design] = {
|
||||
t: t(`account:generateANewThing`, { thing: t(`designs:${design}.t`) }),
|
||||
s: `new/patterns/${design}`,
|
||||
}
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
|
||||
const createCrumbs = (path, nav) =>
|
||||
path.map((crumb, i) => {
|
||||
const entry = get(nav, path.slice(0, i + 1), { t: 'no-title', s: path.join('/') })
|
||||
const val = { t: entry.t, s: entry.s }
|
||||
if (entry.o) val.o = entry.o
|
||||
|
||||
return val
|
||||
})
|
||||
|
||||
const createSections = (nav) => {
|
||||
const sections = {}
|
||||
for (const slug of Object.keys(nav)) {
|
||||
const entry = nav[slug]
|
||||
const val = { t: entry.t, s: entry.s }
|
||||
if (entry.o) val.o = entry.o
|
||||
if (!entry.h) sections[slug] = val
|
||||
}
|
||||
|
||||
return orderBy(sections, ['o', 't'])
|
||||
}
|
||||
|
||||
export const useNavigation = ({ path, locale }) => {
|
||||
const { t } = useTranslation(ns)
|
||||
const { account } = useAccount()
|
||||
|
||||
const nav = sitePages(t, account?.control)
|
||||
|
||||
// Create crumbs array
|
||||
const crumbs = createCrumbs(path, nav)
|
||||
const sections = createSections(nav)
|
||||
|
||||
return {
|
||||
crumbs,
|
||||
sections,
|
||||
slug: path.join('/'),
|
||||
nav: path.length > 1 ? get(nav, path[0]) : path.length === 0 ? sections : nav[path[0]],
|
||||
title: crumbs.length > 0 ? crumbs.slice(-1)[0].t : '',
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
"develop": "next dev -p 8000",
|
||||
"e2e": "yarn playwright test",
|
||||
"lint": "next lint",
|
||||
"prebuild": "node --experimental-json-modules ../shared/prebuild/index.mjs",
|
||||
"prebuild": "SITE=lab node --experimental-json-modules ../shared/prebuild/index.mjs",
|
||||
"start": "yarn prebuild && yarn dev"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
|
|
|
@ -1,6 +1,44 @@
|
|||
import 'shared/styles/globals.css'
|
||||
import { appWithTranslation } from 'next-i18next'
|
||||
import React from 'react'
|
||||
import Bugsnag from '@bugsnag/js'
|
||||
import BugsnagPluginReact from '@bugsnag/plugin-react'
|
||||
import { siteConfig } from 'site/site.config.mjs'
|
||||
import { Toaster as DefaultToaster } from 'react-hot-toast'
|
||||
import { ContextWrapper } from 'shared/components/wrappers/context.mjs'
|
||||
|
||||
const FreeSewingLab = ({ Component, pageProps }) => <Component {...pageProps} />
|
||||
Bugsnag.start({
|
||||
apiKey: siteConfig.bugsnag.key,
|
||||
collectUserIp: false,
|
||||
plugins: [new BugsnagPluginReact()],
|
||||
})
|
||||
|
||||
const ErrorBoundary = Bugsnag.getPlugin('react').createErrorBoundary(React)
|
||||
|
||||
const FreeSewingLab = ({ Component, pageProps }) => (
|
||||
<ErrorBoundary>
|
||||
<ContextWrapper>
|
||||
<Component {...pageProps} />
|
||||
<DefaultToaster
|
||||
position="bottom-right"
|
||||
toastOptions={{
|
||||
className: 'bg-base-100 text-base-content',
|
||||
success: {
|
||||
className: 'bg-success text-success-content',
|
||||
},
|
||||
error: {
|
||||
className: 'bg-error text-error-content',
|
||||
},
|
||||
loading: {
|
||||
className: 'bg-warning text-warning-content',
|
||||
},
|
||||
custom: {
|
||||
className: 'bg-accent text-accent-content',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</ContextWrapper>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
|
||||
export default appWithTranslation(FreeSewingLab)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { PatternListPageTemplate } from 'site/page-templates/design-list.mjs'
|
||||
|
||||
const Page = () => <PatternListPageTemplate section="accessories" />
|
||||
|
||||
export default Page
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale)),
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { PatternListPageTemplate } from 'site/page-templates/design-list.mjs'
|
||||
|
||||
const Page = () => <PatternListPageTemplate section="blocks" />
|
||||
|
||||
export default Page
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale)),
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { PatternListPageTemplate } from 'site/page-templates/design-list.mjs'
|
||||
|
||||
const Page = () => <PatternListPageTemplate section="garments" />
|
||||
|
||||
export default Page
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale)),
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,3 +1,47 @@
|
|||
// Dependencies
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
//import { useTranslation } from 'next-i18next'
|
||||
import Head from 'next/head'
|
||||
// Components
|
||||
import { PageWrapper } from 'shared/components/wrappers/page.mjs'
|
||||
import { Popout } from 'shared/components/popout.mjs'
|
||||
import { PageLink } from 'shared/components/page-link.mjs'
|
||||
|
||||
/*
|
||||
* Each page MUST be wrapped in the PageWrapper component.
|
||||
* You also MUST spread props.page into this wrapper component
|
||||
* when path and locale come from static props (as here)
|
||||
* or set them manually.
|
||||
*/
|
||||
const HomePage = ({ page }) => (
|
||||
<PageWrapper {...page}>
|
||||
<Head>
|
||||
<title>Welcome to FreeSewing.org</title>
|
||||
</Head>
|
||||
<div>
|
||||
<div className="max-w-xl m-auto my-32 px-6">
|
||||
<Popout fixme>
|
||||
Create homepage. Meanwhile check <PageLink href="/signup" txt="the signup flow" />
|
||||
</Popout>
|
||||
</div>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
)
|
||||
|
||||
export default HomePage
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale)),
|
||||
page: {
|
||||
locale,
|
||||
path: [],
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Hooks
|
||||
import { useApp } from 'site/hooks/useApp.mjs'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
@ -164,3 +208,5 @@ export async function getStaticProps({ locale }) {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { PatternListPageTemplate } from 'site/page-templates/design-list.mjs'
|
||||
|
||||
const Page = () => <PatternListPageTemplate section="utilities" />
|
||||
|
||||
export default Page
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale)),
|
||||
},
|
||||
}
|
||||
}
|
6
sites/lab/site.config.mjs
Normal file
6
sites/lab/site.config.mjs
Normal file
|
@ -0,0 +1,6 @@
|
|||
export const siteConfig = {
|
||||
bugsnag: {
|
||||
key: 'aa417d92c1c11ac80a2134d37e7327a2',
|
||||
},
|
||||
languages: ['en', 'es', 'de', 'fr', 'nl'],
|
||||
}
|
|
@ -11,8 +11,8 @@ import { LoadingContext } from 'shared/context/loading-context.mjs'
|
|||
import Markdown from 'react-markdown'
|
||||
import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs'
|
||||
import { Popout } from 'shared/components/popout.mjs'
|
||||
import { SaveSettingsButton } from 'site/components/buttons/save-settings-button.mjs'
|
||||
import { ContinueButton } from 'site/components/buttons/continue-button.mjs'
|
||||
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
|
||||
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
|
||||
|
||||
export const ns = ['account', 'toast']
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import { LoadingContext } from 'shared/context/loading-context.mjs'
|
|||
import Link from 'next/link'
|
||||
import { Popout } from 'shared/components/popout.mjs'
|
||||
import { BackToAccountButton } from './shared.mjs'
|
||||
import { SaveSettingsButton } from 'site/components/buttons/save-settings-button.mjs'
|
||||
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
|
||||
import {
|
||||
GdprProfileDetails,
|
||||
GdprMeasurementsDetails,
|
||||
|
|
|
@ -9,7 +9,7 @@ import { useToast } from 'shared/hooks/use-toast.mjs'
|
|||
import { LoadingContext } from 'shared/context/loading-context.mjs'
|
||||
// Components
|
||||
import { BackToAccountButton } from './shared.mjs'
|
||||
import { SaveSettingsButton } from 'site/components/buttons/save-settings-button.mjs'
|
||||
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
|
||||
|
||||
export const ns = ['account', 'toast']
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import { useBackend } from 'shared/hooks/use-backend.mjs'
|
|||
import { useToast } from 'shared/hooks/use-toast.mjs'
|
||||
// Components
|
||||
import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs'
|
||||
import { ContinueButton } from 'site/components/buttons/continue-button.mjs'
|
||||
import { SaveSettingsButton } from 'site/components/buttons/save-settings-button.mjs'
|
||||
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
|
||||
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
|
||||
|
||||
export const ns = ['account', 'toast']
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { LoadingContext } from 'shared/context/loading-context.mjs'
|
|||
// Components
|
||||
import Link from 'next/link'
|
||||
import { BackToAccountButton } from './shared.mjs'
|
||||
import { SaveSettingsButton } from 'site/components/buttons/save-settings-button.mjs'
|
||||
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
|
||||
import { Popout } from 'shared/components/popout.mjs'
|
||||
import { RightIcon } from 'shared/components/icons.mjs'
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ import { Tab } from './bio.mjs'
|
|||
import Timeago from 'react-timeago'
|
||||
import { Spinner } from 'shared/components/spinner.mjs'
|
||||
import Link from 'next/link'
|
||||
import { SaveSettingsButton } from 'site/components/buttons/save-settings-button.mjs'
|
||||
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
|
||||
|
||||
export const ns = ['account', 'patterns', 'toast']
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ export const FreeSewingIcon = (props) => (
|
|||
</IconWrapper>
|
||||
)
|
||||
|
||||
export const GithubIcon = (props) => (
|
||||
export const GitHubIcon = (props) => (
|
||||
<IconWrapper {...props} stroke={0} fill>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</IconWrapper>
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
HelpIcon,
|
||||
DiscordIcon,
|
||||
FacebookIcon,
|
||||
GithubIcon,
|
||||
GitHubIcon,
|
||||
InstagramIcon,
|
||||
RedditIcon,
|
||||
TwitterIcon,
|
||||
|
@ -37,7 +37,7 @@ const socialList = {
|
|||
href: social.Facebook,
|
||||
},
|
||||
GitHub: {
|
||||
icon: <GithubIcon {...iconClasses(4)} />,
|
||||
icon: <GitHubIcon {...iconClasses(4)} />,
|
||||
href: social.GitHub,
|
||||
},
|
||||
Reddit: {
|
||||
|
|
|
@ -23,7 +23,6 @@ export const prebuildDesigns = async () => {
|
|||
|
||||
// Compile list of designs
|
||||
for (const design in allDesigns) {
|
||||
console.log(design)
|
||||
if (allDesigns[design]?.tags) designs.push(design)
|
||||
}
|
||||
|
||||
|
@ -41,17 +40,19 @@ export const prebuildDesigns = async () => {
|
|||
const header =
|
||||
'// This file is auto-generated by the prebuild script | Any changes will be overwritten\n'
|
||||
const nl = '\n'
|
||||
const dir = ['..', 'shared', 'prebuild', 'data']
|
||||
promises.push(fs.mkdir(path.resolve(...dir), { recursive: true }))
|
||||
promises.push(
|
||||
fs.writeFile(
|
||||
path.resolve('..', 'org', 'prebuild', 'designs.mjs'),
|
||||
path.resolve(...dir, 'designs.mjs'),
|
||||
`${header}export const designs = ${JSON.stringify(designs)}${nl}`
|
||||
),
|
||||
fs.writeFile(
|
||||
path.resolve('..', 'org', 'prebuild', 'design-measurements.mjs'),
|
||||
path.resolve(...dir, 'design-measurements.mjs'),
|
||||
`${header}export const measurements = ${JSON.stringify(measurements)}${nl}`
|
||||
),
|
||||
fs.writeFile(
|
||||
path.resolve('..', 'org', 'prebuild', 'design-options.mjs'),
|
||||
path.resolve(...dir, 'design-options.mjs'),
|
||||
`${header}export const options = ${JSON.stringify(options)}${nl}`
|
||||
)
|
||||
)
|
||||
|
|
|
@ -4,19 +4,19 @@ import { prebuildGitData } from './git.mjs'
|
|||
import { prebuildContributors } from './contributors.mjs'
|
||||
import { prebuildPatrons } from './patrons.mjs'
|
||||
import { prebuildI18n } from './i18n.mjs'
|
||||
//import { prebuildLab } from './lab.mjs'
|
||||
//import { prebuildDesigns } from './designs.mjs'
|
||||
import { prebuildLab } from './lab.mjs'
|
||||
import { prebuildDesigns } from './designs.mjs'
|
||||
import { generateOgImage } from './og/index.mjs'
|
||||
|
||||
const run = async () => {
|
||||
const SITE = process.env.SITE || 'lab'
|
||||
prebuildDesigns()
|
||||
let docPages
|
||||
if (['org', 'dev'].includes(SITE)) {
|
||||
console.log('in orgdev')
|
||||
await prebuildGitData(SITE)
|
||||
const docPages = await prebuildDocs(SITE)
|
||||
prebuildNavigation(docPages, false, SITE)
|
||||
// FIXME: This breaks because it runs as prebuild but requires core to be built
|
||||
//if (SITE === 'org') prebuildDesigns()
|
||||
if (process.env.GENERATE_OG_IMAGES) {
|
||||
// Create og image for the home page
|
||||
await generateOgImage({
|
||||
|
@ -35,8 +35,9 @@ const run = async () => {
|
|||
lead: '404',
|
||||
})
|
||||
}
|
||||
} else {
|
||||
await prebuildLab()
|
||||
}
|
||||
//else await prebuildLab()
|
||||
|
||||
await prebuildI18n(SITE)
|
||||
await prebuildContributors(SITE)
|
||||
|
@ -44,4 +45,4 @@ const run = async () => {
|
|||
console.log()
|
||||
}
|
||||
|
||||
run()
|
||||
//run()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import fs_ from 'fs'
|
||||
import path from 'path'
|
||||
import { capitalize } from '../utils.mjs'
|
||||
import { designsByType, plugins, designs } from '../../../config/software/index.mjs'
|
||||
import { plugins, designs } from '../../../config/software/index.mjs'
|
||||
|
||||
const fs = fs_.promises
|
||||
|
||||
|
@ -16,28 +16,13 @@ const header = `/*
|
|||
*
|
||||
*/`
|
||||
|
||||
const pageTemplate = (design) => `${header}
|
||||
import { ${capitalize(design)} } from 'designs/${design}/src/index.mjs'
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||
import { WorkbenchPage } from 'site/page-templates/workbench.mjs'
|
||||
|
||||
const Page = (props) => <WorkbenchPage {...props} design={${capitalize(design)}} version="next"/>
|
||||
export default Page
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale)),
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
/*
|
||||
* Main method that does what needs doing
|
||||
*/
|
||||
|
||||
export const prebuildLab = async () => {
|
||||
// FIXME: handle this
|
||||
return
|
||||
const promises = []
|
||||
for (const section in designsByType) {
|
||||
// Iterate over sections
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue