@sanity/dashboard 5.0.1 → 6.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/LICENSE +1 -1
- package/README.md +4 -50
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +605 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -79
- package/lib/index.d.mts +0 -65
- package/lib/index.d.ts +0 -65
- package/lib/index.esm.js +0 -568
- package/lib/index.esm.js.map +0 -1
- package/lib/index.js +0 -564
- package/lib/index.js.map +0 -1
- package/lib/index.mjs +0 -568
- package/lib/index.mjs.map +0 -1
- package/sanity.json +0 -8
- package/src/components/DashboardLayout.tsx +0 -10
- package/src/components/DashboardWidgetContainer.tsx +0 -69
- package/src/components/NotFoundWidget.tsx +0 -30
- package/src/components/WidgetGroup.tsx +0 -106
- package/src/containers/Dashboard.tsx +0 -19
- package/src/containers/DashboardContext.tsx +0 -8
- package/src/containers/WidgetContainer.tsx +0 -21
- package/src/index.ts +0 -7
- package/src/plugin.tsx +0 -72
- package/src/types.ts +0 -21
- package/src/versionedClient.ts +0 -5
- package/src/widgets/projectInfo/ProjectInfo.tsx +0 -221
- package/src/widgets/projectInfo/index.ts +0 -10
- package/src/widgets/projectInfo/types.ts +0 -28
- package/src/widgets/projectUsers/ProjectUser.tsx +0 -45
- package/src/widgets/projectUsers/ProjectUsers.tsx +0 -148
- package/src/widgets/projectUsers/index.ts +0 -10
- package/src/widgets/sanityTutorials/SanityTutorials.tsx +0 -77
- package/src/widgets/sanityTutorials/Tutorial.tsx +0 -111
- package/src/widgets/sanityTutorials/dataAdapter.ts +0 -49
- package/src/widgets/sanityTutorials/index.ts +0 -10
- package/v2-incompatible.js +0 -11
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import {Box, Flex, rem, Stack, Text} from '@sanity/ui'
|
|
3
|
-
import {styled} from 'styled-components'
|
|
4
|
-
import {useListFormat, type User, UserAvatar} from 'sanity'
|
|
5
|
-
import {RobotIcon} from '@sanity/icons'
|
|
6
|
-
|
|
7
|
-
const Root = styled(Flex)`
|
|
8
|
-
height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height
|
|
9
|
-
box-sizing: content-box;
|
|
10
|
-
`
|
|
11
|
-
|
|
12
|
-
export interface ProjectUserProps {
|
|
13
|
-
user: User
|
|
14
|
-
isRobot: boolean
|
|
15
|
-
roles: string[]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function ProjectUser({user, isRobot, roles}: ProjectUserProps) {
|
|
19
|
-
const listFormat = useListFormat({style: 'narrow'})
|
|
20
|
-
return (
|
|
21
|
-
<Root align="center">
|
|
22
|
-
<Flex align="center" flex={1} gap={2}>
|
|
23
|
-
<Box flex="none">
|
|
24
|
-
{isRobot ? (
|
|
25
|
-
<Text size={2}>
|
|
26
|
-
<RobotIcon />
|
|
27
|
-
</Text>
|
|
28
|
-
) : (
|
|
29
|
-
<UserAvatar user={user} />
|
|
30
|
-
)}
|
|
31
|
-
</Box>
|
|
32
|
-
|
|
33
|
-
<Stack flex={1} space={2}>
|
|
34
|
-
<Text size={1} style={{color: 'inherit'}} textOverflow="ellipsis" weight="medium">
|
|
35
|
-
{user.displayName}
|
|
36
|
-
</Text>
|
|
37
|
-
|
|
38
|
-
<Text muted size={1} textOverflow="ellipsis">
|
|
39
|
-
{listFormat.format(roles)}
|
|
40
|
-
</Text>
|
|
41
|
-
</Stack>
|
|
42
|
-
</Flex>
|
|
43
|
-
</Root>
|
|
44
|
-
)
|
|
45
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import React, {useCallback, useEffect, useState} from 'react'
|
|
2
|
-
import {from} from 'rxjs'
|
|
3
|
-
import {map, switchMap} from 'rxjs/operators'
|
|
4
|
-
import {Stack, Spinner, Box, Text, Button} from '@sanity/ui'
|
|
5
|
-
import {Role, useUserStore} from 'sanity'
|
|
6
|
-
import {useVersionedClient} from '../../versionedClient'
|
|
7
|
-
import {User} from 'sanity'
|
|
8
|
-
import {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'
|
|
9
|
-
import {ProjectUser} from './ProjectUser'
|
|
10
|
-
|
|
11
|
-
function getInviteUrl(projectId: string) {
|
|
12
|
-
return `https://manage.sanity.io/projects/${projectId}/members`
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface Member {
|
|
16
|
-
id: string
|
|
17
|
-
roles: Role[]
|
|
18
|
-
isRobot: boolean
|
|
19
|
-
isCurrentUser: boolean
|
|
20
|
-
createdAt: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface Project {
|
|
24
|
-
id: string
|
|
25
|
-
members: Member[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function ProjectUsers() {
|
|
29
|
-
const [project, setProject] = useState<Project | undefined>()
|
|
30
|
-
const [users, setUsers] = useState<User[] | undefined>()
|
|
31
|
-
const [error, setError] = useState<Error | undefined>()
|
|
32
|
-
|
|
33
|
-
const userStore = useUserStore()
|
|
34
|
-
const versionedClient = useVersionedClient()
|
|
35
|
-
|
|
36
|
-
const fetchData = useCallback(() => {
|
|
37
|
-
const {projectId} = versionedClient.config()
|
|
38
|
-
const subscription = versionedClient.observable
|
|
39
|
-
.request<Project>({
|
|
40
|
-
uri: `/projects/${projectId}`,
|
|
41
|
-
tag: 'dashboard.project-users',
|
|
42
|
-
})
|
|
43
|
-
.pipe(
|
|
44
|
-
switchMap((_project) =>
|
|
45
|
-
from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(
|
|
46
|
-
map((_users) => ({project: _project, users: _users})),
|
|
47
|
-
),
|
|
48
|
-
),
|
|
49
|
-
)
|
|
50
|
-
.subscribe({
|
|
51
|
-
next: ({users: _users, project: _project}) => {
|
|
52
|
-
setProject(_project)
|
|
53
|
-
setUsers(
|
|
54
|
-
(Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>
|
|
55
|
-
sortUsersByRobotStatus(userA, userB, _project),
|
|
56
|
-
),
|
|
57
|
-
)
|
|
58
|
-
},
|
|
59
|
-
error: (e: Error) => setError(e),
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
return () => subscription.unsubscribe()
|
|
63
|
-
}, [userStore, versionedClient])
|
|
64
|
-
|
|
65
|
-
useEffect(() => fetchData(), [fetchData])
|
|
66
|
-
|
|
67
|
-
const handleRetryFetch = useCallback(() => fetchData(), [fetchData])
|
|
68
|
-
|
|
69
|
-
const isLoading = !users || !project
|
|
70
|
-
|
|
71
|
-
if (error) {
|
|
72
|
-
return (
|
|
73
|
-
<DashboardWidgetContainer header="Project users">
|
|
74
|
-
<Box padding={4}>
|
|
75
|
-
<Text>
|
|
76
|
-
Something went wrong while fetching data. You could{' '}
|
|
77
|
-
<a onClick={handleRetryFetch} title="Retry users fetch" style={{cursor: 'pointer'}}>
|
|
78
|
-
retry
|
|
79
|
-
</a>
|
|
80
|
-
..?
|
|
81
|
-
</Text>
|
|
82
|
-
</Box>
|
|
83
|
-
</DashboardWidgetContainer>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<DashboardWidgetContainer
|
|
89
|
-
header="Project users"
|
|
90
|
-
footer={
|
|
91
|
-
<Button
|
|
92
|
-
style={{width: '100%'}}
|
|
93
|
-
paddingX={2}
|
|
94
|
-
paddingY={4}
|
|
95
|
-
mode="bleed"
|
|
96
|
-
tone="primary"
|
|
97
|
-
text="Manage members"
|
|
98
|
-
as="a"
|
|
99
|
-
loading={isLoading}
|
|
100
|
-
href={isLoading ? undefined : getInviteUrl(project.id)}
|
|
101
|
-
/>
|
|
102
|
-
}
|
|
103
|
-
>
|
|
104
|
-
{isLoading && (
|
|
105
|
-
<Box paddingY={5} paddingX={2}>
|
|
106
|
-
<Stack space={4}>
|
|
107
|
-
<Text align="center" muted size={1}>
|
|
108
|
-
<Spinner />
|
|
109
|
-
</Text>
|
|
110
|
-
<Text align="center" size={1} muted>
|
|
111
|
-
Loading items…
|
|
112
|
-
</Text>
|
|
113
|
-
</Stack>
|
|
114
|
-
</Box>
|
|
115
|
-
)}
|
|
116
|
-
|
|
117
|
-
{!isLoading && (
|
|
118
|
-
<Stack space={3} padding={3}>
|
|
119
|
-
{users?.map((user) => {
|
|
120
|
-
const membership = project.members.find((member) => member.id === user.id)
|
|
121
|
-
return (
|
|
122
|
-
<ProjectUser
|
|
123
|
-
key={user.id}
|
|
124
|
-
user={user}
|
|
125
|
-
isRobot={membership?.isRobot ?? false}
|
|
126
|
-
roles={membership?.roles.map((role) => role.title) || []}
|
|
127
|
-
/>
|
|
128
|
-
)
|
|
129
|
-
})}
|
|
130
|
-
</Stack>
|
|
131
|
-
)}
|
|
132
|
-
</DashboardWidgetContainer>
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function sortUsersByRobotStatus(userA: User, userB: User, project: Project) {
|
|
137
|
-
const {members} = project
|
|
138
|
-
const membershipA = members.find((member) => member.id === userA?.id)
|
|
139
|
-
const membershipB = members.find((member) => member.id === userB?.id)
|
|
140
|
-
|
|
141
|
-
// On ties, sort by when the user was added
|
|
142
|
-
if (membershipA?.isRobot === membershipB?.isRobot) {
|
|
143
|
-
return (membershipA?.createdAt || '') > (membershipB?.createdAt || '') ? 1 : -1
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Robots go to the bottom
|
|
147
|
-
return membershipA?.isRobot ? 1 : -1
|
|
148
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import {ProjectUsers} from './ProjectUsers'
|
|
2
|
-
import {LayoutConfig, DashboardWidget} from '../../types'
|
|
3
|
-
|
|
4
|
-
export function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {
|
|
5
|
-
return {
|
|
6
|
-
name: 'project-info',
|
|
7
|
-
component: ProjectUsers,
|
|
8
|
-
layout: config?.layout,
|
|
9
|
-
}
|
|
10
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import React, {useEffect, useState} from 'react'
|
|
2
|
-
import {Flex} from '@sanity/ui'
|
|
3
|
-
import {Tutorial} from './Tutorial'
|
|
4
|
-
import {FeedItem, Guide, useDataAdapter} from './dataAdapter'
|
|
5
|
-
import {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'
|
|
6
|
-
|
|
7
|
-
function createUrl(slug: {current: string}, type?: string) {
|
|
8
|
-
if (type === 'tutorial') {
|
|
9
|
-
return `https://www.sanity.io/docs/tutorials/${slug.current}`
|
|
10
|
-
} else if (type === 'guide') {
|
|
11
|
-
return `https://www.sanity.io/docs/guides/${slug.current}`
|
|
12
|
-
}
|
|
13
|
-
return false
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface SanityTutorialsProps {
|
|
17
|
-
templateRepoId: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function SanityTutorials(props: SanityTutorialsProps) {
|
|
21
|
-
const {templateRepoId} = props
|
|
22
|
-
const [feedItems, setFeedItems] = useState<FeedItem[]>([])
|
|
23
|
-
|
|
24
|
-
const {getFeed, urlBuilder} = useDataAdapter()
|
|
25
|
-
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
const subscription = getFeed(templateRepoId).subscribe((response) => {
|
|
28
|
-
setFeedItems(response.items)
|
|
29
|
-
})
|
|
30
|
-
return () => {
|
|
31
|
-
subscription.unsubscribe()
|
|
32
|
-
}
|
|
33
|
-
}, [setFeedItems, getFeed, templateRepoId])
|
|
34
|
-
|
|
35
|
-
const title = 'Learn about Sanity'
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<DashboardWidgetContainer header={title}>
|
|
39
|
-
<Flex as="ul" overflow="auto" align="stretch" paddingY={2}>
|
|
40
|
-
{feedItems?.map((feedItem, index) => {
|
|
41
|
-
if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {
|
|
42
|
-
return null
|
|
43
|
-
}
|
|
44
|
-
const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}
|
|
45
|
-
const subtitle = feedItem.category
|
|
46
|
-
const {guideOrTutorial = {} as Guide} = feedItem
|
|
47
|
-
const href =
|
|
48
|
-
(guideOrTutorial.slug
|
|
49
|
-
? createUrl(guideOrTutorial.slug, guideOrTutorial._type)
|
|
50
|
-
: feedItem.externalLink) || feedItem.externalLink
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<Flex
|
|
54
|
-
as="li"
|
|
55
|
-
key={feedItem._id}
|
|
56
|
-
paddingRight={index < feedItems?.length - 1 ? 1 : 3}
|
|
57
|
-
paddingLeft={index === 0 ? 3 : 0}
|
|
58
|
-
align="stretch"
|
|
59
|
-
style={{minWidth: 272, width: '30%'}}
|
|
60
|
-
>
|
|
61
|
-
<Tutorial
|
|
62
|
-
title={feedItem.title}
|
|
63
|
-
href={href ?? ''}
|
|
64
|
-
presenterName={presenter.name}
|
|
65
|
-
presenterSubtitle={subtitle}
|
|
66
|
-
showPlayIcon={feedItem.hasVideo}
|
|
67
|
-
posterURL={
|
|
68
|
-
feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined
|
|
69
|
-
}
|
|
70
|
-
/>
|
|
71
|
-
</Flex>
|
|
72
|
-
)
|
|
73
|
-
})}
|
|
74
|
-
</Flex>
|
|
75
|
-
</DashboardWidgetContainer>
|
|
76
|
-
)
|
|
77
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'
|
|
3
|
-
import {PlayIcon} from '@sanity/icons'
|
|
4
|
-
import {styled} from 'styled-components'
|
|
5
|
-
|
|
6
|
-
const PlayIconBox = styled(Box)`
|
|
7
|
-
position: absolute;
|
|
8
|
-
top: 50%;
|
|
9
|
-
left: 50%;
|
|
10
|
-
transform: translate(-50%, -50%);
|
|
11
|
-
|
|
12
|
-
&:before {
|
|
13
|
-
content: '';
|
|
14
|
-
position: absolute;
|
|
15
|
-
top: 50%;
|
|
16
|
-
left: 50%;
|
|
17
|
-
transform: translate(-50%, -50%);
|
|
18
|
-
width: 2.75em;
|
|
19
|
-
height: 2.75em;
|
|
20
|
-
border-radius: 50%;
|
|
21
|
-
background: ${({theme}) => theme.sanity.color.card.enabled.bg};
|
|
22
|
-
opacity: 0.75;
|
|
23
|
-
}
|
|
24
|
-
`
|
|
25
|
-
|
|
26
|
-
const Root = styled(Flex)`
|
|
27
|
-
&:hover {
|
|
28
|
-
${PlayIconBox} {
|
|
29
|
-
&:before {
|
|
30
|
-
opacity: 1;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
`
|
|
35
|
-
|
|
36
|
-
const PosterCard = styled(Card)`
|
|
37
|
-
width: 100%;
|
|
38
|
-
padding-bottom: calc(9 / 16 * 100%);
|
|
39
|
-
position: relative;
|
|
40
|
-
`
|
|
41
|
-
|
|
42
|
-
const Poster = styled.img`
|
|
43
|
-
position: absolute;
|
|
44
|
-
top: 0;
|
|
45
|
-
left: 0;
|
|
46
|
-
height: 100%;
|
|
47
|
-
width: 100%;
|
|
48
|
-
object-fit: cover;
|
|
49
|
-
display: block;
|
|
50
|
-
|
|
51
|
-
&:not([src]) {
|
|
52
|
-
display: none;
|
|
53
|
-
}
|
|
54
|
-
`
|
|
55
|
-
|
|
56
|
-
export interface TutorialProps {
|
|
57
|
-
title: string
|
|
58
|
-
posterURL?: string
|
|
59
|
-
href: string
|
|
60
|
-
showPlayIcon?: boolean
|
|
61
|
-
presenterName?: string
|
|
62
|
-
presenterSubtitle?: string
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function Tutorial(props: TutorialProps) {
|
|
66
|
-
const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<Root flex={1}>
|
|
70
|
-
<Card
|
|
71
|
-
sizing="border"
|
|
72
|
-
flex={1}
|
|
73
|
-
padding={2}
|
|
74
|
-
radius={2}
|
|
75
|
-
as="a"
|
|
76
|
-
href={href}
|
|
77
|
-
target="_blank"
|
|
78
|
-
rel="noopener noreferrer"
|
|
79
|
-
style={{position: 'relative'}}
|
|
80
|
-
>
|
|
81
|
-
<Flex direction="column" style={{height: '100%'}}>
|
|
82
|
-
{posterURL && (
|
|
83
|
-
<PosterCard marginBottom={1}>
|
|
84
|
-
<Poster src={posterURL} />
|
|
85
|
-
{showPlayIcon && (
|
|
86
|
-
<PlayIconBox display="flex">
|
|
87
|
-
<Text align="center">
|
|
88
|
-
<PlayIcon />
|
|
89
|
-
</Text>
|
|
90
|
-
</PlayIconBox>
|
|
91
|
-
)}
|
|
92
|
-
</PosterCard>
|
|
93
|
-
)}
|
|
94
|
-
<Flex direction="column" justify="space-between" paddingY={2} flex={1}>
|
|
95
|
-
<Heading as="h3" size={1}>
|
|
96
|
-
{title}
|
|
97
|
-
</Heading>
|
|
98
|
-
<Box marginTop={4}>
|
|
99
|
-
<Stack space={2} flex={1}>
|
|
100
|
-
<Text size={1}>{presenterName}</Text>
|
|
101
|
-
<Text size={0} style={{opacity: 0.7}}>
|
|
102
|
-
{presenterSubtitle}
|
|
103
|
-
</Text>
|
|
104
|
-
</Stack>
|
|
105
|
-
</Box>
|
|
106
|
-
</Flex>
|
|
107
|
-
</Flex>
|
|
108
|
-
</Card>
|
|
109
|
-
</Root>
|
|
110
|
-
)
|
|
111
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import {useMemo} from 'react'
|
|
2
|
-
import {useVersionedClient} from '../../versionedClient'
|
|
3
|
-
import imageUrlBuilder from '@sanity/image-url'
|
|
4
|
-
|
|
5
|
-
const tutorialsProjectConfig = {
|
|
6
|
-
projectId: '3do82whm',
|
|
7
|
-
dataset: 'next',
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface Guide {
|
|
11
|
-
_type?: string
|
|
12
|
-
slug?: {current: string}
|
|
13
|
-
presenter?: {
|
|
14
|
-
name?: string
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface FeedItem {
|
|
19
|
-
_id: string
|
|
20
|
-
title?: string
|
|
21
|
-
poster?: string
|
|
22
|
-
category?: string
|
|
23
|
-
guideOrTutorial?: Guide
|
|
24
|
-
externalLink?: string
|
|
25
|
-
presenter?: {
|
|
26
|
-
name?: string
|
|
27
|
-
}
|
|
28
|
-
hasVideo?: boolean
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function useDataAdapter() {
|
|
32
|
-
const versionedClient = useVersionedClient()
|
|
33
|
-
return useMemo(
|
|
34
|
-
() => ({
|
|
35
|
-
getFeed: (templateRepoId: string) => {
|
|
36
|
-
const uri = templateRepoId
|
|
37
|
-
? `/addons/dashboard?templateRepoId=${templateRepoId}`
|
|
38
|
-
: '/addons/dashboard'
|
|
39
|
-
return versionedClient.observable.request<{items: FeedItem[]}>({
|
|
40
|
-
uri,
|
|
41
|
-
tag: 'dashboard.sanity-tutorials',
|
|
42
|
-
withCredentials: false,
|
|
43
|
-
})
|
|
44
|
-
},
|
|
45
|
-
urlBuilder: imageUrlBuilder(tutorialsProjectConfig),
|
|
46
|
-
}),
|
|
47
|
-
[versionedClient],
|
|
48
|
-
)
|
|
49
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import {SanityTutorials} from './SanityTutorials'
|
|
2
|
-
import {LayoutConfig, DashboardWidget} from '../../types'
|
|
3
|
-
|
|
4
|
-
export function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {
|
|
5
|
-
return {
|
|
6
|
-
name: 'sanity-tutorials',
|
|
7
|
-
component: SanityTutorials,
|
|
8
|
-
layout: config?.layout ?? {width: 'full'},
|
|
9
|
-
}
|
|
10
|
-
}
|
package/v2-incompatible.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const {showIncompatiblePluginDialog} = require('@sanity/incompatible-plugin')
|
|
2
|
-
const {name, version, sanityExchangeUrl} = require('./package.json')
|
|
3
|
-
|
|
4
|
-
export default showIncompatiblePluginDialog({
|
|
5
|
-
name: name,
|
|
6
|
-
versions: {
|
|
7
|
-
v3: version,
|
|
8
|
-
v2: '^2.30.0',
|
|
9
|
-
},
|
|
10
|
-
sanityExchangeUrl,
|
|
11
|
-
})
|