diff --git a/sites/org/components/github/create-showcase.mjs b/sites/org/components/github/create-showcase.mjs index 0d39955ba2e..4f6b33391b6 100644 --- a/sites/org/components/github/create-showcase.mjs +++ b/sites/org/components/github/create-showcase.mjs @@ -23,6 +23,7 @@ import { Tab } from 'shared/components/account/bio.mjs' import { CodeBox } from 'shared/components/code-box.mjs' import { PostArticle, ns as mdxNs } from 'site/components/mdx/posts/article.mjs' import { PageLink } from 'shared/components/page-link.mjs' +import { OkIcon, WarningIcon as KoIcon } from 'shared/components/icons.mjs' export const ns = nsMerge('account', 'posts', authNs, mdxNs) @@ -40,16 +41,16 @@ const Item = ({ title, children }) => ( ) -const dataAsMd = ({ title, maker, caption, intro, designs }) => `--- -title: "${data.title}" -maker: ${data.maker} -caption: "${data.caption}" -date: ${yyymmvv()} -intro: "${data.intro}" +const dataAsMd = ({ title, maker, caption, intro, designs, body }) => `--- +title: "${title}" +maker: ${maker} +caption: "${caption}" +date: ${yyyymmdd()} +intro: "${intro}" designs: [${designs.map((design) => `"${design}"`).join(', ')}] --- -${data.body} +${body} ` @@ -96,7 +97,6 @@ export const CreateShowcasePost = ({ noTitle = false }) => { } const setExtraImg = (key, img) => { - console.log('setting extra', { key, img }) const newImages = { ...extraImages } newImages[key] = img setExtraImages(newImages) @@ -161,10 +161,11 @@ export const CreateShowcasePost = ({ noTitle = false }) => { - {!account.github && ( + {!account.data?.githubUser && !account.data?.githubEmail && (
Optional: Are you on GitHub? @@ -225,10 +226,19 @@ const ShowcaseEditor = ({ {t('showcaseNewInfo')} - Designs:{' '} - {designs.map((d) => capitalize(d)).join(', ')} - +
+ {designs.length > 0 ? ( + + ) : ( + + )} + Design: + {designs.length > 0 ? ( + {designs.map((d) => capitalize(d)).join(', ')} + ) : ( + Please select at least 1 design + )} +
} > Pick one or more designs that are featured in this post. @@ -236,9 +246,19 @@ const ShowcaseEditor = ({
- Title: {title} - +
+ {title.length > 10 ? ( + + ) : ( + + )} + Title: + {title.length > 10 ? ( + {title} + ) : ( + Please enter a post title + )} +
} > Give your post a title. A good title is more than just a few words. @@ -246,9 +266,19 @@ const ShowcaseEditor = ({
- Slug: {slug} - +
+ {slug.length > 3 ? ( + + ) : ( + + )} + Slug: + {slug.length > 3 ? ( + {slug} + ) : ( + Please enter a slug (or post title) + )} +
} > @@ -259,9 +289,19 @@ const ShowcaseEditor = ({
- Main Image: {img} - +
+ {img.length > 3 ? ( + + ) : ( + + )} + Main Image: + {img.length > 3 ? ( + {img} + ) : ( + Please provide a main image for the post + )} +
} > @@ -272,9 +312,21 @@ const ShowcaseEditor = ({
- Main Image Caption: {caption} - +
+ {caption.length > 3 ? ( + + ) : ( + + )} + Main Image Caption: + {caption.length > 3 ? ( + {caption} + ) : ( + + Please provide a caption for the main image + + )} +
} > @@ -285,9 +337,19 @@ const ShowcaseEditor = ({
- Intro: {intro} - +
+ {intro.length > 3 ? ( + + ) : ( + + )} + Intro: + {intro.length > 3 ? ( + {intro} + ) : ( + Please provide an intro for link proviews + )} +
} > A brief paragraph that will be shown on post previews on social media and so on. @@ -322,6 +384,14 @@ const ShowcaseEditor = ({ <>

To include this image in your post, use this markdown snippet:

+

+ +

)} @@ -339,9 +409,19 @@ const ShowcaseEditor = ({
- Post body: {body.slice(0, 30) + '...'} - +
+ {body.length > 3 ? ( + + ) : ( + + )} + Post body: + {body.length > 3 ? ( + {body.slice(0, 30) + '...'} + ) : ( + Please provide a post body + )} +
} > The actual post body. Supports Markdown. diff --git a/sites/org/pages/account/index.mjs b/sites/org/pages/account/index.mjs index 294f3a1b973..5634f609957 100644 --- a/sites/org/pages/account/index.mjs +++ b/sites/org/pages/account/index.mjs @@ -1,6 +1,8 @@ // Dependencies import dynamic from 'next/dynamic' import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +// Hooks +import { useTranslation } from 'next-i18next' // Components import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { ns as authNs } from 'shared/components/wrappers/auth/index.mjs' @@ -22,13 +24,17 @@ const DynamicAccountOverview = dynamic( { ssr: false } ) -const AccountIndexPage = ({ page }) => ( - - - - - -) +const AccountIndexPage = ({ page }) => { + const { t } = useTranslation(ns) + + return ( + + + + + + ) +} export default AccountIndexPage diff --git a/sites/shared/components/account/en.yaml b/sites/shared/components/account/en.yaml index 20d7d886303..c158265df9b 100644 --- a/sites/shared/components/account/en.yaml +++ b/sites/shared/components/account/en.yaml @@ -20,7 +20,6 @@ signOut: Sign Out politeOhCrap: Oh fiddlesticks bio: Bio email: E-mail Address -github: Github Username img: Profile image username: Username compare: Metricset Comparison @@ -128,7 +127,12 @@ emailChangeConfirmation: We have sent an E-mail to your new address to confirm t vagueError: Something went wrong, and we're not certain how to handle it. Please try again, or involve a human being for assistance. # github -githubTitle: Enter your github username here to receive updates when you report a problem through this website. +githubTitle: Link your GitHub identity +githubWhy1: Enter your GitHub username and email here and we will use them when interacting with GitHub on your behalf. +githubWhy2: Note that both your GitHub username and email is public info. This merely allows us to make a link between your FreeSewing account and GitHub account. +githubWhy3 : For example, when you report a problem on this website, we can mention you so you will receive notifications when there is an update. For this, your username is sufficient. +githubWhy4: When you submit a showcase post or make changed to our content, we can credit those commits to you if we have both your username and the email address you use on GitHub. +tooComplex: If all of this in confusing, you don't have to provide this info. It's an advanced feature. # languge languageTitle: Which language do you prefer? diff --git a/sites/shared/components/account/github.mjs b/sites/shared/components/account/github.mjs index 6cf0c764d16..c57360a77e9 100644 --- a/sites/shared/components/account/github.mjs +++ b/sites/shared/components/account/github.mjs @@ -10,6 +10,7 @@ import { LoadingContext } from 'shared/context/loading-context.mjs' // Components import { BackToAccountButton } from './shared.mjs' import { SaveSettingsButton } from 'shared/components/buttons/save-settings-button.mjs' +import { Popout } from 'shared/components/popout/index.mjs' export const ns = ['account', 'toast'] @@ -24,12 +25,13 @@ export const GithubSettings = ({ title = false, welcome = false }) => { const toast = useToast() // State - const [github, setGithub] = useState(account.github || '') + const [githubUsername, setGithubUsername] = useState(account.data.githubUsername || '') + const [githubEmail, setGithubEmail] = useState(account.data.githubEmail || '') // Helper method to save changes const save = async () => { startLoading() - const result = await backend.updateAccount({ github }) + const result = await backend.updateAccount({ data: { githubUsername, githubEmail } }) if (result.success) { setAccount(result.data.account) toast.for.settingsSaved() @@ -40,17 +42,35 @@ export const GithubSettings = ({ title = false, welcome = false }) => { return (
{title ?

{t('githubTitle')}

: null} -
+ +
setGithub(evt.target.value)} + value={githubUsername} + onChange={(evt) => setGithubUsername(evt.target.value)} className="input w-full input-bordered flex flex-row" type="text" - placeholder={t('github')} + placeholder={account.username} + /> +
+ +
+ setGithubEmail(evt.target.value)} + className="input w-full input-bordered flex flex-row" + type="text" + placeholder={`${account.username}@users.freesewing.org`} />
{!welcome && } + +

{t('githubWhy1')}

+

{t('githubWhy2')}

+

{t('githubWhy3')}

+

{t('githubWhy4')}

+

{t('tooComplex')}

+
) } diff --git a/sites/shared/components/wrappers/auth/index.mjs b/sites/shared/components/wrappers/auth/index.mjs index 323ad9b83dd..7f10339913d 100644 --- a/sites/shared/components/wrappers/auth/index.mjs +++ b/sites/shared/components/wrappers/auth/index.mjs @@ -104,7 +104,7 @@ const ConsentLacking = ({ t, banner }) => ( export const AuthWrapper = ({ children, app, requiredRole = 'user' }) => { const { t } = useTranslation(ns) - const { account, token, admin, stopImpersonating } = useAccount() + const { account, token, admin, stopImpersonating, signOut } = useAccount() const backend = useBackend() const [ready, setReady] = useState(false) @@ -123,9 +123,15 @@ export const AuthWrapper = ({ children, app, requiredRole = 'user' }) => { }) } } + const verifyUser = async () => { + const result = await backend.ping() + if (result.success) { + } else signOut() + } if (admin && admin.token) verifyAdmin() + if (token) verifyUser() setReady(true) - }, [admin]) + }, [admin, token]) if (!ready) return diff --git a/sites/shared/hooks/use-account-reload.mjs b/sites/shared/hooks/use-account-reload.mjs deleted file mode 100644 index 59c4c28dfb5..00000000000 --- a/sites/shared/hooks/use-account-reload.mjs +++ /dev/null @@ -1,17 +0,0 @@ -// Hooks -import { useAccount } from 'shared/hooks/use-account.mjs' -import { useBackend } from 'shared/hooks/use-backend.mjs' - -export const useAccountReload = () => { - // Hooks - const { setAccount, token } = useAccount() - const backend = useBackend(token) - - // Helper method to reload account - const reload = async () => { - const result = await backend.reloadAccount() - if (result.success) setAccount(result.data.account) - } - - return reload -} diff --git a/sites/shared/hooks/use-backend.mjs b/sites/shared/hooks/use-backend.mjs index f1a0f998370..07af1cb8ee3 100644 --- a/sites/shared/hooks/use-backend.mjs +++ b/sites/shared/hooks/use-backend.mjs @@ -302,7 +302,7 @@ Backend.prototype.createIssue = async function (data) { * Create showcase Pull Request */ Backend.prototype.createShowcasePr = async function (data) { - return responseHandler(await api.post(`/flows/pr/showcase`, data, this.auth)) + return responseHandler(await api.post(`/flows/pr/showcase/jwt`, data, this.auth)) } /* * Send translation invite @@ -346,6 +346,13 @@ Backend.prototype.removeImage = async function (id) { return responseHandler(await api.delete(`/images/${id}/jwt`, this.auth)) } +/* + * Ping backend to see if current token is still valid + */ +Backend.prototype.ping = async function () { + return responseHandler(await api.get(`/whoami/jwt`, this.auth)) +} + /* * Search user (admin method) */