diff --git a/sites/org/components/crowdin/suggest-language.mjs b/sites/org/components/crowdin/suggest-language.mjs index 64d295e5f13..460159ecc01 100644 --- a/sites/org/components/crowdin/suggest-language.mjs +++ b/sites/org/components/crowdin/suggest-language.mjs @@ -1,8 +1,7 @@ // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useToast } from 'shared/hooks/use-toast.mjs' import { useState, useContext } from 'react' // Components import { ChoiceButton } from 'shared/components/choice-button.mjs' @@ -43,12 +42,9 @@ const languages = [ ] export const SuggestLanguageForm = () => { - // Context - const { startLoading, stopLoading } = useContext(LoadingContext) - // Hooks const backend = useBackend() - const toast = useToast() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [language, setLanguage] = useState(false) @@ -58,15 +54,12 @@ export const SuggestLanguageForm = () => { const [comments, setComments] = useState('') const sendSuggestion = async () => { - startLoading() + setLoadingStatus([true, 'status:contactingBackend']) const result = await backend.sendLanguageSuggestion({ language, help, friends, comments }) if (result.success) { setSent(true) - stopLoading() - toast.success('Suggestion submitted') - } else { - toast.for.backendError() - } + setLoadingStatus([true, 'status:nailedIt', true, true]) + } else setLoadingStatus([true, 'status:backendError', true, false]) } if (sent) diff --git a/sites/org/components/crowdin/translator-invite.mjs b/sites/org/components/crowdin/translator-invite.mjs index 78bc79996d7..559795c8af5 100644 --- a/sites/org/components/crowdin/translator-invite.mjs +++ b/sites/org/components/crowdin/translator-invite.mjs @@ -2,10 +2,9 @@ import { siteConfig } from 'site/site.config.mjs' import translators from 'site/prebuild/translators.json' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useToast } from 'shared/hooks/use-toast.mjs' import { useState, useContext } from 'react' import { useTranslation } from 'next-i18next' // Components @@ -22,28 +21,22 @@ const languages = [ ].sort() export const TranslatorInvite = () => { - // Context - const { startLoading, stopLoading } = useContext(LoadingContext) - // Hooks const { t } = useTranslation(ns) const backend = useBackend() - const toast = useToast() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [team, setTeam] = useState(false) const [sent, setSent] = useState(false) const sendInvite = async () => { - startLoading() + setLoadingStatus([true, 'status:contactingBackend']) const result = await backend.sendTranslatorInvite(team) if (result.success) { setSent(true) - stopLoading() - toast.success(t('translation:inviteSent')) - } else { - toast.for.backendError() - } + setLoadingStatus([true, 'status:settingsSaved', true, true]) + } else setLoadingStatus([true, 'status:backendError', true, false]) } if (sent) diff --git a/sites/org/components/curate/sets/edit.mjs b/sites/org/components/curate/sets/edit.mjs index 9115e44441f..5e5236f0a46 100644 --- a/sites/org/components/curate/sets/edit.mjs +++ b/sites/org/components/curate/sets/edit.mjs @@ -5,14 +5,13 @@ import { freeSewingConfig as conf } from 'shared/config/freesewing.config.mjs' import { measurements } from 'config/measurements.mjs' import { measurements as designMeasurements } from 'shared/prebuild/data/design-measurements.mjs' // 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' // Hooks import { useState, useEffect, useContext } from 'react' import { useTranslation } from 'next-i18next' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useToast } from 'shared/hooks/use-toast.mjs' // Components import { Collapse } from 'shared/components/collapse.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 { V3Wip } from 'shared/components/v3-wip.mjs' -export const ns = ['toast', 'curate', 'sets', 'account'] +export const ns = ['curate', 'sets', 'account'] const EditField = (props) => { if (props.field === 'nameEn') return @@ -137,7 +136,7 @@ export const EditCuratedSet = ({ id }) => { /* // Context - const { startLoading, stopLoading } = useContext(LoadingContext) + const { setLoadingStatus } = useContext(LoadingStatusContext) const { setModal } = useContext(ModalContext) // Hooks @@ -171,8 +170,6 @@ export const EditCuratedSet = ({ id }) => { }, [reload, backend, id]) const editProps = { - startLoading, - stopLoading, account, backend, t, diff --git a/sites/org/components/curate/sets/index.mjs b/sites/org/components/curate/sets/index.mjs index 5e81de38df9..774c4ac9033 100644 --- a/sites/org/components/curate/sets/index.mjs +++ b/sites/org/components/curate/sets/index.mjs @@ -2,7 +2,7 @@ import { capitalize } from 'shared/utils.mjs' import { siteConfig } from 'site/site.config.mjs' // 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' // Hooks import { useState, useEffect, useContext } from 'react' @@ -27,28 +27,17 @@ export const Row = ({ title, children }) => ( ) -const CuratedSet = ({ - set, - account, - t, - startLoading, - stopLoading, - backend, - refresh, - toast, - language, -}) => { +const CuratedSet = ({ set, account, t, setLoadingStatus, backend, refresh, toast, language }) => { const { setModal } = useContext(ModalContext) const remove = async () => { - startLoading() + setLoadingStatus([true, 'status:contactingBackend']) const result = await backend.removeCuratedMeasurementsSet(set.id) - if (result) toast.success(t('gone')) - else toast.for.backendError() + if (result) setLoadingStatus([true, 'status:settingsSaved', true, true]) + else setLoadingStatus([true, 'status:backendError', true, false]) // This just forces a refresh of the list from the server // We obviously did not add a key here, but rather removed one refresh() - stopLoading() } const removeModal = () => { @@ -119,7 +108,7 @@ const CuratedSet = ({ export const CurateSets = () => { // Context - const { startLoading, stopLoading } = useContext(LoadingContext) + const { setLoadingStatus } = useContext(LoadingStatusContext) // Hooks const { account } = useAccount() @@ -209,7 +198,7 @@ export const CurateSets = () => { {list.map((set) => ( ))} diff --git a/sites/org/components/github/create-post.mjs b/sites/org/components/github/create-post.mjs index f29626f3ca6..d04bea63d1f 100644 --- a/sites/org/components/github/create-post.mjs +++ b/sites/org/components/github/create-post.mjs @@ -5,6 +5,8 @@ import { useState, Fragment } from 'react' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { Popout } from 'shared/components/popout/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 { PageLink, WebLink } from 'shared/components/link.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) @@ -64,7 +65,7 @@ export const CreatePost = ({ type = 'showcase' }) => { const backend = useBackend() const { account } = useAccount() const { t, i18n } = useTranslation(ns) - const { loading, setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { loading, setLoadingStatus } = useContext(LoadingStatusContext) // State const [designs, setDesigns] = useState([]) @@ -151,7 +152,6 @@ export const CreatePost = ({ type = 'showcase' }) => { return ( - {pr ? (

