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

91
.gitignore vendored
View file

@ -1,45 +1,46 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies # dependencies
node_modules node_modules
.pnp .pnp
.pnp.js .pnp.js
.pnpm-store .pnpm-store
package-lock.json package-lock.json
# testing # testing
/coverage /coverage
# next.js # next.js
/.next /.next
/out /out
# production # production
/build /build
/public/script.js /public/script.js
/geo /geo
/dist /dist
/generated /generated
/src/generated /src/generated
pm2.yml
# misc
.DS_Store # misc
.idea .DS_Store
.yarn .idea
*.iml .yarn
*.log *.iml
.vscode *.log
.tool-versions .vscode
.tool-versions
# debug
npm-debug.log* # debug
yarn-debug.log* npm-debug.log*
yarn-error.log* yarn-debug.log*
yarn-error.log*
# local env files
.env # local env files
.env.* .env
*.env.* .env.*
*.env.*
*.dev.yml
*.dev.yml

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>
<FormField <Grid columns="1fr auto" alignItems="end" gap>
name="slug" <FormField
rules={{ name="slug"
required: formatMessage(labels.required), label={formatMessage({ id: 'label.slug', defaultMessage: 'Slug' })}
}} rules={{
style={{ display: 'none' }} required: formatMessage(labels.required),
> }}
<input type="hidden" /> >
</FormField> <TextField autoComplete="off" />
</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>