|
| 1 | +/* eslint-disable @typescript-eslint/no-floating-promises */ |
1 | 2 | import * as React from 'react'; |
2 | 3 | import { useIntl } from 'react-intl'; |
3 | 4 |
|
4 | | -import { unstable_useContentManagerContext } from '@strapi/strapi/admin'; |
| 5 | +import { unstable_useContentManagerContext, useFetchClient } from '@strapi/strapi/admin'; |
| 6 | +import { useMutation, useQuery, useQueryClient } from 'react-query'; |
5 | 7 |
|
6 | 8 | import { |
7 | 9 | Box, |
8 | | - Flex, |
9 | 10 | TextInput, |
10 | 11 | Checkbox, |
11 | | - Link, |
12 | | - Accordion, |
13 | 12 | Field, |
| 13 | + Typography, |
| 14 | + Modal, |
| 15 | + Button, |
14 | 16 | } from '@strapi/design-system'; |
| 17 | +import { Form, Formik } from 'formik'; |
15 | 18 |
|
16 | 19 | import getTrad from '../../helpers/getTrad'; |
17 | 20 | import { UrlAliasEntity } from '../../types/url-aliases'; |
18 | 21 |
|
19 | 22 | const EditForm = () => { |
20 | | - const { form } = unstable_useContentManagerContext(); |
| 23 | + const context = unstable_useContentManagerContext(); |
| 24 | + const [open, setOpen] = React.useState(false); |
21 | 25 |
|
22 | | - const { values, onChange } = form; |
| 26 | + const { id, model } = context; |
| 27 | + const { get, put } = useFetchClient(); |
| 28 | + const queryClient = useQueryClient(); |
| 29 | + const aliases = useQuery(`aliases-${model}-${id}`, async () => get<UrlAliasEntity[]>(`/webtools/url-alias/findFrom?model=${model}&documentId=${id}`)); |
| 30 | + const mutation = useMutation((updatedAlias: Partial<UrlAliasEntity>) => put(`/webtools/url-alias/update/${aliases.data.data[0].documentId}`, { |
| 31 | + data: updatedAlias, |
| 32 | + })); |
23 | 33 |
|
24 | | - const modifiedDataUrlAliases = |
25 | | - (values.url_alias as UrlAliasEntity[])?.length |
26 | | - ? values.url_alias as UrlAliasEntity[] |
27 | | - : [{ |
28 | | - generated: true, |
29 | | - }] as UrlAliasEntity[]; |
30 | | - const { formatMessage } = useIntl(); |
31 | | - |
32 | | - const updateValue = (index: number, name: string, value: string | number) => { |
33 | | - const updatedUrlAliases = [...modifiedDataUrlAliases]; |
| 34 | + // Re-fetch the aliases when the modal is opened. |
| 35 | + React.useEffect(() => { |
| 36 | + if (open) queryClient.invalidateQueries(`aliases-${model}-${id}`); |
| 37 | + }, [open, queryClient, model, id]); |
34 | 38 |
|
35 | | - updatedUrlAliases[index] = { |
36 | | - ...updatedUrlAliases[index], |
37 | | - [name]: value, |
38 | | - }; |
39 | | - onChange('url_alias', updatedUrlAliases); |
40 | | - }; |
41 | | - |
42 | | - const [expanded, setExpanded] = React.useState<number | null>(0); |
43 | | - // eslint-disable-next-line max-len |
44 | | - const toggle = (index: number) => setExpanded((prevExpanded) => (prevExpanded === index ? null : index)); |
| 39 | + const { formatMessage } = useIntl(); |
45 | 40 |
|
46 | 41 | return ( |
47 | | - <Flex> |
48 | | - <Accordion.Root |
49 | | - size="S" |
50 | | - > |
51 | | - {modifiedDataUrlAliases?.map((alias, index) => ( |
52 | | - <Accordion.Item |
53 | | - key={alias.id} |
54 | | - value={`acc-${alias.id}`} |
55 | | - > |
56 | | - <Accordion.Header> |
57 | | - <Accordion.Trigger |
58 | | - description={alias.url_path ? alias.url_path : 'Initial URL alias'} |
59 | | - > |
60 | | - {`Alias #${index + 1}`} |
61 | | - </Accordion.Trigger> |
62 | | - </Accordion.Header> |
63 | | - <Accordion.Content> |
64 | | - <Box> |
65 | | - <Checkbox |
66 | | - onValueChange={(value: string) => { |
67 | | - updateValue(index, 'generated', value); |
68 | | - }} |
69 | | - // @ts-ignore |
70 | | - value={alias.generated !== undefined ? alias.generated : true} |
71 | | - name={`generated-${index}`} |
72 | | - hint="Uncheck this to create a custom alias below." |
73 | | - > |
74 | | - {formatMessage({ |
75 | | - id: getTrad('EditView.ExcludeFromSitemap'), |
76 | | - defaultMessage: ' Generate automatic URL alias', |
77 | | - })} |
78 | | - </Checkbox> |
79 | | - <Link href="/admin/plugins/webtools/patterns">Configure URL alias patterns.</Link> |
80 | | - </Box> |
81 | | - <Box paddingTop={4}> |
82 | | - <Field.Root |
83 | | - hint='Specify a path by which this data can be accessed in the browser. For example, type "/about" when writing an about page.' |
84 | | - > |
85 | | - <Field.Label> |
86 | | - URL alias |
87 | | - </Field.Label> |
88 | | - <TextInput |
89 | | - name={`path-${index}`} |
90 | | - disabled={alias.generated !== undefined ? alias.generated : true} |
91 | | - onChange={(e: React.ChangeEvent<HTMLInputElement>) => { |
92 | | - if (e.target.value.match(/^[A-Za-z0-9-_.~[\]/]*$/)) { |
93 | | - updateValue(index, 'url_path', e.target.value); |
94 | | - } |
95 | | - }} |
96 | | - value={alias.url_path} |
97 | | - /> |
98 | | - <Field.Hint /> |
99 | | - </Field.Root> |
100 | | - </Box> |
101 | | - </Accordion.Content> |
102 | | - </Accordion.Item> |
103 | | - ))} |
104 | | - </Accordion.Root> |
105 | | - </Flex> |
| 42 | + <Formik |
| 43 | + initialValues={{ |
| 44 | + generated: aliases.data?.data?.[0]?.generated, |
| 45 | + url_path: aliases.data?.data?.[0]?.url_path, |
| 46 | + }} |
| 47 | + onSubmit={async (values) => { |
| 48 | + await mutation.mutateAsync(values); |
| 49 | + setOpen(false); |
| 50 | + }} |
| 51 | + enableReinitialize |
| 52 | + > |
| 53 | + {({ setFieldValue, values, handleSubmit }) => ( |
| 54 | + <Modal.Root open={open} onOpenChange={setOpen}> |
| 55 | + <Modal.Trigger> |
| 56 | + <Button |
| 57 | + size="S" |
| 58 | + variant="secondary" |
| 59 | + style={{ width: '100%' }} |
| 60 | + disabled={aliases.data.data.length === 0} |
| 61 | + > |
| 62 | + Edit URL alias |
| 63 | + </Button> |
| 64 | + </Modal.Trigger> |
| 65 | + <Modal.Content> |
| 66 | + <Modal.Header> |
| 67 | + <Typography fontWeight="bold" textColor="neutral800" id="title"> |
| 68 | + test |
| 69 | + </Typography> |
| 70 | + </Modal.Header> |
| 71 | + <Modal.Body> |
| 72 | + {/** @ts-ignore */} |
| 73 | + <Form> |
| 74 | + <Box> |
| 75 | + <Field.Root hint="Uncheck this to create a custom alias below."> |
| 76 | + <Checkbox |
| 77 | + onCheckedChange={(value) => { |
| 78 | + setFieldValue('generated', value); |
| 79 | + }} |
| 80 | + checked={values.generated !== undefined ? values.generated : true} |
| 81 | + name="generated" |
| 82 | + > |
| 83 | + {formatMessage({ |
| 84 | + id: getTrad('EditView.ExcludeFromSitemap'), |
| 85 | + defaultMessage: ' Generate automatic URL alias', |
| 86 | + })} |
| 87 | + </Checkbox> |
| 88 | + <Field.Hint /> |
| 89 | + </Field.Root> |
| 90 | + </Box> |
| 91 | + <Box paddingTop={4}> |
| 92 | + <Field.Root |
| 93 | + hint='Specify a path by which this data can be accessed in the browser. For example, type "/about" when writing an about page.' |
| 94 | + > |
| 95 | + <Field.Label> |
| 96 | + URL alias |
| 97 | + </Field.Label> |
| 98 | + <TextInput |
| 99 | + name="path" |
| 100 | + disabled={values.generated !== undefined ? values.generated : true} |
| 101 | + onChange={(e: React.ChangeEvent<HTMLInputElement>) => { |
| 102 | + if (e.target.value.match(/^[A-Za-z0-9-_.~[\]/]*$/)) { |
| 103 | + setFieldValue('url_path', e.target.value); |
| 104 | + } |
| 105 | + }} |
| 106 | + value={values.url_path} |
| 107 | + /> |
| 108 | + <Field.Hint /> |
| 109 | + </Field.Root> |
| 110 | + </Box> |
| 111 | + </Form> |
| 112 | + </Modal.Body> |
| 113 | + <Modal.Footer> |
| 114 | + <Modal.Close> |
| 115 | + <Button variant="tertiary"> |
| 116 | + Cancel |
| 117 | + </Button> |
| 118 | + </Modal.Close> |
| 119 | + <Button onClick={() => handleSubmit()}>Save</Button> |
| 120 | + </Modal.Footer> |
| 121 | + </Modal.Content> |
| 122 | + </Modal.Root> |
| 123 | + )} |
| 124 | + </Formik> |
106 | 125 | ); |
107 | 126 | }; |
108 | 127 |
|
|
0 commit comments