feat(app): changelog version auto create
Some checks failed
Build and Push Docker Image / tests (push) Successful in 39s
Build and Push Docker Image / build (push) Failing after 1m8s

This commit is contained in:
Lars Hampe 2024-11-01 21:15:46 +01:00
parent ede09bcf04
commit 1be0facd64
12 changed files with 191 additions and 12 deletions

View File

@ -1,17 +1,21 @@
import { Link, useParams } from '@tanstack/react-router'
import { HandIcon, WorkflowIcon } from 'lucide-react'
export const ChangelogVersionCreateStep01 = () => {
export const ChangelogVersionCreateStep01 = ({
nextStep,
}: { nextStep: () => void }) => {
const { id } = useParams({ from: '/changelog/$id' })
return (
<div className="flex gap-10 mt-3">
<div className="border rounded border-muted p-5 flex items-center justify-center w-full flex-col">
<button
type="button"
className="flex-col hover:border-accent border rounded border-muted p-5 flex items-center justify-center w-full"
onClick={nextStep}
>
<WorkflowIcon />
Automatic
<small className="uppercase text-muted-foreground text-xs">
Coming soon
</small>
</div>
</button>
<Link
className="flex-col hover:border-accent border rounded border-muted p-5 flex items-center justify-center w-full"
to="/changelog/$id/versionCreate"

View File

@ -0,0 +1,74 @@
import { VersionCreateAutoInput } from '@boring.tools/schema'
import {
Button,
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
Input,
} from '@boring.tools/ui'
import { zodResolver } from '@hookform/resolvers/zod'
import { useNavigate, useParams } from '@tanstack/react-router'
import { useForm } from 'react-hook-form'
import type { z } from 'zod'
import { useChangelogVersionCreateAuto } from '../../../../hooks/useChangelog'
export const ChangelogVersionCreateStep02 = () => {
const { id } = useParams({ from: '/changelog/$id' })
const navigate = useNavigate({ from: `/changelog/${id}` })
const autoVersion = useChangelogVersionCreateAuto()
const form = useForm<z.infer<typeof VersionCreateAutoInput>>({
resolver: zodResolver(VersionCreateAutoInput),
defaultValues: {
changelogId: id,
version: null,
},
})
const onSubmit = (values: z.infer<typeof VersionCreateAutoInput>) => {
autoVersion.mutate(values, {
onSuccess(data) {
navigate({
to: '/changelog/$id/version/$versionId',
params: { id, versionId: data.id },
})
},
})
}
return (
<div className="flex gap-10 mt-3">
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 w-full"
>
<FormField
control={form.control}
name="version"
render={({ field }) => (
<FormItem>
<FormLabel>Version</FormLabel>
<FormControl>
<Input placeholder="v1.0.1" {...field} autoFocus />
</FormControl>{' '}
<FormDescription>
Leave blank for auto generating.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<div className="flex gap-5 mt-5 w-full justify-end items-end md:col-span-6">
<Button type="submit">Create</Button>
</div>
</form>
</Form>
</div>
)
}

View File

@ -7,11 +7,23 @@ import {
DialogTrigger,
} from '@boring.tools/ui'
import { PlusCircleIcon } from 'lucide-react'
import { useEffect, useState } from 'react'
import { ChangelogVersionCreateStep01 } from './Step01'
import { ChangelogVersionCreateStep02 } from './Step02'
export const ChangelogVersionCreate = () => {
const [isOpen, setIsOpen] = useState(false)
const [step, setStep] = useState(1)
const nextStep = () => setStep((prev) => prev + 1)
useEffect(() => {
if (!isOpen) {
setStep(1)
}
}, [isOpen])
return (
<Dialog>
<Dialog open={isOpen} onOpenChange={(state) => setIsOpen(state)}>
<DialogTrigger>
<PlusCircleIcon />
</DialogTrigger>
@ -25,7 +37,8 @@ export const ChangelogVersionCreate = () => {
</DialogDescription>
</DialogHeader>
<ChangelogVersionCreateStep01 />
{step === 1 && <ChangelogVersionCreateStep01 nextStep={nextStep} />}
{step === 2 && <ChangelogVersionCreateStep02 />}
</DialogContent>
</Dialog>
)

View File

@ -3,6 +3,7 @@ import type {
ChangelogOutput,
ChangelogUpdateInput,
CommitOutput,
VersionCreateAutoInput,
VersionCreateInput,
VersionOutput,
VersionUpdateInput,
@ -18,6 +19,7 @@ type ChangelogUpdate = z.infer<typeof ChangelogUpdateInput>
type Version = z.infer<typeof VersionOutput>
type VersionCreate = z.infer<typeof VersionCreateInput>
type VersionCreateAuto = z.infer<typeof VersionCreateAutoInput>
type VersionUpdate = z.infer<typeof VersionUpdateInput>
type Commit = z.infer<typeof CommitOutput>
@ -155,6 +157,29 @@ export const useChangelogVersionCreate = () => {
})
}
export const useChangelogVersionCreateAuto = () => {
const { getToken } = useAuth()
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (
payload: VersionCreateAuto,
): Promise<Readonly<Version>> =>
await queryFetch({
path: 'changelog/version/auto',
data: payload,
method: 'post',
token: await getToken(),
}),
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: ['changelogList'] })
queryClient.invalidateQueries({
queryKey: ['changelogById', data.changelogId],
})
},
})
}
export const useChangelogVersionById = ({ id }: { id: string }) => {
const { getToken } = useAuth()

View File

@ -43,7 +43,7 @@ import {
import '@mdxeditor/editor/style.css'
import { format } from 'date-fns'
import { CalendarIcon } from 'lucide-react'
import { useEffect, useRef } from 'react'
import { useEffect, useRef, useState } from 'react'
import { ChangelogVersionDelete } from '../components/Changelog/VersionDelete'
import { VersionStatus } from '../components/Changelog/VersionStatus'
@ -55,6 +55,7 @@ const Component = () => {
const { data, error, isPending, refetch } = useChangelogVersionById({
id: versionId,
})
const [editorValue, setEditorValue] = useState('')
const form = useForm<z.infer<typeof VersionUpdateInput>>({
resolver: zodResolver(VersionUpdateInput),
defaultValues: data,
@ -74,9 +75,8 @@ const Component = () => {
useEffect(() => {
if (data) {
mdxEditorRef.current?.setMarkdown(data.markdown)
form.reset(data)
}
}, [data, form.reset])
}, [data])
if (error) {
return (

View File

@ -29,6 +29,7 @@ const Component = () => {
title: '',
description: '',
isSemver: true,
isConventional: true,
},
})
@ -115,6 +116,33 @@ const Component = () => {
</FormItem>
)}
/>
<FormField
control={form.control}
name="isConventional"
render={({ field }) => (
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md ">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<div className="space-y-1 leading-none">
<FormLabel>Using Conventional Commits</FormLabel>
<FormDescription>
If this changelog is using{' '}
<a
href="https://www.conventionalcommits.org/en/v1.0.0/"
className="text-emerald-700"
>
conventional commits
</a>
</FormDescription>
</div>
</FormItem>
)}
/>
<Button type="submit">Create</Button>
</form>
</Form>

View File

@ -0,0 +1,22 @@
meta {
name: Create Auto
type: http
seq: 1
}
post {
url: {{API_URL}}/v1/changelog/version/auto
body: json
auth: bearer
}
auth:bearer {
token: {{TOKEN}}
}
body:json {
{
"changelogId": "d83fe688-3331-4e64-9af6-318f82e511d4",
"commitIds": ["01cc79df-6d16-4496-b9ba-b238d686efc4"]
}
}

View File

@ -11,5 +11,5 @@ get {
}
auth:bearer {
token: bt_7b83481e2ae0f6ab728730511adbe491f6668eb3
token: {{TOKEN}}
}

View File

@ -1,3 +1,6 @@
vars {
API_URL: http://localhost:3000
}
vars:secret [
TOKEN
]

BIN
bun.lockb

Binary file not shown.

View File

@ -7,6 +7,7 @@ export const ChangelogCreateInput = z
title: z.string().min(3, 'Title must contain at least 3 charachters.'),
description: z.string(),
isSemver: z.boolean().default(true),
isConventional: z.boolean().default(true),
})
.openapi({
required: ['title', 'userId'],

View File

@ -14,3 +14,12 @@ export const VersionCreateInput = z
.openapi({
required: ['changelogId', 'version', 'markdown', 'releasedAt'],
})
export const VersionCreateAutoInput = z
.object({
version: z.string().optional().nullable(),
changelogId: z.string().uuid(),
})
.openapi({
required: ['changelogId'],
})