1
0
Fork 0

chore: Adapt sites to recent changes

This commit is contained in:
Joost De Cock 2022-06-17 12:02:09 +02:00
parent 147920daeb
commit 43ee0f1790
392 changed files with 1269 additions and 1190 deletions

77
.gitignore vendored
View file

@ -3,10 +3,12 @@
# .env # .env
.env .env
# Specifics # Plugins
export plugins/plugin-theme/src/bundle.css.js
packages/plugin-theme/src/bundle.css.js plugins/plugin-theme/css
packages/plugin-theme/css
# Components package build artifacts
packages/components/Blockquote packages/components/Blockquote
packages/components/Draft packages/components/Draft
packages/components/DraftConfigurator packages/components/DraftConfigurator
@ -27,8 +29,12 @@ packages/components/withGist
packages/components/withLanguage packages/components/withLanguage
packages/components/withStorage packages/components/withStorage
packages/components/Workbench packages/components/Workbench
# Code coverage reports
packages/core/coverage packages/core/coverage
packages/workbench packages/*/report
# Utils package build artifacts
packages/utils/backend packages/utils/backend
packages/utils/camelCase packages/utils/camelCase
packages/utils/capitalize packages/utils/capitalize
@ -54,60 +60,48 @@ packages/utils/tiler
packages/utils/validateEmail packages/utils/validateEmail
packages/utils/validateTld packages/utils/validateTld
packages/*/example/yarn.lock # Any NPM or Yarn lock files
packages/*/report designs/*/package-lock.json
designs/*/yarn.lock
packages/*/package-lock.json packages/*/package-lock.json
packages/*/yarn.lock packages/*/yarn.lock
packages/strapi/.cache plugins/*/package-lock.json
plugins/*/yarn.lock
packages/freesewing.dev/public/locales/en/*.json # NPM lock files for sites (we use yarn)
sites/*/package-lock.json
packages/freesewing.org/public/locales/en/*.json # Strapi cache
packages/freesewing.org/public/locales/es/*.json sites/strapi/.cache
packages/freesewing.org/public/locales/de/*.json
packages/freesewing.org/public/locales/fr/*.json
packages/freesewing.org/public/locales/nl/*.json
packages/freesewing.lab/public/locales/en/*.json # Sites prebuild artifacts
packages/freesewing.lab/public/locales/es/*.json sites/*/public/locales/*/*.json
packages/freesewing.lab/public/locales/de/*.json sites/*/public/feeds/*
packages/freesewing.lab/public/locales/fr/*.json
packages/freesewing.lab/public/locales/nl/*.json
packages/freesewing.org/public/feeds/* # Lab auto-generated pages
packages/freesewing.dev/public/feeds/* sites/lab/lib
sites/lab/pages
packages/freesewing.lab/lib # Node dependencies
packages/freesewing.lab/pages
# dependencies
node_modules node_modules
# build # Build folders
dist dist
build build
export
#prebuild # Prebuild files
prebuild/*.json prebuild/*.json
# yarn # Yarn
.yarn .yarn
.yarnrc .yarnrc
# NextJS # NextJS
.next .next
packages/freesewing.dev/out sites/*/out
packages/freesewing.lab/out sites/*/public/mdx
packages/freesewing.org/out sites/*/prebuild
packages/freesewing.dev/public/mdx
packages/freesewing.lab/public/mdx
packages/freesewing.org/public/mdx
packages/freesewing.dev/prebuild
packages/freesewing.lab/prebuild
packages/freesewing.org/prebuild
# Mock registry (verdaccio)
.registry
# misc # misc
.DS_Store .DS_Store
@ -127,9 +121,6 @@ packages/i18n/sort.sh
scripts/taskrunner.sh scripts/taskrunner.sh
scripts/verdaccio.sh scripts/verdaccio.sh
# Local Netlify folder
.netlify
# Don't ignore the specific Points.dist() docs folder # Don't ignore the specific Points.dist() docs folder
!markdown/dev/reference/api/point/dist !markdown/dev/reference/api/point/dist

File diff suppressed because it is too large Load diff

View file

@ -45,3 +45,5 @@ export const degreeMeasurements = ['shoulderSlope']
/* Helper method to determine whether a measurement uses degrees */ /* Helper method to determine whether a measurement uses degrees */
export const isDegreeMeasurement = (measie) => degreeMeasurements.indexOf(measie) !== -1 export const isDegreeMeasurement = (measie) => degreeMeasurements.indexOf(measie) !== -1

View file