Thank you for submitting this {type} post

diff --git a/sites/org/components/github/create-showcase.mjs b/sites/org/components/github/create-showcase.mjs index e2b7eb8e8f5..1057516c267 100644 --- a/sites/org/components/github/create-showcase.mjs +++ b/sites/org/components/github/create-showcase.mjs @@ -5,6 +5,8 @@ import { useState, Fragment } from 'react' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { Popout } from 'shared/components/popout/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 { PageLink, WebLink } from 'shared/components/link.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) @@ -53,7 +54,7 @@ export const CreateShowcasePost = () => { const { account } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { loading, setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { loading, setLoadingStatus } = useContext(LoadingStatusContext) const [designs, setDesigns] = useState([]) const [title, setTitle] = useState('') @@ -135,7 +136,6 @@ export const CreateShowcasePost = () => { return ( - {pr ? (

Thank you for submitting this showcase

diff --git a/sites/org/components/layouts/docs.mjs b/sites/org/components/layouts/docs.mjs index 1155df2cc46..8fb739640bc 100644 --- a/sites/org/components/layouts/docs.mjs +++ b/sites/org/components/layouts/docs.mjs @@ -1,4 +1,5 @@ import { NavigationContext } from 'shared/context/navigation-context.mjs' +import { nsMerge } from 'shared/utils.mjs' // Hooks import { useContext } from 'react' // Components @@ -16,10 +17,10 @@ import { ns as navNs, } from 'shared/components/navigation/sitenav.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' -export const ns = [navNs, 'docs'] //navNs +export const ns = nsMerge(navNs, 'docs', metaNs) export const FrontmatterHead = ({ frontmatter, slug, locale }) => ( diff --git a/sites/org/pages/_app.mjs b/sites/org/pages/_app.mjs index 3c508238cbc..32608364d09 100644 --- a/sites/org/pages/_app.mjs +++ b/sites/org/pages/_app.mjs @@ -4,7 +4,6 @@ import React from 'react' import Bugsnag from '@bugsnag/js' import BugsnagPluginReact from '@bugsnag/plugin-react' import { siteConfig } from 'site/site.config.mjs' -import { Toaster as DefaultToaster } from 'react-hot-toast' import { ContextWrapper } from 'shared/components/wrappers/context.mjs' Bugsnag.start({ @@ -19,24 +18,6 @@ const FreeSewingOrg = ({ Component, pageProps }) => ( - ) diff --git a/sites/org/pages/account/apikeys/[id].mjs b/sites/org/pages/account/apikeys/[id].mjs index 215eb98de71..ca7932ea350 100644 --- a/sites/org/pages/account/apikeys/[id].mjs +++ b/sites/org/pages/account/apikeys/[id].mjs @@ -6,14 +6,13 @@ import { nsMerge } from 'shared/utils.mjs' import { useTranslation } from 'next-i18next' import { useState, useEffect } from 'react' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components 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 apikeysNs } from 'shared/components/account/apikeys.mjs' // 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 @@ -38,26 +37,20 @@ const DynamicApikey = dynamic( const ApikeyPage = ({ page, id }) => { const { t } = useTranslation(ns) const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const [apikey, setApikey] = useState() useEffect(() => { const getApikey = async () => { - setLoadingStatus([true, t('backendLoadingStarted')]) const result = await backend.getApikey(id) - if (result.success) { - setApikey(result.data.apikey) - console.log(result.data.apikey) - setLoadingStatus([true, 'backendLoadingCompleted', true, true]) - } else setLoadingStatus([false]) + if (result.success) setApikey(result.data.apikey) + else setLoadingStatus([false]) } getApikey() }, [id]) return ( - diff --git a/sites/org/pages/account/bookmarks/[id].mjs b/sites/org/pages/account/bookmarks/[id].mjs index c5a43eee48f..8fa13d6f9b1 100644 --- a/sites/org/pages/account/bookmarks/[id].mjs +++ b/sites/org/pages/account/bookmarks/[id].mjs @@ -6,7 +6,6 @@ import { nsMerge } from 'shared/utils.mjs' import { useTranslation } from 'next-i18next' import { useState, useEffect } from 'react' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs' @@ -38,25 +37,20 @@ const DynamicBookmark = dynamic( const BookmarkPage = ({ page, id }) => { const { t } = useTranslation(ns) const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() const [bookmark, setBookmark] = useState() useEffect(() => { const getBookmark = async () => { - setLoadingStatus([true, t('backendLoadingStarted')]) const result = await backend.getBookmark(id) - if (result.success) { - setBookmark(result.data.bookmark) - setLoadingStatus([true, 'backendLoadingCompleted', true, true]) - } else setLoadingStatus([false]) + if (result.success) setBookmark(result.data.bookmark) + else setLoadingStatus([false]) } getBookmark() }, [id]) return ( - diff --git a/sites/org/pages/confirm/emailchange/[...confirmation].mjs b/sites/org/pages/confirm/emailchange/[...confirmation].mjs index b527cddb094..ea70309fb05 100644 --- a/sites/org/pages/confirm/emailchange/[...confirmation].mjs +++ b/sites/org/pages/confirm/emailchange/[...confirmation].mjs @@ -2,11 +2,10 @@ import { useEffect, useState, useContext } from 'react' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useAccount } from 'shared/hooks/use-account.mjs' -import { useToast } from 'shared/hooks/use-toast.mjs' import { useRouter } from 'next/router' import { useTranslation } from 'next-i18next' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Dependencies import { serverSideTranslations } from 'next-i18next/serverSideTranslations' 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 ConfirmSignUpPage = ({ page }) => { - // Context - const { startLoading, stopLoading } = useContext(LoadingContext) - // Hooks const { setAccount, setToken, token } = useAccount() const backend = useBackend() - const toast = useToast() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { t } = useTranslation(ns) const router = useRouter() // Get confirmation ID and check from url @@ -41,7 +37,7 @@ const ConfirmSignUpPage = ({ page }) => { useEffect(() => { // Async inside useEffect requires this approach const confirmEmail = async () => { - startLoading() + setLoadingStatus([true, 'status:contactingBackend']) const confirmation = await backend.loadConfirmation({ id, check }) if (confirmation?.result === 'success' && confirmation.confirmation) { const result = await backend.updateAccount({ @@ -50,35 +46,23 @@ const ConfirmSignUpPage = ({ page }) => { check: confirmation.confirmation.check, }) if (result.success) { + setLoadingStatus([true, 'status:settingsSaved', true, true]) setAccount(result.data.account) setToken(result.data.token) - stopLoading() setError(false) - toast.for.settingsSaved() router.push('/account') } else { - stopLoading() + setLoadingStatus([true, 'status:backendError', true, false]) setError(true) } } else { - stopLoading() + setLoadingStatus([true, 'status:backendError', true, false]) setError(true) } } // Call async methods if (token) confirmEmail() - }, [ - id, - check, - token, - backend, - router, - setAccount, - setToken, - startLoading, - stopLoading, - toast.for, - ]) + }, [id, check, token, backend, router, setAccount, setToken]) // Update path with dynamic ID if (!page) return null diff --git a/sites/org/pages/docs/[...slug].mjs b/sites/org/pages/docs/[...slug].mjs index c4a69dd90e3..a954289eff9 100644 --- a/sites/org/pages/docs/[...slug].mjs +++ b/sites/org/pages/docs/[...slug].mjs @@ -1,3 +1,4 @@ +import { nsMerge } from 'shared/utils.mjs' // Used in static paths import { pages } from 'site/prebuild/docs.en.mjs' // 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 { 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 @@ -49,7 +50,7 @@ export default DocsPage export async function getStaticProps({ locale, params }) { return { props: { - ...(await serverSideTranslations('en', ['docs', ...ns])), + ...(await serverSideTranslations('en', ns)), slug: params.slug.join('/'), locale, page: { diff --git a/sites/org/pages/newsletter/subscribe/[...tokens].mjs b/sites/org/pages/newsletter/subscribe/[...tokens].mjs index 11c51905905..460cc24758f 100644 --- a/sites/org/pages/newsletter/subscribe/[...tokens].mjs +++ b/sites/org/pages/newsletter/subscribe/[...tokens].mjs @@ -6,7 +6,7 @@ import { useState, useContext } from 'react' import { useTranslation } from 'next-i18next' import { useBackend } from 'shared/hooks/use-backend.mjs' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { Popout } from 'shared/components/popout/index.mjs' @@ -23,15 +23,15 @@ const namespaces = nsMerge(pageNs, 'newsletter') */ const NewsletterPage = ({ page, id, ehash }) => { const { t } = useTranslation(namespaces) - const { setLoading } = useContext(LoadingContext) + const { setLoadingStatus } = useContext(LoadingStatusContext) const backend = useBackend() const [confirmed, setConfirmed] = useState(false) const handler = async () => { - setLoading(true) + setLoadingStatus([true, 'status:contactingBackend']) await backend.confirmNewsletterSubscribe({ id, ehash }) - setLoading(false) + setLoadingStatus([true, 'status:settingsSaved', true, true]) setConfirmed(true) } diff --git a/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs b/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs index 6396ef0f0e8..d9b98a96204 100644 --- a/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs +++ b/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs @@ -6,7 +6,7 @@ import { useState, useContext } from 'react' import { useTranslation } from 'next-i18next' import { useBackend } from 'shared/hooks/use-backend.mjs' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { Popout } from 'shared/components/popout/index.mjs' @@ -23,15 +23,15 @@ const namespaces = nsMerge(pageNs, 'newsletter') */ const NewsletterPage = ({ page, id, ehash }) => { const { t } = useTranslation(namespaces) - const { setLoading } = useContext(LoadingContext) + const { setLoadingStatus } = useContext(LoadingStatusContext) const backend = useBackend() const [confirmed, setConfirmed] = useState(false) const handler = async () => { - setLoading(true) + setLoadingStatus([true, 'status:contactingBackend']) await backend.confirmNewsletterUnsubscribe({ id, ehash }) - setLoading(false) + setLoadingStatus([true, 'status:settingsSaved', true, true]) setConfirmed(true) } diff --git a/sites/org/pages/signin/callback/[provider].mjs b/sites/org/pages/signin/callback/[provider].mjs index 1c6622d4ba5..4774f47d090 100644 --- a/sites/org/pages/signin/callback/[provider].mjs +++ b/sites/org/pages/signin/callback/[provider].mjs @@ -6,8 +6,9 @@ import { useEffect } from 'react' import { useRouter } from 'next/router' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useAccount } from 'shared/hooks/use-account.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { BareLayout } from 'site/components/layouts/bare.mjs' @@ -27,7 +28,7 @@ const OauthCallbackPage = ({ page, provider }) => { const { t } = useTranslation(ns) const backend = useBackend() const { setAccount, setToken, setSeenUser } = useAccount() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) useEffect(() => { const oauthFlow = async () => { @@ -53,7 +54,6 @@ const OauthCallbackPage = ({ page, provider }) => { return ( -
diff --git a/sites/shared/components/account/apikeys.mjs b/sites/shared/components/account/apikeys.mjs index 6573c057759..3bd1f6d00b8 100644 --- a/sites/shared/components/account/apikeys.mjs +++ b/sites/shared/components/account/apikeys.mjs @@ -4,11 +4,12 @@ import { useTranslation } from 'next-i18next' import { DateTime } from 'luxon' import { CopyToClipboard } from 'react-copy-to-clipboard' import { shortDate, formatNumber } from 'shared/utils.mjs' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useRouter } from 'next/router' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { BackToAccountButton, DisplayRow, NumberBullet } from './shared.mjs' import { Popout } from 'shared/components/popout/index.mjs' @@ -55,7 +56,7 @@ const ExpiryPicker = ({ t, expires, setExpires }) => { const CopyInput = ({ text }) => { const { t } = useTranslation(['status']) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const [copied, setCopied] = useState(false) @@ -67,7 +68,6 @@ const CopyInput = ({ text }) => { return (
- { const [level, setLevel] = useState(1) const [expires, setExpires] = useState(Date.now()) const [apikey, setApikey] = useState(false) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { t, i18n } = useTranslation(ns) // FIXME: implement a solution for loading docs dynamically the is simple and work as expected const docs = {} @@ -179,7 +179,6 @@ const NewKey = ({ account, setGenerate, backend }) => { return (
- {apikey ? ( ) : ( @@ -264,7 +263,7 @@ export const Apikeys = () => { const { account } = useAccount() const backend = useBackend() const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() + const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext) // State const [keys, setKeys] = useState([]) @@ -319,7 +318,6 @@ export const Apikeys = () => { return (
-

{ const { account, setAccount } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [bio, setBio] = useState(account.bio) @@ -53,7 +54,6 @@ export const BioSettings = ({ welcome = false }) => { return (

- { // Component for the 'new/apikey' page export const NewBookmark = () => { // Hooks - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const router = useRouter() const backend = useBackend() const { t, i18n } = useTranslation(ns) @@ -72,7 +73,6 @@ export const NewBookmark = () => { return (
- { // Hooks const backend = useBackend() const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() + const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext) // State const [bookmarks, setBookmarks] = useState([]) @@ -167,7 +167,6 @@ export const Bookmarks = () => { return (
-

{ // Hooks const { account, setAccount } = useAccount() const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { t, i18n } = useTranslation(ns) // State @@ -47,7 +48,6 @@ export const CompareSettings = ({ welcome = false }) => { return (

- (
{ // Hooks const { account, setAccount, setToken } = useAccount() const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { t } = useTranslation(ns) // State @@ -73,7 +74,6 @@ export const ConsentSettings = ({ title = false }) => { return (
- {title ?

{t('privacyMatters')}

: null}

{t('compliant')}

{t('consentWhyAnswer')}

diff --git a/sites/shared/components/account/control.mjs b/sites/shared/components/account/control.mjs index b72c525f6d7..0b8092ac8bf 100644 --- a/sites/shared/components/account/control.mjs +++ b/sites/shared/components/account/control.mjs @@ -1,10 +1,11 @@ // Dependencies import { useState } from 'react' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { BackToAccountButton, Icons, welcomeSteps } from './shared.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' @@ -19,7 +20,7 @@ export const useControlState = () => { // Hooks const { account, setAccount, token } = useAccount() const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State 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 }) => { @@ -61,7 +62,6 @@ export const ControlSettings = ({ welcome = false, noBack = false }) => { return (
- { const { account, setAccount } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [email, setEmail] = useState(account.email) @@ -42,7 +43,6 @@ export const EmailSettings = () => { return (
- {changed ? (

{t('oneMoreThing')}

diff --git a/sites/shared/components/account/en.yaml b/sites/shared/components/account/en.yaml index da971a91649..ccdc1789364 100644 --- a/sites/shared/components/account/en.yaml +++ b/sites/shared/components/account/en.yaml @@ -193,6 +193,7 @@ csetBookmark: Curated Measurements Sets docBookmark: Documentation customBookmark: Custom Bookmarks yourBookmarks: Your bookmarks +bookmarkThisPage: Bookmark this page # sets set: Measurements Set diff --git a/sites/shared/components/account/export.mjs b/sites/shared/components/account/export.mjs index 061244c3c3a..2ca1c939f48 100644 --- a/sites/shared/components/account/export.mjs +++ b/sites/shared/components/account/export.mjs @@ -1,9 +1,10 @@ // Dependencies import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useState } from 'react' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { BackToAccountButton } from './shared.mjs' import { Popout } from 'shared/components/popout/index.mjs' @@ -15,7 +16,7 @@ export const ExportAccount = () => { // Hooks const backend = useBackend() const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const [link, setLink] = useState() @@ -31,7 +32,6 @@ export const ExportAccount = () => { return (
- {link ? (
{t('exportDownload')}
diff --git a/sites/shared/components/account/github.mjs b/sites/shared/components/account/github.mjs index 132080bba1f..e5d7cdfdfa5 100644 --- a/sites/shared/components/account/github.mjs +++ b/sites/shared/components/account/github.mjs @@ -1,10 +1,11 @@ // Dependencies import { useState } from 'react' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { BackToAccountButton } from './shared.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' @@ -18,7 +19,7 @@ export const GithubSettings = () => { const { account, setAccount } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [githubUsername, setGithubUsername] = useState(account.data.githubUsername || '') @@ -36,7 +37,6 @@ export const GithubSettings = () => { return (
-

{t('githubTitle')}

{ const { account, setAccount } = useAccount() const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { t, i18n } = useTranslation(ns) const [img, setImg] = useState('') @@ -36,7 +37,6 @@ export const ImgSettings = ({ welcome = false }) => { return (
- {!welcome || img !== false ? ( img { // Hooks const { account, setAccount } = useAccount() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const backend = useBackend() const { t, i18n } = useTranslation(ns) @@ -44,7 +45,6 @@ export const ImperialSettings = ({ welcome = false }) => { return (
- { // Hooks const { account, setAccount } = useAccount() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const backend = useBackend() const { t, i18n } = useTranslation(ns) @@ -39,7 +40,6 @@ export const LanguageSettings = () => { return (
- { const { account, setAccount } = useAccount() const backend = useBackend() const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [enable, setEnable] = useState(false) @@ -87,7 +88,6 @@ export const MfaSettings = ({ title = false, welcome = false }) => { return (
- {title ?

{titleText}

: null} {enable ? ( <> diff --git a/sites/shared/components/account/newsletter.mjs b/sites/shared/components/account/newsletter.mjs index 8caf3da0ffc..3c83c520622 100644 --- a/sites/shared/components/account/newsletter.mjs +++ b/sites/shared/components/account/newsletter.mjs @@ -1,10 +1,11 @@ // Dependencies import { useState } from 'react' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { BackToAccountButton, Icons, welcomeSteps } from './shared.mjs' import { ContinueButton } from 'shared/components/buttons/continue-button.mjs' @@ -19,7 +20,7 @@ export const NewsletterSettings = ({ welcome = false }) => { const { account, setAccount } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { LoadingStatus, setLoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [selection, setSelection] = useState(account?.newsletter ? 'yes' : 'no') @@ -44,7 +45,6 @@ export const NewsletterSettings = ({ welcome = false }) => { return (
- { const { account, setAccount } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [password, setPassword] = useState('') @@ -38,7 +39,6 @@ export const PasswordSettings = ({ welcome = false }) => { return (
- { // Hooks const { account, control } = useAccount() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const backend = useBackend() const { t, i18n } = useTranslation(ns) // FIXME: implement a solution for loading docs dynamically @@ -122,7 +123,6 @@ export const Pattern = ({ id, publicOnly = false }) => { const heading = ( <> -
@@ -428,7 +428,7 @@ export const Patterns = () => { // Hooks const backend = useBackend() const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus, LoadingProgress } = useLoadingStatus() + const { setLoadingStatus, LoadingProgress } = useContext(LoadingStatusContext) // State const [patterns, setPatterns] = useState([]) @@ -483,7 +483,6 @@ export const Patterns = () => { return (
-

diff --git a/sites/shared/components/account/platform.mjs b/sites/shared/components/account/platform.mjs index 458938ac9b9..13e62f89564 100644 --- a/sites/shared/components/account/platform.mjs +++ b/sites/shared/components/account/platform.mjs @@ -1,10 +1,11 @@ // Dependencies import { useState } from 'react' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { BackToAccountButton } from './shared.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' @@ -18,7 +19,7 @@ export const PlatformSettings = ({ platform }) => { const { account, setAccount } = useAccount() const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [platformId, setPlatformId] = useState(account.data[platform] || '') @@ -37,7 +38,6 @@ export const PlatformSettings = ({ platform }) => { return (

- { const { setAccount } = useAccount() const backend = useBackend() const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // Helper method to reload account const reload = async () => { @@ -28,7 +29,6 @@ export const ReloadAccount = ({ title = false }) => { return (
- {title ?

{t('reloadMsg1')}

: null}

{t('reloadMsg2')}

- ) -} - -*/ diff --git a/sites/shared/components/account/username.mjs b/sites/shared/components/account/username.mjs index cacfff3217f..8d8d495debe 100644 --- a/sites/shared/components/account/username.mjs +++ b/sites/shared/components/account/username.mjs @@ -1,10 +1,11 @@ // Dependencies import { useState } from 'react' import { useTranslation } from 'next-i18next' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import { Icons, welcomeSteps, BackToAccountButton } from './shared.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 { DynamicOrgDocs } from 'shared/components/dynamic-docs/org.mjs' -export const ns = ['account', 'toast'] +export const ns = ['account', 'status'] export const UsernameSettings = ({ welcome = false }) => { // Hooks const { account, setAccount } = useAccount() const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { t, i18n } = useTranslation(ns) const [username, setUsername] = useState(account.username) const [available, setAvailable] = useState(true) @@ -52,7 +53,6 @@ export const UsernameSettings = ({ welcome = false }) => { return (
- { - const toast = useToast() const backend = useBackend() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { impersonate } = useAccount() if (!userId) return null const impersonateUser = async () => { + setLoadingStatus([true, 'status:contactingBackend']) const result = await backend.adminImpersonateUser(userId) if (result.success) { impersonate(result.data) - toast.for.settingsSaved() - } else toast.for.backendError() + setLoadingStatus([true, 'status:settingsSaved', true, true]) + } else setLoadingStatus([true, 'status:backendError', true, false]) } return ( @@ -132,7 +135,7 @@ export const User = ({ user }) => ( export const ManageUser = ({ userId }) => { // Hooks const backend = useBackend() - const toast = useToast() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [user, setUser] = useState({}) @@ -147,11 +150,12 @@ export const ManageUser = ({ userId }) => { }, [userId]) const updateUser = async (data) => { + setLoadingStatus([true, 'status:contactingBackend']) const result = await backend.adminUpdateUser({ id: userId, data }) if (result.success) { - toast.for.settingsSaved() + setLoadingStatus([true, 'status:settingsSaved', true, true]) setUser(result.data.user) - } else toast.for.backendError() + } else setLoadingStatus([true, 'status:backendError', true, false]) } return user.id ? ( diff --git a/sites/shared/components/bookmarks.mjs b/sites/shared/components/bookmarks.mjs new file mode 100644 index 00000000000..6fea9d4ccf6 --- /dev/null +++ b/sites/shared/components/bookmarks.mjs @@ -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 ( + <> +

{t('account:bookmarkThisPage')}

+ + + + ) +} + +export const BookmarkButton = ({ slug, type, title }) => { + const { t } = useTranslation('account') + const { setModal } = useContext(ModalContext) + + return ( + + ) +} diff --git a/sites/shared/components/buttons/continue-button.mjs b/sites/shared/components/buttons/continue-button.mjs index ce964c58423..dc01034a2e3 100644 --- a/sites/shared/components/buttons/continue-button.mjs +++ b/sites/shared/components/buttons/continue-button.mjs @@ -2,14 +2,14 @@ import { useContext } from 'react' import { useTranslation } from 'next-i18next' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { Spinner } from 'shared/components/spinner.mjs' import Link from 'next/link' export const ContinueButton = ({ btnProps = {}, link = false }) => { // Context - const { loading } = useContext(LoadingContext) + const { loading } = useContext(LoadingStatusContext) // Hooks const { t } = useTranslation(['account']) diff --git a/sites/shared/components/buttons/save-settings-button.mjs b/sites/shared/components/buttons/save-settings-button.mjs index ef90a19de10..af8a36d6ee4 100644 --- a/sites/shared/components/buttons/save-settings-button.mjs +++ b/sites/shared/components/buttons/save-settings-button.mjs @@ -2,12 +2,12 @@ import { useContext } from 'react' import { useTranslation } from 'next-i18next' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { Spinner } from 'shared/components/spinner.mjs' export const SaveSettingsButton = ({ btnProps = {}, welcome = false, label = false }) => { - const { loading } = useContext(LoadingContext) + const { loading } = useContext(LoadingStatusContext) const { t } = useTranslation(['account']) let classes = 'btn mt-4 capitalize ' if (welcome) { diff --git a/sites/shared/components/curated-sets.mjs b/sites/shared/components/curated-sets.mjs index 0f4a0342103..5b5244d4187 100644 --- a/sites/shared/components/curated-sets.mjs +++ b/sites/shared/components/curated-sets.mjs @@ -7,9 +7,9 @@ import { shortDate, cloudflareImageUrl, capitalize } from 'shared/utils.mjs' // Hooks import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Context import { ModalContext } from 'shared/context/modal-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Components import { DisplayRow } from './account/shared.mjs' import { ModalWrapper } from 'shared/components/wrappers/modal.mjs' @@ -135,7 +135,7 @@ const ShowCuratedSet = ({ cset }) => { export const CuratedSet = ({ id }) => { // Hooks - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const backend = useBackend() // State @@ -158,7 +158,6 @@ export const CuratedSet = ({ id }) => { return (
-
) @@ -168,7 +167,7 @@ export const CuratedSet = ({ id }) => { export const CuratedSets = () => { // Hooks const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [sets, setSets] = useState([]) @@ -191,7 +190,6 @@ export const CuratedSets = () => { return (
- {selected && }
diff --git a/sites/shared/components/inputs.mjs b/sites/shared/components/inputs.mjs index 2ee4f3d0dd4..ff444c69afd 100644 --- a/sites/shared/components/inputs.mjs +++ b/sites/shared/components/inputs.mjs @@ -3,12 +3,12 @@ import { cloudflareImageUrl } from 'shared/utils.mjs' import { collection } from 'shared/hooks/use-design.mjs' // Context import { ModalContext } from 'shared/context/modal-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useState, useCallback, useContext } from 'react' import { useTranslation } from 'next-i18next' import { useDropzone } from 'react-dropzone' import { useBackend } from 'shared/hooks/use-backend.mjs' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Components import Markdown from 'react-markdown' import { ResetIcon, DocsIcon, UploadIcon } from 'shared/components/icons.mjs' @@ -278,7 +278,7 @@ export const ImageInput = ({ }) => { const { t } = useTranslation(ns) const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const [url, setUrl] = useState(false) const [uploadedId, setUploadedId] = useState(false) @@ -316,7 +316,6 @@ export const ImageInput = ({ if (current) return ( -
-
list ? ( @@ -54,11 +60,19 @@ const CreditsList = ({ updates, frontmatter, locale, t }) => ( ) 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] || {} frontmatter.maintainers = ['joostdecock'] - locale = 'fr' + locale = i18n.language /* * FIXME @@ -70,13 +84,18 @@ export const MdxMetaData = ({ frontmatter, locale, slug }) => { return (
- - - {t('editThisPage')} - + {localControl > 2 && ( + + )}
{ // Context const { addPages } = useContext(NavigationContext) + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [pattern, setPattern] = useState({}) @@ -42,7 +43,6 @@ export const ManagePattern = ({ id = false }) => { const backend = useBackend() const { t, i18n } = useTranslation(ns) const { language } = i18n - const toast = useToast() // async effect helper const loadPattern = async () => { @@ -82,7 +82,7 @@ export const ManagePattern = ({ id = false }) => { if (result.success) { if (result.data.pattern) { setPattern(result.data.pattern) - toast.for.settingsSaved() + setLoadingStatus([true, 'settingsSaved', true, true]) } } } @@ -125,17 +125,13 @@ export const ManagePattern = ({ id = false }) => { <>

{t('update')}

{/* Name is always shown */} - + {pattern.name} {/* img: Control level determines whether or not to show this */} {pattern.id && account.control >= conf.account.patterns.img ? ( - + { {/* notes: Control level determines whether or not to show this */} {account.control >= conf.account.patterns.notes ? ( - + {pattern.notes} ) : null} diff --git a/sites/shared/components/ribbon.mjs b/sites/shared/components/ribbon.mjs index 18c1aed044d..9220a92f5ff 100644 --- a/sites/shared/components/ribbon.mjs +++ b/sites/shared/components/ribbon.mjs @@ -1,10 +1,10 @@ // Hooks import { useContext } from 'react' // Context -import { LoadingContext } from 'shared/context/loading-context.mjs' +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' export const Ribbon = () => { - const { loading } = useContext(LoadingContext) + const { loading } = useContext(LoadingStatusContext) return (
{ // Hooks const { t } = useTranslation(ns) const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const router = useRouter() const [submission, setSubmission] = useState(false) @@ -57,7 +58,6 @@ export const CsetSubmission = ({ id }) => { return (
- {submission.name} diff --git a/sites/shared/components/support.mjs b/sites/shared/components/support.mjs index 40f7f153757..366eef655f6 100644 --- a/sites/shared/components/support.mjs +++ b/sites/shared/components/support.mjs @@ -1,8 +1,9 @@ import { freeSewingConfig as config } from 'shared/config/freesewing.config.mjs' +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useTranslation } from 'next-i18next' import { useState, Fragment } from 'react' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' // Components @@ -118,7 +119,7 @@ const SupportType = ({ type, active, t, update }) => ( export const SupportForm = () => { const { t } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const { account } = useAccount() const backend = useBackend() @@ -212,7 +213,6 @@ export const SupportForm = () => { return (
- setType(false)} t={t} /> ( export const Migrate = () => { const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus, loading } = useLoadingStatus() + const { loading, setLoadingStatus } = useContext(LoadingStatusContext) const { setAccount, setSeenUser, setToken } = useAccount() const router = useRouter() @@ -61,14 +62,12 @@ export const Migrate = () => { if (result === 'success') return ( <> - ) if (result === 'exists') return ( <> -

{t('signup:v3UserAlreadyExists')}

@@ -87,7 +86,6 @@ export const Migrate = () => { if (result === 'failed') return ( <> -

{t('signup:noWorkie')}

@@ -106,7 +104,6 @@ export const Migrate = () => { return ( <> -

{t('signup:migrateV2')}

{t('migrateV2Desc')}

diff --git a/sites/shared/components/susi/sign-in.mjs b/sites/shared/components/susi/sign-in.mjs index 057996cfae1..5bcb8b4ae78 100644 --- a/sites/shared/components/susi/sign-in.mjs +++ b/sites/shared/components/susi/sign-in.mjs @@ -1,10 +1,11 @@ +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useState, useEffect } from 'react' import { useAccount } from 'shared/hooks/use-account.mjs' import { useTranslation } from 'next-i18next' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useRouter } from 'next/router' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' import { horFlexClasses, horFlexClassesNoSm, capitalize } from 'shared/utils.mjs' // Components import Link from 'next/link' @@ -28,7 +29,7 @@ export const SignIn = () => { const { t, i18n } = useTranslation(ns) const backend = useBackend() const router = useRouter() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const [username, setUsername] = useState('') const [password, setPassword] = useState('') @@ -117,7 +118,6 @@ export const SignIn = () => { if (magicLinkSent) return ( <> -

{t('susi:emailSent')}

@@ -138,7 +138,6 @@ export const SignIn = () => { return ( <> -

{seenBefore ? t('susi:welcomeBackName', { name: seenUser }) : t('susi:welcome')}

{t('susi:signInToThing', { thing: 'FreeSewing' })}:

{!seenBefore && ( diff --git a/sites/shared/components/susi/sign-up.mjs b/sites/shared/components/susi/sign-up.mjs index ddc23e05b29..47fbd6acf6d 100644 --- a/sites/shared/components/susi/sign-up.mjs +++ b/sites/shared/components/susi/sign-up.mjs @@ -2,8 +2,8 @@ import { useState, useContext } from 'react' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useTranslation } from 'next-i18next' -import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs' // Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs' // Dependencies import { validateEmail, validateTld, horFlexClasses, horFlexClassesNoSm } from 'shared/utils.mjs' @@ -32,7 +32,7 @@ export const SignUp = () => { const backend = useBackend() const { t, i18n } = useTranslation(ns) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const [email, setEmail] = useState('') const [emailValid, setEmailValid] = useState(false) @@ -98,7 +98,6 @@ export const SignUp = () => { return (
-

{result ? ( result === 'success' ? ( diff --git a/sites/shared/components/workbench/views/edit/index.mjs b/sites/shared/components/workbench/views/edit/index.mjs index b586baa8ec5..7cec1435ddc 100644 --- a/sites/shared/components/workbench/views/edit/index.mjs +++ b/sites/shared/components/workbench/views/edit/index.mjs @@ -1,22 +1,26 @@ +// Dependencies import yaml from 'js-yaml' 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 { useTranslation } from 'next-i18next' -import { useToast } from 'shared/hooks/use-toast.mjs' +// Components import { CloseIcon } from 'shared/components/icons.mjs' -import { capitalize } from 'shared/utils.mjs' import { V3Wip } from 'shared/components/v3-wip.mjs' -export const ns = ['wbedit'] +export const ns = [] /** a view for editing the gist as yaml */ export const EditView = ({ settings, setSettings, design, Design }) => { const inputRef = useRef(null) + const { setLoadingStatus } = useContext(LoadingStatusContext) const [error, setError] = useState(false) const [success, setSuccess] = useState(false) const { t } = useTranslation(ns) const patternConfig = useMemo(() => new Design().getConfig(), [Design]) - const toast = useToast() // parse the settings to yaml and set them as the value on the textArea useEffect(() => { @@ -29,6 +33,7 @@ export const EditView = ({ settings, setSettings, design, Design }) => { setSuccess(false) try { + setLoadingStatus([true, 'status:contactingBackend']) // parse back to json const editedAsJson = yaml.load(inputRef.current.value) @@ -43,7 +48,7 @@ export const EditView = ({ settings, setSettings, design, Design }) => { // save regardless setSettings(editedAsJson) setSuccess(true) - if (validation.valid) toast.success(t('success')) + if (validation.valid) setLoadingStatus([true, 'status:settingsSaved', true, true]) } catch (e) { console.log(e) setError(e.message) diff --git a/sites/shared/components/workbench/views/exporting/index.mjs b/sites/shared/components/workbench/views/exporting/index.mjs index a24eeb0e872..21369d2ca18 100644 --- a/sites/shared/components/workbench/views/exporting/index.mjs +++ b/sites/shared/components/workbench/views/exporting/index.mjs @@ -1,14 +1,17 @@ -import { useState, useContext } from 'react' -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' +// Dependencies import { exportTypes, handleExport, ns as exportNs, } 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' export const ns = ['exporting', exportNs] @@ -16,8 +19,10 @@ export const ns = ['exporting', exportNs] export const ExportView = ({ settings, ui, design, Design }) => { const [link, setLink] = useState(false) const [format, setFormat] = useState(false) - const { startLoading, stopLoading } = useContext(LoadingContext) - const toast = useToast() + const { setLoadingStatus } = useContext(LoadingStatusContext) + + const startLoading = () => setLoadingStatus([true, 'exporting']) + const stopLoading = () => setLoadingStatus([true, 'status:nailedIt', true, true]) const { t } = useTranslation(ns) const doExport = (format) => { @@ -38,7 +43,7 @@ export const ExportView = ({ settings, ui, design, Design }) => { } }, onError: (e) => { - if (e.data?.error) toast.error(e.data.error.message) + if (e.data?.error) setLoadingStatus([true, e.data.error.message, true, false]) }, }) } diff --git a/sites/shared/components/workbench/views/measies/index.mjs b/sites/shared/components/workbench/views/measies/index.mjs index b47856db1ef..1398d29728b 100644 --- a/sites/shared/components/workbench/views/measies/index.mjs +++ b/sites/shared/components/workbench/views/measies/index.mjs @@ -5,7 +5,8 @@ import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { designMeasurements, horFlexClasses } from 'shared/utils.mjs' // Hooks 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 import { 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 }) => { const { t } = useTranslation(['workbench']) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) const loadMeasurements = (set) => { update.settings([ @@ -37,7 +38,6 @@ export const MeasiesView = ({ design, Design, settings, update, missingMeasureme return (
-

{t('account:measurements')}

{missingMeasurements && settings.measurements && diff --git a/sites/shared/components/workbench/views/print/index.mjs b/sites/shared/components/workbench/views/print/index.mjs index 4706c7a7a00..c0dbc925ea1 100644 --- a/sites/shared/components/workbench/views/print/index.mjs +++ b/sites/shared/components/workbench/views/print/index.mjs @@ -1,18 +1,21 @@ -import { useContext } from 'react' -import { useTranslation } from 'next-i18next' -import { pagesPlugin } from 'shared/plugins/plugin-layout-part.mjs' +// Dependencies +import { nsMerge } from 'shared/utils.mjs' import { handleExport, ns as exportNs, } 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 { 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 { 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 { nsMerge } from 'shared/utils.mjs' export const ns = nsMerge(menuNs, wrapperNs, exportNs, 'print', 'status') @@ -30,8 +33,7 @@ export const PrintView = ({ Design, }) => { const { t } = useTranslation(ns) - const loading = useContext(LoadingContext) - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { loading, setLoadingStatus } = useContext(LoadingStatusContext) const defaultSettings = defaultPrintSettings(settings.units) // add the pages plugin to the draft @@ -74,7 +76,6 @@ export const PrintView = ({ return ( <> - { const { t } = useTranslation(ns) const backend = useBackend() const router = useRouter() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // State const [name, setName] = useState(`${capitalize(design)} / ${shortDate(router.locale)}`) @@ -80,7 +81,6 @@ export const SaveView = ({ design, settings }) => { return ( -

{t('workbench:savePattern')}

{savedId && ( diff --git a/sites/shared/components/workbench/views/view-header.mjs b/sites/shared/components/workbench/views/view-header.mjs index 3213a4c539b..68be0136588 100644 --- a/sites/shared/components/workbench/views/view-header.mjs +++ b/sites/shared/components/workbench/views/view-header.mjs @@ -1,8 +1,14 @@ +// Dependencies +import { capitalize, shortDate } from 'shared/utils.mjs' +// Hooks 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 { useTranslation } from 'next-i18next' 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 { PaperlessIcon, SaIcon, @@ -17,8 +23,6 @@ import { ZoomOutIcon, } from 'shared/components/icons.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'] @@ -73,7 +77,7 @@ export const ViewHeader = ({ update, settings, ui, control, account, design, set const { t, i18n } = useTranslation(ns) const { zoomFunctions, zoomed } = useContext(PanZoomContext) const backend = useBackend() - const { setLoadingStatus, LoadingStatus } = useLoadingStatus() + const { setLoadingStatus } = useContext(LoadingStatusContext) // make the zoom buttons so we can pass them to the mobile menubar const headerZoomButtons = useMemo( @@ -127,7 +131,6 @@ export const ViewHeader = ({ update, settings, ui, control, account, design, set 'lg:top-24' )} transition-[top] duration-300 ease-in-out`} > -
{headerZoomButtons} diff --git a/sites/shared/components/wrappers/context.mjs b/sites/shared/components/wrappers/context.mjs index 3cc0e896247..7afd9a0fae3 100644 --- a/sites/shared/components/wrappers/context.mjs +++ b/sites/shared/components/wrappers/context.mjs @@ -1,14 +1,14 @@ 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 { MobileMenubarContextProvider } from 'shared/context/mobile-menubar-context.mjs' export const ContextWrapper = ({ children }) => ( - + {children} - + ) diff --git a/sites/shared/components/wrappers/header.mjs b/sites/shared/components/wrappers/header.mjs index 2068cb90a69..e3de2673b65 100644 --- a/sites/shared/components/wrappers/header.mjs +++ b/sites/shared/components/wrappers/header.mjs @@ -1,10 +1,11 @@ +// Context +import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useContext } from 'react' -import { LoadingContext } from 'shared/context/loading-context.mjs' import { Ribbon } from 'shared/components/ribbon.mjs' export const HeaderWrapper = ({ show, children }) => { - const { loading } = useContext(LoadingContext) + const { loading } = useContext(LoadingStatusContext) return (
{ @@ -32,6 +34,7 @@ export const PageWrapper = (props) => { * Contexts */ const { modalContent } = useContext(ModalContext) + const { LoadingStatus } = useContext(LoadingStatusContext) /* * 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 key={currentTheme} // This forces the data-theme update > + {Layout ? {children} : children} diff --git a/sites/shared/context/loading-context.mjs b/sites/shared/context/loading-context.mjs deleted file mode 100644 index 48484cc264f..00000000000 --- a/sites/shared/context/loading-context.mjs +++ /dev/null @@ -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 {children} -} diff --git a/sites/shared/hooks/use-loading-status.mjs b/sites/shared/context/loading-status-context.mjs similarity index 72% rename from sites/shared/hooks/use-loading-status.mjs rename to sites/shared/context/loading-status-context.mjs index 91338e29ce9..f5287317f7d 100644 --- a/sites/shared/hooks/use-loading-status.mjs +++ b/sites/shared/context/loading-status-context.mjs @@ -1,10 +1,12 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, createContext } from 'react' import { Spinner } from 'shared/components/spinner.mjs' import { OkIcon, WarningIcon } from 'shared/components/icons.mjs' import { useTranslation } from 'next-i18next' export const ns = ['status'] +export const LoadingStatusContext = createContext([false]) + /* * Timeout in seconds before the loading status dissapears */ @@ -20,12 +22,9 @@ const LoadingStatus = ({ loadingStatus }) => { if (loadingStatus[2]) { if (timer) clearTimeout(timer) setTimer( - window.setTimeout( - () => { - setFade('opacity-0') - }, - timeout * 1000 - 350 - ) + window.setTimeout(() => { + setFade('opacity-0') + }, timeout * 1000 - 350) ) } }, [loadingStatus[2]]) @@ -66,7 +65,7 @@ const LoadingProgress = ({ val = 0, max = 1, msg }) => (
) -export const useLoadingStatus = () => { +export const LoadingStatusContextProvider = ({ children }) => { /* * LoadingStatus should hold an array with 1 to 4 elements: * 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 * 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 [__loadingStatus, __setLoadingStatus] = useState({ + status: [false], + setLoadingStatus, + loading: false, + LoadingStatus: () => , + LoadingProgress, + }) + useEffect(() => { - if (loadingStatus[2]) { + if (__loadingStatus.status[2]) { if (timer) clearTimeout(timer) setTimer( window.setTimeout(() => { @@ -86,12 +92,20 @@ export const useLoadingStatus = () => { }, timeout * 1000) ) } - }, [loadingStatus[2]]) + }, [__loadingStatus.status[2]]) - return { - setLoadingStatus, - loading: loadingStatus[0], - LoadingStatus: () => , - LoadingProgress, + function setLoadingStatus(newStatus) { + __setLoadingStatus({ + ...__loadingStatus, + status: newStatus, + loading: newStatus[0] || false, + LoadingStatus: () => , + }) } + + return ( + + {children} + + ) } diff --git a/sites/shared/hooks/use-toast.mjs b/sites/shared/hooks/use-toast.mjs deleted file mode 100644 index 6416666b0c9..00000000000 --- a/sites/shared/hooks/use-toast.mjs +++ /dev/null @@ -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: , - error: , - info: , - warning: , - accent: , -} - -const Toast = ({ type = 'info', children }) => ( -
-
- {icons[type]} -
{children}
-
-
-) - -/* Custom toast methods */ -const toastMethods = (t) => ({ - info: (children) => toastMethod.custom({children}), - warning: (children) => toastMethod.custom({children}), - error: (children) => toastMethod.custom({children}), - accent: (children) => toastMethod.custom({children}), - success: (children) => toastMethod.custom({children}), - for: { - settingsSaved: () => - toastMethod.custom( - - {t('settingsSaved')} - - ), - backendError: () => - toastMethod.custom( - - {t('backendError')} ¯\_(ツ)_/¯ - - ), - }, -}) - -/* - * The toast hook - */ -export function useToast() { - const { t } = useTranslation(['toast']) - - return toastMethods(t) -} diff --git a/sites/shared/i18n/docs/en.yaml b/sites/shared/i18n/docs/en.yaml index 54683466d99..ddbf399de38 100644 --- a/sites/shared/i18n/docs/en.yaml +++ b/sites/shared/i18n/docs/en.yaml @@ -22,3 +22,4 @@ toc: Table of contents credits: Credits contentsBy: Contents by translators: Translators +title: Title