From dba3c3731a306c105eb709b824cb1013d8c3edcb Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Fri, 20 Oct 2023 10:43:43 +0200 Subject: [PATCH] feat(org): Admin updates for curated sets --- .gitignore | 1 + sites/org/pages/admin/cset/[id].mjs | 46 +++++++++++++++++++++ sites/org/pages/admin/cset/index.mjs | 38 ++++++++++++++++++ sites/org/pages/admin/index.mjs | 5 +++ sites/shared/components/curated-sets.mjs | 51 ++++++++++++++++++------ sites/shared/components/inputs.mjs | 33 +++++++++++++++ sites/shared/i18n/sections/en.yaml | 1 + sites/shared/prebuild/sitenav-org.mjs | 13 ++++++ 8 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 sites/org/pages/admin/cset/[id].mjs create mode 100644 sites/org/pages/admin/cset/index.mjs diff --git a/.gitignore b/.gitignore index a77a2b2d193..64bbf3c3f3b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # See https://help.github.com/ignore-files/ for more about ignoring files. dump +production.sqlite # .env .env diff --git a/sites/org/pages/admin/cset/[id].mjs b/sites/org/pages/admin/cset/[id].mjs new file mode 100644 index 00000000000..880dce8d9d5 --- /dev/null +++ b/sites/org/pages/admin/cset/[id].mjs @@ -0,0 +1,46 @@ +import { nsMerge } from 'shared/utils.mjs' +// Dependencies +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 { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs' +import { EditCuratedSet, ns as csetNs } from 'shared/components/curated-sets.mjs' + +// Translation namespaces used on this page +const ns = nsMerge(pageNs, authNs, csetNs, 'curate') + +const EditCuratedSetPage = ({ page, id }) => { + const { t } = useTranslation(ns) + + return ( + + + + + + ) +} + +export default EditCuratedSetPage + +export async function getStaticProps({ locale, params }) { + return { + props: { + ...(await serverSideTranslations(locale, ns)), + id: params.id, + page: { + locale, + path: ['curate', 'sets', params.id], + }, + }, + } +} + +export async function getStaticPaths() { + return { + paths: [], + fallback: true, + } +} diff --git a/sites/org/pages/admin/cset/index.mjs b/sites/org/pages/admin/cset/index.mjs new file mode 100644 index 00000000000..b76d4933ef2 --- /dev/null +++ b/sites/org/pages/admin/cset/index.mjs @@ -0,0 +1,38 @@ +// Dependencies +import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +import { nsMerge } from 'shared/utils.mjs' +// Hooks +import { useState } from 'react' +import { useTranslation } from 'next-i18next' +import { useBackend } from 'shared/hooks/use-backend.mjs' +// Components +import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' +import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs' +import { Loading } from 'shared/components/spinner.mjs' +import { Hits } from 'shared/components/admin.mjs' +import { CuratedSetsList } from 'shared/components/curated-sets.mjs' + +// Translation namespaces used on this page +const namespaces = nsMerge(pageNs, authNs) + +const AdminPage = ({ page }) => ( + + + `/admin/cset/${id}`} /> + + +) + +export default AdminPage + +export async function getStaticProps({ locale }) { + return { + props: { + ...(await serverSideTranslations(locale, namespaces)), + page: { + locale, + path: ['admin', 'cset'], + }, + }, + } +} diff --git a/sites/org/pages/admin/index.mjs b/sites/org/pages/admin/index.mjs index 64b2c7aa853..dcc1b1db3a1 100644 --- a/sites/org/pages/admin/index.mjs +++ b/sites/org/pages/admin/index.mjs @@ -10,6 +10,7 @@ import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { Loading } from 'shared/components/spinner.mjs' import { Hits } from 'shared/components/admin.mjs' +import { PageLink } from 'shared/components/link.mjs' // Translation namespaces used on this page const namespaces = nsMerge(pageNs, authNs) @@ -39,6 +40,10 @@ const AdminPage = ({ page }) => { return ( +

+ Other admin links: + +

Search users
( const props = { className: 'aspect-[1/3] w-auto h-96', style: { - backgroundImage: `url(${cloudflareImageUrl({ id: set.img, type: 'lineup' })})`, + backgroundImage: `url(${cloudflareImageUrl({ id: `cset-${set.id}`, type: 'lineup' })})`, width: 'auto', backgroundSize: 'contain', backgroundRepeat: 'no-repeat', @@ -118,7 +119,7 @@ const ShowCuratedSet = ({ cset }) => { onClick={() => setModal( - + ) } @@ -130,7 +131,10 @@ const ShowCuratedSet = ({ cset }) => {

{t('data')}

- {cset[`name${capitalize(lang)}`]} + + + + {cset.height}cm {control >= controlLevels.sets.notes && ( @@ -198,7 +202,7 @@ export const CuratedSet = ({ id }) => { export const CuratedSetPicker = (props) => // Component for the curated-sets page -export const CuratedSets = ({ href = false, clickHandler = false }) => { +export const CuratedSets = ({ href = false, clickHandler = false, published = true }) => { // Hooks const backend = useBackend() const { setLoadingStatus } = useContext(LoadingStatusContext) @@ -214,7 +218,9 @@ export const CuratedSets = ({ href = false, clickHandler = false }) => { const result = await backend.getCuratedSets() if (result.success) { const allSets = {} - for (const set of result.data.curatedSets) allSets[set.id] = set + for (const set of result.data.curatedSets) { + if (!published || set.published) allSets[set.id] = set + } setSets(allSets) setLoadingStatus([true, 'status:dataLoaded', true, true]) } else setLoadingStatus([true, 'status:backendError', true, false]) @@ -223,7 +229,7 @@ export const CuratedSets = ({ href = false, clickHandler = false }) => { }, []) const lineupProps = { - sets: Object.values(sets), + sets: orderBy(sets, 'height', 'asc'), } if (typeof href === 'function') lineupProps.href = href else lineupProps.onClick = clickHandler ? clickHandler : (set) => setSelected(set.id) @@ -236,7 +242,7 @@ export const CuratedSets = ({ href = false, clickHandler = false }) => { ) } -// Component for the maintaining the list of curated-sets +// Component for the maintaining the list of curated-sets export const CuratedSetsList = ({ href = false }) => { // Hooks const { t } = useTranslation(ns) @@ -328,6 +334,7 @@ export const CuratedSetsList = ({ href = false }) => { {t('curate:img')} {t('curate:name')} {t('curate:published')} + {t('curate:height')} {t('curate:createdAt')} @@ -342,15 +349,23 @@ export const CuratedSetsList = ({ href = false }) => { onClick={() => toggleSelect(set.id)} /> - {set.id} + + + - {set.nameEn} + + + {set.published ? : } + {set.height}cm {set.createdAt} ))} @@ -415,6 +430,7 @@ export const EditCuratedSet = ({ id }) => { k = `notes${capitalize(lang)}` if (data[k] !== cset[k]) changes[k] = data[k] } + if (data.height !== cset.height) changes.height = Number(data.height) if (data.img !== cset.img) changes.img = data.img if (data.published !== cset.published) changes.published = data.published for (const m in data.measies) { @@ -431,7 +447,7 @@ export const EditCuratedSet = ({ id }) => {
updateData('published', val)} list={[ { @@ -458,6 +474,17 @@ export const EditCuratedSet = ({ id }) => { current={data.published} /> + updateData('height', val)} + current={Number(data.height)} + valid={notEmpty} + /> +

{t('measies')}

) +/* + * Input for integers + */ +export const NumberInput = ({ + label, // Label to use + update, // onChange handler + valid, // Method that should return whether the value is valid or not + current, // The current value + original, // The original value + placeholder, // The placeholder text + docs = false, // Docs to load, if any + id = '', // An id to tie the input to the label + labelBL = false, // Bottom-Left label + labelBR = false, // Bottom-Right label + max = 0, + min = 220, + step = 1, +}) => ( + + update(evt.target.value)} + className={`input w-full input-bordered ${ + current === original ? 'input-secondary' : valid(current) ? 'input-success' : 'input-error' + }`} + {...{ max, min, step }} + /> + +) + /* * Input for strings */ diff --git a/sites/shared/i18n/sections/en.yaml b/sites/shared/i18n/sections/en.yaml index ec1bad767eb..631bd311640 100644 --- a/sites/shared/i18n/sections/en.yaml +++ b/sites/shared/i18n/sections/en.yaml @@ -28,6 +28,7 @@ sets: Your Measurements Sets patterns: Your Patterns curate: Curate curateSets: Curate Sets +curatedSets: Curated Measurements Sets code: Code patternsAbout: Lists the patterns that you have stored in your FreeSewing account setsAbout: Lists the measurements sets that you have stored in your FreeSewing account diff --git a/sites/shared/prebuild/sitenav-org.mjs b/sites/shared/prebuild/sitenav-org.mjs index e2f71b5cce4..b28d386057e 100644 --- a/sites/shared/prebuild/sitenav-org.mjs +++ b/sites/shared/prebuild/sitenav-org.mjs @@ -112,6 +112,11 @@ export const extendSiteNav = async (siteNav, lang) => { t: t('sections:admin'), _: 1, s: 'admin', + cset: { + t: 'Curated Measurement Sets', + s: 'admin/cset', + _: 1, + }, } // Add account @@ -161,6 +166,14 @@ export const extendSiteNav = async (siteNav, lang) => { t: t('yourProfile'), } + // Add curated measurements sets + siteNav['curated-sets'] = { + m: 1, + s: 'curated-sets', + t: t('sections:curatedSets'), + n: 1, + } + // Add translation siteNav.translation = { s: 'translation',