@ -1,51 +1,59 @@
{ {
"aaron": "A FreeSewing pattern for a A-shirt or tank top", "accessories": {
"albert": "A FreeSewing pattern for an apron", "benjamin": "A FreeSewing pattern for a bow tie",
"bee": "A FreeSewing pattern for a bikini top", "florence": "A FreeSewing pattern for a face mask",
"bella": "A FreeSewing pattern for a womenswear bodice block", "florent": "A FreeSewing pattern for a flat cap",
"benjamin": "A FreeSewing pattern for a bow tie", "hi": "A FreeSewing pattern for a shark plush toy",
"bent": "A FreeSewing pattern for a menswear body block with a two-part sleeve", "holmes": "A FreeSewing pattern for a Sherlock Holmes hat",
"breanna": "A FreeSewing pattern for a basic body block for womenswear", "hortensia": "A FreeSewing pattern for a handbag",
"brian": "A FreeSewing pattern for a basic body block for menswear", "trayvon": "A FreeSewing pattern for a tie"
"bruce": "A FreeSewing pattern for boxer briefs", },
"carlita": "A FreeSewing pattern for Sherlock Holmes cosplay; Or just a nice long coat", "blocks": {
"carlton": "A FreeSewing pattern for Sherlock Holmes cosplay; Or just a nice long coat", "bella": "A FreeSewing pattern for a womenswear bodice block",
"cathrin": "A FreeSewing pattern for a underbust corset / waist trainer", "bent": "A FreeSewing pattern for a menswear body block with a two-part sleeve",
"charlie": "A FreeSewing pattern for chino trousers", "breanna": "A FreeSewing pattern for a basic body block for womenswear",
"cornelius": "A FreeSewing pattern for cycling breeches, based on the Keystone drafting system", "brian": "A FreeSewing pattern for a basic body block for menswear",
"diana": "A FreeSewing pattern for a top with a draped neck", "titan": "A FreeSewing pattern for a unisex trouser block"
"examples": "A FreeSewing pattern holding examples for our documentation", },
"florence": "A FreeSewing pattern for a face mask", "garments": {
"florent": "A FreeSewing pattern for a flat cap", "aaron": "A FreeSewing pattern for a A-shirt or tank top",
"hi": "A FreeSewing pattern for a shark plush toy", "albert": "A FreeSewing pattern for an apron",
"holmes": "A FreeSewing pattern for a Sherlock Holmes hat", "bee": "A FreeSewing pattern for a bikini top",
"hortensia": "A FreeSewing pattern for a handbag", "bruce": "A FreeSewing pattern for boxer briefs",
"huey": "A FreeSewing pattern for a zip-up hoodie", "carlita": "A FreeSewing pattern for Sherlock Holmes cosplay; Or just a nice long coat",
"hugo": "A FreeSewing pattern for a hooded jumper with raglan sleeves", "carlton": "A FreeSewing pattern for Sherlock Holmes cosplay; Or just a nice long coat",
"jaeger": "A FreeSewing pattern for a sport coat style jacket", "cathrin": "A FreeSewing pattern for a underbust corset / waist trainer",
"legend": "A FreeSewing pattern to document pattern notation", "charlie": "A FreeSewing pattern for chino trousers",
"lucy": "A FreeSewing pattern for a historical tie-on pocket", "cornelius": "A FreeSewing pattern for cycling breeches, based on the Keystone drafting system",
"lunetius": "A FreeSewing pattern for a lacerna, a historical Roman cloak", "diana": "A FreeSewing pattern for a top with a draped neck",
"paco": "A FreeSewing pattern for summer pants", "huey": "A FreeSewing pattern for a zip-up hoodie",
"penelope": "A FreeSewing pattern for a pencil skirt", "hugo": "A FreeSewing pattern for a hooded jumper with raglan sleeves",
"plugintest": "A FreeSewing pattern to test (y)our plugins", "jaeger": "A FreeSewing pattern for a sport coat style jacket",
"rendertest": "A FreeSewing pattern to test (y)our render engine our CSS", "lucy": "A FreeSewing pattern for a historical tie-on pocket",
"sandy": "A FreeSewing pattern for a circle skirt", "lunetius": "A FreeSewing pattern for a lacerna, a historical Roman cloak",
"shin": "A FreeSewing pattern for swim trunks", "paco": "A FreeSewing pattern for summer pants",
"simon": "A FreeSewing pattern for a button down shirt", "penelope": "A FreeSewing pattern for a pencil skirt",
"simone": "A FreeSewing pattern for a button down shirt (Simone = Simon for people with breasts)", "sandy": "A FreeSewing pattern for a circle skirt",
"sven": "A FreeSewing pattern for a straightforward sweater", "shin": "A FreeSewing pattern for swim trunks",
"tamiko": "A FreeSewing pattern for a zero-waste top", "simon": "A FreeSewing pattern for a button down shirt",
"teagan": "A FreeSewing pattern for a T-shirt", "simone": "A FreeSewing pattern for a button down shirt (Simone = Simon for people with breasts)",
"theo": "A FreeSewing pattern for classic trousers", "sven": "A FreeSewing pattern for a straightforward sweater",
"tiberius": "A FreeSewing pattern for a tunica, a historical Roman tunic", "tamiko": "A FreeSewing pattern for a zero-waste top",
"titan": "A FreeSewing pattern for a unisex trouser block", "teagan": "A FreeSewing pattern for a T-shirt",
"trayvon": "A FreeSewing pattern for a tie", "theo": "A FreeSewing pattern for classic trousers",
"tutorial": "A FreeSewing pattern for a baby bib that's used in our tutorial", "tiberius": "A FreeSewing pattern for a tunica, a historical Roman tunic",
"unice": "A FreeSewing pattern for a basic, highly-customizable underwear pattern", "unice": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
"ursula": "A FreeSewing pattern for a basic, highly-customizable underwear pattern", "ursula": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
"wahid": "A FreeSewing pattern for a classic fitted waistcoat", "wahid": "A FreeSewing pattern for a classic fitted waistcoat",
"walburga": "A FreeSewing pattern for a wappenrock (tabard/surcoat), a historical European/medieval (ish) garment", "walburga": "A FreeSewing pattern for a wappenrock (tabard/surcoat), a historical European/medieval (ish) garment",
"waralee": "A FreeSewing pattern for wrap pants", "waralee": "A FreeSewing pattern for wrap pants",
"yuri": "A FreeSewing pattern for a fancy zipless sweater based on the Huey hoodie" "yuri": "A FreeSewing pattern for a fancy zipless sweater based on the Huey hoodie"
},
"utilities": {
"examples": "A FreeSewing pattern holding examples for our documentation",
"legend": "A FreeSewing pattern to document pattern notation",
"plugintest": "A FreeSewing pattern to test (y)our plugins",
"rendertest": "A FreeSewing pattern to test (y)our render engine our CSS",
"tutorial": "A FreeSewing pattern for a baby bib that's used in our tutorial"
}
} }

