Skip to content

Commit

Permalink
displaying artwork asset images via strategy after dialog opens
Browse files Browse the repository at this point in the history
  • Loading branch information
goodeats committed Jun 13, 2024
1 parent ac5b4d1 commit ba595e7
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 138 deletions.
157 changes: 56 additions & 101 deletions app/components/templates/form/fetcher-image-select.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { useForm, conform } from '@conform-to/react'
import { conform, useForm } from '@conform-to/react'
import { getFieldsetConstraint } from '@conform-to/zod'
import { type FetcherWithComponents } from '@remix-run/react'
import { useEffect, useState } from 'react'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { type z } from 'zod'
import { ErrorList, Field, TextareaField } from '#app/components/forms'
import {
ImagePreview,
ImagePreviewContainer,
ImagePreviewLabel,
ImagePreviewSkeleton,
ImagePreviewWrapper,
ImageUploadInput,
noImagePreviewClassName,
} from '#app/components/image'
import { FlexColumn } from '#app/components/layout'
import {
Expand All @@ -28,11 +25,13 @@ import {
DialogTitle,
DialogTrigger,
} from '#app/components/ui/dialog'
import { Icon, type IconName } from '#app/components/ui/icon'
import { type IconName } from '#app/components/ui/icon'
import { Label } from '#app/components/ui/label'
import { PanelIconButton } from '#app/components/ui/panel-icon-button'
import { StatusButton } from '#app/components/ui/status-button'
import { type IAssetParent } from '#app/models/asset/asset.server'
import { type IAssetImage } from '#app/models/asset/image/image.server'
import { type IAssetImageSrcStrategy } from '#app/strategies/asset.image.src.strategy'
import { useIsPending } from '#app/utils/misc'
import { TooltipHydrated } from '../tooltip'

Expand All @@ -41,8 +40,9 @@ export const FetcherImageSelect = ({
route,
schema,
formId,
image,
imgSrc,
images,
parent,
strategy,
icon,
iconText,
tooltipText,
Expand All @@ -55,8 +55,9 @@ export const FetcherImageSelect = ({
route: string
schema: z.ZodSchema<any>
formId: string
image?: IAssetImage
imgSrc?: string
images: IAssetImage[]
parent: IAssetParent
strategy: IAssetImageSrcStrategy
icon: IconName
iconText: string
tooltipText: string
Expand All @@ -66,27 +67,22 @@ export const FetcherImageSelect = ({
children: JSX.Element
}) => {
const [open, setOpen] = useState(false)
const [name, setName] = useState(image?.name ?? '')
const [altText, setAltText] = useState(image?.attributes.altText ?? '')

const lastSubmission = fetcher.data?.submission
const isPending = useIsPending()
const [form, fields] = useForm({
id: formId,
constraint: getFieldsetConstraint(schema),
lastSubmission,
defaultValue: {
id: image?.id ?? '',
name,
description: image?.description ?? '',
altText,
onSubmit: async (event, { formData }) => {
event.preventDefault()
fetcher.submit(formData, {
method: 'POST',
action: route,
})
},
})

const [previewImage, setPreviewImage] = useState<string | null>(
imgSrc ?? null,
)

// close after successful submission
useEffect(() => {
if (fetcher.state === 'idle' && fetcher.data?.status === 'success') {
Expand Down Expand Up @@ -118,89 +114,48 @@ export const FetcherImageSelect = ({
{children}

<DialogFormsContainer>
<Label>Image</Label>
<FlexColumn>
<ImagePreviewContainer>
<ImagePreviewWrapper>
<ImagePreviewLabel
htmlFor={fields.file.id}
className={!previewImage ? noImagePreviewClassName : ''}
>
{previewImage ? (
<div className="relative">
<ImagePreview
src={previewImage}
alt={altText ?? ''}
/>
</div>
) : (
<ImagePreviewSkeleton>
<Icon name="plus" />
</ImagePreviewSkeleton>
)}
<ImageUploadInput
aria-label="Image"
onChange={(
event: React.ChangeEvent<HTMLInputElement>,
) => {
const file = event.target.files?.[0]
<Label>Images</Label>
{images.map(image => {
const { id, name, description, attributes } = image
const { altText } = attributes
const imgSrc = strategy.getAssetSrc({
parentId: parent.id,
assetId: id,
})

if (file) {
const reader = new FileReader()
reader.onloadend = () => {
setPreviewImage(reader.result as string)
}
reader.readAsDataURL(file)
setName(file.name)
} else {
setPreviewImage(null)
setName('')
}
}}
accept="image/*"
{...conform.input(fields.file, {
type: 'file',
ariaAttributes: true,
})}
/>
</ImagePreviewLabel>
</ImagePreviewWrapper>
<div className="min-h-[32px] px-4 pb-3 pt-1">
<ErrorList
id={fields.file.errorId}
errors={fields.file.errors}
return (
<FlexColumn key={image.id}>
<ImagePreviewContainer>
<ImagePreviewWrapper>
<ImagePreviewLabel htmlFor={fields.file.id}>
<div className="relative">
<ImagePreview
src={imgSrc}
alt={altText ?? 'No alt text'}
/>
</div>
</ImagePreviewLabel>
</ImagePreviewWrapper>
</ImagePreviewContainer>
<ImageUploadInput
className="hidden"
disabled={true}
aria-label="Image"
accept="image/*"
{...conform.input(fields.file, {
type: 'file',
ariaAttributes: true,
})}
/>
<input type="hidden" name="name" value={name} />
<input
type="hidden"
name="description"
value={description ?? ''}
/>
</div>
</ImagePreviewContainer>
<Field
labelProps={{ children: 'Name' }}
inputProps={{
autoFocus: true,
...conform.input(fields.name, { ariaAttributes: true }),
onChange: e => setName(e.currentTarget.value),
}}
errors={fields.name.errors}
/>
<TextareaField
labelProps={{ children: 'Description' }}
textareaProps={{
...conform.textarea(fields.description, {
ariaAttributes: true,
}),
}}
errors={fields.description.errors}
/>
<TextareaField
labelProps={{ children: 'Alt Text' }}
textareaProps={{
...conform.textarea(fields.altText, {
ariaAttributes: true,
}),
onChange: e => setAltText(e.currentTarget.value),
}}
errors={fields.altText.errors}
/>
</FlexColumn>
</FlexColumn>
)
})}
</DialogFormsContainer>
</fetcher.Form>
</DialogContentGrid>
Expand Down
8 changes: 8 additions & 0 deletions app/models/asset/asset.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { type Asset } from '@prisma/client'
import { type DateOrString } from '#app/definitions/prisma-helper'
import { type assetTypeEnum } from '#app/schema/asset'
import { type IArtworkWithAssets } from '../artwork/artwork.server'
import { type IArtworkVersionWithChildren } from '../artwork-version/artwork-version.server'
import { type ILayerWithChildren } from '../layer/layer.server'
import { type IUser } from '../user/user.server'
import {
type IAssetImage,
Expand Down Expand Up @@ -46,6 +49,11 @@ export interface IAssetsByTypeWithType {
assets: IAssetType[]
}

export type IAssetParent =
| IArtworkWithAssets
| IArtworkVersionWithChildren
| ILayerWithChildren

interface IAssetData {
name: string
description?: string
Expand Down
20 changes: 10 additions & 10 deletions app/models/asset/image/image.create.artwork-version.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type IntentActionArgs } from '#app/definitions/intent-action-args'
import { type IArtwork } from '#app/models/artwork/artwork.server'
import { NewAssetImageArtworkSchema } from '#app/schema/asset/image.artwork'
import { type IArtworkVersion } from '#app/models/artwork-version/artwork-version.server'
import { NewAssetImageArtworkVersionSchema } from '#app/schema/asset/image.artwork-version'
import { ValidateArtworkVersionParentSubmissionStrategy } from '#app/strategies/validate-submission.strategy'
import { validateEntityImageSubmission } from '#app/utils/conform-utils'
import { prisma } from '#app/utils/db.server'
Expand All @@ -10,7 +10,7 @@ import {
} from './image.create.server'
import { stringifyAssetImageAttributes } from './utils'

export const validateNewAssetImageArtworkSubmission = async ({
export const validateNewAssetImageArtworkVersionSubmission = async ({
userId,
formData,
}: IntentActionArgs) => {
Expand All @@ -19,24 +19,24 @@ export const validateNewAssetImageArtworkSubmission = async ({
return await validateEntityImageSubmission({
userId,
formData,
schema: NewAssetImageArtworkSchema,
schema: NewAssetImageArtworkVersionSchema,
strategy,
})
}

export interface IAssetImageArtworkCreateSubmission
export interface IAssetImageArtworkVersionCreateSubmission
extends IAssetImageCreateSubmission {
artworkId: IArtwork['id']
artworkVersionId: IArtworkVersion['id']
}

interface IAssetImageArtworkCreateData extends IAssetImageCreateData {
artworkId: IArtwork['id']
interface IAssetImageArtworkVersionCreateData extends IAssetImageCreateData {
artworkVersionId: IArtworkVersion['id']
}

export const createAssetImageArtwork = ({
export const createAssetImageArtworkVersion = ({
data,
}: {
data: IAssetImageArtworkCreateData
data: IAssetImageArtworkVersionCreateData
}) => {
const { attributes, ...rest } = data
const jsonAttributes = stringifyAssetImageAttributes(attributes)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { DashboardEntityPanel } from '#app/components/templates/panel/dashboard-entity-panel'
import { type IAssetsByTypeWithType } from '#app/models/asset/asset.server'
import { type AssetParentType } from '#app/schema/asset'
import {
type IAssetParent,
type IAssetsByTypeWithType,
} from '#app/models/asset/asset.server'
import { type IDashboardPanelCreateEntityStrategy } from '#app/strategies/component/dashboard-panel/create-entity.strategy'
import { type IDashboardPanelEntityActionStrategy } from '#app/strategies/component/dashboard-panel/entity-action/entity-action'
import { type IDashboardPanelUpdateEntityOrderStrategy } from '#app/strategies/component/dashboard-panel/update-entity-order.strategy'
Expand All @@ -12,7 +14,7 @@ export const PanelAssets = ({
strategyReorder,
strategyActions,
}: {
parent: AssetParentType
parent: IAssetParent
strategyEntityNew: IDashboardPanelCreateEntityStrategy
strategyReorder: IDashboardPanelUpdateEntityOrderStrategy
strategyActions: IDashboardPanelEntityActionStrategy
Expand Down Expand Up @@ -49,7 +51,7 @@ export const PanelAsset = ({
strategyReorder,
strategyActions,
}: {
parent: AssetParentType
parent: IAssetParent
assetTypePanel: IAssetsByTypeWithType
strategyEntityNew: IDashboardPanelCreateEntityStrategy
strategyReorder: IDashboardPanelUpdateEntityOrderStrategy
Expand Down
Loading

0 comments on commit ba595e7

Please sign in to comment.