sanity-plugin-dashboard-widget-vercel 3.1.6 → 4.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.
- package/README.md +8 -36
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1380 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -85
- package/lib/index.d.mts +0 -6
- package/lib/index.d.ts +0 -6
- package/lib/index.js +0 -1007
- package/lib/index.js.map +0 -1
- package/lib/index.mjs +0 -1005
- package/lib/index.mjs.map +0 -1
- package/sanity.json +0 -8
- package/src/app.tsx +0 -135
- package/src/client.ts +0 -7
- package/src/components/DeployButton/index.tsx +0 -86
- package/src/components/Deployment/index.tsx +0 -126
- package/src/components/DeploymentPlaceholder/index.tsx +0 -41
- package/src/components/DeploymentTarget/index.tsx +0 -51
- package/src/components/DeploymentTargets/index.tsx +0 -24
- package/src/components/Deployments/index.tsx +0 -187
- package/src/components/DialogForm/index.tsx +0 -220
- package/src/components/FormFieldInputLabel/index.tsx +0 -65
- package/src/components/FormFieldInputText/index.tsx +0 -43
- package/src/components/PlaceholderAvatar/index.tsx +0 -20
- package/src/components/PlaceholderText/index.tsx +0 -32
- package/src/components/StateDebug/index.tsx +0 -46
- package/src/components/StatusDot/index.tsx +0 -22
- package/src/components/TableCell/index.tsx +0 -81
- package/src/constants.ts +0 -26
- package/src/hooks/useDeployments.ts +0 -89
- package/src/index.ts +0 -16
- package/src/machines/deploy.ts +0 -117
- package/src/machines/deploymentTargetList.ts +0 -149
- package/src/machines/dialog.ts +0 -62
- package/src/machines/form.ts +0 -155
- package/src/machines/refresh.ts +0 -47
- package/src/types/index.ts +0 -49
- package/src/utils/fetcher.ts +0 -37
- package/src/utils/sanitizeFormData.ts +0 -26
- package/src/utils/useCardColor.ts +0 -5
- package/v2-incompatible.js +0 -11
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import {EditIcon} from '@sanity/icons'
|
|
2
|
-
import {Box, Button, Flex, Text, Tooltip} from '@sanity/ui'
|
|
3
|
-
import React, {FC} from 'react'
|
|
4
|
-
|
|
5
|
-
import Deployments from '../Deployments'
|
|
6
|
-
import {Sanity} from '../../types'
|
|
7
|
-
|
|
8
|
-
type Props = {
|
|
9
|
-
item: Sanity.DeploymentTarget
|
|
10
|
-
onDialogEdit: (deploymentTarget: Sanity.DeploymentTarget) => void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const DeploymentTarget: FC<Props> = (props: Props) => {
|
|
14
|
-
const {item, onDialogEdit} = props
|
|
15
|
-
|
|
16
|
-
const deploymentTarget = {
|
|
17
|
-
deployHook: item.deployHook,
|
|
18
|
-
deployLimit: item.deployLimit,
|
|
19
|
-
name: item.name,
|
|
20
|
-
projectId: item.projectId,
|
|
21
|
-
teamId: item.teamId,
|
|
22
|
-
token: item.token,
|
|
23
|
-
} as Sanity.DeploymentTarget
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<Box style={{position: 'relative'}}>
|
|
27
|
-
{/* Header */}
|
|
28
|
-
<Flex align="center" justify="space-between" marginTop={2} paddingX={3}>
|
|
29
|
-
<Text size={2}>{item.name}</Text>
|
|
30
|
-
|
|
31
|
-
<Tooltip
|
|
32
|
-
content={
|
|
33
|
-
<Box padding={2}>
|
|
34
|
-
<Text muted size={1}>
|
|
35
|
-
Edit deployment target
|
|
36
|
-
</Text>
|
|
37
|
-
</Box>
|
|
38
|
-
}
|
|
39
|
-
placement="left"
|
|
40
|
-
>
|
|
41
|
-
<Button fontSize={1} icon={EditIcon} mode="bleed" onClick={() => onDialogEdit(item)} />
|
|
42
|
-
</Tooltip>
|
|
43
|
-
</Flex>
|
|
44
|
-
|
|
45
|
-
{/* Content */}
|
|
46
|
-
<Deployments deploymentTarget={deploymentTarget} />
|
|
47
|
-
</Box>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default DeploymentTarget
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import {Stack} from '@sanity/ui'
|
|
3
|
-
|
|
4
|
-
import DeploymentTarget from '../DeploymentTarget'
|
|
5
|
-
import {Sanity} from '../../types'
|
|
6
|
-
|
|
7
|
-
type Props = {
|
|
8
|
-
items: Sanity.DeploymentTarget[]
|
|
9
|
-
onDialogEdit: (deploymentTarget: Sanity.DeploymentTarget) => void
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const DeploymentTargets = (props: Props) => {
|
|
13
|
-
const {items, onDialogEdit} = props
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<Stack space={5}>
|
|
17
|
-
{items?.map((item) => (
|
|
18
|
-
<DeploymentTarget item={item} key={item._id} onDialogEdit={onDialogEdit} />
|
|
19
|
-
))}
|
|
20
|
-
</Stack>
|
|
21
|
-
)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export default DeploymentTargets
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import {Box, Text, useToast} from '@sanity/ui'
|
|
2
|
-
import {useMachine} from '@xstate/react'
|
|
3
|
-
import React, {useEffect, useRef} from 'react'
|
|
4
|
-
import useDeepCompareEffect from 'use-deep-compare-effect'
|
|
5
|
-
|
|
6
|
-
import {WIDGET_NAME} from '../../constants'
|
|
7
|
-
import useDeployments from '../../hooks/useDeployments'
|
|
8
|
-
import refreshMachine from '../../machines/refresh'
|
|
9
|
-
import Deployment from '../Deployment'
|
|
10
|
-
import DeployButton from '../DeployButton'
|
|
11
|
-
import DeploymentPlaceholder from '../DeploymentPlaceholder'
|
|
12
|
-
import StateDebug from '../StateDebug'
|
|
13
|
-
import TableCell from '../TableCell'
|
|
14
|
-
import {Sanity} from '../../types'
|
|
15
|
-
import {useCardColor} from '../../utils/useCardColor'
|
|
16
|
-
|
|
17
|
-
type Props = {
|
|
18
|
-
deploymentTarget: Sanity.DeploymentTarget
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const Deployments = (props: Props) => {
|
|
22
|
-
const {deploymentTarget} = props
|
|
23
|
-
|
|
24
|
-
// Refs
|
|
25
|
-
const refTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
26
|
-
|
|
27
|
-
// XState
|
|
28
|
-
const [refreshState, refreshStateTransition] = useMachine(refreshMachine)
|
|
29
|
-
|
|
30
|
-
// Fetch deployments - disable hook / auto-refetching on error state
|
|
31
|
-
const {deployments, error, isFetching, isSuccess, refetch} = useDeployments(deploymentTarget, {
|
|
32
|
-
enabled: !refreshState.matches('error'),
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const toast = useToast()
|
|
36
|
-
const isError = refreshState.matches('error')
|
|
37
|
-
|
|
38
|
-
const handleDeploySuccess = () => {
|
|
39
|
-
if (refTimeout.current) {
|
|
40
|
-
clearTimeout(refTimeout.current)
|
|
41
|
-
}
|
|
42
|
-
refTimeout.current = setTimeout(() => {
|
|
43
|
-
refetch({
|
|
44
|
-
cancelRefetch: true,
|
|
45
|
-
throwOnError: true,
|
|
46
|
-
})
|
|
47
|
-
}, 4000)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
return () => {
|
|
52
|
-
if (refTimeout.current) {
|
|
53
|
-
clearTimeout(refTimeout.current)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}, [])
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
if (error) {
|
|
60
|
-
refreshStateTransition({type: 'ERROR'})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (isFetching) {
|
|
64
|
-
refreshStateTransition({type: 'REFRESH'})
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!isFetching && isSuccess) {
|
|
68
|
-
refreshStateTransition({type: 'REFRESHED'})
|
|
69
|
-
}
|
|
70
|
-
}, [error, isFetching, isSuccess, refreshStateTransition])
|
|
71
|
-
|
|
72
|
-
useDeepCompareEffect(() => {
|
|
73
|
-
if (!refreshState.matches('refreshing')) {
|
|
74
|
-
refreshStateTransition({type: 'REFRESH'})
|
|
75
|
-
}
|
|
76
|
-
}, [deploymentTarget])
|
|
77
|
-
|
|
78
|
-
useDeepCompareEffect(() => {
|
|
79
|
-
if (isError) {
|
|
80
|
-
toast.push({
|
|
81
|
-
closable: true,
|
|
82
|
-
description: `Unable to fetch deployments for ${deploymentTarget.name}`,
|
|
83
|
-
duration: 8000,
|
|
84
|
-
status: 'error',
|
|
85
|
-
title: WIDGET_NAME,
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
}, [deploymentTarget, isError])
|
|
89
|
-
|
|
90
|
-
const hasFetched = typeof deployments !== 'undefined'
|
|
91
|
-
const hasDeployments = deployments && deployments.length > 0
|
|
92
|
-
|
|
93
|
-
const {border} = useCardColor()
|
|
94
|
-
return (
|
|
95
|
-
<Box marginTop={3} style={{position: 'relative'}}>
|
|
96
|
-
{/* xstate debug */}
|
|
97
|
-
<StateDebug name="Refresh" state={refreshState} />
|
|
98
|
-
|
|
99
|
-
{!refreshState.matches('error') && (
|
|
100
|
-
<>
|
|
101
|
-
<Box
|
|
102
|
-
as="table"
|
|
103
|
-
style={{
|
|
104
|
-
borderBottom: `1px solid ${border}`,
|
|
105
|
-
borderCollapse: 'collapse',
|
|
106
|
-
display: 'table',
|
|
107
|
-
tableLayout: 'fixed',
|
|
108
|
-
width: '100%',
|
|
109
|
-
}}
|
|
110
|
-
>
|
|
111
|
-
<Box as="thead" style={{display: 'table-header-group'}}>
|
|
112
|
-
<tr>
|
|
113
|
-
{/* Deployment */}
|
|
114
|
-
<TableCell header>Deployment</TableCell>
|
|
115
|
-
|
|
116
|
-
{/* State */}
|
|
117
|
-
<TableCell header variant="state">
|
|
118
|
-
State
|
|
119
|
-
</TableCell>
|
|
120
|
-
|
|
121
|
-
{/* Branch */}
|
|
122
|
-
<TableCell header variant="branch">
|
|
123
|
-
Branch
|
|
124
|
-
</TableCell>
|
|
125
|
-
|
|
126
|
-
{/* Age */}
|
|
127
|
-
<TableCell header variant="age">
|
|
128
|
-
Age
|
|
129
|
-
</TableCell>
|
|
130
|
-
|
|
131
|
-
{/* Creator */}
|
|
132
|
-
<TableCell header variant="age">
|
|
133
|
-
Creator
|
|
134
|
-
</TableCell>
|
|
135
|
-
</tr>
|
|
136
|
-
</Box>
|
|
137
|
-
|
|
138
|
-
<Box as="tbody" style={{display: 'table-header-group'}}>
|
|
139
|
-
{/* Placeholders */}
|
|
140
|
-
{!deployments &&
|
|
141
|
-
new Array(deploymentTarget?.deployLimit)
|
|
142
|
-
.fill(undefined)
|
|
143
|
-
.map((_, index) => <DeploymentPlaceholder key={index} />)}
|
|
144
|
-
{/* Deployments */}
|
|
145
|
-
{hasDeployments &&
|
|
146
|
-
deployments?.map((deployment) => (
|
|
147
|
-
<Deployment deployment={deployment} key={deployment.uid} />
|
|
148
|
-
))}
|
|
149
|
-
</Box>
|
|
150
|
-
</Box>
|
|
151
|
-
|
|
152
|
-
{/* No results */}
|
|
153
|
-
{hasFetched && !hasDeployments && (
|
|
154
|
-
<Box padding={3} style={{width: '100%'}}>
|
|
155
|
-
<Text muted size={1}>
|
|
156
|
-
No deployments found. Don't forget to specify a valid team ID if your project
|
|
157
|
-
belongs to a team.
|
|
158
|
-
</Text>
|
|
159
|
-
</Box>
|
|
160
|
-
)}
|
|
161
|
-
</>
|
|
162
|
-
)}
|
|
163
|
-
|
|
164
|
-
{/* Error message */}
|
|
165
|
-
{refreshState.matches('error') && (
|
|
166
|
-
<Box padding={3}>
|
|
167
|
-
<Text muted size={1}>
|
|
168
|
-
Unable to fetch recent deployments. Please check your network and deployment settings.
|
|
169
|
-
</Text>
|
|
170
|
-
</Box>
|
|
171
|
-
)}
|
|
172
|
-
|
|
173
|
-
{/* Deploy button */}
|
|
174
|
-
{!refreshState.matches('error') && deploymentTarget.deployHook && (
|
|
175
|
-
<Box>
|
|
176
|
-
<DeployButton
|
|
177
|
-
deployHook={deploymentTarget.deployHook}
|
|
178
|
-
onDeploySuccess={handleDeploySuccess}
|
|
179
|
-
targetName={deploymentTarget.name}
|
|
180
|
-
/>
|
|
181
|
-
</Box>
|
|
182
|
-
)}
|
|
183
|
-
</Box>
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export default Deployments
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import {yupResolver} from '@hookform/resolvers/yup'
|
|
2
|
-
import {Box, Button, Dialog, Flex, Stack, useToast} from '@sanity/ui'
|
|
3
|
-
import {useActor} from '@xstate/react'
|
|
4
|
-
import React, {FC, useEffect} from 'react'
|
|
5
|
-
import {useForm} from 'react-hook-form'
|
|
6
|
-
import * as yup from 'yup'
|
|
7
|
-
|
|
8
|
-
import {Z_INDEX_DIALOG} from '../../constants'
|
|
9
|
-
import {formMachine} from '../../machines/form'
|
|
10
|
-
import sanitizeFormData from '../../utils/sanitizeFormData'
|
|
11
|
-
import FormFieldInputText from '../FormFieldInputText'
|
|
12
|
-
import {Sanity} from '../../types'
|
|
13
|
-
import {useSanityClient} from '../../client'
|
|
14
|
-
import {toPromise} from 'xstate'
|
|
15
|
-
|
|
16
|
-
type Props = {
|
|
17
|
-
deploymentTarget?: Sanity.DeploymentTarget
|
|
18
|
-
onClose: () => void
|
|
19
|
-
onCreate?: (deploymentTarget: Sanity.DeploymentTarget) => void
|
|
20
|
-
onDelete?: (id: string) => void
|
|
21
|
-
onUpdate?: (deploymentTarget: Sanity.DeploymentTarget) => void
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type FormData = yup.InferType<typeof formSchema>
|
|
25
|
-
|
|
26
|
-
const formSchema = yup.object().shape({
|
|
27
|
-
deployHook: yup.string().url('Deploy hook must be a valid URL'),
|
|
28
|
-
deployLimit: yup
|
|
29
|
-
.number()
|
|
30
|
-
.positive()
|
|
31
|
-
.integer()
|
|
32
|
-
.min(1, 'Deploy limit must no less than 1')
|
|
33
|
-
.max(15, 'Deploy limit must no higher than 15')
|
|
34
|
-
.typeError('Deploy limit must be a number')
|
|
35
|
-
.required('Deploy limit must be a positive integer between 1 and 15'),
|
|
36
|
-
name: yup.string().required('Name cannot be empty'),
|
|
37
|
-
projectId: yup.string().required('Vercel Project ID cannot be empty'),
|
|
38
|
-
teamId: yup.string(),
|
|
39
|
-
token: yup.string().required('Vercel Account Token cannot be empty'),
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
const DialogForm: FC<Props> = (props: Props) => {
|
|
43
|
-
const {deploymentTarget, onClose, onCreate, onDelete, onUpdate} = props
|
|
44
|
-
const client = useSanityClient()
|
|
45
|
-
const toast = useToast()
|
|
46
|
-
|
|
47
|
-
const [formState, formStateTransition, formStateActorRef] = useActor(formMachine, {
|
|
48
|
-
input: {client},
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const formUpdating = formState.hasTag('busy')
|
|
52
|
-
|
|
53
|
-
// react-hook-form v7
|
|
54
|
-
const {
|
|
55
|
-
formState: {errors, isDirty, isValid},
|
|
56
|
-
handleSubmit,
|
|
57
|
-
register,
|
|
58
|
-
} = useForm<FormData>({
|
|
59
|
-
// @ts-expect-error - fix typings later
|
|
60
|
-
defaultValues: {
|
|
61
|
-
deployHook: deploymentTarget?.deployHook || '',
|
|
62
|
-
deployLimit: deploymentTarget?.deployLimit || 5,
|
|
63
|
-
name: deploymentTarget?.name || '',
|
|
64
|
-
projectId: deploymentTarget?.projectId || '',
|
|
65
|
-
teamId: deploymentTarget?.teamId || '',
|
|
66
|
-
token: deploymentTarget?.token || '',
|
|
67
|
-
},
|
|
68
|
-
mode: 'onChange',
|
|
69
|
-
resolver: yupResolver(formSchema),
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Handle errors and reaching the done state
|
|
74
|
-
*/
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
if (formState.matches('error')) {
|
|
77
|
-
toast.push({
|
|
78
|
-
status: 'error',
|
|
79
|
-
title: formState.context.message || 'An error occurred',
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* If the machine is done it means it reached updated, created, deleted or error state.
|
|
84
|
-
* We don't care which one, we just want to close the dialog
|
|
85
|
-
*/
|
|
86
|
-
if (formState.status === 'done') {
|
|
87
|
-
onClose()
|
|
88
|
-
}
|
|
89
|
-
}, [formState, onClose, toast])
|
|
90
|
-
|
|
91
|
-
// Callbacks
|
|
92
|
-
// - submit react-hook-form
|
|
93
|
-
const onSubmit = async (formData: FormData) => {
|
|
94
|
-
const sanitizedFormData = sanitizeFormData(formData)
|
|
95
|
-
if (deploymentTarget) {
|
|
96
|
-
formStateTransition({type: 'UPDATE', id: deploymentTarget._id, formData: sanitizedFormData})
|
|
97
|
-
} else {
|
|
98
|
-
formStateTransition({type: 'CREATE', formData: sanitizedFormData})
|
|
99
|
-
}
|
|
100
|
-
await toPromise(formStateActorRef)
|
|
101
|
-
const snapshot = formStateActorRef.getSnapshot()
|
|
102
|
-
const {document} = snapshot.context
|
|
103
|
-
if (!document) return
|
|
104
|
-
if (snapshot.matches('created')) {
|
|
105
|
-
onCreate?.(document)
|
|
106
|
-
} else if (snapshot.matches('updated')) {
|
|
107
|
-
onUpdate?.(document)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const handleDelete = async () => {
|
|
112
|
-
const id = deploymentTarget!._id
|
|
113
|
-
formStateTransition({type: 'DELETE', id})
|
|
114
|
-
await toPromise(formStateActorRef)
|
|
115
|
-
if (formStateActorRef.getSnapshot().matches('deleted')) {
|
|
116
|
-
onDelete?.(id)
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<Dialog
|
|
122
|
-
footer={
|
|
123
|
-
<Box padding={3}>
|
|
124
|
-
<Flex justify={deploymentTarget ? 'space-between' : 'flex-end'}>
|
|
125
|
-
{/* Delete button */}
|
|
126
|
-
{deploymentTarget && (
|
|
127
|
-
<Button
|
|
128
|
-
loading={formState.matches('deleting')}
|
|
129
|
-
disabled={formUpdating}
|
|
130
|
-
fontSize={1}
|
|
131
|
-
mode="bleed"
|
|
132
|
-
onClick={handleDelete}
|
|
133
|
-
text="Delete"
|
|
134
|
-
tone="critical"
|
|
135
|
-
/>
|
|
136
|
-
)}
|
|
137
|
-
|
|
138
|
-
{/* Submit button */}
|
|
139
|
-
<Button
|
|
140
|
-
loading={formState.matches('creating') || formState.matches('updating')}
|
|
141
|
-
disabled={!isDirty || !isValid}
|
|
142
|
-
fontSize={1}
|
|
143
|
-
onClick={handleSubmit(onSubmit)}
|
|
144
|
-
text={deploymentTarget ? 'Update and close' : 'Create'}
|
|
145
|
-
tone="primary"
|
|
146
|
-
/>
|
|
147
|
-
</Flex>
|
|
148
|
-
</Box>
|
|
149
|
-
}
|
|
150
|
-
header={`${deploymentTarget ? 'Edit' : 'Create'} deployment target`}
|
|
151
|
-
id="create"
|
|
152
|
-
onClose={onClose}
|
|
153
|
-
width={1}
|
|
154
|
-
zOffset={Z_INDEX_DIALOG}
|
|
155
|
-
>
|
|
156
|
-
{/* We reverse direction to ensure that inline links dont autofocus before other form elements */}
|
|
157
|
-
<Box as="form" padding={4} onSubmit={handleSubmit(onSubmit)}>
|
|
158
|
-
{/* Hidden button to enable enter key submissions */}
|
|
159
|
-
<button style={{display: 'none'}} tabIndex={-1} type="submit" />
|
|
160
|
-
|
|
161
|
-
{/* Form fields */}
|
|
162
|
-
<Stack space={5}>
|
|
163
|
-
{/* Title */}
|
|
164
|
-
<FormFieldInputText
|
|
165
|
-
disabled={formUpdating}
|
|
166
|
-
description="Name displayed in this plugin (e.g. production, staging)"
|
|
167
|
-
error={errors?.name}
|
|
168
|
-
label="Name"
|
|
169
|
-
// @ts-expect-error - fix typings later
|
|
170
|
-
{...register('name')}
|
|
171
|
-
/>
|
|
172
|
-
|
|
173
|
-
<FormFieldInputText
|
|
174
|
-
disabled={formUpdating}
|
|
175
|
-
error={errors?.token}
|
|
176
|
-
label="Vercel Account Token"
|
|
177
|
-
// @ts-expect-error - fix typings later
|
|
178
|
-
{...register('token')}
|
|
179
|
-
/>
|
|
180
|
-
|
|
181
|
-
<FormFieldInputText
|
|
182
|
-
disabled={formUpdating}
|
|
183
|
-
error={errors?.projectId}
|
|
184
|
-
label="Vercel Project ID"
|
|
185
|
-
// @ts-expect-error - fix typings later
|
|
186
|
-
{...register('projectId')}
|
|
187
|
-
/>
|
|
188
|
-
|
|
189
|
-
<FormFieldInputText
|
|
190
|
-
description="Required only if your project is owned by a team account"
|
|
191
|
-
disabled={formUpdating}
|
|
192
|
-
error={errors?.teamId}
|
|
193
|
-
label="Vercel Team ID (optional)"
|
|
194
|
-
// @ts-expect-error - fix typings later
|
|
195
|
-
{...register('teamId')}
|
|
196
|
-
/>
|
|
197
|
-
|
|
198
|
-
<FormFieldInputText
|
|
199
|
-
description="Enter a valid deploy hook URL to enable manual deploys"
|
|
200
|
-
disabled={formUpdating}
|
|
201
|
-
error={errors?.deployHook}
|
|
202
|
-
label="Vercel Deploy Hook (optional)"
|
|
203
|
-
// @ts-expect-error - fix typings later
|
|
204
|
-
{...register('deployHook')}
|
|
205
|
-
/>
|
|
206
|
-
|
|
207
|
-
<FormFieldInputText
|
|
208
|
-
disabled={formUpdating}
|
|
209
|
-
error={errors?.deployLimit}
|
|
210
|
-
label="Number of deploys to display"
|
|
211
|
-
// @ts-expect-error - fix typings later
|
|
212
|
-
{...register('deployLimit', {valueAsNumber: true})}
|
|
213
|
-
/>
|
|
214
|
-
</Stack>
|
|
215
|
-
</Box>
|
|
216
|
-
</Dialog>
|
|
217
|
-
)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export default DialogForm
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import {ErrorOutlineIcon} from '@sanity/icons'
|
|
2
|
-
import {Box, Inline, Text, Tooltip} from '@sanity/ui'
|
|
3
|
-
import React, {FC} from 'react'
|
|
4
|
-
import {FieldError} from 'react-hook-form'
|
|
5
|
-
import {styled} from 'styled-components'
|
|
6
|
-
|
|
7
|
-
type Props = {
|
|
8
|
-
description?: string
|
|
9
|
-
error?: FieldError
|
|
10
|
-
label: string
|
|
11
|
-
name: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const StyledErrorOutlineIcon = styled(ErrorOutlineIcon)(({theme}) => {
|
|
15
|
-
return {
|
|
16
|
-
color: theme.sanity.color.spot.red,
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
const FormFieldInputLabel: FC<Props> = (props: Props) => {
|
|
21
|
-
const {description, error, label, name} = props
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<Box marginBottom={3}>
|
|
25
|
-
{/* Label */}
|
|
26
|
-
<Inline space={2}>
|
|
27
|
-
<Text as="label" htmlFor={name} size={1} weight="semibold">
|
|
28
|
-
{label}
|
|
29
|
-
</Text>
|
|
30
|
-
|
|
31
|
-
{/* Error icon + tooltip */}
|
|
32
|
-
{error && (
|
|
33
|
-
<Text size={1}>
|
|
34
|
-
<Tooltip
|
|
35
|
-
content={
|
|
36
|
-
<Box padding={2}>
|
|
37
|
-
<Text muted size={1}>
|
|
38
|
-
<StyledErrorOutlineIcon style={{marginRight: '0.1em'}} />
|
|
39
|
-
{error.message}
|
|
40
|
-
</Text>
|
|
41
|
-
</Box>
|
|
42
|
-
}
|
|
43
|
-
fallbackPlacements={['top', 'left']}
|
|
44
|
-
placement="right"
|
|
45
|
-
portal
|
|
46
|
-
>
|
|
47
|
-
<StyledErrorOutlineIcon />
|
|
48
|
-
</Tooltip>
|
|
49
|
-
</Text>
|
|
50
|
-
)}
|
|
51
|
-
</Inline>
|
|
52
|
-
|
|
53
|
-
{/* Description */}
|
|
54
|
-
{description && (
|
|
55
|
-
<Box marginY={3}>
|
|
56
|
-
<Text htmlFor={name} muted size={1}>
|
|
57
|
-
{description}
|
|
58
|
-
</Text>
|
|
59
|
-
</Box>
|
|
60
|
-
)}
|
|
61
|
-
</Box>
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export default FormFieldInputLabel
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {Box, TextInput} from '@sanity/ui'
|
|
2
|
-
import React, {forwardRef} from 'react'
|
|
3
|
-
import {FieldError} from 'react-hook-form'
|
|
4
|
-
|
|
5
|
-
import FormFieldInputLabel from '../FormFieldInputLabel'
|
|
6
|
-
|
|
7
|
-
type Props = {
|
|
8
|
-
description?: string
|
|
9
|
-
disabled?: boolean
|
|
10
|
-
error?: FieldError
|
|
11
|
-
label: string
|
|
12
|
-
name: string
|
|
13
|
-
placeholder?: string
|
|
14
|
-
value?: string
|
|
15
|
-
onChange?: React.ChangeEventHandler<HTMLInputElement>
|
|
16
|
-
onBlur?: React.FocusEventHandler<HTMLInputElement>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const FormFieldInputText = forwardRef<HTMLInputElement, Props>((props: Props, ref) => {
|
|
20
|
-
const {description, disabled, error, label, name, placeholder, value, onChange, onBlur} = props
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<Box>
|
|
24
|
-
{/* Label */}
|
|
25
|
-
<FormFieldInputLabel description={description} error={error} label={label} name={name} />
|
|
26
|
-
{/* Input */}
|
|
27
|
-
<TextInput
|
|
28
|
-
autoComplete="off"
|
|
29
|
-
autoFocus
|
|
30
|
-
defaultValue={value}
|
|
31
|
-
disabled={disabled}
|
|
32
|
-
id={name}
|
|
33
|
-
name={name}
|
|
34
|
-
placeholder={placeholder}
|
|
35
|
-
onChange={onChange}
|
|
36
|
-
onBlur={onBlur}
|
|
37
|
-
ref={ref}
|
|
38
|
-
/>
|
|
39
|
-
</Box>
|
|
40
|
-
)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
export default FormFieldInputText
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {Box} from '@sanity/ui'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import {useCardColor} from '../../utils/useCardColor'
|
|
4
|
-
|
|
5
|
-
const PlaceholderAvatar = () => {
|
|
6
|
-
const {border} = useCardColor()
|
|
7
|
-
return (
|
|
8
|
-
<Box
|
|
9
|
-
style={{
|
|
10
|
-
backgroundColor: border,
|
|
11
|
-
borderRadius: '20px',
|
|
12
|
-
height: '20px',
|
|
13
|
-
userSelect: 'none',
|
|
14
|
-
width: '20px',
|
|
15
|
-
}}
|
|
16
|
-
/>
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default PlaceholderAvatar
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {Box, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import {useCardColor} from '../../utils/useCardColor'
|
|
4
|
-
|
|
5
|
-
type Props = {
|
|
6
|
-
rows: number
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const PlaceholderText = (props: Props) => {
|
|
10
|
-
const {rows} = props
|
|
11
|
-
const {border} = useCardColor()
|
|
12
|
-
return (
|
|
13
|
-
<Box
|
|
14
|
-
style={{
|
|
15
|
-
backgroundColor: border,
|
|
16
|
-
borderRadius: '3px',
|
|
17
|
-
userSelect: 'none',
|
|
18
|
-
width: '100%',
|
|
19
|
-
}}
|
|
20
|
-
>
|
|
21
|
-
<Stack space={2}>
|
|
22
|
-
{new Array(rows).fill(undefined).map((_, index) => (
|
|
23
|
-
<Text key={index} size={1}>
|
|
24
|
-
|
|
25
|
-
</Text>
|
|
26
|
-
))}
|
|
27
|
-
</Stack>
|
|
28
|
-
</Box>
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export default PlaceholderText
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {Box, Card, Stack, Text} from '@sanity/ui'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
|
|
4
|
-
import {DEBUG_MODE} from '../../constants'
|
|
5
|
-
|
|
6
|
-
type Props = {
|
|
7
|
-
name: string
|
|
8
|
-
state: any // TODO: type correctly
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const StateDebug = (props: Props) => {
|
|
12
|
-
const {name, state} = props
|
|
13
|
-
|
|
14
|
-
if (!DEBUG_MODE) {
|
|
15
|
-
return null
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<Card
|
|
20
|
-
scheme="dark"
|
|
21
|
-
style={{
|
|
22
|
-
backgroundColor: 'rgba(0, 0, 255, 0.9)',
|
|
23
|
-
borderRadius: '3px',
|
|
24
|
-
fontSize: 1,
|
|
25
|
-
fontWeight: 500,
|
|
26
|
-
lineHeight: 'body',
|
|
27
|
-
right: 0,
|
|
28
|
-
opacity: 0.75,
|
|
29
|
-
pointerEvents: 'none',
|
|
30
|
-
position: 'absolute',
|
|
31
|
-
textAlign: 'left',
|
|
32
|
-
top: 0,
|
|
33
|
-
zIndex: 9000,
|
|
34
|
-
}}
|
|
35
|
-
>
|
|
36
|
-
<Box padding={2}>
|
|
37
|
-
<Stack space={2}>
|
|
38
|
-
<Text size={0}>Name: {name}</Text>
|
|
39
|
-
<Text size={0}>state.value: {JSON.stringify(state.value)}</Text>
|
|
40
|
-
</Stack>
|
|
41
|
-
</Box>
|
|
42
|
-
</Card>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export default StateDebug
|