View file

@ -1,4 +1,4 @@
import designs from './designs.json' import designsByType from './designs.json'
import packages from './packages.json' import packages from './packages.json'
import plugins from './plugins.json' import plugins from './plugins.json'
import sites from './sites.json' import sites from './sites.json'
@ -8,8 +8,15 @@ const unpack = (obj, folder) => Object.fromEntries(
Object.keys(obj).map(name => [name, { name, folder, description: obj[name], type: folder.slice(0, -1) } ]) Object.keys(obj).map(name => [name, { name, folder, description: obj[name], type: folder.slice(0, -1) } ])
) )
const designs = {
...designsByType.accessories,
...designsByType.blocks,
...designsByType.garments,
...designsByType.utilities,
}
// Re-Export imported JSON // Re-Export imported JSON
export { designs, packages, plugins, sites } export { designs, designsByType, packages, plugins, sites }
// All software // All software
export const software = { export const software = {

View file

@ -1,9 +1,9 @@
{ {
"backend": "FreeSewing backend", "backend": "FreeSewing backend",
"freesewing.dev": "FreeSewing website with documentation for contributors & developers", "dev": "FreeSewing website with documentation for contributors & developers",
"freesewing.lab": "FreeSewing website to test various patterns", "lab": "FreeSewing website to test various patterns",
"freesewing.org": "FreeSewing website", "org": "FreeSewing website",
"freesewing.shared": "Shared code and React components for different websites", "shared": "Shared code and React components for different websites",
"strapi": "Freesewing's Strapi instance", "strapi": "Freesewing's Strapi instance",
"svgtopdf": "FreeSewing on-demand tiler" "svgtopdf": "FreeSewing on-demand tiler"
} }

View file

@ -4,7 +4,7 @@ import glob from 'glob'
import yaml from 'js-yaml' import yaml from 'js-yaml'
import chalk from 'chalk' import chalk from 'chalk'
import mustache from 'mustache' import mustache from 'mustache'
import { capitalize } from '../sites/freesewing.shared/utils.mjs' import { capitalize } from '../sites/shared/utils.mjs'
import conf from '../lerna.json' import conf from '../lerna.json'
const { version } = conf const { version } = conf
import { import {

View file

@ -4,8 +4,6 @@ const config = {
index: 'freesewing.dev', index: 'freesewing.dev',
key: '589c7a7e4d9c95a4f12868581259bf3a', // Search-only API key key: '589c7a7e4d9c95a4f12868581259bf3a', // Search-only API key
}, },
strapi: 'https://posts.freesewing.org',
monorepo: 'https://github.com/freesewing/freesewing'
} }
export default config export default config

View file

@ -0,0 +1,37 @@
import { useRouter } from 'next/router'
import Link from 'next/link'
// Shared components
import Aside from 'shared/components/navigation/aside'
import ThemePicker from 'shared/components/theme-picker'
import Breadcrumbs from 'shared/components/breadcrumbs.js'
import { getCrumbs } from 'shared/utils'
const DefaultLayout = ({ app, title=false, crumbs=false, children=[] }) => {
const router = useRouter()
const slug = router.asPath.slice(1)
const breadcrumbs = crumbs
? crumbs
: getCrumbs(app, slug, title)
return (
<div className="m-auto flex flex-row justify-center">
<Aside app={app} slug={slug} before={<ThemePicker app={app} className="block sm:hidden"/>}/>
<section className="py-28 md:py-36 max-w-7xl px-6 xl:pl-8 2xl:pl-16">
<div>
{title && (
<>
<Breadcrumbs title={title} crumbs={breadcrumbs} />
{title
? <h1>{title}</h1>
: <h1>{app.getTitle(slug)}</h1>
}
</>
)}
{children}
</div>
</section>
</div>
)
}
export default DefaultLayout

View file

@ -5,7 +5,7 @@ import { useRouter } from 'next/router'
import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch/lite';
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { InstantSearch, connectHits, connectHighlight, connectSearchBox } from 'react-instantsearch-dom' import { InstantSearch, connectHits, connectHighlight, connectSearchBox } from 'react-instantsearch-dom'
import config from 'site/freesewing.config.js' import config from 'site/algolia.config.mjs'
const searchClient = algoliasearch(config.algolia.app, config.algolia.key) const searchClient = algoliasearch(config.algolia.app, config.algolia.key)

View file

@ -0,0 +1,3 @@
import i18n from '../shared/config/i18n.config.mjs'
export default i18n()

View file

@ -1,4 +1,4 @@
import configBuilder from '../freesewing.shared/config/next.mjs' import configBuilder from '../shared/config/next.mjs'
import i18nConfig from './next-i18next.config.js' import i18nConfig from './next-i18next.config.js'
const config = configBuilder('dev') const config = configBuilder('dev')

View file

@ -3,16 +3,14 @@
"version": "2.21.0-rc.0", "version": "2.21.0-rc.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 3002", "dev": "node --experimental-json-modules ./node_modules/.bin/next dev -p 8000",
"develop": "next dev -p 3002", "develop": "next dev -p 3002",
"prebuild": "SITE=dev node ../freesewing.shared/prebuild/index.mjs", "prebuild": "SITE=dev node --experimental-json-modules ../shared/prebuild/index.mjs",
"build": "next build", "build": "next build",
"export": "yarn prebuild && next build && next export && node scripts/algolia.mjs", "export": "yarn prebuild && next build && next export && node scripts/algolia.mjs",
"start": "next start -p 3002", "start": "next start -p 3002",
"lint": "next lint", "lint": "next lint",
"testdeploy": "next build && next export && netlify-cli deploy", "serve": "pm2 start npm --name 'dev' -- run start"
"deploy": "next build && next export && netlify-cli deploy --prod",
"serve": "pm2 start npm --name 'freesewing.dev' -- run start"
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^1.0.5", "@heroicons/react": "^1.0.5",

View file

@ -0,0 +1,107 @@
import Page from 'site/components/wrappers/page.js'
import useApp from 'site/hooks/useApp.js'
import Link from 'next/link'
import TimeAgo from 'react-timeago'
import { strapiHost } from 'shared/config/freesewing.mjs'
import { strapiImage } from 'shared/utils'
import { useTranslation } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
const strapi = "https://posts.freesewing.org"
const textShadow = {
style: {
textShadow: "1px 1px 1px #000000, -1px -1px 1px #000000, 1px -1px 1px #000000, -1px 1px 1px #000000, 2px 2px 1px #000000"
}
}
const Preview = ({ app, post }) => (
<div className="shadow rounded-lg">
<Link href={`/blog/${post.slug}`}>
<a title={post.title} className="hover:underline">
<div className="bg-base-100 w-full aspect-video shadow flex flex-column items-end rounded-lg" style={{
backgroundImage: `url(${strapi}${post.image.sizes.medium.url})`,
backgroundSize: 'cover',
}}>
<div className="grow"></div>
<div className="text-right mb-3 lg:mb-8">
<div className={`
bg-neutral text-neutral-content bg-opacity-40 text-right
px-4 py-1
lg:px-8 lg:py-4
`}>
<h5 className={`
text-neutral-content
text-xl font-bold
md:text-2xl md:font-normal
xl:text-3xl
`} {...textShadow}
>
{post.title}
</h5>
<p className={`
hidden md:block
m-0 p-1 -mt-2
text-neutral-content
leading-normal text-sm font-normal
opacity-70
`}{ ...textShadow}>
<TimeAgo date={post.date} /> by <strong>{post.author}</strong>
</p>
</div>
</div>
</div>
</a>
</Link>
</div>
)
const BlogIndexPage = (props) => {
const app = useApp()
const { t } = useTranslation()
return (
<Page app={app} title={t('blog')} slug='blog'>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2 max-w-7xl">
{props.posts.map(post => <Preview app={app} post={post} key={post.slug}/>)
}
</div>
</Page>
)
}
export default BlogIndexPage
/*
* getStaticProps() is used to fetch data at build-time.
*
* On this page, it is loading the blog content from strapi.
*
* This, in combination with getStaticPaths() below means this
* page will be used to render/generate all blog content.
*
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
*/
export async function getStaticProps({ params, locale }) {
const posts = await fetch(
`${strapiHost}/blogposts?_locale=en&_sort=date:DESC&dev_eq=true`
)
.then(response => response.json())
.then(data => data)
.catch(err => console.log(err))
return {
props: {
posts: posts.map(post => ({
slug: post.slug,
title: post.title,
date: post.date,
author: post.author.displayname,
image: strapiImage(post.image, ['medium']),
})),
...(await serverSideTranslations(locale)),
}
}
}

View file

@ -0,0 +1,5 @@
// Can't seem to make this work as ESM
const config = require('../shared/config/postcss.config.js')
module.exports = config

View file

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 313 KiB

After

Width:  |  Height:  |  Size: 313 KiB

Before After
Before After

View file

@ -0,0 +1,4 @@
// Can't seem to make this work as ESM
const config = require('../shared/config/tailwind.config.js')
module.exports = config

View file

@ -1,78 +0,0 @@
import React from 'react'
import { useRouter } from 'next/router'
import Link from 'next/link'
// Shared components
import Logo from 'shared/components/logos/freesewing.js'
import Aside from 'shared/components/navigation/aside'
import get from 'lodash.get'
const PageTitle = ({ app, slug, title }) => {
if (title) return <h1>{title}</h1>
if (slug) return <h1>{get(app.navigation, slug.split('/')).__title}</h1>
return <h1>FIXME: This page has no title</h1>
}
const Breadcrumbs = ({ app, slug=false, title }) => {
if (!slug) return null
const crumbs = []
const chunks = slug.split('/')
for (const i in chunks) {
const j = parseInt(i)+parseInt(1)
const page = get(app.navigation, chunks.slice(0,j))
if (page) crumbs.push([page.__linktitle, '/'+chunks.slice(0,j).join('/'), (j < chunks.length)])
}
return (
<ul className="flex flex-row flex-wrap gap-2 font-bold">
<li>
<Link href="/">
<a title="To the homepage" className="text-base-content">
<Logo size={24} fill="currentColor" stroke={false}/>
</a>
</Link>
</li>
{crumbs.map(crumb => (
<React.Fragment key={crumb[1]}>
<li className="text-base-content">&raquo;</li>
<li>
{crumb[2]
? (
<Link href={crumb[1]}>
<a title={crumb[0]} className="text-secondary hover:text-secondary-focus">
{crumb[0]}
</a>
</Link>
)
: <span className="text-base-content">{crumb[0]}</span>
}
</li>
</React.Fragment>
))}
</ul>
)
}
const DefaultLayout = ({ app, title=false, children=[] }) => {
const router = useRouter()
const slug = router.asPath.slice(1)
return (
<div className="m-auto flex flex-row justify-center">
<Aside app={app} slug={slug} />
<section className="py-28 md:py-36">
<div>
{title && (
<div className="px-8 xl:pl-8 2xl:pl-16">
<Breadcrumbs app={app} slug={slug} title={title} />
<PageTitle app={app} slug={slug} title={title} />
</div>
)}
{children}
</div>
</section>
</div>
)
}
export default DefaultLayout

View file

@ -1,115 +0,0 @@
import React from 'react'
import { useState } from 'react'
import { useRouter } from 'next/router'
import Link from 'next/link'
// Shared components
import Logo from 'shared/components/logos/freesewing.js'
import PrimaryNavigation from 'shared/components/navigation/primary'
import get from 'lodash.get'
import Right from 'shared/components/icons/right.js'
import Left from 'shared/components/icons/left.js'
// Site components
import Header from 'site/components/header'
import Footer from 'site/components/footer'
import Search from 'site/components/search'
const PageTitle = ({ app, slug, title }) => {
if (title) return <h1>{title}</h1>
if (slug) return <h1>{get(app.navigation, slug.split('/')).__title}</h1>
return <h1>FIXME: This page has no title</h1>
}
const Breadcrumbs = ({ app, slug=false, title }) => {
if (!slug) return null
const crumbs = []
const chunks = slug.split('/')
for (const i in chunks) {
const j = parseInt(i)+parseInt(1)
const page = get(app.navigation, chunks.slice(0,j))
if (page) crumbs.push([page.__linktitle, '/'+chunks.slice(0,j).join('/'), (j < chunks.length)])
}
return (
<ul className="flex flex-row flex-wrap gap-2 font-bold">
<li>
<Link href="/">
<a title="To the homepage" className="text-base-content">
<Logo size={24} fill="currentColor" stroke={false}/>
</a>
</Link>
</li>
{crumbs.map(crumb => (
<React.Fragment key={crumb[1]}>
<li className="text-base-content">&raquo;</li>
<li>
{crumb[2]
? (
<Link href={crumb[1]}>
<a title={crumb[0]} className="text-secondary hover:text-secondary-focus">
{crumb[0]}
</a>
</Link>
)
: <span className="text-base-content">{crumb[0]}</span>
}
</li>
</React.Fragment>
))}
</ul>
)
}
const LayoutWrapper = ({
app,
title=false,
children=[],
search,
setSearch,
noSearch=false,
workbench=false,
AltMenu=null,
}) => {
const startNavigation = () => {
app.startLoading()
// Force close of menu on mobile if it is open
if (app.primaryNavigation) app.setPrimaryNavigation(false)
// Force close of search modal if it is open
if (search) setSearch(false)
}
const router = useRouter()
router.events?.on('routeChangeStart', startNavigation)
router.events?.on('routeChangeComplete', () => app.stopLoading())
const slug = router.asPath.slice(1)
const [collapsePrimaryNav, setCollapsePrimaryNav] = useState(workbench || false)
const [collapseAltMenu, setCollapseAltMenu] = useState(false)
return (
<div className={`
flex flex-col justify-between
min-h-screen
bg-base-100
`}>
<Header app={app} setSearch={setSearch} />
<main className="grow">{children}</main>
{!noSearch && search && (
<>
<div className={`
fixed w-full max-h-screen bg-base-100 top-0 z-30 pt-0 pb-16 px-8
md:rounded-lg md:top-24
md:max-w-xl md:m-auto md:inset-x-12
md:max-w-2xl
lg:max-w-4xl
`}>
<Search app={app} search={search} setSearch={setSearch}/>
</div>
<div className="fixed top-0 left-0 w-full min-h-screen bg-neutral z-20 bg-opacity-70"></div>
</>
)}
<Footer app={app} />
</div>
)
}
export default LayoutWrapper

View file

@ -1,3 +0,0 @@
import i18n from '../freesewing.shared/config/i18n.config.mjs'
export default i18n()

View file

@ -1,88 +0,0 @@
import Page from 'shared/components/wrappers/page.js'
import useApp from 'site/hooks/useApp.js'
import Link from 'next/link'
import { posts } from 'site/prebuild/strapi.blog.en.js'
import orderBy from 'lodash.orderby'
import TimeAgo from 'react-timeago'
import Head from 'next/head'
import HelpUs from 'site/components/help-us.js'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
const strapi = "https://posts.freesewing.org"
const Preview = ({ app, post }) => (
<div className="theme-gradient p-1 hover:p-0 hover:mb-1 hover:pointer transition-all">
<Link href={`/blog/${post.slug}`}>
<a title={post.title} className="hover:underline">
<div className="bg-base-100 w-full aspect-video shadow flex flex-column items-end" style={{
backgroundImage: `url(${strapi}${post.img})`,
backgroundSize: 'cover',
}}>
<div className="grow"></div>
<div className="text-right">
<div className={`
bg-neutral text-neutral-content
bg-opacity-80
px-4 text-right
`}>
<h5 className={`
text-neutral-content
text-xl font-normal
md:text-2xl md:font-light
`}>
{post.title}
</h5>
<p className={`
m-0 p-1 -mt-2
text-neutral-content
opacity-50
leading-normal text-sm font-normal
`}>
<TimeAgo date={post.date} /> by {post.author}
</p>
</div>
</div>
</div>
</a>
</Link>
</div>
)
const BlogIndexPage = (props) => {
const app = useApp()
return (
<Page app={app} title='FreeSewing Development Blog' slug='blog'>
<Head>
<meta property="og:title" content="FreeSewing Developers Blog" key="title" />
<meta property="og:type" content="article" key='type' />
<meta property="og:description" content="Content for developers and contributors alike. Strictly no sewing stuff" key='type' />
<meta property="og:article:author" content='Joost De Cock' key='author' />
<meta property="og:image" content="https://canary.backend.freesewing.org/og-img/en/dev/blog" key='image' />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content="https://freesewing.dev/blog" key='url' />
<meta property="og:locale" content="en_US" key='locale' />
<meta property="og:site_name" content="freesewing.dev" key='site' />
</Head>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
{Object.values(orderBy(posts, ['date'], ['desc']))
.map(post => <Preview app={app} post={post} key={post.slug}/>)
}
</div>
<HelpUs slug='/blog' />
</Page>
)
}
export default BlogIndexPage
export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations('en')),
}
}
}

