mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
refactor(link): simplify LinkEditForm state management and improve slug handling
- Removed unnecessary useEffect for slug initialization and replaced it with a more efficient state setup. - Updated handleSubmit to conditionally include the slug in the payload based on link creation or modification. - Enhanced form handling by utilizing watch for dynamic slug updates and improved validation messages for slug input.
This commit is contained in:
parent
fc78c4a5ff
commit
c3332552d7
2 changed files with 43 additions and 37 deletions
|
|
@ -10,7 +10,7 @@ import {
|
|||
Row,
|
||||
TextField,
|
||||
} from '@umami/react-zen';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useConfig, useLinkQuery, useMessages } from '@/components/hooks';
|
||||
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
|
||||
import { ChevronDown, ChevronRight, RefreshCw } from '@/components/icons';
|
||||
|
|
@ -42,11 +42,15 @@ export function LinkEditForm({
|
|||
const { linksUrl } = useConfig();
|
||||
const hostUrl = linksUrl || LINKS_URL;
|
||||
const { data, isLoading } = useLinkQuery(linkId);
|
||||
const [slug, setSlug] = useState(generateId());
|
||||
const [initialSlug] = useState(() => generateId());
|
||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||
|
||||
const handleSubmit = async (data: any) => {
|
||||
await mutateAsync(data, {
|
||||
const handleSubmit = async (formData: any) => {
|
||||
const { slug: formSlug, ...rest } = formData;
|
||||
// Only include slug if creating new link or if it was modified
|
||||
const payload = !linkId || formSlug !== data?.slug ? formData : rest;
|
||||
|
||||
await mutateAsync(payload, {
|
||||
onSuccess: async () => {
|
||||
toast(formatMessage(messages.saved));
|
||||
touch('links');
|
||||
|
|
@ -56,13 +60,7 @@ export function LinkEditForm({
|
|||
});
|
||||
};
|
||||
|
||||
const handleSlug = () => {
|
||||
const slug = generateId();
|
||||
|
||||
setSlug(slug);
|
||||
|
||||
return slug;
|
||||
};
|
||||
const handleSlug = () => generateId();
|
||||
|
||||
const checkUrl = (url: string) => {
|
||||
if (!isValidUrl(url)) {
|
||||
|
|
@ -71,12 +69,6 @@ export function LinkEditForm({
|
|||
return true;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setSlug(data.slug);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
if (linkId && isLoading) {
|
||||
return <Loading placement="absolute" />;
|
||||
}
|
||||
|
|
@ -85,15 +77,27 @@ export function LinkEditForm({
|
|||
<Form
|
||||
onSubmit={handleSubmit}
|
||||
error={getErrorMessage(error)}
|
||||
defaultValues={{
|
||||
slug,
|
||||
...data,
|
||||
ogTitle: data?.ogTitle || '',
|
||||
ogDescription: data?.ogDescription || '',
|
||||
ogImageUrl: data?.ogImageUrl || '',
|
||||
}}
|
||||
{...(linkId
|
||||
? {
|
||||
values: {
|
||||
...data,
|
||||
ogTitle: data?.ogTitle || '',
|
||||
ogDescription: data?.ogDescription || '',
|
||||
ogImageUrl: data?.ogImageUrl || '',
|
||||
},
|
||||
}
|
||||
: {
|
||||
defaultValues: {
|
||||
slug: initialSlug,
|
||||
ogTitle: '',
|
||||
ogDescription: '',
|
||||
ogImageUrl: '',
|
||||
},
|
||||
})}
|
||||
>
|
||||
{({ setValue }) => {
|
||||
{({ setValue, watch }) => {
|
||||
const currentSlug = watch('slug') ?? initialSlug;
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
|
|
@ -116,7 +120,7 @@ export function LinkEditForm({
|
|||
<Label>{formatMessage(labels.link)}</Label>
|
||||
<Row alignItems="center" gap>
|
||||
<TextField
|
||||
value={`${hostUrl}/${slug}`}
|
||||
value={`${hostUrl}/${currentSlug}`}
|
||||
autoComplete="off"
|
||||
isReadOnly
|
||||
allowCopy
|
||||
|
|
@ -157,17 +161,17 @@ export function LinkEditForm({
|
|||
<TextField autoComplete="off" />
|
||||
</FormField>
|
||||
|
||||
<Column>
|
||||
<Label>{formatMessage(labels.path)}</Label>
|
||||
<TextField
|
||||
value={slug}
|
||||
onChange={(value: string) => {
|
||||
setSlug(value);
|
||||
setValue('slug', value, { shouldDirty: true });
|
||||
}}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Column>
|
||||
<FormField
|
||||
label={formatMessage(labels.path)}
|
||||
name="slug"
|
||||
rules={{
|
||||
required: formatMessage(labels.required),
|
||||
minLength: { value: 4, message: formatMessage(labels.tooShort) },
|
||||
maxLength: { value: 100, message: formatMessage(labels.tooLong) },
|
||||
}}
|
||||
>
|
||||
<TextField autoComplete="off" minLength={4} maxLength={100} />
|
||||
</FormField>
|
||||
</Column>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ export const labels = defineMessages({
|
|||
ok: { id: 'label.ok', defaultMessage: 'OK' },
|
||||
unknown: { id: 'label.unknown', defaultMessage: 'Unknown' },
|
||||
required: { id: 'label.required', defaultMessage: 'Required' },
|
||||
tooShort: { id: 'label.too-short', defaultMessage: 'Too short' },
|
||||
tooLong: { id: 'label.too-long', defaultMessage: 'Too long' },
|
||||
save: { id: 'label.save', defaultMessage: 'Save' },
|
||||
cancel: { id: 'label.cancel', defaultMessage: 'Cancel' },
|
||||
continue: { id: 'label.continue', defaultMessage: 'Continue' },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue