sanity-plugin-media 4.3.6 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/package.json +6 -15
  2. package/dist/index.cjs +0 -4721
  3. package/dist/index.cjs.map +0 -1
  4. package/dist/index.d.cts +0 -239
  5. package/dist/index.d.cts.map +0 -1
  6. package/sanity.json +0 -8
  7. package/src/__tests__/fixtures/createEpicTestStore.ts +0 -28
  8. package/src/__tests__/fixtures/listenMock.ts +0 -9
  9. package/src/__tests__/fixtures/mockSanityClient.ts +0 -84
  10. package/src/__tests__/fixtures/renderWithProviders.tsx +0 -55
  11. package/src/__tests__/fixtures/rootState.ts +0 -27
  12. package/src/__tests__/fixtures/withinDialog.ts +0 -28
  13. package/src/components/AssetGridVirtualized/index.tsx +0 -94
  14. package/src/components/AssetMetadata/index.tsx +0 -122
  15. package/src/components/AssetTableVirtualized/index.tsx +0 -73
  16. package/src/components/AutoTagInputWrapper/index.tsx +0 -85
  17. package/src/components/Browser/Browser.test.tsx +0 -45
  18. package/src/components/Browser/index.tsx +0 -90
  19. package/src/components/Browser/useBrowserInit.ts +0 -126
  20. package/src/components/ButtonAssetCopy/index.tsx +0 -65
  21. package/src/components/ButtonViewGroup/index.tsx +0 -39
  22. package/src/components/CardAsset/CardAsset.test.tsx +0 -323
  23. package/src/components/CardAsset/index.tsx +0 -290
  24. package/src/components/CardUpload/index.tsx +0 -161
  25. package/src/components/Controls/index.tsx +0 -136
  26. package/src/components/DebugControls/index.tsx +0 -80
  27. package/src/components/Dialog/index.tsx +0 -11
  28. package/src/components/DialogAssetEdit/Details.tsx +0 -181
  29. package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +0 -216
  30. package/src/components/DialogAssetEdit/index.tsx +0 -493
  31. package/src/components/DialogConfirm/index.tsx +0 -90
  32. package/src/components/DialogSearchFacets/index.tsx +0 -42
  33. package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +0 -121
  34. package/src/components/DialogTagCreate/index.tsx +0 -111
  35. package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +0 -165
  36. package/src/components/DialogTagEdit/index.tsx +0 -201
  37. package/src/components/DialogTags/index.tsx +0 -45
  38. package/src/components/Dialogs/index.tsx +0 -76
  39. package/src/components/DocumentList/index.tsx +0 -62
  40. package/src/components/FileAssetPreview/index.tsx +0 -37
  41. package/src/components/FileIcon/index.tsx +0 -43
  42. package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +0 -63
  43. package/src/components/FormBuilderTool/index.tsx +0 -69
  44. package/src/components/FormFieldInputLabel/index.tsx +0 -66
  45. package/src/components/FormFieldInputTags/index.tsx +0 -98
  46. package/src/components/FormFieldInputText/index.tsx +0 -41
  47. package/src/components/FormFieldInputTextarea/index.tsx +0 -43
  48. package/src/components/FormSubmitButton/index.tsx +0 -59
  49. package/src/components/Header/index.tsx +0 -80
  50. package/src/components/Image/index.tsx +0 -41
  51. package/src/components/Items/index.tsx +0 -68
  52. package/src/components/Notifications/index.tsx +0 -24
  53. package/src/components/OrderSelect/index.tsx +0 -66
  54. package/src/components/PickedBar/index.tsx +0 -77
  55. package/src/components/Progress/index.tsx +0 -38
  56. package/src/components/ReduxProvider/index.tsx +0 -96
  57. package/src/components/SearchFacet/index.tsx +0 -66
  58. package/src/components/SearchFacetNumber/index.tsx +0 -133
  59. package/src/components/SearchFacetSelect/index.tsx +0 -110
  60. package/src/components/SearchFacetString/index.tsx +0 -88
  61. package/src/components/SearchFacetTags/index.tsx +0 -121
  62. package/src/components/SearchFacets/index.tsx +0 -72
  63. package/src/components/SearchFacetsControl/index.tsx +0 -140
  64. package/src/components/TableHeader/index.tsx +0 -110
  65. package/src/components/TableHeaderItem/index.tsx +0 -61
  66. package/src/components/TableRowAsset/index.tsx +0 -419
  67. package/src/components/TableRowUpload/index.tsx +0 -164
  68. package/src/components/Tag/index.tsx +0 -200
  69. package/src/components/TagIcon/index.tsx +0 -22
  70. package/src/components/TagView/index.tsx +0 -39
  71. package/src/components/TagViewHeader/index.tsx +0 -70
  72. package/src/components/TagsPanel/index.tsx +0 -40
  73. package/src/components/TagsVirtualized/index.tsx +0 -160
  74. package/src/components/TextInputNumber/index.tsx +0 -32
  75. package/src/components/TextInputSearch/index.tsx +0 -60
  76. package/src/components/Tool/index.tsx +0 -13
  77. package/src/components/UploadDropzone/UploadDropzone.test.tsx +0 -40
  78. package/src/components/UploadDropzone/index.tsx +0 -173
  79. package/src/config/orders.ts +0 -28
  80. package/src/config/searchFacets.ts +0 -312
  81. package/src/constants.ts +0 -87
  82. package/src/contexts/AssetSourceDispatchContext.tsx +0 -38
  83. package/src/contexts/DropzoneDispatchContext.tsx +0 -32
  84. package/src/contexts/ToolOptionsContext.tsx +0 -66
  85. package/src/formSchema/index.test.ts +0 -56
  86. package/src/formSchema/index.ts +0 -39
  87. package/src/hooks/useBreakpointIndex.ts +0 -50
  88. package/src/hooks/useKeyPress.ts +0 -39
  89. package/src/hooks/usePortalPopoverProps.ts +0 -13
  90. package/src/hooks/useTypedSelector.ts +0 -7
  91. package/src/hooks/useVersionedClient.ts +0 -6
  92. package/src/index.ts +0 -5
  93. package/src/modules/assets/actions.ts +0 -42
  94. package/src/modules/assets/deleteAndUpdateEpics.test.ts +0 -87
  95. package/src/modules/assets/fetchEpic.test.ts +0 -73
  96. package/src/modules/assets/index.ts +0 -782
  97. package/src/modules/assets/reducer.test.ts +0 -91
  98. package/src/modules/assets/tagsAndListenerEpics.test.ts +0 -206
  99. package/src/modules/debug/index.ts +0 -28
  100. package/src/modules/dialog/actions.ts +0 -10
  101. package/src/modules/dialog/epics.test.ts +0 -168
  102. package/src/modules/dialog/index.ts +0 -238
  103. package/src/modules/dialog/reducer.test.ts +0 -185
  104. package/src/modules/index.ts +0 -117
  105. package/src/modules/notifications/epics.test.ts +0 -374
  106. package/src/modules/notifications/index.ts +0 -199
  107. package/src/modules/notifications/reducer.test.ts +0 -54
  108. package/src/modules/search/index.test.ts +0 -36
  109. package/src/modules/search/index.ts +0 -167
  110. package/src/modules/selected/index.ts +0 -22
  111. package/src/modules/selectors.test.ts +0 -21
  112. package/src/modules/selectors.ts +0 -17
  113. package/src/modules/tags/epics.test.ts +0 -96
  114. package/src/modules/tags/index.test.ts +0 -42
  115. package/src/modules/tags/index.ts +0 -540
  116. package/src/modules/types.ts +0 -3
  117. package/src/modules/uploads/actions.ts +0 -13
  118. package/src/modules/uploads/epics.test.ts +0 -109
  119. package/src/modules/uploads/index.test.ts +0 -59
  120. package/src/modules/uploads/index.ts +0 -272
  121. package/src/operators/checkTagName.test.ts +0 -29
  122. package/src/operators/checkTagName.ts +0 -33
  123. package/src/operators/debugThrottle.ts +0 -25
  124. package/src/plugin.tsx +0 -54
  125. package/src/schemas/tag.ts +0 -28
  126. package/src/styled/GlobalStyles/index.tsx +0 -40
  127. package/src/styled/react-select/creatable.tsx +0 -184
  128. package/src/styled/react-select/single.tsx +0 -184
  129. package/src/types/index.ts +0 -346
  130. package/src/types/sanity-ui.d.ts +0 -5
  131. package/src/utils/applyMediaTags.ts +0 -87
  132. package/src/utils/blocksToText.test.ts +0 -43
  133. package/src/utils/blocksToText.ts +0 -27
  134. package/src/utils/constructFilter.test.ts +0 -120
  135. package/src/utils/constructFilter.ts +0 -98
  136. package/src/utils/generatePreviewBlobUrl.test.ts +0 -68
  137. package/src/utils/generatePreviewBlobUrl.ts +0 -53
  138. package/src/utils/getAssetResolution.test.ts +0 -13
  139. package/src/utils/getAssetResolution.ts +0 -7
  140. package/src/utils/getDocumentAssetIds.test.ts +0 -50
  141. package/src/utils/getDocumentAssetIds.ts +0 -35
  142. package/src/utils/getSchemeColor.test.ts +0 -12
  143. package/src/utils/getSchemeColor.ts +0 -43
  144. package/src/utils/getTagSelectOptions.test.ts +0 -44
  145. package/src/utils/getTagSelectOptions.ts +0 -16
  146. package/src/utils/getUniqueDocuments.test.ts +0 -26
  147. package/src/utils/getUniqueDocuments.ts +0 -15
  148. package/src/utils/imageDprUrl.test.ts +0 -46
  149. package/src/utils/imageDprUrl.ts +0 -27
  150. package/src/utils/isSupportedAssetType.test.ts +0 -16
  151. package/src/utils/isSupportedAssetType.ts +0 -15
  152. package/src/utils/mediaField.ts +0 -73
  153. package/src/utils/sanitizeFormData.test.ts +0 -59
  154. package/src/utils/sanitizeFormData.ts +0 -26
  155. package/src/utils/typeGuards.test.ts +0 -18
  156. package/src/utils/typeGuards.ts +0 -9
  157. package/src/utils/uploadSanityAsset.test.ts +0 -29
  158. package/src/utils/uploadSanityAsset.ts +0 -97
  159. package/src/utils/withMaxConcurrency.test.ts +0 -43
  160. package/src/utils/withMaxConcurrency.ts +0 -55
  161. package/src/utils/zodFormResolver.ts +0 -17
  162. package/v2-incompatible.js +0 -11
@@ -1,90 +0,0 @@
1
- import {WarningOutlineIcon} from '@sanity/icons'
2
- import {Box, Button, Flex, Stack, Text} from '@sanity/ui'
3
- import {type ReactNode} from 'react'
4
- import {useDispatch} from 'react-redux'
5
-
6
- import {dialogActions} from '../../modules/dialog'
7
- import type {DialogConfirmProps} from '../../types'
8
- import Dialog from '../Dialog'
9
-
10
- type Props = {
11
- children?: ReactNode
12
- dialog: DialogConfirmProps
13
- }
14
-
15
- const DialogConfirm = (props: Props) => {
16
- const {children, dialog} = props
17
-
18
- // Redux
19
- const dispatch = useDispatch()
20
-
21
- // Callbacks
22
- const handleClose = () => {
23
- dispatch(dialogActions.remove({id: dialog?.id}))
24
- }
25
-
26
- const handleConfirm = () => {
27
- // Close target dialog, if provided
28
- if (dialog?.closeDialogId) {
29
- dispatch(dialogActions.remove({id: dialog?.closeDialogId}))
30
- }
31
-
32
- if (dialog?.confirmCallbackAction) {
33
- dispatch(dialog.confirmCallbackAction)
34
- }
35
-
36
- // Close self
37
- handleClose()
38
- }
39
-
40
- const Footer = () => (
41
- <Box padding={3}>
42
- <Flex justify="space-between">
43
- <Button fontSize={1} mode="bleed" onClick={handleClose} text="Cancel" />
44
- <Button
45
- fontSize={1}
46
- onClick={handleConfirm}
47
- text={dialog?.confirmText}
48
- tone={dialog?.tone}
49
- />
50
- </Flex>
51
- </Box>
52
- )
53
-
54
- const Header = () => (
55
- <Flex align="center">
56
- <Box paddingX={1}>
57
- <WarningOutlineIcon />
58
- </Box>
59
- <Box marginLeft={2}>{dialog?.headerTitle}</Box>
60
- </Flex>
61
- )
62
-
63
- return (
64
- <Dialog
65
- animate
66
- // oxlint-disable-next-line react/react-compiler
67
- footer={<Footer />}
68
- // oxlint-disable-next-line react/react-compiler
69
- header={<Header />}
70
- id="confirm"
71
- onClose={handleClose}
72
- width={1}
73
- >
74
- <Box paddingX={4} paddingY={4}>
75
- <Stack space={3}>
76
- {dialog?.title && <Text size={1}>{dialog.title}</Text>}
77
- {dialog?.description && (
78
- <Text muted size={1}>
79
- <em>{dialog.description}</em>
80
- </Text>
81
- )}
82
- </Stack>
83
- </Box>
84
-
85
- {children}
86
- </Dialog>
87
- )
88
- }
89
-
90
- export default DialogConfirm
@@ -1,42 +0,0 @@
1
- import {Box} from '@sanity/ui'
2
- import {type ReactNode, useCallback} from 'react'
3
- import {useDispatch} from 'react-redux'
4
-
5
- import {dialogActions} from '../../modules/dialog'
6
- import type {DialogSearchFacetsProps} from '../../types'
7
- import Dialog from '../Dialog'
8
- import SearchFacets from '../SearchFacets'
9
- import SearchFacetsControl from '../SearchFacetsControl'
10
-
11
- type Props = {
12
- children: ReactNode
13
- dialog: DialogSearchFacetsProps
14
- }
15
-
16
- const DialogSearchFacets = (props: Props) => {
17
- const {
18
- children,
19
- dialog: {id},
20
- } = props
21
-
22
- // Redux
23
- const dispatch = useDispatch()
24
-
25
- // Callbacks
26
- const handleClose = useCallback(() => {
27
- dispatch(dialogActions.clear())
28
- }, [dispatch])
29
-
30
- return (
31
- <Dialog animate header="Filters" id={id} onClose={handleClose} width={1}>
32
- <Box padding={3}>
33
- <SearchFacets layout="stack" />
34
- <SearchFacetsControl />
35
- </Box>
36
-
37
- {children}
38
- </Dialog>
39
- )
40
- }
41
-
42
- export default DialogSearchFacets
@@ -1,121 +0,0 @@
1
- import {screen, waitFor} from '@testing-library/react'
2
- import userEvent from '@testing-library/user-event'
3
- import {describe, expect, it, vi} from 'vitest'
4
-
5
- import {renderWithProviders} from '../../__tests__/fixtures/renderWithProviders'
6
- import {createTestRootState} from '../../__tests__/fixtures/rootState'
7
- import {getDialogRoot, inputByName, withinDialog} from '../../__tests__/fixtures/withinDialog'
8
- import {tagsActions} from '../../modules/tags'
9
- import DialogTagCreate from './index'
10
-
11
- describe('DialogTagCreate', () => {
12
- it('dispatches tag create flow when form is valid', async () => {
13
- const user = userEvent.setup()
14
- const {store} = renderWithProviders(
15
- <DialogTagCreate dialog={{id: 'dlg-1', type: 'tagCreate'}}>
16
- <span />
17
- </DialogTagCreate>,
18
- )
19
-
20
- const dlg = withinDialog(/create tag/i, screen)
21
- await user.type(inputByName(/create tag/i, screen, 'name'), 'my-tag')
22
- await user.click(dlg.getByRole('button', {name: /save and close/i}))
23
-
24
- expect(store.getState().tags.creating).toBe(true)
25
- })
26
-
27
- it('dispatches createRequest with a trimmed tag name', async () => {
28
- const user = userEvent.setup()
29
- const {store} = renderWithProviders(
30
- <DialogTagCreate dialog={{id: 'dlg-1', type: 'tagCreate'}}>
31
- <span />
32
- </DialogTagCreate>,
33
- )
34
- const dispatchSpy = vi.spyOn(store, 'dispatch')
35
- const dlg = withinDialog(/create tag/i, screen)
36
-
37
- await user.type(inputByName(/create tag/i, screen, 'name'), ' spaced ')
38
- await user.click(dlg.getByRole('button', {name: /save and close/i}))
39
-
40
- await waitFor(() => {
41
- let createAction
42
- for (const call of dispatchSpy.mock.calls) {
43
- const action = call[0]
44
- if (tagsActions.createRequest.match(action)) {
45
- createAction = action
46
- break
47
- }
48
- }
49
- expect(createAction).toBeDefined()
50
- expect(createAction?.payload).toEqual({name: 'spaced'})
51
- })
52
- })
53
-
54
- it('keeps Save disabled until the name is non-empty and valid', async () => {
55
- const user = userEvent.setup()
56
- renderWithProviders(
57
- <DialogTagCreate dialog={{id: 'dlg-1', type: 'tagCreate'}}>
58
- <span />
59
- </DialogTagCreate>,
60
- )
61
-
62
- expect(
63
- withinDialog(/create tag/i, screen).getByRole('button', {name: /save and close/i}),
64
- ).toBeDisabled()
65
-
66
- const nameInput = inputByName(/create tag/i, screen, 'name')
67
- await user.type(nameInput, 'a')
68
- await user.tab()
69
- await waitFor(() => {
70
- expect(
71
- withinDialog(/create tag/i, screen).getByRole('button', {name: /save and close/i}),
72
- ).not.toBeDisabled()
73
- })
74
- })
75
-
76
- it('clears the entire dialog stack when the dialog close control is used', async () => {
77
- const user = userEvent.setup()
78
- const base = createTestRootState({
79
- dialog: {
80
- items: [
81
- {id: 'dlg-1', type: 'tagCreate'},
82
- {id: 'tags', type: 'tags'},
83
- ],
84
- },
85
- })
86
-
87
- const {store} = renderWithProviders(
88
- <DialogTagCreate dialog={{id: 'dlg-1', type: 'tagCreate'}}>
89
- <span />
90
- </DialogTagCreate>,
91
- {preloaded: base},
92
- )
93
-
94
- const dlg = withinDialog(/create tag/i, screen)
95
- await user.click(dlg.getByRole('button', {name: /close dialog/i}))
96
-
97
- expect(store.getState().dialog.items).toEqual([])
98
- })
99
-
100
- it('shows an error indicator beside the name when tag creation failed on the server', async () => {
101
- const base = createTestRootState({
102
- tags: {
103
- ...createTestRootState().tags,
104
- creatingError: {message: 'Tag already exists', statusCode: 409},
105
- },
106
- })
107
-
108
- renderWithProviders(
109
- <DialogTagCreate dialog={{id: 'dlg-1', type: 'tagCreate'}}>
110
- <span />
111
- </DialogTagCreate>,
112
- {preloaded: base},
113
- )
114
-
115
- await waitFor(() => {
116
- expect(
117
- getDialogRoot(/create tag/i, screen).querySelector('[data-sanity-icon="error-outline"]'),
118
- ).toBeTruthy()
119
- })
120
- })
121
- })
@@ -1,111 +0,0 @@
1
- import {Box, Flex} from '@sanity/ui'
2
- import {type ReactNode, useEffect} from 'react'
3
- import {type SubmitHandler, useForm} from 'react-hook-form'
4
- import {useDispatch} from 'react-redux'
5
-
6
- import {tagFormSchema} from '../../formSchema'
7
- import useTypedSelector from '../../hooks/useTypedSelector'
8
- import {dialogActions} from '../../modules/dialog'
9
- import {tagsActions} from '../../modules/tags'
10
- import type {DialogTagCreateProps, TagFormData} from '../../types'
11
- import sanitizeFormData from '../../utils/sanitizeFormData'
12
- import zodFormResolver from '../../utils/zodFormResolver'
13
- import Dialog from '../Dialog'
14
- import FormFieldInputText from '../FormFieldInputText'
15
- import FormSubmitButton from '../FormSubmitButton'
16
-
17
- type Props = {
18
- children: ReactNode
19
- dialog: DialogTagCreateProps
20
- }
21
-
22
- const DialogTagCreate = (props: Props) => {
23
- const {
24
- children,
25
- dialog: {id},
26
- } = props
27
-
28
- const dispatch = useDispatch()
29
-
30
- const creating = useTypedSelector((state) => state.tags.creating)
31
- const creatingError = useTypedSelector((state) => state.tags.creatingError)
32
-
33
- const {
34
- // Read the formState before render to subscribe the form state through Proxy
35
- formState: {errors, isDirty, isValid},
36
- handleSubmit,
37
- register,
38
- setError,
39
- } = useForm<TagFormData>({
40
- defaultValues: {
41
- name: '',
42
- },
43
- mode: 'onChange',
44
- resolver: zodFormResolver<TagFormData>(tagFormSchema),
45
- })
46
-
47
- const formUpdating = creating
48
-
49
- const handleClose = () => {
50
- dispatch(dialogActions.clear())
51
- }
52
-
53
- // - submit react-hook-form
54
- const onSubmit: SubmitHandler<TagFormData> = (formData) => {
55
- const sanitizedFormData = sanitizeFormData(formData)
56
-
57
- dispatch(tagsActions.createRequest({name: sanitizedFormData['name']}))
58
- }
59
-
60
- useEffect(() => {
61
- if (creatingError) {
62
- setError('name', {
63
- message: creatingError?.message,
64
- })
65
- }
66
- }, [creatingError, setError])
67
-
68
- const Footer = () => (
69
- <Box padding={3}>
70
- <Flex justify="flex-end">
71
- {/* Submit button */}
72
- <FormSubmitButton
73
- disabled={formUpdating || !isDirty || !isValid}
74
- isValid={isValid}
75
- onClick={handleSubmit(onSubmit)}
76
- />
77
- </Flex>
78
- </Box>
79
- )
80
-
81
- return (
82
- <Dialog
83
- animate
84
- // oxlint-disable-next-line react/react-compiler
85
- footer={<Footer />}
86
- header="Create Tag"
87
- id={id}
88
- onClose={handleClose}
89
- width={1}
90
- >
91
- {/* Form fields */}
92
- <Box as="form" padding={4} onSubmit={handleSubmit(onSubmit)}>
93
- {/* Hidden button to enable enter key submissions */}
94
- <button style={{display: 'none'}} tabIndex={-1} type="submit" />
95
-
96
- {/* Title */}
97
- <FormFieldInputText
98
- {...register('name')}
99
- disabled={formUpdating}
100
- error={errors?.name?.message}
101
- label="Name"
102
- name="name"
103
- />
104
- </Box>
105
-
106
- {children}
107
- </Dialog>
108
- )
109
- }
110
-
111
- export default DialogTagCreate
@@ -1,165 +0,0 @@
1
- import {fireEvent, screen, waitFor} from '@testing-library/react'
2
- import userEvent from '@testing-library/user-event'
3
- import {Subject} from 'rxjs'
4
- import {describe, expect, it, vi} from 'vitest'
5
-
6
- import {createMockSanityClient} from '../../__tests__/fixtures/mockSanityClient'
7
- import {renderWithProviders} from '../../__tests__/fixtures/renderWithProviders'
8
- import {createTestRootState} from '../../__tests__/fixtures/rootState'
9
- import {inputByName, withinDialog} from '../../__tests__/fixtures/withinDialog'
10
- import {tagsActions} from '../../modules/tags'
11
- import type {Tag} from '../../types'
12
- import DialogTagEdit from './index'
13
-
14
- const tag: Tag = {
15
- _id: 't1',
16
- _type: 'media.tag',
17
- _createdAt: '',
18
- _updatedAt: '',
19
- _rev: 'r1',
20
- name: {_type: 'slug', current: 'alpha'},
21
- }
22
-
23
- const tagsPreloaded = {
24
- allIds: ['t1'],
25
- byIds: {
26
- t1: {_type: 'tag' as const, tag, picked: false, updating: false},
27
- },
28
- creating: false,
29
- fetchCount: -1,
30
- fetching: false,
31
- panelVisible: true,
32
- }
33
-
34
- vi.mock('../../hooks/useVersionedClient', () => ({
35
- default: () =>
36
- createMockSanityClient({
37
- listen: vi.fn(() => new Subject()),
38
- }),
39
- }))
40
-
41
- describe('DialogTagEdit', () => {
42
- it('dispatches updateRequest when name changes and form submits', async () => {
43
- const user = userEvent.setup()
44
- const {store} = renderWithProviders(
45
- <DialogTagEdit dialog={{id: 'dlg-1', type: 'tagEdit', tagId: 't1'}}>
46
- <span />
47
- </DialogTagEdit>,
48
- {
49
- preloaded: {
50
- tags: tagsPreloaded,
51
- },
52
- },
53
- )
54
-
55
- const dlg = withinDialog(/edit tag/i, screen)
56
- const input = inputByName(/edit tag/i, screen, 'name')
57
- await user.clear(input)
58
- await user.type(input, 'beta')
59
- await user.click(dlg.getByRole('button', {name: /save and close/i}))
60
-
61
- expect(store.getState().tags.byIds['t1']!.updating).toBe(true)
62
- })
63
-
64
- it('dispatches updateRequest with slug-shaped form data', async () => {
65
- const user = userEvent.setup()
66
- const {store} = renderWithProviders(
67
- <DialogTagEdit dialog={{id: 'dlg-1', type: 'tagEdit', tagId: 't1'}}>
68
- <span />
69
- </DialogTagEdit>,
70
- {
71
- preloaded: {
72
- tags: tagsPreloaded,
73
- },
74
- },
75
- )
76
- const dispatchSpy = vi.spyOn(store, 'dispatch')
77
- const dlg = withinDialog(/edit tag/i, screen)
78
-
79
- const input = inputByName(/edit tag/i, screen, 'name')
80
- await user.clear(input)
81
- await user.type(input, 'gamma')
82
- await user.click(dlg.getByRole('button', {name: /save and close/i}))
83
-
84
- await waitFor(() => {
85
- let updateAction
86
- for (const call of dispatchSpy.mock.calls) {
87
- const action = call[0]
88
- if (tagsActions.updateRequest.match(action)) {
89
- updateAction = action
90
- break
91
- }
92
- }
93
- expect(updateAction).toBeDefined()
94
- expect(updateAction?.payload).toMatchObject({
95
- closeDialogId: 't1',
96
- formData: {
97
- name: {_type: 'slug', current: 'gamma'},
98
- },
99
- tag,
100
- })
101
- })
102
- })
103
-
104
- it('does not enable Save until the name is edited', () => {
105
- renderWithProviders(
106
- <DialogTagEdit dialog={{id: 'dlg-1', type: 'tagEdit', tagId: 't1'}}>
107
- <span />
108
- </DialogTagEdit>,
109
- {
110
- preloaded: {
111
- tags: tagsPreloaded,
112
- },
113
- },
114
- )
115
-
116
- const dlg = withinDialog(/edit tag/i, screen)
117
- expect(dlg.getByRole('button', {name: /save and close/i})).toBeDisabled()
118
- })
119
-
120
- it('removes only this dialog when closed', async () => {
121
- const user = userEvent.setup()
122
- const base = createTestRootState({
123
- dialog: {
124
- items: [
125
- {id: 'dlg-1', type: 'tagEdit', tagId: 't1'},
126
- {id: 'tags', type: 'tags'},
127
- ],
128
- },
129
- tags: tagsPreloaded,
130
- })
131
-
132
- const {store} = renderWithProviders(
133
- <DialogTagEdit dialog={{id: 'dlg-1', type: 'tagEdit', tagId: 't1'}}>
134
- <span />
135
- </DialogTagEdit>,
136
- {preloaded: base},
137
- )
138
-
139
- const dlg = withinDialog(/edit tag/i, screen)
140
- await user.click(dlg.getByRole('button', {name: /close dialog/i}))
141
-
142
- expect(store.getState().dialog.items).toEqual([{id: 'tags', type: 'tags'}])
143
- })
144
-
145
- it('opens the delete confirmation dialog when Delete is clicked', async () => {
146
- const {store} = renderWithProviders(
147
- <DialogTagEdit dialog={{id: 'dlg-1', type: 'tagEdit', tagId: 't1'}}>
148
- <span />
149
- </DialogTagEdit>,
150
- {
151
- preloaded: {
152
- tags: tagsPreloaded,
153
- },
154
- },
155
- )
156
-
157
- const dlg = withinDialog(/edit tag/i, screen)
158
- fireEvent.click(dlg.getByRole('button', {name: /^delete$/i}))
159
-
160
- const confirm = store.getState().dialog.items.find((d) => d.type === 'confirm')
161
- expect(confirm).toBeDefined()
162
- expect(confirm?.title).toMatch(/permanently delete/i)
163
- expect(confirm?.headerTitle).toBe('Confirm deletion')
164
- })
165
- })