View file

@ -1,3 +0,0 @@
import i18n from '../freesewing.shared/config/i18n.config.mjs'
export default i18n()

View file

@ -1,46 +0,0 @@
import path from 'path'
import { readdirSync } from 'fs'
import i18nConfig from './next-i18next.config.js'
const getDirectories = source =>
readdirSync(source, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name)
const pkgs = getDirectories(path.resolve(`../`))
const config = {
experimental: {
externalDir: true,
},
i18n: i18nConfig.i18n,
pageExtensions: [ 'js' ],
webpack: (config, options) => {
// YAML support
config.module.rules.push({
test: /\.ya?ml$/,
type: 'json',
use: 'yaml-loader'
})
// Suppress warnings about importing version from package.json
// We'll deal with it in v3 of FreeSewing
config.ignoreWarnings = [
/only default export is available soon/
]
// Aliases
config.resolve.alias.shared = path.resolve('../freesewing.shared/')
config.resolve.alias.site = path.resolve(`.`)
config.resolve.alias.lib = path.resolve(`./lib`)
config.resolve.alias.pkgs = path.resolve(`../`)
// This forces webpack to load the code from source, rather than compiled bundle
for (const pkg of pkgs) {
config.resolve.alias[`@freesewing/${pkg}$`] = path.resolve(`../${pkg}/src/index.js`)
}
return config
}
}
export default config

