Skip to content

Commit

Permalink
fix bugs
Browse files Browse the repository at this point in the history
crop not rendering correctly and file not showing in edit form
  • Loading branch information
henrikskog committed May 8, 2024
1 parent f152b5e commit 71dc6cf
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 66 deletions.
6 changes: 4 additions & 2 deletions apps/dashboard/src/app/(dashboard)/offline/write-form.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { ImageVariantSchema, OfflineWriteSchema } from "@dotkomonline/types"
import { FileAssetSchema, ImageVariantSchema, OfflineWriteSchema } from "@dotkomonline/types"
import type { z } from "zod"
import { createDateTimeInput, createFileInput, createImageInput, createTextInput, useFormBuilder } from "../../form"

const FormSchema = OfflineWriteSchema.omit({
imageVariantId: true,
pdfAssetKey: true,
}).extend({
image: ImageVariantSchema,
pdf: FileAssetSchema,
})
type FormSchema = z.infer<typeof FormSchema>

Expand All @@ -29,7 +31,7 @@ export const useOfflineWriteForm = ({ onSubmit, label, defaultValues }: UseOffli
label: "Utgivelsesdato",
placeholder: "2023-10-05",
}),
pdfAssetKey: createFileInput({
pdf: createFileInput({
label: "Fil",
placeholder: "Last opp",
}),
Expand Down
4 changes: 2 additions & 2 deletions apps/dashboard/src/app/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ export function createImageInput<F extends FieldValues>({
name={name}
render={({ field }) => (
<ImageUpload
setImage={field.onChange}
image={field.value}
setImageVariant={field.onChange}
imageVariant={field.value}
cropAspectLock={props.cropAspectLock}
error={state.errors[name]}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client"
import type { FileAsset } from "@dotkomonline/types"
import { Anchor, Box, Text } from "@mantine/core"
import type React from "react"
import type { ReactNode } from "react"
Expand All @@ -7,7 +8,7 @@ import { buildAssetUrl } from "../../../utils/s3"

interface Props {
onFileLoad: (image: string) => void
value?: string
value: FileAsset
error?: ReactNode
}

Expand All @@ -32,8 +33,8 @@ export default function FileUpload({ onFileLoad, value, error }: Props) {
)}
</Box>
{!!value && (
<Anchor href={buildAssetUrl(value)} target="_blank">
{value}
<Anchor href={buildAssetUrl(value.key)} target="_blank">
{value.originalFilename}
</Anchor>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export function CropPreview({ imgSrc, completedCrop, imgRef, scale, hidden }: Sh
const crop: PercentCrop = completedCrop || {
x: 0,
y: 0,
width: imgRef.current?.width,
height: imgRef.current.height,
width: 100,
height: 100,
unit: "%",
}

Expand Down
52 changes: 26 additions & 26 deletions apps/dashboard/src/components/molecules/ImageUpload/ImageUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { useEffect } from "react"
import type { ReactNode } from "react"
import type { PercentCrop } from "react-image-crop"
import {
useCreateImageMutation,
useUpdateImageMutation,
useCreateImageVariantMutation,
useUpdateImageVariantMutation,
useUploadImageAssetToS3,
} from "../../../modules/asset/mutations"
import { buildAssetUrl } from "../../../utils/s3"
Expand All @@ -21,33 +21,33 @@ import { imageUploadNotifications } from "./notifications"
import { getFileFromUrl, getImageDimensions, mapCropToFrontend, percentToPixelCrop } from "./utils"

interface Props {
setImage: (image: ImageVariant | null) => void
image: ImageVariant | null
setImageVariant: (image: ImageVariant | null) => void
imageVariant: ImageVariant | null
cropAspectLock?: number | undefined
error?: ReactNode
}

export default function ImageUpload({ setImage, cropAspectLock, image, error }: Props) {
export default function ImageUpload({ setImageVariant, cropAspectLock, imageVariant, error }: Props) {
const [imgSrc, setImgSrc] = useState("")
const [scale, setScale] = useState(1)
const [completedCrop, setCompletedCrop] = useState<PercentCrop | undefined>(mapCropToFrontend(image))
const [completedCrop, setCompletedCrop] = useState<PercentCrop | undefined>(mapCropToFrontend(imageVariant))

const [cropOpen, { toggle: toggleShowCrop }] = useDisclosure()
const imgRef = useRef<HTMLImageElement>(null)

const uploadToS3 = useUploadImageAssetToS3()
const createImage = useCreateImageMutation()
const updateImage = useUpdateImageMutation()
const createImageVariant = useCreateImageVariantMutation()
const updateImageVariant = useUpdateImageVariantMutation()

async function reset() {
setImage(null)
setImageVariant(null)
}

useEffect(() => {
if (image) {
loadFileFromAssetKey(image.asset.key)
if (imageVariant) {
loadFileFromAssetKey(imageVariant.asset.key)
}
}, [image])
}, [imageVariant])

async function loadFileFromAssetKey(assetKey: string) {
const url = buildAssetUrl(assetKey)
Expand Down Expand Up @@ -76,23 +76,23 @@ export default function ImageUpload({ setImage, cropAspectLock, image, error }:
notify.syncBackend()
await loadFileFromAssetKey(uploadedRawAsset.key)

const newImage = {
const newImageVariant = {
assetKey: uploadedRawAsset.key,
crop: null,
altText: "Uploaded image",
}

if (!image) {
if (!imageVariant) {
// Create new image
const res = await createImage.mutateAsync(newImage)
setImage(res)
const res = await createImageVariant.mutateAsync(newImageVariant)
setImageVariant(res)
notify.complete()
return
}

// Update existing image
const res = await updateImage.mutateAsync({ id: image.id, image: newImage })
setImage(res)
const res = await updateImageVariant.mutateAsync({ id: imageVariant.id, image: newImageVariant })
setImageVariant(res)

notify.complete()
}
Expand All @@ -118,28 +118,28 @@ export default function ImageUpload({ setImage, cropAspectLock, image, error }:
}

async function onSetCrop() {
if (!image) {
if (!imageVariant) {
throw new Error("Invalid state. ImageVariant value not set at crop time")
}

const result = await updateImage.mutateAsync({
id: image.id,
const result = await updateImageVariant.mutateAsync({
id: imageVariant.id,
image: {
assetKey: image.asset.key,
assetKey: imageVariant.asset.key,
crop: getRealSizeCropValues(),
},
})

toggleShowCrop()
setImage(result)
setImageVariant(result)
}

return (
<div>
{error && <div style={{ color: "red" }}>{error}</div>}
{!image && <input type="file" accept="image/*" onChange={onSelectFile} />}
{!imageVariant && <input type="file" accept="image/*" onChange={onSelectFile} />}
<div>
{!!image && (
{!!imageVariant && (
<>
{cropOpen && (
<div>
Expand All @@ -164,7 +164,7 @@ export default function ImageUpload({ setImage, cropAspectLock, image, error }:
</button>
</div>
)}
{!cropOpen && !!image && (
{!cropOpen && !!imageVariant && (
<div>
<button onClick={toggleShowCrop} type="button">
Endre crop
Expand Down
4 changes: 2 additions & 2 deletions apps/dashboard/src/modules/asset/mutations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ export const useUploadImageAssetToS3 = () => {
}
}

export const useCreateImageMutation = () => {
export const useCreateImageVariantMutation = () => {
return trpc.asset.createImageVariation.useMutation()
}

export const useUpdateImageMutation = () => {
export const useUpdateImageVariantMutation = () => {
return trpc.asset.updateImageVariation.useMutation()
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const CreateOfflineModal: FC<ContextModalProps> = ({ context, id }) => {
label: "Opprett ny Offline",
onSubmit: async (data) => {
createOffline.mutate({
pdfAssetKey: data.pdfAssetKey,
pdfAssetKey: data.pdf.key,
imageVariantId: data.image.id,
title: data.title,
published: data.published,
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/modules/offline/use-offline-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const useOfflineTable = ({ data }: Props) => {
header: () => "Utgivelsesdato",
cell: (info) => <Text>{formatDate(info.getValue())}</Text>,
}),
columnHelper.accessor("fileAsset", {
columnHelper.accessor("pdf", {
header: () => "Fil",
cell: (info) => {
const asset = info.getValue()
Expand Down
14 changes: 4 additions & 10 deletions packages/core/src/modules/offline/offline-repository.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import type { Database } from "@dotkomonline/db"
import type { DB } from "@dotkomonline/db/src/db.generated"
import {
type Offline,
type OfflineId,
OfflineSchema,
type OfflineWithoutAssets,
type OfflineWrite,
} from "@dotkomonline/types"
import { type Offline, type OfflineId, OfflineSchema, type OfflineWrite } from "@dotkomonline/types"
import type { ExpressionBuilder, Kysely } from "kysely"
import { jsonObjectFrom } from "kysely/helpers/postgres"
import { type Cursor, type Keys, orderedQuery } from "../../utils/db-utils"

export interface OfflineRepository {
getById(id: OfflineId): Promise<OfflineWithoutAssets | null>
getById(id: OfflineId): Promise<Offline | null>
getAll(take: number, cursor?: Cursor): Promise<Offline[]>
create(values: OfflineWrite): Promise<Offline>
update(id: OfflineId, data: Partial<OfflineWrite>): Promise<Offline>
Expand Down Expand Up @@ -53,7 +47,7 @@ export class OfflineRepositoryImpl implements OfflineRepository {
title: query.title,
published: query.published,
image: query.imageVariant,
fileAsset: query.pdfAsset,
pdf: query.pdfAsset,
}

if (!offline) {
Expand Down Expand Up @@ -87,7 +81,7 @@ export class OfflineRepositoryImpl implements OfflineRepository {
title: offline.title,
published: offline.published,
image: offline.imageVariant,
fileAsset: offline.pdfAsset,
pdf: offline.pdfAsset,
}

result.push(OfflineSchema.parse(parsed))
Expand Down
8 changes: 3 additions & 5 deletions packages/gateway-trpc/src/modules/offline/offline-router.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PaginateInputSchema } from "@dotkomonline/core"
import { OfflineSchemaWithoutAssets, OfflineWriteSchema } from "@dotkomonline/types"
import { OfflineSchema, OfflineWriteSchema } from "@dotkomonline/types"
import { z } from "zod"
import { protectedProcedure, t } from "../../trpc"

Expand All @@ -8,17 +8,15 @@ export const offlineRouter = t.router({
edit: protectedProcedure
.input(
z.object({
id: OfflineSchemaWithoutAssets.shape.id,
id: OfflineSchema.shape.id,
input: OfflineWriteSchema.partial(),
})
)
.mutation(async ({ input: changes, ctx }) => ctx.offlineService.update(changes.id, changes.input)),
all: t.procedure
.input(PaginateInputSchema)
.query(async ({ input, ctx }) => ctx.offlineService.getAll(input.take, input.cursor)),
get: t.procedure
.input(OfflineSchemaWithoutAssets.shape.id)
.query(async ({ input, ctx }) => ctx.offlineService.get(input)),
get: t.procedure.input(OfflineSchema.shape.id).query(async ({ input, ctx }) => ctx.offlineService.get(input)),
createPresignedPost: protectedProcedure
.input(
z.object({
Expand Down
14 changes: 2 additions & 12 deletions packages/types/src/offline.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
import { z } from "zod"
import { FileAssetSchema, ImageVariantSchema } from "./asset"

export const OfflineSchemaWithoutAssets = z.object({
id: z.string().ulid(),
title: z.string().max(1000).min(1),
published: z.date(),
fileAsset: FileAssetSchema, // joining with asset is cheap and file name may be used
image: ImageVariantSchema,
})

export const OfflineSchema = z.object({
id: z.string().ulid(),
title: z.string().max(1000).min(1),
published: z.date(),
fileAsset: FileAssetSchema, // joining with asset is cheap and file name may be used
pdf: FileAssetSchema, // joining with asset is cheap and file name may be used
image: ImageVariantSchema,
})

export const OfflineWriteSchema = OfflineSchema.omit({
id: true,
image: true,
fileAsset: true,
pdf: true,
}).extend({
imageVariantId: z.string(),
pdfAssetKey: z.string(),
Expand All @@ -29,5 +21,3 @@ export const OfflineWriteSchema = OfflineSchema.omit({
export type Offline = z.infer<typeof OfflineSchema>
export type OfflineId = Offline["id"]
export type OfflineWrite = z.infer<typeof OfflineWriteSchema>

export type OfflineWithoutAssets = z.infer<typeof OfflineSchemaWithoutAssets>

0 comments on commit 71dc6cf

Please sign in to comment.