Merge pull request #3866 from RaenonX/master
Some checks are pending
Node.js CI / build (push) Waiting to run

Added custom slug for links
This commit is contained in:
Mike Cao 2026-01-06 18:23:28 -08:00 committed by GitHub
commit 5213e04f44
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 76 additions and 80 deletions

1
.gitignore vendored
View file

@ -21,6 +21,7 @@ package-lock.json
/dist /dist
/generated /generated
/src/generated /src/generated
pm2.yml
# misc # misc
.DS_Store .DS_Store

View file

@ -4,13 +4,14 @@ import {
Form, Form,
FormField, FormField,
FormSubmitButton, FormSubmitButton,
Grid,
Icon, Icon,
Label, Label,
Loading, Loading,
Row, Row,
TextField, TextField,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { useEffect, useState } from 'react'; import { useState } from 'react';
import { useConfig, useLinkQuery, useMessages } from '@/components/hooks'; import { useConfig, useLinkQuery, useMessages } from '@/components/hooks';
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery'; import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
import { RefreshCw } from '@/components/icons'; import { RefreshCw } from '@/components/icons';
@ -42,7 +43,7 @@ export function LinkEditForm({
const { linksUrl } = useConfig(); const { linksUrl } = useConfig();
const hostUrl = linksUrl || LINKS_URL; const hostUrl = linksUrl || LINKS_URL;
const { data, isLoading } = useLinkQuery(linkId); const { data, isLoading } = useLinkQuery(linkId);
const [slug, setSlug] = useState(generateId()); const [defaultSlug] = useState(generateId());
const handleSubmit = async (data: any) => { const handleSubmit = async (data: any) => {
await mutateAsync(data, { await mutateAsync(data, {
@ -55,14 +56,6 @@ export function LinkEditForm({
}); });
}; };
const handleSlug = () => {
const slug = generateId();
setSlug(slug);
return slug;
};
const checkUrl = (url: string) => { const checkUrl = (url: string) => {
if (!isValidUrl(url)) { if (!isValidUrl(url)) {
return formatMessage(labels.invalidUrl); return formatMessage(labels.invalidUrl);
@ -70,19 +63,19 @@ export function LinkEditForm({
return true; return true;
}; };
useEffect(() => {
if (data) {
setSlug(data.slug);
}
}, [data]);
if (linkId && isLoading) { if (linkId && isLoading) {
return <Loading placement="absolute" />; return <Loading placement="absolute" />;
} }
return ( return (
<Form onSubmit={handleSubmit} error={getErrorMessage(error)} defaultValues={{ slug, ...data }}> <Form
{({ setValue }) => { onSubmit={handleSubmit}
error={getErrorMessage(error)}
defaultValues={{ slug: defaultSlug, ...data }}
>
{({ setValue, watch }) => {
const slug = watch('slug');
return ( return (
<> <>
<FormField <FormField
@ -101,15 +94,25 @@ export function LinkEditForm({
<TextField placeholder="https://example.com" autoComplete="off" /> <TextField placeholder="https://example.com" autoComplete="off" />
</FormField> </FormField>
<Grid columns="1fr auto" alignItems="end" gap>
<FormField <FormField
name="slug" name="slug"
label={formatMessage({ id: 'label.slug', defaultMessage: 'Slug' })}
rules={{ rules={{
required: formatMessage(labels.required), required: formatMessage(labels.required),
}} }}
style={{ display: 'none' }}
> >
<input type="hidden" /> <TextField autoComplete="off" />
</FormField> </FormField>
<Button
variant="quiet"
onPress={() => setValue('slug', generateId(), { shouldDirty: true })}
>
<Icon>
<RefreshCw />
</Icon>
</Button>
</Grid>
<Column> <Column>
<Label>{formatMessage(labels.link)}</Label> <Label>{formatMessage(labels.link)}</Label>
@ -121,14 +124,6 @@ export function LinkEditForm({
allowCopy allowCopy
style={{ width: '100%' }} style={{ width: '100%' }}
/> />
<Button
variant="quiet"
onPress={() => setValue('slug', handleSlug(), { shouldDirty: true })}
>
<Icon>
<RefreshCw />
</Icon>
</Button>
</Row> </Row>
</Column> </Column>