View file

@ -1,5 +0,0 @@
// Can't seem to make this work as ESM
const config = require('../freesewing.shared/config/postcss.config.js')
module.exports = config

View file

@ -1 +0,0 @@
../../../freesewing.dev/public/img/splash.jpg

View file

@ -1,4 +0,0 @@
// Can't seem to make this work as ESM
const config = require('../freesewing.shared/config/tailwind.config.js')
module.exports = config

View file

@ -1,5 +0,0 @@
// Can't seem to make this work as ESM
const config = require('../freesewing.shared/config/postcss.config.js')
module.exports = config

View file

@ -1,4 +0,0 @@
// Can't seem to make this work as ESM
const config = require('../freesewing.shared/config/tailwind.config.js')
module.exports = config

View file

@ -1,60 +0,0 @@
{
"accessories": [
"florence",
"florent",
"hi",
"holmes",
"hortensia",
"lucy",
"trayvon"
],
"blocks": [
"bella",
"bent",
"brian",
"titan"
],
"garments": [
"aaron",
"albert",
"bee",
"benjamin",
"breanna",
"bruce",
"carlita",
"carlton",
"cathrin",
"charlie",
"cornelius",
"diana",
"huey",
"hugo",
"jaeger",
"lunetius",
"paco",
"penelope",
"sandy",
"shin",
"simon",
"simone",
"sven",
"tamiko",
"teagan",
"theo",
"tiberius",
"unice",
"ursula",
"wahid",
"walburga",
"waralee",
"yuri"
],
"utilities": [
"examples",
"legend",
"plugintest",
"rendertest",
"tutorial"
]
}

