✨ Able to set product icon and previews
This commit is contained in:
parent
7e0dff9f0f
commit
45c871cb06
@ -1,6 +1,6 @@
|
|||||||
import { Collapse, Alert, TextField, Button, Box } from '@mui/material'
|
import { Collapse, Alert, TextField, Button, Box } from '@mui/material'
|
||||||
import { useRouter } from 'next-nprogress-bar'
|
import { useRouter } from 'next-nprogress-bar'
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useForm } from 'react-hook-form'
|
import { useForm } from 'react-hook-form'
|
||||||
import { MaProduct } from 'solar-js-sdk'
|
import { MaProduct } from 'solar-js-sdk'
|
||||||
|
|
||||||
@ -11,6 +11,9 @@ export interface MatrixProductForm {
|
|||||||
alias: string
|
alias: string
|
||||||
description: string
|
description: string
|
||||||
introduction: string
|
introduction: string
|
||||||
|
icon: string
|
||||||
|
previews: string[]
|
||||||
|
tags: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MaProductForm({
|
export default function MaProductForm({
|
||||||
@ -28,11 +31,24 @@ export default function MaProductForm({
|
|||||||
alias: defaultValue?.alias ?? '',
|
alias: defaultValue?.alias ?? '',
|
||||||
description: defaultValue?.description ?? '',
|
description: defaultValue?.description ?? '',
|
||||||
introduction: defaultValue?.meta?.introduction ?? '',
|
introduction: defaultValue?.meta?.introduction ?? '',
|
||||||
|
icon: defaultValue?.icon ?? '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const [previews, setPreviews] = useState<string[]>([])
|
||||||
|
const [tags, setTags] = useState<string[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (defaultValue?.previews) {
|
||||||
|
setPreviews(defaultValue.previews)
|
||||||
|
}
|
||||||
|
if (defaultValue?.tags) {
|
||||||
|
setTags(defaultValue.tags)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [busy, setBusy] = useState<boolean>(false)
|
const [busy, setBusy] = useState<boolean>(false)
|
||||||
|
|
||||||
@ -47,7 +63,11 @@ export default function MaProductForm({
|
|||||||
async function submit(data: MatrixProductForm) {
|
async function submit(data: MatrixProductForm) {
|
||||||
try {
|
try {
|
||||||
setBusy(true)
|
setBusy(true)
|
||||||
await onSubmit(data)
|
await onSubmit({
|
||||||
|
...data,
|
||||||
|
previews,
|
||||||
|
tags,
|
||||||
|
})
|
||||||
callback()
|
callback()
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setError(err.toString())
|
setError(err.toString())
|
||||||
@ -65,10 +85,26 @@ export default function MaProductForm({
|
|||||||
</Alert>
|
</Alert>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
|
||||||
|
<TextField label="Icon" placeholder="Image URL or Attachment RID" {...register('icon')} />
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Previews"
|
||||||
|
placeholder="Comma separated, Image URL or Attachment RID, the first one will be used as the banner"
|
||||||
|
value={previews.join(',')}
|
||||||
|
onChange={(val) => setPreviews(val.target.value.split(',').map((v) => v.trim()))}
|
||||||
|
/>
|
||||||
|
|
||||||
<TextField label="Name" {...register('name')} />
|
<TextField label="Name" {...register('name')} />
|
||||||
|
|
||||||
<TextField label="Alias" {...register('alias')} />
|
<TextField label="Alias" {...register('alias')} />
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
label="Tags"
|
||||||
|
placeholder="Comma separated"
|
||||||
|
value={tags.join(',')}
|
||||||
|
onChange={(val) => setTags(val.target.value.split(',').map((v) => v.trim()))}
|
||||||
|
/>
|
||||||
|
|
||||||
<TextField minRows={3} maxRows={3} multiline label="Description" {...register('description')} />
|
<TextField minRows={3} maxRows={3} multiline label="Description" {...register('description')} />
|
||||||
|
|
||||||
<TextField minRows={5} multiline label="Introduction" {...register('introduction')} />
|
<TextField minRows={5} multiline label="Introduction" {...register('introduction')} />
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { ConsoleLayout, getConsoleStaticProps } from '@/components/layouts/ConsoleLayout'
|
import { ConsoleLayout, getConsoleStaticProps } from '@/components/layouts/ConsoleLayout'
|
||||||
import { Box, Button, Container, Typography, Grid2 as Grid, Card, CardContent, CardActions } from '@mui/material'
|
import { Box, Button, Container, Typography, Grid2 as Grid, Card, CardContent, CardActions } from '@mui/material'
|
||||||
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||||
import { sni, MaProduct, MaRelease } from 'solar-js-sdk'
|
import { sni, MaProduct, MaRelease, getAttachmentUrl } from 'solar-js-sdk'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import NextLink from 'next/link'
|
import NextLink from 'next/link'
|
||||||
|
import Image from 'next/image'
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = (async (context) => {
|
export const getServerSideProps: GetServerSideProps = (async (context) => {
|
||||||
const id = context.params!.id
|
const id = context.params!.id
|
||||||
@ -45,52 +46,63 @@ export default function ProductDetails({ product }: InferGetServerSidePropsType<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ConsoleLayout>
|
<ConsoleLayout>
|
||||||
<Container sx={{ py: 16, display: 'flex', flexDirection: 'column', gap: 8 }}>
|
<>
|
||||||
<Box maxWidth="sm">
|
{product.previews && (
|
||||||
<Typography variant="h3" component="h1">
|
<img
|
||||||
{product.name}
|
src={getAttachmentUrl(product.previews[0])}
|
||||||
</Typography>
|
alt={product.name}
|
||||||
<Typography variant="subtitle1">{product.description}</Typography>
|
style={{ objectFit: 'cover', aspectRatio: 16 / 5 }}
|
||||||
</Box>
|
className='border-b border-1'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<Box display="flex" flexDirection="column" gap={2}>
|
<Container sx={{ pt: (product.previews ? 8 : 16), pb: 16, display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
<Typography variant="h4" component="h2">
|
<Box maxWidth="sm">
|
||||||
Releases
|
<Typography variant="h3" component="h1">
|
||||||
</Typography>
|
{product.name}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="subtitle1">{product.description}</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<NextLink passHref href={`/console/matrix/products/${product.id}/releases/new`}>
|
<Box display="flex" flexDirection="column" gap={2}>
|
||||||
<Button variant="contained">Create a release</Button>
|
<Typography variant="h4" component="h2">
|
||||||
</NextLink>
|
Releases
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<Grid container columns={{ xs: 1, sm: 2, md: 3 }} spacing={2}>
|
<NextLink passHref href={`/console/matrix/products/${product.id}/releases/new`}>
|
||||||
{releases.map((r: any) => (
|
<Button variant="contained">Create a release</Button>
|
||||||
<Grid size={1} key={r.id}>
|
</NextLink>
|
||||||
<Card>
|
|
||||||
<CardContent>
|
|
||||||
<Typography variant="caption">{r.version}</Typography>
|
|
||||||
<Typography variant="h5" component="h2">
|
|
||||||
{r.meta.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body1" gutterBottom>
|
|
||||||
{r.type == 0 ? 'Full Release' : 'Patch Release'}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Typography variant="body1">{r.meta.description}</Typography>
|
<Grid container columns={{ xs: 1, sm: 2, md: 3 }} spacing={2}>
|
||||||
</CardContent>
|
{releases.map((r: any) => (
|
||||||
<CardActions>
|
<Grid size={1} key={r.id}>
|
||||||
<NextLink passHref href={`/console/matrix/products/${r.productId}/releases/${r.id}/edit`}>
|
<Card>
|
||||||
<Button size="small">Edit</Button>
|
<CardContent>
|
||||||
</NextLink>
|
<Typography variant="caption">{r.version}</Typography>
|
||||||
<Button size="small" color="error" onClick={() => deleteRelease(r.id)}>
|
<Typography variant="h5" component="h2">
|
||||||
Delete
|
{r.meta.title}
|
||||||
</Button>
|
</Typography>
|
||||||
</CardActions>
|
<Typography variant="body1" gutterBottom>
|
||||||
</Card>
|
{r.type == 0 ? 'Full Release' : 'Patch Release'}
|
||||||
</Grid>
|
</Typography>
|
||||||
))}
|
|
||||||
</Grid>
|
<Typography variant="body1">{r.meta.description}</Typography>
|
||||||
</Box>
|
</CardContent>
|
||||||
</Container>
|
<CardActions>
|
||||||
|
<NextLink passHref href={`/console/matrix/products/${r.productId}/releases/${r.id}/edit`}>
|
||||||
|
<Button size="small">Edit</Button>
|
||||||
|
</NextLink>
|
||||||
|
<Button size="small" color="error" onClick={() => deleteRelease(r.id)}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</CardActions>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
</ConsoleLayout>
|
</ConsoleLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user