1
0
Fork 0

feat(org): Bookmarks for docs

This commit is contained in:
joostdecock 2023-09-04 08:40:05 +02:00
parent e21d262ec2
commit 2106a38154
66 changed files with 380 additions and 467 deletions

View file

@ -1,8 +1,7 @@
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs'
import { useState, useContext } from 'react' import { useState, useContext } from 'react'
// Components // Components
import { ChoiceButton } from 'shared/components/choice-button.mjs' import { ChoiceButton } from 'shared/components/choice-button.mjs'
@ -43,12 +42,9 @@ const languages = [
] ]
export const SuggestLanguageForm = () => { export const SuggestLanguageForm = () => {
// Context
const { startLoading, stopLoading } = useContext(LoadingContext)
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
const toast = useToast() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [language, setLanguage] = useState(false) const [language, setLanguage] = useState(false)
@ -58,15 +54,12 @@ export const SuggestLanguageForm = () => {
const [comments, setComments] = useState('') const [comments, setComments] = useState('')
const sendSuggestion = async () => { const sendSuggestion = async () => {
startLoading() setLoadingStatus([true, 'status:contactingBackend'])
const result = await backend.sendLanguageSuggestion({ language, help, friends, comments }) const result = await backend.sendLanguageSuggestion({ language, help, friends, comments })
if (result.success) { if (result.success) {
setSent(true) setSent(true)
stopLoading() setLoadingStatus([true, 'status:nailedIt', true, true])
toast.success('Suggestion submitted') } else setLoadingStatus([true, 'status:backendError', true, false])
} else {
toast.for.backendError()
}
} }
if (sent) if (sent)

View file

@ -2,10 +2,9 @@
import { siteConfig } from 'site/site.config.mjs' import { siteConfig } from 'site/site.config.mjs'
import translators from 'site/prebuild/translators.json' import translators from 'site/prebuild/translators.json'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs'
import { useState, useContext } from 'react' import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Components // Components
@ -22,28 +21,22 @@ const languages = [
].sort() ].sort()
export const TranslatorInvite = () => { export const TranslatorInvite = () => {
// Context
const { startLoading, stopLoading } = useContext(LoadingContext)
// Hooks // Hooks
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const toast = useToast() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [team, setTeam] = useState(false) const [team, setTeam] = useState(false)
const [sent, setSent] = useState(false) const [sent, setSent] = useState(false)
const sendInvite = async () => { const sendInvite = async () => {
startLoading() setLoadingStatus([true, 'status:contactingBackend'])
const result = await backend.sendTranslatorInvite(team) const result = await backend.sendTranslatorInvite(team)
if (result.success) { if (result.success) {
setSent(true) setSent(true)
stopLoading() setLoadingStatus([true, 'status:settingsSaved', true, true])
toast.success(t('translation:inviteSent')) } else setLoadingStatus([true, 'status:backendError', true, false])
} else {
toast.for.backendError()
}
} }
if (sent) if (sent)

View file

@ -5,14 +5,13 @@ import { freeSewingConfig as conf } from 'shared/config/freesewing.config.mjs'
import { measurements } from 'config/measurements.mjs' import { measurements } from 'config/measurements.mjs'
import { measurements as designMeasurements } from 'shared/prebuild/data/design-measurements.mjs' import { measurements as designMeasurements } from 'shared/prebuild/data/design-measurements.mjs'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
// Hooks // Hooks
import { useState, useEffect, useContext } from 'react' import { useState, useEffect, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs'
// Components // Components
import { Collapse } from 'shared/components/collapse.mjs' import { Collapse } from 'shared/components/collapse.mjs'
import { ClearIcon, EditIcon, FilterIcon } from 'shared/components/icons.mjs' import { ClearIcon, EditIcon, FilterIcon } from 'shared/components/icons.mjs'
@ -22,7 +21,7 @@ import { PageLink } from 'shared/components/link.mjs'
import { ModalDesignPicker } from 'shared/components/modal/design-picker.mjs' import { ModalDesignPicker } from 'shared/components/modal/design-picker.mjs'
import { V3Wip } from 'shared/components/v3-wip.mjs' import { V3Wip } from 'shared/components/v3-wip.mjs'
export const ns = ['toast', 'curate', 'sets', 'account'] export const ns = ['curate', 'sets', 'account']
const EditField = (props) => { const EditField = (props) => {
if (props.field === 'nameEn') return <EditName {...props} lang="en" /> if (props.field === 'nameEn') return <EditName {...props} lang="en" />
@ -137,7 +136,7 @@ export const EditCuratedSet = ({ id }) => {
/* /*
// Context // Context
const { startLoading, stopLoading } = useContext(LoadingContext) const { setLoadingStatus } = useContext(LoadingStatusContext)
const { setModal } = useContext(ModalContext) const { setModal } = useContext(ModalContext)
// Hooks // Hooks
@ -171,8 +170,6 @@ export const EditCuratedSet = ({ id }) => {
}, [reload, backend, id]) }, [reload, backend, id])
const editProps = { const editProps = {
startLoading,
stopLoading,
account, account,
backend, backend,
t, t,

View file

@ -2,7 +2,7 @@
import { capitalize } from 'shared/utils.mjs' import { capitalize } from 'shared/utils.mjs'
import { siteConfig } from 'site/site.config.mjs' import { siteConfig } from 'site/site.config.mjs'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
// Hooks // Hooks
import { useState, useEffect, useContext } from 'react' import { useState, useEffect, useContext } from 'react'
@ -27,28 +27,17 @@ export const Row = ({ title, children }) => (
</div> </div>
) )
const CuratedSet = ({ const CuratedSet = ({ set, account, t, setLoadingStatus, backend, refresh, toast, language }) => {
set,
account,
t,
startLoading,
stopLoading,
backend,
refresh,
toast,
language,
}) => {
const { setModal } = useContext(ModalContext) const { setModal } = useContext(ModalContext)
const remove = async () => { const remove = async () => {
startLoading() setLoadingStatus([true, 'status:contactingBackend'])
const result = await backend.removeCuratedMeasurementsSet(set.id) const result = await backend.removeCuratedMeasurementsSet(set.id)
if (result) toast.success(t('gone')) if (result) setLoadingStatus([true, 'status:settingsSaved', true, true])
else toast.for.backendError() else setLoadingStatus([true, 'status:backendError', true, false])
// This just forces a refresh of the list from the server // This just forces a refresh of the list from the server
// We obviously did not add a key here, but rather removed one // We obviously did not add a key here, but rather removed one
refresh() refresh()
stopLoading()
} }
const removeModal = () => { const removeModal = () => {
@ -119,7 +108,7 @@ const CuratedSet = ({
export const CurateSets = () => { export const CurateSets = () => {
// Context // Context
const { startLoading, stopLoading } = useContext(LoadingContext) const { setLoadingStatus } = useContext(LoadingStatusContext)
// Hooks // Hooks
const { account } = useAccount() const { account } = useAccount()
@ -209,7 +198,7 @@ export const CurateSets = () => {
{list.map((set) => ( {list.map((set) => (
<CuratedSet <CuratedSet
key={set.id} key={set.id}
{...{ set, account, t, startLoading, stopLoading, backend, refresh, toast, language }} {...{ set, account, t, setLoadingStatus, backend, refresh, toast, language }}
/> />
))} ))}
</div> </div>

View file

@ -5,6 +5,8 @@ import { useState, Fragment } from 'react'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs'
@ -22,7 +24,6 @@ import { CodeBox } from 'shared/components/code-box.mjs'
import { PostArticle, ns as mdxNs } from 'site/components/mdx/posts/article.mjs' import { PostArticle, ns as mdxNs } from 'site/components/mdx/posts/article.mjs'
import { PageLink, WebLink } from 'shared/components/link.mjs' import { PageLink, WebLink } from 'shared/components/link.mjs'
import { OkIcon, WarningIcon as KoIcon } from 'shared/components/icons.mjs' import { OkIcon, WarningIcon as KoIcon } from 'shared/components/icons.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
export const ns = nsMerge('account', 'posts', authNs, mdxNs) export const ns = nsMerge('account', 'posts', authNs, mdxNs)
@ -64,7 +65,7 @@ export const CreatePost = ({ type = 'showcase' }) => {
const backend = useBackend() const backend = useBackend()
const { account } = useAccount() const { account } = useAccount()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { loading, setLoadingStatus, LoadingStatus } = useLoadingStatus() const { loading, setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [designs, setDesigns] = useState([]) const [designs, setDesigns] = useState([])
@ -151,7 +152,6 @@ export const CreatePost = ({ type = 'showcase' }) => {
return ( return (
<AuthWrapper> <AuthWrapper>
<LoadingStatus />
{pr ? ( {pr ? (
<div className="w-full max-w-3xl m-auto p-4"> <div className="w-full max-w-3xl m-auto p-4">
<h1>Thank you for submitting this {type} post</h1> <h1>Thank you for submitting this {type} post</h1>

View file

@ -5,6 +5,8 @@ import { useState, Fragment } from 'react'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs'
@ -22,7 +24,6 @@ import { CodeBox } from 'shared/components/code-box.mjs'
import { PostArticle, ns as mdxNs } from 'site/components/mdx/posts/article.mjs' import { PostArticle, ns as mdxNs } from 'site/components/mdx/posts/article.mjs'
import { PageLink, WebLink } from 'shared/components/link.mjs' import { PageLink, WebLink } from 'shared/components/link.mjs'
import { OkIcon, WarningIcon as KoIcon } from 'shared/components/icons.mjs' import { OkIcon, WarningIcon as KoIcon } from 'shared/components/icons.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
export const ns = nsMerge('account', 'posts', authNs, mdxNs) export const ns = nsMerge('account', 'posts', authNs, mdxNs)
@ -53,7 +54,7 @@ export const CreateShowcasePost = () => {
const { account } = useAccount() const { account } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { loading, setLoadingStatus, LoadingStatus } = useLoadingStatus() const { loading, setLoadingStatus } = useContext(LoadingStatusContext)
const [designs, setDesigns] = useState([]) const [designs, setDesigns] = useState([])
const [title, setTitle] = useState('') const [title, setTitle] = useState('')
@ -135,7 +136,6 @@ export const CreateShowcasePost = () => {
return ( return (
<AuthWrapper> <AuthWrapper>
<LoadingStatus />
{pr ? ( {pr ? (
<div className="w-full max-w-3xl m-auto p-4"> <div className="w-full max-w-3xl m-auto p-4">
<h1>Thank you for submitting this showcase</h1> <h1>Thank you for submitting this showcase</h1>

View file

@ -1,4 +1,5 @@
import { NavigationContext } from 'shared/context/navigation-context.mjs' import { NavigationContext } from 'shared/context/navigation-context.mjs'
import { nsMerge } from 'shared/utils.mjs'
// Hooks // Hooks
import { useContext } from 'react' import { useContext } from 'react'
// Components // Components
@ -16,10 +17,10 @@ import {
ns as navNs, ns as navNs,
} from 'shared/components/navigation/sitenav.mjs' } from 'shared/components/navigation/sitenav.mjs'
import { Toc } from 'shared/components/mdx/toc.mjs' import { Toc } from 'shared/components/mdx/toc.mjs'
import { MdxMetaData } from 'shared/components/mdx/meta.mjs' import { MdxMetaData, ns as metaNs } from 'shared/components/mdx/meta.mjs'
import { PrevNext } from 'shared/components/prev-next.mjs' import { PrevNext } from 'shared/components/prev-next.mjs'
export const ns = [navNs, 'docs'] //navNs export const ns = nsMerge(navNs, 'docs', metaNs)
export const FrontmatterHead = ({ frontmatter, slug, locale }) => ( export const FrontmatterHead = ({ frontmatter, slug, locale }) => (
<Head> <Head>

View file

@ -4,7 +4,6 @@ import React from 'react'
import Bugsnag from '@bugsnag/js' import Bugsnag from '@bugsnag/js'
import BugsnagPluginReact from '@bugsnag/plugin-react' import BugsnagPluginReact from '@bugsnag/plugin-react'
import { siteConfig } from 'site/site.config.mjs' import { siteConfig } from 'site/site.config.mjs'
import { Toaster as DefaultToaster } from 'react-hot-toast'
import { ContextWrapper } from 'shared/components/wrappers/context.mjs' import { ContextWrapper } from 'shared/components/wrappers/context.mjs'
Bugsnag.start({ Bugsnag.start({
@ -19,24 +18,6 @@ const FreeSewingOrg = ({ Component, pageProps }) => (
<ErrorBoundary> <ErrorBoundary>
<ContextWrapper> <ContextWrapper>
<Component {...pageProps} /> <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> </ContextWrapper>
</ErrorBoundary> </ErrorBoundary>
) )

View file

@ -6,14 +6,13 @@ import { nsMerge } from 'shared/utils.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs'
import { ns as apikeysNs } from 'shared/components/account/apikeys.mjs' import { ns as apikeysNs } from 'shared/components/account/apikeys.mjs'
// Translation namespaces used on this page // Translation namespaces used on this page
const ns = nsMerge(apikeysNs, authNs, pageNs, 'status') const ns = nsMerge(apikeysNs, authNs, pageNs)
/* /*
* Some things should never generated as SSR * Some things should never generated as SSR
@ -38,26 +37,20 @@ const DynamicApikey = dynamic(
const ApikeyPage = ({ page, id }) => { const ApikeyPage = ({ page, id }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus()
const [apikey, setApikey] = useState() const [apikey, setApikey] = useState()
useEffect(() => { useEffect(() => {
const getApikey = async () => { const getApikey = async () => {
setLoadingStatus([true, t('backendLoadingStarted')])
const result = await backend.getApikey(id) const result = await backend.getApikey(id)
if (result.success) { if (result.success) setApikey(result.data.apikey)
setApikey(result.data.apikey) else setLoadingStatus([false])
console.log(result.data.apikey)
setLoadingStatus([true, 'backendLoadingCompleted', true, true])
} else setLoadingStatus([false])
} }
getApikey() getApikey()
}, [id]) }, [id])
return ( return (
<PageWrapper {...page} title={`${t('apikeys')}: ${apikey?.name}`}> <PageWrapper {...page} title={`${t('apikeys')}: ${apikey?.name}`}>
<LoadingStatus />
<DynamicAuthWrapper> <DynamicAuthWrapper>
<DynamicApikey apikey={apikey} t={t} /> <DynamicApikey apikey={apikey} t={t} />
</DynamicAuthWrapper> </DynamicAuthWrapper>

View file

@ -6,7 +6,6 @@ import { nsMerge } from 'shared/utils.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs'
@ -38,25 +37,20 @@ const DynamicBookmark = dynamic(
const BookmarkPage = ({ page, id }) => { const BookmarkPage = ({ page, id }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus()
const [bookmark, setBookmark] = useState() const [bookmark, setBookmark] = useState()
useEffect(() => { useEffect(() => {
const getBookmark = async () => { const getBookmark = async () => {
setLoadingStatus([true, t('backendLoadingStarted')])
const result = await backend.getBookmark(id) const result = await backend.getBookmark(id)
if (result.success) { if (result.success) setBookmark(result.data.bookmark)
setBookmark(result.data.bookmark) else setLoadingStatus([false])
setLoadingStatus([true, 'backendLoadingCompleted', true, true])
} else setLoadingStatus([false])
} }
getBookmark() getBookmark()
}, [id]) }, [id])
return ( return (
<PageWrapper {...page} title={`${t('bookmarks')}: ${bookmark?.title}`}> <PageWrapper {...page} title={`${t('bookmarks')}: ${bookmark?.title}`}>
<LoadingStatus />
<DynamicAuthWrapper> <DynamicAuthWrapper>
<DynamicBookmark bookmark={bookmark} /> <DynamicBookmark bookmark={bookmark} />
</DynamicAuthWrapper> </DynamicAuthWrapper>

View file

@ -2,11 +2,10 @@
import { useEffect, useState, useContext } from 'react' import { useEffect, useState, useContext } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Dependencies // Dependencies
import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import Link from 'next/link' import Link from 'next/link'
@ -22,13 +21,10 @@ import { HelpIcon } from 'shared/components/icons.mjs'
const ns = Array.from(new Set([...pageNs, 'account'])) const ns = Array.from(new Set([...pageNs, 'account']))
const ConfirmSignUpPage = ({ page }) => { const ConfirmSignUpPage = ({ page }) => {
// Context
const { startLoading, stopLoading } = useContext(LoadingContext)
// Hooks // Hooks
const { setAccount, setToken, token } = useAccount() const { setAccount, setToken, token } = useAccount()
const backend = useBackend() const backend = useBackend()
const toast = useToast() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const router = useRouter() const router = useRouter()
// Get confirmation ID and check from url // Get confirmation ID and check from url
@ -41,7 +37,7 @@ const ConfirmSignUpPage = ({ page }) => {
useEffect(() => { useEffect(() => {
// Async inside useEffect requires this approach // Async inside useEffect requires this approach
const confirmEmail = async () => { const confirmEmail = async () => {
startLoading() setLoadingStatus([true, 'status:contactingBackend'])
const confirmation = await backend.loadConfirmation({ id, check }) const confirmation = await backend.loadConfirmation({ id, check })
if (confirmation?.result === 'success' && confirmation.confirmation) { if (confirmation?.result === 'success' && confirmation.confirmation) {
const result = await backend.updateAccount({ const result = await backend.updateAccount({
@ -50,35 +46,23 @@ const ConfirmSignUpPage = ({ page }) => {
check: confirmation.confirmation.check, check: confirmation.confirmation.check,
}) })
if (result.success) { if (result.success) {
setLoadingStatus([true, 'status:settingsSaved', true, true])
setAccount(result.data.account) setAccount(result.data.account)
setToken(result.data.token) setToken(result.data.token)
stopLoading()
setError(false) setError(false)
toast.for.settingsSaved()
router.push('/account') router.push('/account')
} else { } else {
stopLoading() setLoadingStatus([true, 'status:backendError', true, false])
setError(true) setError(true)
} }
} else { } else {
stopLoading() setLoadingStatus([true, 'status:backendError', true, false])
setError(true) setError(true)
} }
} }
// Call async methods // Call async methods
if (token) confirmEmail() if (token) confirmEmail()
}, [ }, [id, check, token, backend, router, setAccount, setToken])
id,
check,
token,
backend,
router,
setAccount,
setToken,
startLoading,
stopLoading,
toast.for,
])
// Update path with dynamic ID // Update path with dynamic ID
if (!page) return null if (!page) return null

View file

@ -1,3 +1,4 @@
import { nsMerge } from 'shared/utils.mjs'
// Used in static paths // Used in static paths
import { pages } from 'site/prebuild/docs.en.mjs' import { pages } from 'site/prebuild/docs.en.mjs'
// Dependencies // Dependencies
@ -11,7 +12,7 @@ import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
import { DocsLayout, ns as layoutNs } from 'site/components/layouts/docs.mjs' import { DocsLayout, ns as layoutNs } from 'site/components/layouts/docs.mjs'
import { loaders } from 'shared/components/dynamic-docs/org.mjs' import { loaders } from 'shared/components/dynamic-docs/org.mjs'
export const ns = [...pageNs, layoutNs] export const ns = nsMerge(pageNs, layoutNs)
/** /**
* a page to display documentation markdown * a page to display documentation markdown
@ -49,7 +50,7 @@ export default DocsPage
export async function getStaticProps({ locale, params }) { export async function getStaticProps({ locale, params }) {
return { return {
props: { props: {
...(await serverSideTranslations('en', ['docs', ...ns])), ...(await serverSideTranslations('en', ns)),
slug: params.slug.join('/'), slug: params.slug.join('/'),
locale, locale,
page: { page: {

View file

@ -6,7 +6,7 @@ import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -23,15 +23,15 @@ const namespaces = nsMerge(pageNs, 'newsletter')
*/ */
const NewsletterPage = ({ page, id, ehash }) => { const NewsletterPage = ({ page, id, ehash }) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
const { setLoading } = useContext(LoadingContext) const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const [confirmed, setConfirmed] = useState(false) const [confirmed, setConfirmed] = useState(false)
const handler = async () => { const handler = async () => {
setLoading(true) setLoadingStatus([true, 'status:contactingBackend'])
await backend.confirmNewsletterSubscribe({ id, ehash }) await backend.confirmNewsletterSubscribe({ id, ehash })
setLoading(false) setLoadingStatus([true, 'status:settingsSaved', true, true])
setConfirmed(true) setConfirmed(true)
} }

View file

@ -6,7 +6,7 @@ import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -23,15 +23,15 @@ const namespaces = nsMerge(pageNs, 'newsletter')
*/ */
const NewsletterPage = ({ page, id, ehash }) => { const NewsletterPage = ({ page, id, ehash }) => {
const { t } = useTranslation(namespaces) const { t } = useTranslation(namespaces)
const { setLoading } = useContext(LoadingContext) const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const [confirmed, setConfirmed] = useState(false) const [confirmed, setConfirmed] = useState(false)
const handler = async () => { const handler = async () => {
setLoading(true) setLoadingStatus([true, 'status:contactingBackend'])
await backend.confirmNewsletterUnsubscribe({ id, ehash }) await backend.confirmNewsletterUnsubscribe({ id, ehash })
setLoading(false) setLoadingStatus([true, 'status:settingsSaved', true, true])
setConfirmed(true) setConfirmed(true)
} }

View file

@ -6,8 +6,9 @@ import { useEffect } from 'react'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
import { BareLayout } from 'site/components/layouts/bare.mjs' import { BareLayout } from 'site/components/layouts/bare.mjs'
@ -27,7 +28,7 @@ const OauthCallbackPage = ({ page, provider }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const { setAccount, setToken, setSeenUser } = useAccount() const { setAccount, setToken, setSeenUser } = useAccount()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
useEffect(() => { useEffect(() => {
const oauthFlow = async () => { const oauthFlow = async () => {
@ -53,7 +54,6 @@ const OauthCallbackPage = ({ page, provider }) => {
return ( return (
<PageWrapper {...page} layout={BareLayout}> <PageWrapper {...page} layout={BareLayout}>
<LoadingStatus />
<div className="flex flex-col items-center h-screen justify-center text-base-content px-4"> <div className="flex flex-col items-center h-screen justify-center text-base-content px-4">
<div className="max-w-lg w-full"> <div className="max-w-lg w-full">
<Loading /> <Loading />

View file

@ -4,11 +4,12 @@ import { useTranslation } from 'next-i18next'
import { DateTime } from 'luxon' import { DateTime } from 'luxon'
import { CopyToClipboard } from 'react-copy-to-clipboard' import { CopyToClipboard } from 'react-copy-to-clipboard'
import { shortDate, formatNumber } from 'shared/utils.mjs' import { shortDate, formatNumber } from 'shared/utils.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton, DisplayRow, NumberBullet } from './shared.mjs' import { BackToAccountButton, DisplayRow, NumberBullet } from './shared.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -55,7 +56,7 @@ const ExpiryPicker = ({ t, expires, setExpires }) => {
const CopyInput = ({ text }) => { const CopyInput = ({ text }) => {
const { t } = useTranslation(['status']) const { t } = useTranslation(['status'])
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const [copied, setCopied] = useState(false) const [copied, setCopied] = useState(false)
@ -67,7 +68,6 @@ const CopyInput = ({ text }) => {
return ( return (
<div className="flex flez-row gap-2 items-center w-full"> <div className="flex flez-row gap-2 items-center w-full">
<LoadingStatus />
<input <input
readOnly readOnly
value={text} value={text}
@ -147,7 +147,7 @@ const NewKey = ({ account, setGenerate, backend }) => {
const [level, setLevel] = useState(1) const [level, setLevel] = useState(1)
const [expires, setExpires] = useState(Date.now()) const [expires, setExpires] = useState(Date.now())
const [apikey, setApikey] = useState(false) const [apikey, setApikey] = useState(false)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
// FIXME: implement a solution for loading docs dynamically the is simple and work as expected // FIXME: implement a solution for loading docs dynamically the is simple and work as expected
const docs = {} const docs = {}
@ -179,7 +179,6 @@ const NewKey = ({ account, setGenerate, backend }) => {
return ( return (
<div> <div>
<LoadingStatus />
{apikey ? ( {apikey ? (
<ShowKey {...{ apikey, t, clear }} /> <ShowKey {...{ apikey, t, clear }} />
) : ( ) : (
@ -264,7 +263,7 @@ export const Apikeys = () => {
const { account } = useAccount() const { account } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext)
// State // State
const [keys, setKeys] = useState([]) const [keys, setKeys] = useState([])
@ -319,7 +318,6 @@ export const Apikeys = () => {
return ( return (
<div className="max-w-4xl xl:pl-4"> <div className="max-w-4xl xl:pl-4">
<LoadingStatus />
<p className="text-center md:text-right"> <p className="text-center md:text-right">
<Link <Link
className="btn btn-primary capitalize w-full md:w-auto" className="btn btn-primary capitalize w-full md:w-auto"

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs' import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs'
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
@ -30,7 +31,7 @@ export const BioSettings = ({ welcome = false }) => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [bio, setBio] = useState(account.bio) const [bio, setBio] = useState(account.bio)
@ -53,7 +54,6 @@ export const BioSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl xl:pl-4"> <div className="max-w-xl xl:pl-4">
<LoadingStatus />
<MarkdownInput <MarkdownInput
id="account-bio" id="account-bio"
label={t('bioTitle')} label={t('bioTitle')}

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState, useEffect, Fragment } from 'react' import { useState, useEffect, Fragment, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { PlusIcon, TrashIcon, LeftIcon } from 'shared/components/icons.mjs' import { PlusIcon, TrashIcon, LeftIcon } from 'shared/components/icons.mjs'
@ -43,7 +44,7 @@ export const Bookmark = ({ bookmark }) => {
// Component for the 'new/apikey' page // Component for the 'new/apikey' page
export const NewBookmark = () => { export const NewBookmark = () => {
// Hooks // Hooks
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const router = useRouter() const router = useRouter()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
@ -72,7 +73,6 @@ export const NewBookmark = () => {
return ( return (
<div className="max-w-2xl xl:pl-4"> <div className="max-w-2xl xl:pl-4">
<LoadingStatus />
<StringInput <StringInput
id="bookmark-title" id="bookmark-title"
label={t('title')} label={t('title')}
@ -109,7 +109,7 @@ export const Bookmarks = () => {
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext)
// State // State
const [bookmarks, setBookmarks] = useState([]) const [bookmarks, setBookmarks] = useState([])
@ -167,7 +167,6 @@ export const Bookmarks = () => {
return ( return (
<div className="max-w-4xl xl:pl-4"> <div className="max-w-4xl xl:pl-4">
<LoadingStatus />
<p className="text-center md:text-right"> <p className="text-center md:text-right">
<Link <Link
className="btn btn-primary capitalize w-full md:w-auto" className="btn btn-primary capitalize w-full md:w-auto"

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs' import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs'
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
@ -18,7 +19,7 @@ export const CompareSettings = ({ welcome = false }) => {
// Hooks // Hooks
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
// State // State
@ -47,7 +48,6 @@ export const CompareSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<ListInput <ListInput
id="account-compare" id="account-compare"
label={t('compareTitle')} label={t('compareTitle')}

View file

@ -1,11 +1,12 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { nsMerge } from 'shared/utils.mjs' import { nsMerge } from 'shared/utils.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import Link from 'next/link' import Link from 'next/link'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -13,7 +14,7 @@ import { BackToAccountButton } from './shared.mjs'
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
import { GdprAccountDetails, ns as gdprNs } from 'shared/components/gdpr/details.mjs' import { GdprAccountDetails, ns as gdprNs } from 'shared/components/gdpr/details.mjs'
export const ns = nsMerge(gdprNs, 'account', 'toast') export const ns = nsMerge(gdprNs, 'account', 'status')
const Checkbox = ({ value, setter, label, children = null }) => ( const Checkbox = ({ value, setter, label, children = null }) => (
<div <div
@ -39,7 +40,7 @@ export const ConsentSettings = ({ title = false }) => {
// Hooks // Hooks
const { account, setAccount, setToken } = useAccount() const { account, setAccount, setToken } = useAccount()
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
// State // State
@ -73,7 +74,6 @@ export const ConsentSettings = ({ title = false }) => {
return ( return (
<div className="max-w-xl xl:pl-4"> <div className="max-w-xl xl:pl-4">
<LoadingStatus />
{title ? <h2 className="text-4xl">{t('privacyMatters')}</h2> : null} {title ? <h2 className="text-4xl">{t('privacyMatters')}</h2> : null}
<p>{t('compliant')}</p> <p>{t('compliant')}</p>
<p>{t('consentWhyAnswer')}</p> <p>{t('consentWhyAnswer')}</p>

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton, Icons, welcomeSteps } from './shared.mjs' import { BackToAccountButton, Icons, welcomeSteps } from './shared.mjs'
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
@ -19,7 +20,7 @@ export const useControlState = () => {
// Hooks // Hooks
const { account, setAccount, token } = useAccount() const { account, setAccount, token } = useAccount()
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [selection, setSelection] = useState(account.control) const [selection, setSelection] = useState(account.control)
@ -44,7 +45,7 @@ export const useControlState = () => {
} }
} }
return { selection, update, LoadingStatus } return { selection, update }
} }
export const ControlSettings = ({ welcome = false, noBack = false }) => { export const ControlSettings = ({ welcome = false, noBack = false }) => {
@ -61,7 +62,6 @@ export const ControlSettings = ({ welcome = false, noBack = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<ListInput <ListInput
id="account-control" id="account-control"
label={t('controlTitle')} label={t('controlTitle')}

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Verification methods // Verification methods
import { validateEmail, validateTld } from 'shared/utils.mjs' import { validateEmail, validateTld } from 'shared/utils.mjs'
// Components // Components
@ -20,7 +21,7 @@ export const EmailSettings = () => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [email, setEmail] = useState(account.email) const [email, setEmail] = useState(account.email)
@ -42,7 +43,6 @@ export const EmailSettings = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
{changed ? ( {changed ? (
<Popout note> <Popout note>
<h3>{t('oneMoreThing')}</h3> <h3>{t('oneMoreThing')}</h3>

View file

@ -193,6 +193,7 @@ csetBookmark: Curated Measurements Sets
docBookmark: Documentation docBookmark: Documentation
customBookmark: Custom Bookmarks customBookmark: Custom Bookmarks
yourBookmarks: Your bookmarks yourBookmarks: Your bookmarks
bookmarkThisPage: Bookmark this page
# sets # sets
set: Measurements Set set: Measurements Set

View file

@ -1,9 +1,10 @@
// Dependencies // Dependencies
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useState } from 'react' import { useState } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -15,7 +16,7 @@ export const ExportAccount = () => {
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const [link, setLink] = useState() const [link, setLink] = useState()
@ -31,7 +32,6 @@ export const ExportAccount = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
{link ? ( {link ? (
<Popout link> <Popout link>
<h5>{t('exportDownload')}</h5> <h5>{t('exportDownload')}</h5>

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
@ -18,7 +19,7 @@ export const GithubSettings = () => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [githubUsername, setGithubUsername] = useState(account.data.githubUsername || '') const [githubUsername, setGithubUsername] = useState(account.data.githubUsername || '')
@ -36,7 +37,6 @@ export const GithubSettings = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<h2 className="text-4xl">{t('githubTitle')}</h2> <h2 className="text-4xl">{t('githubTitle')}</h2>
<StringInput <StringInput
id="account-github-email" id="account-github-email"

View file

@ -2,10 +2,11 @@
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { cloudflareImageUrl } from 'shared/utils.mjs' import { cloudflareImageUrl } from 'shared/utils.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs' import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs'
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
@ -18,7 +19,7 @@ export const ns = ['account', 'status']
export const ImgSettings = ({ welcome = false }) => { export const ImgSettings = ({ welcome = false }) => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const [img, setImg] = useState('') const [img, setImg] = useState('')
@ -36,7 +37,6 @@ export const ImgSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
{!welcome || img !== false ? ( {!welcome || img !== false ? (
<img <img
alt="img" alt="img"

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { Icons, welcomeSteps, BackToAccountButton, NumberBullet } from './shared.mjs' import { Icons, welcomeSteps, BackToAccountButton, NumberBullet } from './shared.mjs'
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
@ -16,7 +17,7 @@ export const ns = ['account', 'status']
export const ImperialSettings = ({ welcome = false }) => { export const ImperialSettings = ({ welcome = false }) => {
// Hooks // Hooks
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
@ -44,7 +45,6 @@ export const ImperialSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<ListInput <ListInput
id="account-units" id="account-units"
label={t('unitsTitle')} label={t('unitsTitle')}

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus, ns as statusNs } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton, NumberBullet } from './shared.mjs' import { BackToAccountButton, NumberBullet } from './shared.mjs'
import { ListInput } from 'shared/components/inputs.mjs' import { ListInput } from 'shared/components/inputs.mjs'
@ -17,7 +18,7 @@ export const ns = ['account', 'locales', statusNs]
export const LanguageSettings = () => { export const LanguageSettings = () => {
// Hooks // Hooks
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
@ -39,7 +40,6 @@ export const LanguageSettings = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<ListInput <ListInput
id="account-language" id="account-language"
label={t('languageTitle')} label={t('languageTitle')}

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -27,7 +28,7 @@ export const MfaSettings = ({ title = false, welcome = false }) => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [enable, setEnable] = useState(false) const [enable, setEnable] = useState(false)
@ -87,7 +88,6 @@ export const MfaSettings = ({ title = false, welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
{title ? <h2 className="text-4xl">{titleText}</h2> : null} {title ? <h2 className="text-4xl">{titleText}</h2> : null}
{enable ? ( {enable ? (
<> <>

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton, Icons, welcomeSteps } from './shared.mjs' import { BackToAccountButton, Icons, welcomeSteps } from './shared.mjs'
import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
@ -19,7 +20,7 @@ export const NewsletterSettings = ({ welcome = false }) => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { LoadingStatus, setLoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [selection, setSelection] = useState(account?.newsletter ? 'yes' : 'no') const [selection, setSelection] = useState(account?.newsletter ? 'yes' : 'no')
@ -44,7 +45,6 @@ export const NewsletterSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<ListInput <ListInput
id="account-newsletter" id="account-newsletter"
label={t('newsletterTitle')} label={t('newsletterTitle')}

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import Link from 'next/link' import Link from 'next/link'
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
@ -21,7 +22,7 @@ export const PasswordSettings = ({ welcome = false }) => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
@ -38,7 +39,6 @@ export const PasswordSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<PasswordInput <PasswordInput
id="account-password" id="account-password"
label={t('passwordTitle')} label={t('passwordTitle')}

View file

@ -3,11 +3,12 @@ import { useState, useEffect, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { capitalize, shortDate, cloudflareImageUrl, horFlexClasses } from 'shared/utils.mjs' import { capitalize, shortDate, cloudflareImageUrl, horFlexClasses } from 'shared/utils.mjs'
import { freeSewingConfig as conf, controlLevels } from 'shared/config/freesewing.config.mjs' import { freeSewingConfig as conf, controlLevels } from 'shared/config/freesewing.config.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Context // Context
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
// Components // Components
@ -45,7 +46,7 @@ export const ns = ['account', 'patterns', 'status']
export const Pattern = ({ id, publicOnly = false }) => { export const Pattern = ({ id, publicOnly = false }) => {
// Hooks // Hooks
const { account, control } = useAccount() const { account, control } = useAccount()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
// FIXME: implement a solution for loading docs dynamically // FIXME: implement a solution for loading docs dynamically
@ -122,7 +123,6 @@ export const Pattern = ({ id, publicOnly = false }) => {
const heading = ( const heading = (
<> <>
<LoadingStatus />
<div className="flex flex-wrap md:flex-nowrap flex-row gap-2 w-full"> <div className="flex flex-wrap md:flex-nowrap flex-row gap-2 w-full">
<div className="w-full md:w-96 shrink-0"> <div className="w-full md:w-96 shrink-0">
<PatternCard pattern={pattern} size="md" /> <PatternCard pattern={pattern} size="md" />
@ -428,7 +428,7 @@ export const Patterns = () => {
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext)
// State // State
const [patterns, setPatterns] = useState([]) const [patterns, setPatterns] = useState([])
@ -483,7 +483,6 @@ export const Patterns = () => {
return ( return (
<div className="max-w-4xl xl:pl-4"> <div className="max-w-4xl xl:pl-4">
<LoadingStatus />
<p className="text-center md:text-right"> <p className="text-center md:text-right">
<Link className="btn btn-primary capitalize w-full md:w-auto" href="/new/pattern"> <Link className="btn btn-primary capitalize w-full md:w-auto" href="/new/pattern">
<PlusIcon /> <PlusIcon />

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs'
@ -18,7 +19,7 @@ export const PlatformSettings = ({ platform }) => {
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [platformId, setPlatformId] = useState(account.data[platform] || '') const [platformId, setPlatformId] = useState(account.data[platform] || '')
@ -37,7 +38,6 @@ export const PlatformSettings = ({ platform }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<StringInput <StringInput
id={`account-${platform}`} id={`account-${platform}`}
label={t(platform === 'website' ? 'account:websiteTitle' : 'account:platformTitle', { label={t(platform === 'website' ? 'account:websiteTitle' : 'account:platformTitle', {

View file

@ -1,9 +1,10 @@
// Dependencies // Dependencies
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
@ -14,7 +15,7 @@ export const ReloadAccount = ({ title = false }) => {
const { setAccount } = useAccount() const { setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// Helper method to reload account // Helper method to reload account
const reload = async () => { const reload = async () => {
@ -28,7 +29,6 @@ export const ReloadAccount = ({ title = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
{title ? <h2>{t('reloadMsg1')}</h2> : null} {title ? <h2>{t('reloadMsg1')}</h2> : null}
<p>{t('reloadMsg2')}</p> <p>{t('reloadMsg2')}</p>
<button className="btn btn-primary capitalize w-full my-2" onClick={reload}> <button className="btn btn-primary capitalize w-full my-2" onClick={reload}>

View file

@ -1,9 +1,10 @@
// Dependencies // Dependencies
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -15,7 +16,7 @@ export const RemoveAccount = () => {
const { signOut } = useAccount() const { signOut } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// Helper method to export account // Helper method to export account
const removeAccount = async () => { const removeAccount = async () => {
@ -29,7 +30,6 @@ export const RemoveAccount = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<Popout warning> <Popout warning>
<h3>{t('noWayBack')}</h3> <h3>{t('noWayBack')}</h3>
<button className="btn btn-error capitalize w-full my-2" onClick={removeAccount}> <button className="btn btn-error capitalize w-full my-2" onClick={removeAccount}>

View file

@ -1,9 +1,10 @@
// Dependencies // Dependencies
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { BackToAccountButton } from './shared.mjs' import { BackToAccountButton } from './shared.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -15,7 +16,7 @@ export const RestrictAccount = () => {
const { signOut } = useAccount() const { signOut } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// Helper method to export account // Helper method to export account
const restrictAccount = async () => { const restrictAccount = async () => {
@ -29,7 +30,6 @@ export const RestrictAccount = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<Popout warning> <Popout warning>
<h5>{t('proceedWithCaution')}</h5> <h5>{t('proceedWithCaution')}</h5>
<p className="text-lg">{t('restrictWarning')}</p> <p className="text-lg">{t('restrictWarning')}</p>

View file

@ -1,10 +1,9 @@
// Dependencies // Dependencies
import { useState, useEffect, useContext } from 'react'
import { useTranslation } from 'next-i18next'
import { measurements } from 'config/measurements.mjs' import { measurements } from 'config/measurements.mjs'
import { measurements as designMeasurements } from 'shared/prebuild/data/design-measurements.mjs' import { measurements as designMeasurements } from 'shared/prebuild/data/design-measurements.mjs'
import { freeSewingConfig as conf, controlLevels } from 'shared/config/freesewing.config.mjs' import { freeSewingConfig as conf, controlLevels } from 'shared/config/freesewing.config.mjs'
import { siteConfig } from 'site/site.config.mjs' import { siteConfig } from 'site/site.config.mjs'
import { isDegreeMeasurement } from 'config/measurements.mjs'
import { import {
shortDate, shortDate,
cloudflareImageUrl, cloudflareImageUrl,
@ -15,11 +14,13 @@ import {
} from 'shared/utils.mjs' } from 'shared/utils.mjs'
import orderBy from 'lodash.orderby' import orderBy from 'lodash.orderby'
// Hooks // Hooks
import { useState, useEffect, useContext } from 'react'
import { useTranslation } from 'next-i18next'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Context // Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
// Components // Components
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
@ -46,7 +47,6 @@ import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
import Timeago from 'react-timeago' import Timeago from 'react-timeago'
import { DisplayRow } from './shared.mjs' import { DisplayRow } from './shared.mjs'
import { isDegreeMeasurement } from 'config/measurements.mjs'
import { DynamicOrgDocs } from 'shared/components/dynamic-docs/org.mjs' import { DynamicOrgDocs } from 'shared/components/dynamic-docs/org.mjs'
import { import {
StringInput, StringInput,
@ -62,7 +62,7 @@ export const ns = [inputNs, 'account', 'patterns', 'status', 'measurements', 'se
export const NewSet = () => { export const NewSet = () => {
// Hooks // Hooks
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const router = useRouter() const router = useRouter()
@ -82,7 +82,6 @@ export const NewSet = () => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<h5>{t('name')}</h5> <h5>{t('name')}</h5>
<p>{t('setNameDesc')}</p> <p>{t('setNameDesc')}</p>
<input <input
@ -189,7 +188,7 @@ export const MsetCard = ({
export const Mset = ({ id, publicOnly = false }) => { export const Mset = ({ id, publicOnly = false }) => {
// Hooks // Hooks
const { account, control } = useAccount() const { account, control } = useAccount()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
// FIXME: implement a solution for loading docs dynamically the is simple and work as expected // FIXME: implement a solution for loading docs dynamically the is simple and work as expected
@ -295,7 +294,6 @@ export const Mset = ({ id, publicOnly = false }) => {
const heading = ( const heading = (
<> <>
<LoadingStatus />
<div className="flex flex-wrap md:flex-nowrap flex-row gap-2 w-full"> <div className="flex flex-wrap md:flex-nowrap flex-row gap-2 w-full">
<div className="w-full md:w-96 shrink-0"> <div className="w-full md:w-96 shrink-0">
<MsetCard set={mset} control={control} /> <MsetCard set={mset} control={control} />
@ -647,7 +645,7 @@ export const Sets = () => {
const { control } = useAccount() const { control } = useAccount()
const backend = useBackend() const backend = useBackend()
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext)
// State // State
const [sets, setSets] = useState([]) const [sets, setSets] = useState([])
@ -702,7 +700,6 @@ export const Sets = () => {
return ( return (
<div className="max-w-7xl xl:pl-4"> <div className="max-w-7xl xl:pl-4">
<LoadingStatus />
<p className="text-center md:text-right"> <p className="text-center md:text-right">
<Link <Link
className="btn btn-primary capitalize w-full md:w-auto" className="btn btn-primary capitalize w-full md:w-auto"

View file

@ -133,44 +133,3 @@ export const DisplayRow = ({ title, children, keyWidth = 'w-24' }) => (
<div className="grow">{children}</div> <div className="grow">{children}</div>
</div> </div>
) )
/*
// Hooks
import { useContext } from 'react'
import { useTranslation } from 'next-i18next'
// Context
import { LoadingContext } from 'shared/context/loading-context.mjs'
// Components
import { Spinner } from 'shared/components/spinner.mjs'
import Link from 'next/link'
export const ContinueButton = ({ btnProps = {}, link = false }) => {
// Hooks
const { t } = useTranslation(['account'])
let classes = 'btn-primary btn mt-8 capitalize w-full'
const children = (
<span className="flex flex-row items-center gap-2">
{loading ? (
<>
<Spinner />
<span>{t('processing')}</span>
</>
) : (
<span>{t('continue')}</span>
)}
</span>
)
return link ? (
<Link className={classes} tabIndex="-1" {...btnProps}>
{children}
</Link>
) : (
<button className={classes} tabIndex="-1" role="button" {...btnProps}>
{children}
</button>
)
}
*/

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs' import { Icons, welcomeSteps, BackToAccountButton } from './shared.mjs'
import { OkIcon, NoIcon } from 'shared/components/icons.mjs' import { OkIcon, NoIcon } from 'shared/components/icons.mjs'
@ -12,13 +13,13 @@ import { ContinueButton } from 'shared/components/buttons/continue-button.mjs'
import { StringInput } from 'shared/components/inputs.mjs' import { StringInput } from 'shared/components/inputs.mjs'
import { DynamicOrgDocs } from 'shared/components/dynamic-docs/org.mjs' import { DynamicOrgDocs } from 'shared/components/dynamic-docs/org.mjs'
export const ns = ['account', 'toast'] export const ns = ['account', 'status']
export const UsernameSettings = ({ welcome = false }) => { export const UsernameSettings = ({ welcome = false }) => {
// Hooks // Hooks
const { account, setAccount } = useAccount() const { account, setAccount } = useAccount()
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const [username, setUsername] = useState(account.username) const [username, setUsername] = useState(account.username)
const [available, setAvailable] = useState(true) const [available, setAvailable] = useState(true)
@ -52,7 +53,6 @@ export const UsernameSettings = ({ welcome = false }) => {
return ( return (
<div className="max-w-xl"> <div className="max-w-xl">
<LoadingStatus />
<StringInput <StringInput
id="account-username" id="account-username"
label={t('usernameTitle')} label={t('usernameTitle')}

View file

@ -1,33 +1,36 @@
import { useState, useEffect } from 'react' // Depdendencies
import { cloudflareConfig } from 'shared/config/cloudflare.mjs' import { cloudflareConfig } from 'shared/config/cloudflare.mjs'
import { freeSewingConfig } from 'shared/config/freesewing.config.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks
import { useState, useEffect, useContext } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs' // Components
import Link from 'next/link' import Link from 'next/link'
import Markdown from 'react-markdown'
import { Json } from 'shared/components/json.mjs' import { Json } from 'shared/components/json.mjs'
import Markdown from 'react-markdown'
import { AccountRole } from 'shared/components/account/role.mjs' import { AccountRole } from 'shared/components/account/role.mjs'
import { AccountStatus } from 'shared/components/account/status.mjs' import { AccountStatus } from 'shared/components/account/status.mjs'
import { Loading } from 'shared/components/spinner.mjs' import { Loading } from 'shared/components/spinner.mjs'
import { freeSewingConfig } from 'shared/config/freesewing.config.mjs'
const roles = ['user', 'curator', 'bughunter', 'support', 'admin'] const roles = ['user', 'curator', 'bughunter', 'support', 'admin']
export const ImpersonateButton = ({ userId }) => { export const ImpersonateButton = ({ userId }) => {
const toast = useToast()
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus } = useContext(LoadingStatusContext)
const { impersonate } = useAccount() const { impersonate } = useAccount()
if (!userId) return null if (!userId) return null
const impersonateUser = async () => { const impersonateUser = async () => {
setLoadingStatus([true, 'status:contactingBackend'])
const result = await backend.adminImpersonateUser(userId) const result = await backend.adminImpersonateUser(userId)
if (result.success) { if (result.success) {
impersonate(result.data) impersonate(result.data)
toast.for.settingsSaved() setLoadingStatus([true, 'status:settingsSaved', true, true])
} else toast.for.backendError() } else setLoadingStatus([true, 'status:backendError', true, false])
} }
return ( return (
@ -132,7 +135,7 @@ export const User = ({ user }) => (
export const ManageUser = ({ userId }) => { export const ManageUser = ({ userId }) => {
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
const toast = useToast() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [user, setUser] = useState({}) const [user, setUser] = useState({})
@ -147,11 +150,12 @@ export const ManageUser = ({ userId }) => {
}, [userId]) }, [userId])
const updateUser = async (data) => { const updateUser = async (data) => {
setLoadingStatus([true, 'status:contactingBackend'])
const result = await backend.adminUpdateUser({ id: userId, data }) const result = await backend.adminUpdateUser({ id: userId, data })
if (result.success) { if (result.success) {
toast.for.settingsSaved() setLoadingStatus([true, 'status:settingsSaved', true, true])
setUser(result.data.user) setUser(result.data.user)
} else toast.for.backendError() } else setLoadingStatus([true, 'status:backendError', true, false])
} }
return user.id ? ( return user.id ? (

View file

@ -0,0 +1,72 @@
// Dependencies
import { horFlexClasses, notEmpty } from 'shared/utils.mjs'
// Hooks
import { useContext, useState } from 'react'
import { useTranslation } from 'next-i18next'
import { useBackend } from 'shared/hooks/use-backend.mjs'
// Context
import { ModalContext } from 'shared/context/modal-context.mjs'
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
import { BookmarkIcon } from 'shared/components/icons.mjs'
import { StringInput } from 'shared/components/inputs.mjs'
export const ns = 'account'
export const CreateBookmark = ({ type, title, slug }) => {
const backend = useBackend()
const { t, i18n } = useTranslation(ns)
const [name, setName] = useState(title)
const { setLoadingStatus } = useContext(LoadingStatusContext)
const { setModal } = useContext(ModalContext)
const url = i18n.language === 'en' ? `/${slug}` : `/${lang}/${slug}`
const bookmark = async (evt) => {
evt.stopPropagation()
setLoadingStatus([true, 'status:contactingBackend'])
const result = await backend.createBookmark({ type, title, url })
if (result.success) {
setLoadingStatus([true, 'status:nailedIt', true, true])
setModal(false)
} else setLoadingStatus([true, 'backendError', true, false])
}
return (
<>
<h2>{t('account:bookmarkThisPage')}</h2>
<StringInput
label={t('account:title')}
current={name}
update={setName}
valid={notEmpty}
labelBL={url}
/>
<button className="btn btn-primary w-full mt-4" onClick={bookmark}>
<span>{t('account:bookmarkThisPage')}</span>
</button>
</>
)
}
export const BookmarkButton = ({ slug, type, title }) => {
const { t } = useTranslation('account')
const { setModal } = useContext(ModalContext)
return (
<button
className={`btn btn-secondary btn-outline ${horFlexClasses}`}
onClick={() =>
setModal(
<ModalWrapper flex="col" justify="top lg:justify-center" slideFrom="right">
<CreateBookmark {...{ type, title, slug }} />
</ModalWrapper>
)
}
>
<BookmarkIcon />
<span>{t('account:bookmarkThisPage')}</span>
</button>
)
}

View file

@ -2,14 +2,14 @@
import { useContext } from 'react' import { useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { Spinner } from 'shared/components/spinner.mjs' import { Spinner } from 'shared/components/spinner.mjs'
import Link from 'next/link' import Link from 'next/link'
export const ContinueButton = ({ btnProps = {}, link = false }) => { export const ContinueButton = ({ btnProps = {}, link = false }) => {
// Context // Context
const { loading } = useContext(LoadingContext) const { loading } = useContext(LoadingStatusContext)
// Hooks // Hooks
const { t } = useTranslation(['account']) const { t } = useTranslation(['account'])

View file

@ -2,12 +2,12 @@
import { useContext } from 'react' import { useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { Spinner } from 'shared/components/spinner.mjs' import { Spinner } from 'shared/components/spinner.mjs'
export const SaveSettingsButton = ({ btnProps = {}, welcome = false, label = false }) => { export const SaveSettingsButton = ({ btnProps = {}, welcome = false, label = false }) => {
const { loading } = useContext(LoadingContext) const { loading } = useContext(LoadingStatusContext)
const { t } = useTranslation(['account']) const { t } = useTranslation(['account'])
let classes = 'btn mt-4 capitalize ' let classes = 'btn mt-4 capitalize '
if (welcome) { if (welcome) {

View file

@ -7,9 +7,9 @@ import { shortDate, cloudflareImageUrl, capitalize } from 'shared/utils.mjs'
// Hooks // Hooks
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Context // Context
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { DisplayRow } from './account/shared.mjs' import { DisplayRow } from './account/shared.mjs'
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs' import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
@ -135,7 +135,7 @@ const ShowCuratedSet = ({ cset }) => {
export const CuratedSet = ({ id }) => { export const CuratedSet = ({ id }) => {
// Hooks // Hooks
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const backend = useBackend() const backend = useBackend()
// State // State
@ -158,7 +158,6 @@ export const CuratedSet = ({ id }) => {
return ( return (
<div className="max-w-2xl"> <div className="max-w-2xl">
<LoadingStatus />
<ShowCuratedSet cset={cset} /> <ShowCuratedSet cset={cset} />
</div> </div>
) )
@ -168,7 +167,7 @@ export const CuratedSet = ({ id }) => {
export const CuratedSets = () => { export const CuratedSets = () => {
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [sets, setSets] = useState([]) const [sets, setSets] = useState([])
@ -191,7 +190,6 @@ export const CuratedSets = () => {
return ( return (
<div className="max-w-7xl xl:pl-4"> <div className="max-w-7xl xl:pl-4">
<LoadingStatus />
<SetLineup sets={Object.values(sets)} onClick={setSelected} /> <SetLineup sets={Object.values(sets)} onClick={setSelected} />
{selected && <ShowCuratedSet cset={sets[selected]} />} {selected && <ShowCuratedSet cset={sets[selected]} />}
</div> </div>

View file

@ -3,12 +3,12 @@ import { cloudflareImageUrl } from 'shared/utils.mjs'
import { collection } from 'shared/hooks/use-design.mjs' import { collection } from 'shared/hooks/use-design.mjs'
// Context // Context
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useState, useCallback, useContext } from 'react' import { useState, useCallback, useContext } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useDropzone } from 'react-dropzone' import { useDropzone } from 'react-dropzone'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
import { ResetIcon, DocsIcon, UploadIcon } from 'shared/components/icons.mjs' import { ResetIcon, DocsIcon, UploadIcon } from 'shared/components/icons.mjs'
@ -278,7 +278,7 @@ export const ImageInput = ({
}) => { }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const [url, setUrl] = useState(false) const [url, setUrl] = useState(false)
const [uploadedId, setUploadedId] = useState(false) const [uploadedId, setUploadedId] = useState(false)
@ -316,7 +316,6 @@ export const ImageInput = ({
if (current) if (current)
return ( return (
<FormControl label={label} docs={docs}> <FormControl label={label} docs={docs}>
<LoadingStatus />
<div <div
className="bg-base-100 w-full h-36 mb-2 mx-auto flex flex-col items-center text-center justify-center" className="bg-base-100 w-full h-36 mb-2 mx-auto flex flex-col items-center text-center justify-center"
style={{ style={{
@ -340,7 +339,6 @@ export const ImageInput = ({
return ( return (
<FormControl label={label} docs={docs} forId={id}> <FormControl label={label} docs={docs} forId={id}>
<LoadingStatus />
<div <div
{...getRootProps()} {...getRootProps()}
className={` className={`

View file

@ -1,13 +1,19 @@
import { useState, useEffect } from 'react'
import { siteConfig } from 'site/site.config.mjs' import { siteConfig } from 'site/site.config.mjs'
import { horFlexClasses } from 'shared/utils.mjs'
// List of authors // List of authors
import { authors as allAuthors } from 'config/authors.mjs' import { authors as allAuthors } from 'config/authors.mjs'
import { docUpdates } from 'site/prebuild/doc-updates.mjs' import { docUpdates } from 'site/prebuild/doc-updates.mjs'
// Components
import { PageLink } from 'shared/components/link.mjs'
import { TimeAgo } from 'shared/components/timeago/index.mjs'
// Hooks // Hooks
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { EditIcon } from 'shared/components/icons.mjs' import { EditIcon } from 'shared/components/icons.mjs'
import { useAccount } from 'shared/hooks/use-account.mjs'
// Components
import { PageLink } from 'shared/components/link.mjs'
import { TimeAgo } from 'shared/components/timeago/index.mjs'
import { BookmarkButton } from 'shared/components/bookmarks.mjs'
export const ns = 'account'
const PersonList = ({ list }) => const PersonList = ({ list }) =>
list ? ( list ? (
@ -54,11 +60,19 @@ const CreditsList = ({ updates, frontmatter, locale, t }) => (
) )
export const MdxMetaData = ({ frontmatter, locale, slug }) => { export const MdxMetaData = ({ frontmatter, locale, slug }) => {
const { t } = useTranslation('docs') const { control } = useAccount()
const { t, i18n } = useTranslation('docs')
const [localControl, setLocalControl] = useState(1)
// Prevent hydration issues
useEffect(() => {
setLocalControl(control)
}, [])
const updates = docUpdates[slug] || {} const updates = docUpdates[slug] || {}
frontmatter.maintainers = ['joostdecock'] frontmatter.maintainers = ['joostdecock']
locale = 'fr' locale = i18n.language
/* /*
* FIXME * FIXME
@ -70,13 +84,18 @@ export const MdxMetaData = ({ frontmatter, locale, slug }) => {
return ( return (
<div className="hidden xl:block mb-4"> <div className="hidden xl:block mb-4">
<a {localControl > 2 && (
href={`https://github.dev/freesewing/freesewing/blob/develop/markdown/${siteConfig.tld}/${slug}/en.md`} <div className="flex flex-col gap-2 max-w-xs">
className="btn btn-success flex flex-row justify-between items-center w-full px-4 bg-gradient-to-r from-primary to-accent mb-4 hover:from-accent hover:to-accent" <a
> href={`https://github.dev/freesewing/freesewing/blob/develop/markdown/${siteConfig.tld}/${slug}/en.md`}
<EditIcon /> className={`btn btn-secondary btn-outline ${horFlexClasses}`}
<span>{t('editThisPage')}</span> >
</a> <EditIcon />
<span>{t('editThisPage')}</span>
</a>
<BookmarkButton slug={slug} title={frontmatter.title} type="doc" />
</div>
)}
<div <div
className={` className={`
mdx mdx-toc text-base-content text-base mdx mdx-toc text-base-content text-base

View file

@ -4,8 +4,8 @@ import { useState, useContext, useEffect } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs'
// Context // Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
import { NavigationContext } from 'shared/context/navigation-context.mjs' import { NavigationContext } from 'shared/context/navigation-context.mjs'
// Components // Components
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
@ -27,11 +27,12 @@ import { Link, PageLink } from 'shared/components/link.mjs'
import { Popout } from 'shared/components/popout/index.mjs' import { Popout } from 'shared/components/popout/index.mjs'
import { EditRow } from 'shared/components/account/patterns.mjs' import { EditRow } from 'shared/components/account/patterns.mjs'
export const ns = [...ns404, 'toast'] export const ns = ns404
export const ManagePattern = ({ id = false }) => { export const ManagePattern = ({ id = false }) => {
// Context // Context
const { addPages } = useContext(NavigationContext) const { addPages } = useContext(NavigationContext)
const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [pattern, setPattern] = useState({}) const [pattern, setPattern] = useState({})
@ -42,7 +43,6 @@ export const ManagePattern = ({ id = false }) => {
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { language } = i18n const { language } = i18n
const toast = useToast()
// async effect helper // async effect helper
const loadPattern = async () => { const loadPattern = async () => {
@ -82,7 +82,7 @@ export const ManagePattern = ({ id = false }) => {
if (result.success) { if (result.success) {
if (result.data.pattern) { if (result.data.pattern) {
setPattern(result.data.pattern) setPattern(result.data.pattern)
toast.for.settingsSaved() setLoadingStatus([true, 'settingsSaved', true, true])
} }
} }
} }
@ -125,17 +125,13 @@ export const ManagePattern = ({ id = false }) => {
<> <>
<h2>{t('update')}</h2> <h2>{t('update')}</h2>
{/* Name is always shown */} {/* Name is always shown */}
<EditRow title={t('name')} field="name" {...{ pattern, backend, t, toast, refresh }}> <EditRow title={t('name')} field="name" {...{ pattern, backend, t, refresh }}>
{pattern.name} {pattern.name}
</EditRow> </EditRow>
{/* img: Control level determines whether or not to show this */} {/* img: Control level determines whether or not to show this */}
{pattern.id && account.control >= conf.account.patterns.img ? ( {pattern.id && account.control >= conf.account.patterns.img ? (
<EditRow <EditRow title={t('image')} field="img" {...{ pattern, backend, t, refresh }}>
title={t('image')}
field="img"
{...{ pattern, backend, t, toast, refresh }}
>
<img <img
src={pattern.img} src={pattern.img}
className="w-10 mask mask-squircle bg-neutral aspect-square" className="w-10 mask mask-squircle bg-neutral aspect-square"
@ -145,11 +141,7 @@ export const ManagePattern = ({ id = false }) => {
{/* notes: Control level determines whether or not to show this */} {/* notes: Control level determines whether or not to show this */}
{account.control >= conf.account.patterns.notes ? ( {account.control >= conf.account.patterns.notes ? (
<EditRow <EditRow title={t('notes')} field="notes" {...{ pattern, backend, t, refresh }}>
title={t('notes')}
field="notes"
{...{ pattern, backend, t, toast, refresh }}
>
<Markdown>{pattern.notes}</Markdown> <Markdown>{pattern.notes}</Markdown>
</EditRow> </EditRow>
) : null} ) : null}

View file

@ -1,10 +1,10 @@
// Hooks // Hooks
import { useContext } from 'react' import { useContext } from 'react'
// Context // Context
import { LoadingContext } from 'shared/context/loading-context.mjs' import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
export const Ribbon = () => { export const Ribbon = () => {
const { loading } = useContext(LoadingContext) const { loading } = useContext(LoadingStatusContext)
return ( return (
<div <div

View file

@ -1,10 +1,11 @@
// Dependencies // Dependencies
import { cloudflareImageUrl, nsMerge } from 'shared/utils.mjs' import { cloudflareImageUrl, nsMerge } from 'shared/utils.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
// Components // Components
import { AuthWrapper } from 'shared/components/wrappers/auth/index.mjs' import { AuthWrapper } from 'shared/components/wrappers/auth/index.mjs'
@ -20,7 +21,7 @@ export const CsetSubmission = ({ id }) => {
// Hooks // Hooks
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const router = useRouter() const router = useRouter()
const [submission, setSubmission] = useState(false) const [submission, setSubmission] = useState(false)
@ -57,7 +58,6 @@ export const CsetSubmission = ({ id }) => {
return ( return (
<div className="max-w-2xl"> <div className="max-w-2xl">
<LoadingStatus />
<DisplayRow title={t('account:name')} keyWidth="w-48"> <DisplayRow title={t('account:name')} keyWidth="w-48">
{submission.name} {submission.name}
</DisplayRow> </DisplayRow>

View file

@ -1,8 +1,9 @@
import { freeSewingConfig as config } from 'shared/config/freesewing.config.mjs' import { freeSewingConfig as config } from 'shared/config/freesewing.config.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useState, Fragment } from 'react' import { useState, Fragment } from 'react'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
// Components // Components
@ -118,7 +119,7 @@ const SupportType = ({ type, active, t, update }) => (
export const SupportForm = () => { export const SupportForm = () => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const { account } = useAccount() const { account } = useAccount()
const backend = useBackend() const backend = useBackend()
@ -212,7 +213,6 @@ export const SupportForm = () => {
return ( return (
<div className="w-full max-w-4xl mx-auto"> <div className="w-full max-w-4xl mx-auto">
<LoadingStatus />
<SupportType type={type} active={true} update={() => setType(false)} t={t} /> <SupportType type={type} active={true} update={() => setType(false)} t={t} />
<StringInput <StringInput
id="support-title" id="support-title"

View file

@ -1,8 +1,9 @@
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useState } from 'react' import { useState, useContext } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
// Components // Components
@ -24,7 +25,7 @@ const DarkLink = ({ href, txt }) => (
export const Migrate = () => { export const Migrate = () => {
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus, loading } = useLoadingStatus() const { loading, setLoadingStatus } = useContext(LoadingStatusContext)
const { setAccount, setSeenUser, setToken } = useAccount() const { setAccount, setSeenUser, setToken } = useAccount()
const router = useRouter() const router = useRouter()
@ -61,14 +62,12 @@ export const Migrate = () => {
if (result === 'success') if (result === 'success')
return ( return (
<> <>
<LoadingStatus />
<FreeSewingAnimation /> <FreeSewingAnimation />
</> </>
) )
if (result === 'exists') if (result === 'exists')
return ( return (
<> <>
<LoadingStatus />
<h2 className="text-inherit">{t('signup:v3UserAlreadyExists')}</h2> <h2 className="text-inherit">{t('signup:v3UserAlreadyExists')}</h2>
<Robot pose="shrug" className="m-auto w-56 text-inherit" embed /> <Robot pose="shrug" className="m-auto w-56 text-inherit" embed />
<Link href="/signin" className="btn btn-primary w-full my-4"> <Link href="/signin" className="btn btn-primary w-full my-4">
@ -87,7 +86,6 @@ export const Migrate = () => {
if (result === 'failed') if (result === 'failed')
return ( return (
<> <>
<LoadingStatus />
<h2 className="text-inherit">{t('signup:noWorkie')}</h2> <h2 className="text-inherit">{t('signup:noWorkie')}</h2>
<Robot pose="ohno" className="m-auto w-56 text-inherit" embed /> <Robot pose="ohno" className="m-auto w-56 text-inherit" embed />
<Link href="/signup" className="btn btn-primary w-full my-4"> <Link href="/signup" className="btn btn-primary w-full my-4">
@ -106,7 +104,6 @@ export const Migrate = () => {
return ( return (
<> <>
<LoadingStatus />
<h2 className="text-inherit">{t('signup:migrateV2')}</h2> <h2 className="text-inherit">{t('signup:migrateV2')}</h2>
<p className="text-inherit">{t('migrateV2Desc')}</p> <p className="text-inherit">{t('migrateV2Desc')}</p>
<div className="text-base-content"> <div className="text-base-content">

View file

@ -1,10 +1,11 @@
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useAccount } from 'shared/hooks/use-account.mjs' import { useAccount } from 'shared/hooks/use-account.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
import { horFlexClasses, horFlexClassesNoSm, capitalize } from 'shared/utils.mjs' import { horFlexClasses, horFlexClassesNoSm, capitalize } from 'shared/utils.mjs'
// Components // Components
import Link from 'next/link' import Link from 'next/link'
@ -28,7 +29,7 @@ export const SignIn = () => {
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const router = useRouter() const router = useRouter()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const [username, setUsername] = useState('') const [username, setUsername] = useState('')
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
@ -117,7 +118,6 @@ export const SignIn = () => {
if (magicLinkSent) if (magicLinkSent)
return ( return (
<> <>
<LoadingStatus />
<h1 className="text-inherit text-3xl lg:text-5xl mb-4 pb-0 text-center"> <h1 className="text-inherit text-3xl lg:text-5xl mb-4 pb-0 text-center">
{t('susi:emailSent')} {t('susi:emailSent')}
</h1> </h1>
@ -138,7 +138,6 @@ export const SignIn = () => {
return ( return (
<> <>
<LoadingStatus />
<h2>{seenBefore ? t('susi:welcomeBackName', { name: seenUser }) : t('susi:welcome')}</h2> <h2>{seenBefore ? t('susi:welcomeBackName', { name: seenUser }) : t('susi:welcome')}</h2>
<p>{t('susi:signInToThing', { thing: 'FreeSewing' })}:</p> <p>{t('susi:signInToThing', { thing: 'FreeSewing' })}:</p>
{!seenBefore && ( {!seenBefore && (

View file

@ -2,8 +2,8 @@
import { useState, useContext } from 'react' import { useState, useContext } from 'react'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Context // Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
// Dependencies // Dependencies
import { validateEmail, validateTld, horFlexClasses, horFlexClassesNoSm } from 'shared/utils.mjs' import { validateEmail, validateTld, horFlexClasses, horFlexClassesNoSm } from 'shared/utils.mjs'
@ -32,7 +32,7 @@ export const SignUp = () => {
const backend = useBackend() const backend = useBackend()
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const [email, setEmail] = useState('') const [email, setEmail] = useState('')
const [emailValid, setEmailValid] = useState(false) const [emailValid, setEmailValid] = useState(false)
@ -98,7 +98,6 @@ export const SignUp = () => {
return ( return (
<div className="w-full"> <div className="w-full">
<LoadingStatus />
<h2 className="text-inherit"> <h2 className="text-inherit">
{result ? ( {result ? (
result === 'success' ? ( result === 'success' ? (

View file

@ -1,22 +1,26 @@
// Dependencies
import yaml from 'js-yaml' import yaml from 'js-yaml'
import { validateSettings } from './settings-validator.mjs' import { validateSettings } from './settings-validator.mjs'
import { capitalize } from 'shared/utils.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks
import { useEffect, useState, useRef, useMemo } from 'react' import { useEffect, useState, useRef, useMemo } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useToast } from 'shared/hooks/use-toast.mjs' // Components
import { CloseIcon } from 'shared/components/icons.mjs' import { CloseIcon } from 'shared/components/icons.mjs'
import { capitalize } from 'shared/utils.mjs'
import { V3Wip } from 'shared/components/v3-wip.mjs' import { V3Wip } from 'shared/components/v3-wip.mjs'
export const ns = ['wbedit'] export const ns = []
/** a view for editing the gist as yaml */ /** a view for editing the gist as yaml */
export const EditView = ({ settings, setSettings, design, Design }) => { export const EditView = ({ settings, setSettings, design, Design }) => {
const inputRef = useRef(null) const inputRef = useRef(null)
const { setLoadingStatus } = useContext(LoadingStatusContext)
const [error, setError] = useState(false) const [error, setError] = useState(false)
const [success, setSuccess] = useState(false) const [success, setSuccess] = useState(false)
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const patternConfig = useMemo(() => new Design().getConfig(), [Design]) const patternConfig = useMemo(() => new Design().getConfig(), [Design])
const toast = useToast()
// parse the settings to yaml and set them as the value on the textArea // parse the settings to yaml and set them as the value on the textArea
useEffect(() => { useEffect(() => {
@ -29,6 +33,7 @@ export const EditView = ({ settings, setSettings, design, Design }) => {
setSuccess(false) setSuccess(false)
try { try {
setLoadingStatus([true, 'status:contactingBackend'])
// parse back to json // parse back to json
const editedAsJson = yaml.load(inputRef.current.value) const editedAsJson = yaml.load(inputRef.current.value)
@ -43,7 +48,7 @@ export const EditView = ({ settings, setSettings, design, Design }) => {
// save regardless // save regardless
setSettings(editedAsJson) setSettings(editedAsJson)
setSuccess(true) setSuccess(true)
if (validation.valid) toast.success(t('success')) if (validation.valid) setLoadingStatus([true, 'status:settingsSaved', true, true])
} catch (e) { } catch (e) {
console.log(e) console.log(e)
setError(e.message) setError(e.message)

View file

@ -1,14 +1,17 @@
import { useState, useContext } from 'react' // Dependencies
import { useTranslation } from 'next-i18next'
import { Popout } from 'shared/components/popout/index.mjs'
import { WebLink } from 'shared/components/link.mjs'
import { LoadingContext } from 'shared/context/loading-context.mjs'
import { useToast } from 'shared/hooks/use-toast.mjs'
import { import {
exportTypes, exportTypes,
handleExport, handleExport,
ns as exportNs, ns as exportNs,
} from 'shared/components/workbench/exporting/export-handler.mjs' } from 'shared/components/workbench/exporting/export-handler.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks
import { useState, useContext } from 'react'
import { useTranslation } from 'next-i18next'
// Components
import { Popout } from 'shared/components/popout/index.mjs'
import { WebLink } from 'shared/components/link.mjs'
import { V3Wip } from 'shared/components/v3-wip.mjs' import { V3Wip } from 'shared/components/v3-wip.mjs'
export const ns = ['exporting', exportNs] export const ns = ['exporting', exportNs]
@ -16,8 +19,10 @@ export const ns = ['exporting', exportNs]
export const ExportView = ({ settings, ui, design, Design }) => { export const ExportView = ({ settings, ui, design, Design }) => {
const [link, setLink] = useState(false) const [link, setLink] = useState(false)
const [format, setFormat] = useState(false) const [format, setFormat] = useState(false)
const { startLoading, stopLoading } = useContext(LoadingContext) const { setLoadingStatus } = useContext(LoadingStatusContext)
const toast = useToast()
const startLoading = () => setLoadingStatus([true, 'exporting'])
const stopLoading = () => setLoadingStatus([true, 'status:nailedIt', true, true])
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const doExport = (format) => { const doExport = (format) => {
@ -38,7 +43,7 @@ export const ExportView = ({ settings, ui, design, Design }) => {
} }
}, },
onError: (e) => { onError: (e) => {
if (e.data?.error) toast.error(e.data.error.message) if (e.data?.error) setLoadingStatus([true, e.data.error.message, true, false])
}, },
}) })
} }

View file

@ -5,7 +5,8 @@ import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs'
import { designMeasurements, horFlexClasses } from 'shared/utils.mjs' import { designMeasurements, horFlexClasses } from 'shared/utils.mjs'
// Hooks // Hooks
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components // Components
import { import {
UserSetPicker, UserSetPicker,
@ -24,7 +25,7 @@ const iconClasses = { className: 'w-8 h-8 md:w-10 md:h-10 lg:w-12 lg:h-12 shrink
export const MeasiesView = ({ design, Design, settings, update, missingMeasurements, setView }) => { export const MeasiesView = ({ design, Design, settings, update, missingMeasurements, setView }) => {
const { t } = useTranslation(['workbench']) const { t } = useTranslation(['workbench'])
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
const loadMeasurements = (set) => { const loadMeasurements = (set) => {
update.settings([ update.settings([
@ -37,7 +38,6 @@ export const MeasiesView = ({ design, Design, settings, update, missingMeasureme
return ( return (
<div className="max-w-7xl mt-8 mx-auto px-4"> <div className="max-w-7xl mt-8 mx-auto px-4">
<LoadingStatus />
<h2>{t('account:measurements')}</h2> <h2>{t('account:measurements')}</h2>
{missingMeasurements && {missingMeasurements &&
settings.measurements && settings.measurements &&

View file

@ -1,18 +1,21 @@
import { useContext } from 'react' // Dependencies
import { useTranslation } from 'next-i18next' import { nsMerge } from 'shared/utils.mjs'
import { pagesPlugin } from 'shared/plugins/plugin-layout-part.mjs'
import { import {
handleExport, handleExport,
ns as exportNs, ns as exportNs,
} from 'shared/components/workbench/exporting/export-handler.mjs' } from 'shared/components/workbench/exporting/export-handler.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' import { pagesPlugin } from 'shared/plugins/plugin-layout-part.mjs'
import get from 'lodash.get' import get from 'lodash.get'
import { defaultPrintSettings, printSettingsPath } from './config.mjs'
// Hooks
import { useContext } from 'react'
import { useTranslation } from 'next-i18next'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components
import { MovablePattern } from 'shared/components/workbench/pattern/movable/index.mjs' import { MovablePattern } from 'shared/components/workbench/pattern/movable/index.mjs'
import { PrintMenu, ns as menuNs } from './menu.mjs' import { PrintMenu, ns as menuNs } from './menu.mjs'
import { defaultPrintSettings, printSettingsPath } from './config.mjs'
import { LoadingContext } from 'shared/context/loading-context.mjs'
import { PatternWithMenu, ns as wrapperNs } from '../pattern-with-menu.mjs' import { PatternWithMenu, ns as wrapperNs } from '../pattern-with-menu.mjs'
import { nsMerge } from 'shared/utils.mjs'
export const ns = nsMerge(menuNs, wrapperNs, exportNs, 'print', 'status') export const ns = nsMerge(menuNs, wrapperNs, exportNs, 'print', 'status')
@ -30,8 +33,7 @@ export const PrintView = ({
Design, Design,
}) => { }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const loading = useContext(LoadingContext) const { loading, setLoadingStatus } = useContext(LoadingStatusContext)
const { setLoadingStatus, LoadingStatus } = useLoadingStatus()
const defaultSettings = defaultPrintSettings(settings.units) const defaultSettings = defaultPrintSettings(settings.units)
// add the pages plugin to the draft // add the pages plugin to the draft
@ -74,7 +76,6 @@ export const PrintView = ({
return ( return (
<> <>
<LoadingStatus />
<PatternWithMenu <PatternWithMenu
noHeader noHeader
{...{ {...{

View file

@ -1,12 +1,13 @@
// Dependencies // Dependencies
import { capitalize, shortDate, notEmpty, horFlexClassesNoSm } from 'shared/utils.mjs' import { capitalize, shortDate, notEmpty, horFlexClassesNoSm } from 'shared/utils.mjs'
import yaml from 'js-yaml' import yaml from 'js-yaml'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
// Components // Components
import { AuthWrapper } from 'shared/components/wrappers/auth/index.mjs' import { AuthWrapper } from 'shared/components/wrappers/auth/index.mjs'
import { StringInput, MarkdownInput } from 'shared/components/inputs.mjs' import { StringInput, MarkdownInput } from 'shared/components/inputs.mjs'
@ -22,7 +23,7 @@ export const SaveView = ({ design, settings }) => {
const { t } = useTranslation(ns) const { t } = useTranslation(ns)
const backend = useBackend() const backend = useBackend()
const router = useRouter() const router = useRouter()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// State // State
const [name, setName] = useState(`${capitalize(design)} / ${shortDate(router.locale)}`) const [name, setName] = useState(`${capitalize(design)} / ${shortDate(router.locale)}`)
@ -80,7 +81,6 @@ export const SaveView = ({ design, settings }) => {
return ( return (
<AuthWrapper> <AuthWrapper>
<LoadingStatus />
<div className="m-auto mt-8 max-w-2xl px-4"> <div className="m-auto mt-8 max-w-2xl px-4">
<h2>{t('workbench:savePattern')}</h2> <h2>{t('workbench:savePattern')}</h2>
{savedId && ( {savedId && (

View file

@ -1,8 +1,14 @@
// Dependencies
import { capitalize, shortDate } from 'shared/utils.mjs'
// Hooks
import { useContext, useMemo } from 'react' import { useContext, useMemo } from 'react'
import { PanZoomContext } from 'shared/components/workbench/pattern/pan-zoom-context.mjs'
import { useMobileAction } from 'shared/context/mobile-menubar-context.mjs' import { useMobileAction } from 'shared/context/mobile-menubar-context.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import { useBackend } from 'shared/hooks/use-backend.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Components
import { PanZoomContext } from 'shared/components/workbench/pattern/pan-zoom-context.mjs'
import { import {
PaperlessIcon, PaperlessIcon,
SaIcon, SaIcon,
@ -17,8 +23,6 @@ import {
ZoomOutIcon, ZoomOutIcon,
} from 'shared/components/icons.mjs' } from 'shared/components/icons.mjs'
import { shownHeaderSelector } from 'shared/components/wrappers/header.mjs' import { shownHeaderSelector } from 'shared/components/wrappers/header.mjs'
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
import { capitalize, shortDate } from 'shared/utils.mjs'
export const ns = ['common', 'core-settings', 'ui-settings'] export const ns = ['common', 'core-settings', 'ui-settings']
@ -73,7 +77,7 @@ export const ViewHeader = ({ update, settings, ui, control, account, design, set
const { t, i18n } = useTranslation(ns) const { t, i18n } = useTranslation(ns)
const { zoomFunctions, zoomed } = useContext(PanZoomContext) const { zoomFunctions, zoomed } = useContext(PanZoomContext)
const backend = useBackend() const backend = useBackend()
const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const { setLoadingStatus } = useContext(LoadingStatusContext)
// make the zoom buttons so we can pass them to the mobile menubar // make the zoom buttons so we can pass them to the mobile menubar
const headerZoomButtons = useMemo( const headerZoomButtons = useMemo(
@ -127,7 +131,6 @@ export const ViewHeader = ({ update, settings, ui, control, account, design, set
'lg:top-24' 'lg:top-24'
)} transition-[top] duration-300 ease-in-out`} )} transition-[top] duration-300 ease-in-out`}
> >
<LoadingStatus />
<div className="hidden lg:flex flex-row flex-wrap gap-4 py-4 pt-8 w-full bg-neutral text-neutral-content items-center justify-center"> <div className="hidden lg:flex flex-row flex-wrap gap-4 py-4 pt-8 w-full bg-neutral text-neutral-content items-center justify-center">
{headerZoomButtons} {headerZoomButtons}
<Spacer /> <Spacer />

View file

@ -1,14 +1,14 @@
import { ModalContextProvider } from 'shared/context/modal-context.mjs' import { ModalContextProvider } from 'shared/context/modal-context.mjs'
import { LoadingContextProvider } from 'shared/context/loading-context.mjs' import { LoadingStatusContextProvider } from 'shared/context/loading-status-context.mjs'
import { NavigationContextProvider } from 'shared/context/navigation-context.mjs' import { NavigationContextProvider } from 'shared/context/navigation-context.mjs'
import { MobileMenubarContextProvider } from 'shared/context/mobile-menubar-context.mjs' import { MobileMenubarContextProvider } from 'shared/context/mobile-menubar-context.mjs'
export const ContextWrapper = ({ children }) => ( export const ContextWrapper = ({ children }) => (
<ModalContextProvider> <ModalContextProvider>
<LoadingContextProvider> <LoadingStatusContextProvider>
<NavigationContextProvider> <NavigationContextProvider>
<MobileMenubarContextProvider>{children}</MobileMenubarContextProvider> <MobileMenubarContextProvider>{children}</MobileMenubarContextProvider>
</NavigationContextProvider> </NavigationContextProvider>
</LoadingContextProvider> </LoadingStatusContextProvider>
</ModalContextProvider> </ModalContextProvider>
) )

View file

@ -1,10 +1,11 @@
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useContext } from 'react' import { useContext } from 'react'
import { LoadingContext } from 'shared/context/loading-context.mjs'
import { Ribbon } from 'shared/components/ribbon.mjs' import { Ribbon } from 'shared/components/ribbon.mjs'
export const HeaderWrapper = ({ show, children }) => { export const HeaderWrapper = ({ show, children }) => {
const { loading } = useContext(LoadingContext) const { loading } = useContext(LoadingStatusContext)
return ( return (
<header <header
className={` className={`

View file

@ -1,6 +1,8 @@
// Dependencies // Dependencies
import React, { useState, useEffect, useContext } from 'react' import React, { useState, useEffect, useContext } from 'react'
import { nsMerge } from 'shared/utils.mjs' import { nsMerge } from 'shared/utils.mjs'
// Context
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
// Hooks // Hooks
import { useTheme } from 'shared/hooks/use-theme.mjs' import { useTheme } from 'shared/hooks/use-theme.mjs'
// Components // Components
@ -11,7 +13,7 @@ import { DefaultLayout, ns as defaultLayoutNs } from 'site/components/layouts/de
import { Feeds } from 'site/components/feeds.mjs' import { Feeds } from 'site/components/feeds.mjs'
import { ModalContext } from 'shared/context/modal-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs'
export const ns = nsMerge(layoutNs, defaultLayoutNs, 'common') export const ns = nsMerge(layoutNs, defaultLayoutNs, 'status')
/* This component should wrap all page content */ /* This component should wrap all page content */
export const PageWrapper = (props) => { export const PageWrapper = (props) => {
@ -32,6 +34,7 @@ export const PageWrapper = (props) => {
* Contexts * Contexts
*/ */
const { modalContent } = useContext(ModalContext) const { modalContent } = useContext(ModalContext)
const { LoadingStatus } = useContext(LoadingStatusContext)
/* /*
* This forces a re-render upon initial bootstrap of the app * This forces a re-render upon initial bootstrap of the app
@ -59,6 +62,7 @@ export const PageWrapper = (props) => {
data-theme={currentTheme} // This facilitates CSS selectors data-theme={currentTheme} // This facilitates CSS selectors
key={currentTheme} // This forces the data-theme update key={currentTheme} // This forces the data-theme update
> >
<LoadingStatus />
<Feeds /> <Feeds />
<LayoutWrapper {...childProps}> <LayoutWrapper {...childProps}>
{Layout ? <Layout {...childProps}>{children}</Layout> : children} {Layout ? <Layout {...childProps}>{children}</Layout> : children}

View file

@ -1,24 +0,0 @@
import React, { useState } from 'react'
export const LoadingContext = React.createContext(false)
export const LoadingContextProvider = ({ children }) => {
function stopLoading() {
__setLoading({ ...__loading, loading: false })
}
function startLoading() {
__setLoading({ ...__loading, loading: true })
}
function setLoading(loading) {
__setLoading({ ...__loading, loading })
}
const [__loading, __setLoading] = useState({
setLoading,
startLoading,
stopLoading,
loading: false,
})
return <LoadingContext.Provider value={__loading}>{children}</LoadingContext.Provider>
}

View file

@ -1,10 +1,12 @@
import { useState, useEffect } from 'react' import { useState, useEffect, createContext } from 'react'
import { Spinner } from 'shared/components/spinner.mjs' import { Spinner } from 'shared/components/spinner.mjs'
import { OkIcon, WarningIcon } from 'shared/components/icons.mjs' import { OkIcon, WarningIcon } from 'shared/components/icons.mjs'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
export const ns = ['status'] export const ns = ['status']
export const LoadingStatusContext = createContext([false])
/* /*
* Timeout in seconds before the loading status dissapears * Timeout in seconds before the loading status dissapears
*/ */
@ -20,12 +22,9 @@ const LoadingStatus = ({ loadingStatus }) => {
if (loadingStatus[2]) { if (loadingStatus[2]) {
if (timer) clearTimeout(timer) if (timer) clearTimeout(timer)
setTimer( setTimer(
window.setTimeout( window.setTimeout(() => {
() => { setFade('opacity-0')
setFade('opacity-0') }, timeout * 1000 - 350)
},
timeout * 1000 - 350
)
) )
} }
}, [loadingStatus[2]]) }, [loadingStatus[2]])
@ -66,7 +65,7 @@ const LoadingProgress = ({ val = 0, max = 1, msg }) => (
</div> </div>
) )
export const useLoadingStatus = () => { export const LoadingStatusContextProvider = ({ children }) => {
/* /*
* LoadingStatus should hold an array with 1 to 4 elements: * LoadingStatus should hold an array with 1 to 4 elements:
* 0 => Show loading status or not (true or false) * 0 => Show loading status or not (true or false)
@ -74,11 +73,18 @@ export const useLoadingStatus = () => {
* 2 => Set this to true to make the loadingStatus dissapear after 2 seconds * 2 => Set this to true to make the loadingStatus dissapear after 2 seconds
* 3 => Set this to true to show success, false to show error (only when 2 is true) * 3 => Set this to true to show success, false to show error (only when 2 is true)
*/ */
const [loadingStatus, setLoadingStatus] = useState([false])
const [timer, setTimer] = useState(false) const [timer, setTimer] = useState(false)
const [__loadingStatus, __setLoadingStatus] = useState({
status: [false],
setLoadingStatus,
loading: false,
LoadingStatus: () => <LoadingStatus loadingStatus={[false]} />,
LoadingProgress,
})
useEffect(() => { useEffect(() => {
if (loadingStatus[2]) { if (__loadingStatus.status[2]) {
if (timer) clearTimeout(timer) if (timer) clearTimeout(timer)
setTimer( setTimer(
window.setTimeout(() => { window.setTimeout(() => {
@ -86,12 +92,20 @@ export const useLoadingStatus = () => {
}, timeout * 1000) }, timeout * 1000)
) )
} }
}, [loadingStatus[2]]) }, [__loadingStatus.status[2]])
return { function setLoadingStatus(newStatus) {
setLoadingStatus, __setLoadingStatus({
loading: loadingStatus[0], ...__loadingStatus,
LoadingStatus: () => <LoadingStatus loadingStatus={loadingStatus} />, status: newStatus,
LoadingProgress, loading: newStatus[0] || false,
LoadingStatus: () => <LoadingStatus loadingStatus={newStatus} />,
})
} }
return (
<LoadingStatusContext.Provider value={__loadingStatus}>
{children}
</LoadingStatusContext.Provider>
)
} }

View file

@ -1,54 +0,0 @@
import { useTranslation } from 'next-i18next'
import toastMethod from 'react-hot-toast'
import { OkIcon, NoIcon, TipIcon, WarningIcon, ChatIcon } from 'shared/components/icons.mjs'
const icons = {
success: <OkIcon className="w-6 h-6 text-success" />,
error: <NoIcon className="w-6 h-6 text-error" />,
info: <TipIcon className="w-6 h-6 text-info" />,
warning: <WarningIcon className="w-6 h-6 text-warning" />,
accent: <ChatIcon className="w-6 h-6 text-accent" />,
}
const Toast = ({ type = 'info', children }) => (
<div className={`w-64 alert shadow bg-base-100 p-0`}>
<div
className={`w-full m-0 bg-${type} p-4 border bg-opacity-30 rounded-lg flex flex-row items-center`}
>
{icons[type]}
<div>{children}</div>
</div>
</div>
)
/* Custom toast methods */
const toastMethods = (t) => ({
info: (children) => toastMethod.custom(<Toast type="info">{children}</Toast>),
warning: (children) => toastMethod.custom(<Toast type="warning">{children}</Toast>),
error: (children) => toastMethod.custom(<Toast type="error">{children}</Toast>),
accent: (children) => toastMethod.custom(<Toast type="accent">{children}</Toast>),
success: (children) => toastMethod.custom(<Toast type="success">{children}</Toast>),
for: {
settingsSaved: () =>
toastMethod.custom(
<Toast type="success">
<span>{t('settingsSaved')}</span>
</Toast>
),
backendError: () =>
toastMethod.custom(
<Toast type="error">
<span>{t('backendError')} ¯\_()_/¯</span>
</Toast>
),
},
})
/*
* The toast hook
*/
export function useToast() {
const { t } = useTranslation(['toast'])
return toastMethods(t)
}

View file

@ -22,3 +22,4 @@ toc: Table of contents
credits: Credits credits: Credits
contentsBy: Contents by contentsBy: Contents by
translators: Translators translators: Translators
title: Title