View file

@ -1,5 +0,0 @@
export const strapiHost = 'https://posts.freesewing.org'
export const monorepo = 'https://github.com/freesewing/freesewing'

View file

@ -1,7 +0,0 @@
const pitches = [
'This website does not track you',
"Come in, we're open",
'Made-to-measure sewing patterns',
]
export default pitches

View file

@ -1,11 +1,11 @@
import { useState } from 'react' import { useState } from 'react'
// Stores state in local storage // Stores state in local storage
import useLocalStorage from 'shared/hooks/useLocalStorage.js' import useLocalStorage from 'shared/hooks/useLocalStorage.js'
// Patterns // Designs
import patterns from 'shared/config/designs.json' import { designsByType } from 'config/software/index.mjs'
// Locale and translation // Locale and translation
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { capitalize } from 'shared/utils' import { capitalize } from 'shared/utils.mjs'
import { formatVersionUri } from '../components/version-picker.js' import { formatVersionUri } from '../components/version-picker.js'
import useVersion from 'site/hooks/useVersion.js' import useVersion from 'site/hooks/useVersion.js'
import useTheme from 'shared/hooks/useTheme' import useTheme from 'shared/hooks/useTheme'
@ -14,44 +14,46 @@ import useTheme from 'shared/hooks/useTheme'
const initialNavigation = (t, version) => { const initialNavigation = (t, version) => {
const base = { const base = {
accessories: { accessories: {
__title: t('accessoryPatterns'), __title: t('accessoryDesigns'),
__order: t('accessoryPatterns'),
__linktitle: t('accessoryPatterns'),
__slug: 'accessories', __slug: 'accessories',
}, },
blocks: { blocks: {
__title: t('blockPatterns'), __title: t('blockDesigns'),
__order: t('blockPatterns'),
__linktitle: t('blockPatterns'),
__slug: 'blocks', __slug: 'blocks',
}, },
garments: { garments: {
__title: t('garmentPatterns'), __title: t('garmentDesigns'),
__order: t('garmentPatterns'),
__linktitle: t('garmentPatterns'),
__slug: t('garments'), __slug: t('garments'),
}, },
utilities: { utilities: {
__title: t('utilityPatterns'), __title: t('utilityDesigns'),
__order: t('utilityPatterns'),
__linktitle: t('utilityPatterns'),
__slug: 'utilities', __slug: 'utilities',
}, },
} }
for (const type in patterns) { for (const type in designsByType) {
for (const design of patterns[type]) { for (const design in designsByType[type]) {
base[type][design] = { base[type][design] = {
__title: capitalize(design), __title: capitalize(design),
__order: design,
__linktitle: capitalize(design),
__slug: formatVersionUri(version,design) __slug: formatVersionUri(version,design)
} }
} }
} }
for (const key in base) {
base[key].__order = base[key].__title
base[key].__linktitle = base[key].__title
}
return base return base
} }
const designs = {}
for (const type in designsByType) {
designs[type] = []
for (const design in designsByType[type]) {
designs[type].push(design)
}
}
function useApp(full = true) { function useApp(full = true) {
// Version // Version
@ -68,7 +70,7 @@ function useApp(full = true) {
const [primaryMenu, setPrimaryMenu] = useState(false) const [primaryMenu, setPrimaryMenu] = useState(false)
const [navigation, setNavigation] = useState(initialNavigation(t, version)) const [navigation, setNavigation] = useState(initialNavigation(t, version))
const [slug, setSlug] = useState('/') const [slug, setSlug] = useState('/')
const [pattern, setPattern] = useState(false) const [design, setDesign] = useState(false)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
// State methods // State methods
@ -77,12 +79,12 @@ function useApp(full = true) {
return { return {
// Static vars // Static vars
site: 'lab', site: 'lab',
patterns, designs,
// State // State
loading, loading,
navigation, navigation,
pattern, design,
primaryMenu, primaryMenu,
slug, slug,
theme, theme,
@ -90,7 +92,7 @@ function useApp(full = true) {
// State setters // State setters
setLoading, setLoading,
setNavigation, setNavigation,
setPattern, setDesign,
setPrimaryMenu, setPrimaryMenu,
setSlug, setSlug,
setTheme, setTheme,

View file

@ -0,0 +1,3 @@
import i18n from '../shared/config/i18n.config.mjs'
export default i18n()

59
sites/lab/next.config.mjs Normal file
View file

@ -0,0 +1,59 @@
import path from 'path'
import { readdirSync } from 'fs'
import i18nConfig from './next-i18next.config.js'
import { designs, plugins, packages } from '../../config/software/index.mjs'
const getDirectories = source =>
readdirSync(source, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name)
const pkgs = getDirectories(path.resolve(`../`))
const config = {
experimental: {
externalDir: true,
},
i18n: i18nConfig.i18n,
pageExtensions: [ 'js' ],
webpack: (config, options) => {
// YAML support
config.module.rules.push({
test: /\.ya?ml$/,
type: 'json',
use: 'yaml-loader'
})
// Suppress warnings about importing version from package.json
// We'll deal with it in v3 of FreeSewing
config.ignoreWarnings = [
/only default export is available soon/
]
// Aliases
config.resolve.alias.shared = path.resolve('../shared/')
config.resolve.alias.site = path.resolve('.')
config.resolve.alias.lib = path.resolve('./lib')
config.resolve.alias.config = path.resolve('../../config/')
config.resolve.alias.designs = path.resolve('../../designs/')
config.resolve.alias.plugins = path.resolve('../../plugins/')
config.resolve.alias.pkgs = path.resolve('../../packages/')
// Load designs from source, rather than compiled package
for (const design in designs) {
config.resolve.alias[`@freesewing/${design}$`] = path.resolve(`../../designs/${design}/src/index.js`)
}
// Load plugins from source, rather than compiled package
for (const plugin in plugins) {
config.resolve.alias[`@freesewing/${plugin}$`] = path.resolve(`../../plugins/${plugin}/src/index.js`)
}
// Load these from source, rather than compiled package
for (const pkg of ['core', 'config-helpers', 'i18n', 'models']) {
config.resolve.alias[`@freesewing/${pkg}$`] = path.resolve(`../../packages/${pkg}/src/index.js`)
}
return config
}
}
export default config

View file

@ -3,17 +3,15 @@
"version": "2.21.0-rc.0", "version": "2.21.0-rc.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 3002", "dev": "node --experimental-json-modules ./node_modules/.bin/next dev -p 8000",
"develop": "next dev -p 3002", "develop": "next dev -p 8000",
"prebuild": "cd ../utils && npm run build && cd - && SITE=lab node ../freesewing.shared/prebuild/index.mjs", "prebuild": "SITE=lab node --experimental-json-modules ../shared/prebuild/index.mjs",
"cibuild": "yarn prebuild && next build", "cibuild": "yarn prebuild && next build",
"build": "next build", "build": "next build",
"export": "yarn prebuild && next build && next export", "export": "yarn prebuild && next build && next export",
"start": "next start -p 3002", "start": "next start -p 3002",
"lint": "next lint", "lint": "next lint",
"testdeploy": "next build && next export && netlify-cli deploy", "serve": "pm2 start npm --name 'dev' -- run start"
"deploy": "next build && next export && netlify-cli deploy --prod",
"serve": "pm2 start npm --name 'freesewing.dev' -- run start"
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^1.0.5", "@heroicons/react": "^1.0.5",

View file

@ -4,14 +4,14 @@ import WorkbenchWrapper from 'shared/components/wrappers/workbench.js'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import Layout from 'site/components/layouts/lab' import Layout from 'site/components/layouts/lab'
const WorkbenchPage = ({ pattern }) => { const WorkbenchPage = ({ design }) => {
const app = useApp() const app = useApp()
const router = useRouter() const router = useRouter()
const { preload, from } = router.query const { preload, from } = router.query
return ( return (
<Page app={app}> <Page app={app}>
<WorkbenchWrapper {...{ app, pattern, preload, from }} layout={Layout} /> <WorkbenchWrapper {...{ app, design, preload, from }} layout={Layout} />
</Page> </Page>
) )
} }

Some files were not shown because too many files have changed in this diff Show more