sanity-plugin-dashboard-widget-netlify 2.0.4 → 3.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/lib/index.d.ts DELETED
@@ -1,45 +0,0 @@
1
- import {DashboardWidget} from '@sanity/dashboard'
2
- import {LayoutConfig} from '@sanity/dashboard'
3
-
4
- export declare type DeployAction = (site: Site) => void
5
-
6
- export declare function netlifyWidget(config: NetlifyWidgetConfig): DashboardWidget
7
-
8
- export declare type NetlifyWidgetConfig = WidgetOptions & {
9
- layout?: LayoutConfig
10
- }
11
-
12
- export declare interface NetlifyWidgetProps {
13
- title?: string
14
- description?: string
15
- sites?: Site[]
16
- isLoading: boolean
17
- onDeploy: DeployAction
18
- }
19
-
20
- export declare interface Site {
21
- title: string
22
- name?: string
23
- id: string
24
- url?: string
25
- adminUrl?: string
26
- buildHookId: string
27
- branch?: string
28
- }
29
-
30
- export declare interface SiteWidgetOption {
31
- apiId: string
32
- name?: string
33
- title: string
34
- buildHookId: string
35
- url?: string
36
- branch?: string
37
- }
38
-
39
- export declare interface WidgetOptions {
40
- title?: string
41
- description?: string
42
- sites: SiteWidgetOption[]
43
- }
44
-
45
- export {}
package/lib/index.js DELETED
@@ -1,172 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var jsxRuntime = require("react/jsx-runtime"), reactPropsStream = require("react-props-stream"), operators = require("rxjs/operators"), rxjs = require("rxjs"), AbortControllerPolyfill = require("abort-controller"), react = require("react"), ui = require("@sanity/ui"), dashboard = require("@sanity/dashboard"), styledComponents = require("styled-components");
4
- function _interopDefaultCompat(e) {
5
- return e && typeof e == "object" && "default" in e ? e : { default: e };
6
- }
7
- var AbortControllerPolyfill__default = /* @__PURE__ */ _interopDefaultCompat(AbortControllerPolyfill);
8
- const createAbortController = () => "AbortController" in window ? new AbortController() : new AbortControllerPolyfill__default.default(), statusCodeRequest = (input, init) => new rxjs.Observable((subscriber) => {
9
- const controller = createAbortController(), onResponse = (res) => {
10
- subscriber.next(res), subscriber.complete();
11
- }, onError = (err) => {
12
- err.name === "AbortError" ? subscriber.complete() : subscriber.error(err);
13
- };
14
- return fetch(input, { ...init, signal: controller.signal }).then((res) => {
15
- if (res.status < 200 || res.status > 299)
16
- throw new Error(`HTTP Error ${res.status}: ${res.statusText}`);
17
- return res.status;
18
- }).then(onResponse, onError), () => {
19
- controller.abort();
20
- };
21
- });
22
- function deploy(site) {
23
- return site.buildHookId ? statusCodeRequest(`https://api.netlify.com/build_hooks/${site.buildHookId}`, {
24
- method: "POST"
25
- }).pipe(operators.map((result) => ({ result, site }))) : rxjs.of(new Error("Site missing buildHookId"));
26
- }
27
- const stateReducer$ = operators.scan((state, action) => {
28
- switch (action.type) {
29
- case "setSites":
30
- return { ...state, sites: action.sites || [] };
31
- case "deploy/started":
32
- return {
33
- ...state,
34
- sites: state.sites.map((site) => action.site && site.id === action.site.id ? { ...site } : site)
35
- };
36
- case "deploy/failed":
37
- return {
38
- ...state,
39
- error: action.error
40
- };
41
- case "deploy/completed":
42
- return {
43
- ...state,
44
- sites: state.sites.map((site) => action.site && site.id === action.site.id ? { ...site, error: action.error } : site)
45
- };
46
- default:
47
- return state;
48
- }
49
- }), noop = () => {
50
- }, INITIAL_PROPS = {
51
- title: "Netlify sites",
52
- sites: [],
53
- isLoading: !0,
54
- onDeploy: noop
55
- }, props$ = (options) => {
56
- const configuredSites = (options.sites || []).map((site) => ({
57
- id: site.apiId,
58
- name: site.name,
59
- title: site.title,
60
- buildHookId: site.buildHookId,
61
- url: site.url || site.branch && `https://${site.branch}--${site.name}.netlify.app/` || site.name && `https://${site.name}.netlify.app/`,
62
- adminUrl: site.name && `https://app.netlify.com/sites/${site.name}`,
63
- branch: site.branch
64
- })), [onDeploy$, onDeploy] = reactPropsStream.createEventHandler(), setSitesAction$ = rxjs.of(configuredSites).pipe(operators.map((sites) => ({ type: "setSites", sites }))), deployAction$ = onDeploy$.pipe(operators.map((site) => ({ type: "deploy/started", site }))), deployCompletedAction$ = onDeploy$.pipe(operators.switchMap((site) => deploy(site))).pipe(
65
- operators.map(
66
- (result) => ({ type: "deploy/completed", ...result }),
67
- operators.catchError((error) => rxjs.of({ type: "deploy/failed", error }))
68
- )
69
- );
70
- return rxjs.merge(setSitesAction$, deployAction$, deployCompletedAction$).pipe(stateReducer$).subscribe(), rxjs.of(configuredSites).pipe(
71
- operators.map((sites) => ({
72
- sites,
73
- title: options.title || INITIAL_PROPS.title,
74
- description: options.description,
75
- isLoading: !1,
76
- onDeploy
77
- })),
78
- operators.startWith(INITIAL_PROPS)
79
- );
80
- }, Link = (props) => {
81
- const { url, children } = props;
82
- return /* @__PURE__ */ jsxRuntime.jsx("span", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: url, target: "_blank", rel: "noreferrer", children }) });
83
- }, Links = (props) => {
84
- const { url, adminUrl } = props;
85
- return url && adminUrl ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
86
- "(",
87
- /* @__PURE__ */ jsxRuntime.jsx(Link, { url, children: "view" }),
88
- ", ",
89
- /* @__PURE__ */ jsxRuntime.jsx(Link, { url: adminUrl, children: "admin" }),
90
- ")"
91
- ] }) : url ? /* @__PURE__ */ jsxRuntime.jsx(Link, { url, children: "(view)" }) : adminUrl ? /* @__PURE__ */ jsxRuntime.jsx(Link, { url: adminUrl, children: "(admin)" }) : null;
92
- }, IMAGE_PULL_INTERVAL = 1e4, getImageUrl = (siteId, branchName) => {
93
- const baseUrl = `https://api.netlify.com/api/v1/badges/${siteId}/deploy-status`, time = (/* @__PURE__ */ new Date()).getTime(), branch = `branch=${branchName}`;
94
- return branchName ? `${baseUrl}?${time}&${branch}` : `${baseUrl}?${time}`;
95
- }, useBadgeImage = (siteId, branchName) => {
96
- const [src, setSrc] = react.useState(() => getImageUrl(siteId, branchName)), update = react.useCallback(() => setSrc(getImageUrl(siteId, branchName)), [siteId]);
97
- return react.useEffect(() => {
98
- const interval = window.setInterval(update, IMAGE_PULL_INTERVAL);
99
- return () => window.clearInterval(interval);
100
- }, [update]), [src, update];
101
- }, useDeploy = (site, onDeploy, updateBadge) => {
102
- const timeoutRef = react.useRef(-1);
103
- return react.useEffect(() => () => window.clearTimeout(timeoutRef.current), []), react.useCallback(() => {
104
- onDeploy(site), timeoutRef.current = window.setTimeout(updateBadge, 1e3);
105
- }, [site, onDeploy, updateBadge]);
106
- }, SiteItem = (props) => {
107
- const [hasBadgeError, setHasBadgeError] = react.useState(!1), { site, onDeploy } = props, { id, name, title, url, adminUrl, buildHookId, branch } = site, [badge, updateBadge] = useBadgeImage(id, branch), handleDeploy = useDeploy(site, onDeploy, updateBadge);
108
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { as: "li", children: [
109
- /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, paddingY: 2, paddingX: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
110
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { as: "h4", children: [
111
- title || name,
112
- /* @__PURE__ */ jsxRuntime.jsx(Links, { url, adminUrl })
113
- ] }),
114
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "flex-start", children: [
115
- !hasBadgeError && /* @__PURE__ */ jsxRuntime.jsx("img", { src: badge, onError: () => {
116
- setHasBadgeError(!0);
117
- }, alt: "Badge" }),
118
- hasBadgeError && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { tone: "critical", radius: 2, padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, muted: !0, children: "Failed to load badge" }) })
119
- ] })
120
- ] }) }),
121
- buildHookId ? /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingY: 2, paddingX: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { mode: "ghost", onClick: handleDeploy, text: "Deploy" }) }) : null
122
- ] });
123
- };
124
- function SiteList(props) {
125
- const { isLoading, onDeploy, sites } = props;
126
- return isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", justify: "center", align: "center", children: [
127
- /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, { muted: !0 }),
128
- /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginTop: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, children: "Loading sites\u2026" }) })
129
- ] }) }) : !sites || sites && sites.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { tone: "critical", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "No sites are defined in the widget options. Please check your config." }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingY: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { as: "ul", space: 2, children: sites.map((site, index) => /* @__PURE__ */ jsxRuntime.jsx(SiteItem, { onDeploy, site }, `site-${index}`)) }) });
130
- }
131
- const ContentCard = styledComponents.styled(ui.Card)`
132
- min-height: 66px;
133
- `;
134
- function NetlifyWidget(props) {
135
- const netlifySitesUrl = "https://app.netlify.com/account/sites", { title, description, isLoading, sites, onDeploy } = props;
136
- return /* @__PURE__ */ jsxRuntime.jsx(dashboard.DashboardWidgetContainer, { header: title, footer: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { direction: "column", align: "stretch", children: /* @__PURE__ */ jsxRuntime.jsx(
137
- ui.Button,
138
- {
139
- as: "a",
140
- href: isLoading ? void 0 : netlifySitesUrl,
141
- disabled: isLoading,
142
- paddingX: 2,
143
- paddingY: 4,
144
- mode: "bleed",
145
- tone: "primary",
146
- text: "Manage sites at Netlify",
147
- loading: isLoading,
148
- target: "_blank"
149
- }
150
- ) }), children: /* @__PURE__ */ jsxRuntime.jsxs(ContentCard, { paddingY: 1, children: [
151
- description && /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingY: 3, paddingX: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "p", size: 1, muted: !0, children: /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: description } }) }) }),
152
- /* @__PURE__ */ jsxRuntime.jsx(SiteList, { isLoading, onDeploy, sites })
153
- ] }) });
154
- }
155
- var Widget = reactPropsStream.streamingComponent(
156
- (options$) => options$.pipe(
157
- operators.switchMap(
158
- (options) => props$(options).pipe(
159
- operators.map((props) => /* @__PURE__ */ jsxRuntime.jsx(NetlifyWidget, { ...props }))
160
- )
161
- )
162
- )
163
- );
164
- function netlifyWidget(config) {
165
- return {
166
- name: "netlify-widget",
167
- component: () => /* @__PURE__ */ jsxRuntime.jsx(Widget, { ...config }),
168
- layout: config.layout ?? { width: "medium" }
169
- };
170
- }
171
- exports.netlifyWidget = netlifyWidget;
172
- //# sourceMappingURL=index.js.map
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../src/http/utils/createAbortController.ts","../src/http/statusCodeRequest.ts","../src/datastores/deploy.ts","../src/reducers.ts","../src/props.ts","../src/components/SiteItem/Links.tsx","../src/components/SiteItem/index.tsx","../src/components/SiteList.tsx","../src/components/NetlifyWidget.tsx","../src/widget.tsx","../src/plugin.tsx"],"sourcesContent":["import AbortControllerPolyfill from 'abort-controller'\n\nexport const createAbortController = (): AbortController => {\n if (!('AbortController' in window)) {\n return new AbortControllerPolyfill() as AbortController\n }\n return new AbortController()\n}\n","import {Observable} from 'rxjs'\nimport {createAbortController} from './utils/createAbortController'\n\n// eslint-disable-next-line no-undef\nexport const statusCodeRequest = (input: RequestInfo, init?: RequestInit): Observable<number> => {\n return new Observable((subscriber) => {\n const controller = createAbortController()\n const onResponse = (res: number) => {\n subscriber.next(res)\n subscriber.complete()\n }\n const onError = (err: Error) => {\n if (err.name === 'AbortError') {\n subscriber.complete()\n } else {\n subscriber.error(err)\n }\n }\n\n fetch(input, {...init, signal: controller.signal})\n .then((res: Response) => {\n if (res.status < 200 || res.status > 299) {\n throw new Error(`HTTP Error ${res.status}: ${res.statusText}`)\n }\n return res.status\n })\n .then(onResponse, onError)\n\n return () => {\n controller.abort()\n }\n })\n}\n","import {Observable, of} from 'rxjs'\nimport {map} from 'rxjs/operators'\nimport {statusCodeRequest} from '../http/statusCodeRequest'\nimport {Site} from '../types'\n\nexport function deploy(site: Site): Observable<{result: number; site: Site} | Error> {\n if (!site.buildHookId) {\n return of(new Error('Site missing buildHookId'))\n }\n\n return statusCodeRequest(`https://api.netlify.com/build_hooks/${site.buildHookId}`, {\n method: 'POST',\n }).pipe(map((result) => ({result, site})))\n}\n","import {scan} from 'rxjs/operators'\nimport {Site} from './types'\n\ninterface Deployment {\n id: string\n}\n\ninterface Action {\n type: string\n sites?: Site[]\n site?: Site\n error?: Error\n deployments?: Deployment[]\n}\n\ninterface State {\n sites: Site[]\n action: Action\n}\n\nexport const stateReducer$ = scan((state: State, action: Action) => {\n switch (action.type) {\n case 'setSites':\n return {...state, sites: action.sites || []}\n case 'deploy/started':\n return {\n ...state,\n sites: state.sites.map((site: Site) => {\n if (action.site && site.id === action.site.id) {\n return {...site}\n }\n return site\n }),\n }\n case 'deploy/failed':\n return {\n ...state,\n error: action.error,\n }\n case 'deploy/completed':\n return {\n ...state,\n sites: state.sites.map((site: Site) => {\n if (action.site && site.id === action.site.id) {\n return {...site, error: action.error}\n }\n return site\n }),\n }\n default:\n return state\n }\n})\n","import {merge, of} from 'rxjs'\nimport {createEventHandler} from 'react-props-stream'\nimport {catchError, map, startWith, switchMap} from 'rxjs/operators'\nimport {deploy} from './datastores/deploy'\nimport {Site, WidgetOptions} from './types'\nimport {stateReducer$} from './reducers'\n\nconst noop = () => undefined\n\nconst INITIAL_PROPS = {\n title: 'Netlify sites',\n sites: [],\n isLoading: true,\n onDeploy: noop,\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\nexport const props$ = (options: WidgetOptions) => {\n const configuredSites = (options.sites || []).map((site) => ({\n id: site.apiId,\n name: site.name,\n title: site.title,\n buildHookId: site.buildHookId,\n url:\n site.url ||\n (site.branch && `https://${site.branch}--${site.name}.netlify.app/`) ||\n (site.name && `https://${site.name}.netlify.app/`),\n adminUrl: site.name && `https://app.netlify.com/sites/${site.name}`,\n branch: site.branch,\n }))\n\n const [onDeploy$, onDeploy] = createEventHandler<Site>()\n const setSitesAction$ = of(configuredSites).pipe(map((sites) => ({type: 'setSites', sites})))\n const deployAction$ = onDeploy$.pipe(map((site) => ({type: 'deploy/started', site})))\n const deployResult$ = onDeploy$.pipe(switchMap((site) => deploy(site)))\n const deployCompletedAction$ = deployResult$.pipe(\n map(\n (result) => ({type: 'deploy/completed', ...result}),\n catchError((error) => of({type: 'deploy/failed', error}))\n )\n )\n\n merge(setSitesAction$, deployAction$, deployCompletedAction$).pipe(stateReducer$).subscribe()\n\n return of(configuredSites).pipe(\n map((sites) => ({\n sites,\n title: options.title || INITIAL_PROPS.title,\n description: options.description,\n isLoading: false,\n onDeploy,\n })),\n startWith(INITIAL_PROPS)\n )\n}\n","import React, {FunctionComponent, PropsWithChildren} from 'react'\n\nconst Link = (props: PropsWithChildren<{url: string}>) => {\n const {url, children} = props\n\n return (\n <span>\n <a href={url} target=\"_blank\" rel=\"noreferrer\">\n {children}\n </a>\n </span>\n )\n}\n\ntype Props = {\n url?: string\n adminUrl?: string\n}\n\nconst Links: FunctionComponent<Props> = (props) => {\n const {url, adminUrl} = props\n\n if (url && adminUrl) {\n return (\n <span>\n (<Link url={url}>view</Link>, <Link url={adminUrl}>admin</Link>)\n </span>\n )\n }\n\n if (url) {\n return <Link url={url}>(view)</Link>\n }\n if (adminUrl) {\n return <Link url={adminUrl}>(admin)</Link>\n }\n return null\n}\n\nexport default Links\n","import React, {FunctionComponent, useCallback, useEffect, useRef, useState} from 'react'\nimport {Button, Flex, Box, Card, Text, Stack, Label} from '@sanity/ui'\nimport {DeployAction, Site} from '../../types'\nimport Links from './Links'\n\ninterface Props {\n site: Site\n onDeploy: DeployAction\n}\n\nexport const IMAGE_PULL_INTERVAL = 10000\n\nconst getImageUrl = (siteId: string, branchName?: string) => {\n const baseUrl = `https://api.netlify.com/api/v1/badges/${siteId}/deploy-status`\n const time = new Date().getTime()\n const branch = `branch=${branchName}`\n\n return branchName ? `${baseUrl}?${time}&${branch}` : `${baseUrl}?${time}`\n}\n\nconst useBadgeImage = (siteId: string, branchName?: string ) => {\n const [src, setSrc] = useState(() => getImageUrl(siteId, branchName))\n const update = useCallback(() => setSrc(getImageUrl(siteId, branchName)), [siteId])\n\n useEffect(() => {\n const interval = window.setInterval(update, IMAGE_PULL_INTERVAL)\n return () => window.clearInterval(interval)\n }, [update])\n\n return [src, update] as const\n}\n\nconst useDeploy = (site: Site, onDeploy: DeployAction, updateBadge: () => void) => {\n const timeoutRef = useRef(-1)\n useEffect(() => () => window.clearTimeout(timeoutRef.current), [])\n\n return useCallback(() => {\n onDeploy(site)\n timeoutRef.current = window.setTimeout(updateBadge, 1000)\n }, [site, onDeploy, updateBadge])\n}\n\nconst SiteItem: FunctionComponent<Props> = (props) => {\n const [hasBadgeError, setHasBadgeError] = useState(false)\n const {site, onDeploy} = props\n const {id, name, title, url, adminUrl, buildHookId, branch} = site\n\n const [badge, updateBadge] = useBadgeImage(id, branch)\n const handleDeploy = useDeploy(site, onDeploy, updateBadge)\n const handleBadgeError = () => {\n setHasBadgeError(true)\n }\n\n return (\n <Flex as=\"li\">\n <Box flex={1} paddingY={2} paddingX={3}>\n <Stack space={2}>\n <Text as=\"h4\">\n {title || name}\n <Links url={url} adminUrl={adminUrl} />\n </Text>\n\n <Flex justify=\"flex-start\">\n {!hasBadgeError && <img src={badge} onError={handleBadgeError} alt=\"Badge\" />}\n {hasBadgeError && <Card tone=\"critical\" radius={2} padding={2}><Label size={0} muted>Failed to load badge</Label></Card>}\n </Flex>\n </Stack>\n </Box>\n\n {buildHookId ? (\n <Box paddingY={2} paddingX={3}>\n <Button mode=\"ghost\" onClick={handleDeploy} text=\"Deploy\" />\n </Box>\n ) : null}\n </Flex>\n )\n}\n\nexport default SiteItem\n","import React from 'react'\nimport {DeployAction, Site} from '../types'\nimport SiteItem from './SiteItem'\nimport {Flex, Box, Card, Text, Spinner, Stack} from '@sanity/ui'\n\ninterface Props {\n isLoading: boolean\n sites?: Site[]\n onDeploy: DeployAction\n}\n\nexport default function SiteList(props: Props) {\n const {isLoading, onDeploy, sites} = props\n if (isLoading) {\n return (\n <Card padding={4}>\n <Flex direction=\"column\" justify=\"center\" align=\"center\">\n <Spinner muted />\n <Box marginTop={3}>\n <Text muted>Loading sites…</Text>\n </Box>\n </Flex>\n </Card>\n )\n }\n if (!sites || (sites && sites.length === 0)) {\n return (\n <Card tone=\"critical\" padding={3}>\n <Text>No sites are defined in the widget options. Please check your config.</Text>\n </Card>\n )\n }\n return (\n <Box paddingY={2}>\n <Stack as=\"ul\" space={2}>\n {sites.map((site, index) => {\n return <SiteItem onDeploy={onDeploy} site={site} key={`site-${index}`} />\n })}\n </Stack>\n </Box>\n )\n}\n","import React from 'react'\nimport {NetlifyWidgetProps} from '../types'\nimport SiteList from './SiteList'\nimport {DashboardWidgetContainer} from '@sanity/dashboard'\nimport {styled} from 'styled-components'\nimport {Button, Flex, Card, Text, Box} from '@sanity/ui'\n\nconst ContentCard = styled(Card)`\n min-height: 66px;\n`\n\nexport default function NetlifyWidget(props: NetlifyWidgetProps) {\n const netlifySitesUrl = 'https://app.netlify.com/account/sites'\n const {title, description, isLoading, sites, onDeploy} = props\n\n const footer = (\n <Flex direction=\"column\" align=\"stretch\">\n <Button\n as=\"a\"\n href={isLoading ? undefined : netlifySitesUrl}\n disabled={isLoading}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage sites at Netlify\"\n loading={isLoading}\n target=\"_blank\"\n />\n </Flex>\n )\n\n return (\n <DashboardWidgetContainer header={title} footer={footer}>\n <ContentCard paddingY={1}>\n {description && (\n <Box paddingY={3} paddingX={3}>\n <Text as=\"p\" size={1} muted>\n <span dangerouslySetInnerHTML={{__html: description}} />\n </Text>\n </Box>\n )}\n <SiteList isLoading={isLoading} onDeploy={onDeploy} sites={sites} />\n </ContentCard>\n </DashboardWidgetContainer>\n )\n}\n","import React from 'react'\nimport {streamingComponent} from 'react-props-stream'\nimport {map, switchMap} from 'rxjs/operators'\nimport {WidgetOptions} from './types'\nimport {props$} from './props'\nimport NetlifyWidget from './components/NetlifyWidget'\n\nexport default streamingComponent<WidgetOptions>((options$) =>\n options$.pipe(\n switchMap((options) =>\n props$(options).pipe(\n map((props) => {\n return <NetlifyWidget {...props} />\n })\n )\n )\n )\n)\n","import React from 'react'\nimport Widget from './widget'\nimport {WidgetOptions} from './types'\nimport {DashboardWidget, LayoutConfig} from '@sanity/dashboard'\n\nexport type NetlifyWidgetConfig = WidgetOptions & {layout?: LayoutConfig}\n\nexport function netlifyWidget(config: NetlifyWidgetConfig): DashboardWidget {\n return {\n name: 'netlify-widget',\n component: () => {\n return <Widget {...config} />\n },\n layout: config.layout ?? {width: 'medium'},\n }\n}\n"],"names":["AbortControllerPolyfill","Observable","map","of","scan","createEventHandler","switchMap","catchError","merge","startWith","jsx","jsxs","useState","useCallback","useEffect","useRef","Flex","Box","Stack","Text","Card","Label","Button","Spinner","styled","DashboardWidgetContainer","streamingComponent"],"mappings":"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"}
package/lib/index.mjs DELETED
@@ -1,176 +0,0 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { createEventHandler, streamingComponent } from "react-props-stream";
3
- import { map, scan, switchMap, catchError, startWith } from "rxjs/operators";
4
- import { Observable, of, merge } from "rxjs";
5
- import AbortControllerPolyfill from "abort-controller";
6
- import { useState, useCallback, useEffect, useRef } from "react";
7
- import { Flex, Box, Stack, Text, Card, Label, Button, Spinner } from "@sanity/ui";
8
- import { DashboardWidgetContainer } from "@sanity/dashboard";
9
- import { styled } from "styled-components";
10
- const createAbortController = () => "AbortController" in window ? new AbortController() : new AbortControllerPolyfill(), statusCodeRequest = (input, init) => new Observable((subscriber) => {
11
- const controller = createAbortController(), onResponse = (res) => {
12
- subscriber.next(res), subscriber.complete();
13
- }, onError = (err) => {
14
- err.name === "AbortError" ? subscriber.complete() : subscriber.error(err);
15
- };
16
- return fetch(input, { ...init, signal: controller.signal }).then((res) => {
17
- if (res.status < 200 || res.status > 299)
18
- throw new Error(`HTTP Error ${res.status}: ${res.statusText}`);
19
- return res.status;
20
- }).then(onResponse, onError), () => {
21
- controller.abort();
22
- };
23
- });
24
- function deploy(site) {
25
- return site.buildHookId ? statusCodeRequest(`https://api.netlify.com/build_hooks/${site.buildHookId}`, {
26
- method: "POST"
27
- }).pipe(map((result) => ({ result, site }))) : of(new Error("Site missing buildHookId"));
28
- }
29
- const stateReducer$ = scan((state, action) => {
30
- switch (action.type) {
31
- case "setSites":
32
- return { ...state, sites: action.sites || [] };
33
- case "deploy/started":
34
- return {
35
- ...state,
36
- sites: state.sites.map((site) => action.site && site.id === action.site.id ? { ...site } : site)
37
- };
38
- case "deploy/failed":
39
- return {
40
- ...state,
41
- error: action.error
42
- };
43
- case "deploy/completed":
44
- return {
45
- ...state,
46
- sites: state.sites.map((site) => action.site && site.id === action.site.id ? { ...site, error: action.error } : site)
47
- };
48
- default:
49
- return state;
50
- }
51
- }), noop = () => {
52
- }, INITIAL_PROPS = {
53
- title: "Netlify sites",
54
- sites: [],
55
- isLoading: !0,
56
- onDeploy: noop
57
- }, props$ = (options) => {
58
- const configuredSites = (options.sites || []).map((site) => ({
59
- id: site.apiId,
60
- name: site.name,
61
- title: site.title,
62
- buildHookId: site.buildHookId,
63
- url: site.url || site.branch && `https://${site.branch}--${site.name}.netlify.app/` || site.name && `https://${site.name}.netlify.app/`,
64
- adminUrl: site.name && `https://app.netlify.com/sites/${site.name}`,
65
- branch: site.branch
66
- })), [onDeploy$, onDeploy] = createEventHandler(), setSitesAction$ = of(configuredSites).pipe(map((sites) => ({ type: "setSites", sites }))), deployAction$ = onDeploy$.pipe(map((site) => ({ type: "deploy/started", site }))), deployCompletedAction$ = onDeploy$.pipe(switchMap((site) => deploy(site))).pipe(
67
- map(
68
- (result) => ({ type: "deploy/completed", ...result }),
69
- catchError((error) => of({ type: "deploy/failed", error }))
70
- )
71
- );
72
- return merge(setSitesAction$, deployAction$, deployCompletedAction$).pipe(stateReducer$).subscribe(), of(configuredSites).pipe(
73
- map((sites) => ({
74
- sites,
75
- title: options.title || INITIAL_PROPS.title,
76
- description: options.description,
77
- isLoading: !1,
78
- onDeploy
79
- })),
80
- startWith(INITIAL_PROPS)
81
- );
82
- }, Link = (props) => {
83
- const { url, children } = props;
84
- return /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noreferrer", children }) });
85
- }, Links = (props) => {
86
- const { url, adminUrl } = props;
87
- return url && adminUrl ? /* @__PURE__ */ jsxs("span", { children: [
88
- "(",
89
- /* @__PURE__ */ jsx(Link, { url, children: "view" }),
90
- ", ",
91
- /* @__PURE__ */ jsx(Link, { url: adminUrl, children: "admin" }),
92
- ")"
93
- ] }) : url ? /* @__PURE__ */ jsx(Link, { url, children: "(view)" }) : adminUrl ? /* @__PURE__ */ jsx(Link, { url: adminUrl, children: "(admin)" }) : null;
94
- }, IMAGE_PULL_INTERVAL = 1e4, getImageUrl = (siteId, branchName) => {
95
- const baseUrl = `https://api.netlify.com/api/v1/badges/${siteId}/deploy-status`, time = (/* @__PURE__ */ new Date()).getTime(), branch = `branch=${branchName}`;
96
- return branchName ? `${baseUrl}?${time}&${branch}` : `${baseUrl}?${time}`;
97
- }, useBadgeImage = (siteId, branchName) => {
98
- const [src, setSrc] = useState(() => getImageUrl(siteId, branchName)), update = useCallback(() => setSrc(getImageUrl(siteId, branchName)), [siteId]);
99
- return useEffect(() => {
100
- const interval = window.setInterval(update, IMAGE_PULL_INTERVAL);
101
- return () => window.clearInterval(interval);
102
- }, [update]), [src, update];
103
- }, useDeploy = (site, onDeploy, updateBadge) => {
104
- const timeoutRef = useRef(-1);
105
- return useEffect(() => () => window.clearTimeout(timeoutRef.current), []), useCallback(() => {
106
- onDeploy(site), timeoutRef.current = window.setTimeout(updateBadge, 1e3);
107
- }, [site, onDeploy, updateBadge]);
108
- }, SiteItem = (props) => {
109
- const [hasBadgeError, setHasBadgeError] = useState(!1), { site, onDeploy } = props, { id, name, title, url, adminUrl, buildHookId, branch } = site, [badge, updateBadge] = useBadgeImage(id, branch), handleDeploy = useDeploy(site, onDeploy, updateBadge);
110
- return /* @__PURE__ */ jsxs(Flex, { as: "li", children: [
111
- /* @__PURE__ */ jsx(Box, { flex: 1, paddingY: 2, paddingX: 3, children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
112
- /* @__PURE__ */ jsxs(Text, { as: "h4", children: [
113
- title || name,
114
- /* @__PURE__ */ jsx(Links, { url, adminUrl })
115
- ] }),
116
- /* @__PURE__ */ jsxs(Flex, { justify: "flex-start", children: [
117
- !hasBadgeError && /* @__PURE__ */ jsx("img", { src: badge, onError: () => {
118
- setHasBadgeError(!0);
119
- }, alt: "Badge" }),
120
- hasBadgeError && /* @__PURE__ */ jsx(Card, { tone: "critical", radius: 2, padding: 2, children: /* @__PURE__ */ jsx(Label, { size: 0, muted: !0, children: "Failed to load badge" }) })
121
- ] })
122
- ] }) }),
123
- buildHookId ? /* @__PURE__ */ jsx(Box, { paddingY: 2, paddingX: 3, children: /* @__PURE__ */ jsx(Button, { mode: "ghost", onClick: handleDeploy, text: "Deploy" }) }) : null
124
- ] });
125
- };
126
- function SiteList(props) {
127
- const { isLoading, onDeploy, sites } = props;
128
- return isLoading ? /* @__PURE__ */ jsx(Card, { padding: 4, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", justify: "center", align: "center", children: [
129
- /* @__PURE__ */ jsx(Spinner, { muted: !0 }),
130
- /* @__PURE__ */ jsx(Box, { marginTop: 3, children: /* @__PURE__ */ jsx(Text, { muted: !0, children: "Loading sites\u2026" }) })
131
- ] }) }) : !sites || sites && sites.length === 0 ? /* @__PURE__ */ jsx(Card, { tone: "critical", padding: 3, children: /* @__PURE__ */ jsx(Text, { children: "No sites are defined in the widget options. Please check your config." }) }) : /* @__PURE__ */ jsx(Box, { paddingY: 2, children: /* @__PURE__ */ jsx(Stack, { as: "ul", space: 2, children: sites.map((site, index) => /* @__PURE__ */ jsx(SiteItem, { onDeploy, site }, `site-${index}`)) }) });
132
- }
133
- const ContentCard = styled(Card)`
134
- min-height: 66px;
135
- `;
136
- function NetlifyWidget(props) {
137
- const netlifySitesUrl = "https://app.netlify.com/account/sites", { title, description, isLoading, sites, onDeploy } = props;
138
- return /* @__PURE__ */ jsx(DashboardWidgetContainer, { header: title, footer: /* @__PURE__ */ jsx(Flex, { direction: "column", align: "stretch", children: /* @__PURE__ */ jsx(
139
- Button,
140
- {
141
- as: "a",
142
- href: isLoading ? void 0 : netlifySitesUrl,
143
- disabled: isLoading,
144
- paddingX: 2,
145
- paddingY: 4,
146
- mode: "bleed",
147
- tone: "primary",
148
- text: "Manage sites at Netlify",
149
- loading: isLoading,
150
- target: "_blank"
151
- }
152
- ) }), children: /* @__PURE__ */ jsxs(ContentCard, { paddingY: 1, children: [
153
- description && /* @__PURE__ */ jsx(Box, { paddingY: 3, paddingX: 3, children: /* @__PURE__ */ jsx(Text, { as: "p", size: 1, muted: !0, children: /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: description } }) }) }),
154
- /* @__PURE__ */ jsx(SiteList, { isLoading, onDeploy, sites })
155
- ] }) });
156
- }
157
- var Widget = streamingComponent(
158
- (options$) => options$.pipe(
159
- switchMap(
160
- (options) => props$(options).pipe(
161
- map((props) => /* @__PURE__ */ jsx(NetlifyWidget, { ...props }))
162
- )
163
- )
164
- )
165
- );
166
- function netlifyWidget(config) {
167
- return {
168
- name: "netlify-widget",
169
- component: () => /* @__PURE__ */ jsx(Widget, { ...config }),
170
- layout: config.layout ?? { width: "medium" }
171
- };
172
- }
173
- export {
174
- netlifyWidget
175
- };
176
- //# sourceMappingURL=index.mjs.map
package/lib/index.mjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/http/utils/createAbortController.ts","../src/http/statusCodeRequest.ts","../src/datastores/deploy.ts","../src/reducers.ts","../src/props.ts","../src/components/SiteItem/Links.tsx","../src/components/SiteItem/index.tsx","../src/components/SiteList.tsx","../src/components/NetlifyWidget.tsx","../src/widget.tsx","../src/plugin.tsx"],"sourcesContent":["import AbortControllerPolyfill from 'abort-controller'\n\nexport const createAbortController = (): AbortController => {\n if (!('AbortController' in window)) {\n return new AbortControllerPolyfill() as AbortController\n }\n return new AbortController()\n}\n","import {Observable} from 'rxjs'\nimport {createAbortController} from './utils/createAbortController'\n\n// eslint-disable-next-line no-undef\nexport const statusCodeRequest = (input: RequestInfo, init?: RequestInit): Observable<number> => {\n return new Observable((subscriber) => {\n const controller = createAbortController()\n const onResponse = (res: number) => {\n subscriber.next(res)\n subscriber.complete()\n }\n const onError = (err: Error) => {\n if (err.name === 'AbortError') {\n subscriber.complete()\n } else {\n subscriber.error(err)\n }\n }\n\n fetch(input, {...init, signal: controller.signal})\n .then((res: Response) => {\n if (res.status < 200 || res.status > 299) {\n throw new Error(`HTTP Error ${res.status}: ${res.statusText}`)\n }\n return res.status\n })\n .then(onResponse, onError)\n\n return () => {\n controller.abort()\n }\n })\n}\n","import {Observable, of} from 'rxjs'\nimport {map} from 'rxjs/operators'\nimport {statusCodeRequest} from '../http/statusCodeRequest'\nimport {Site} from '../types'\n\nexport function deploy(site: Site): Observable<{result: number; site: Site} | Error> {\n if (!site.buildHookId) {\n return of(new Error('Site missing buildHookId'))\n }\n\n return statusCodeRequest(`https://api.netlify.com/build_hooks/${site.buildHookId}`, {\n method: 'POST',\n }).pipe(map((result) => ({result, site})))\n}\n","import {scan} from 'rxjs/operators'\nimport {Site} from './types'\n\ninterface Deployment {\n id: string\n}\n\ninterface Action {\n type: string\n sites?: Site[]\n site?: Site\n error?: Error\n deployments?: Deployment[]\n}\n\ninterface State {\n sites: Site[]\n action: Action\n}\n\nexport const stateReducer$ = scan((state: State, action: Action) => {\n switch (action.type) {\n case 'setSites':\n return {...state, sites: action.sites || []}\n case 'deploy/started':\n return {\n ...state,\n sites: state.sites.map((site: Site) => {\n if (action.site && site.id === action.site.id) {\n return {...site}\n }\n return site\n }),\n }\n case 'deploy/failed':\n return {\n ...state,\n error: action.error,\n }\n case 'deploy/completed':\n return {\n ...state,\n sites: state.sites.map((site: Site) => {\n if (action.site && site.id === action.site.id) {\n return {...site, error: action.error}\n }\n return site\n }),\n }\n default:\n return state\n }\n})\n","import {merge, of} from 'rxjs'\nimport {createEventHandler} from 'react-props-stream'\nimport {catchError, map, startWith, switchMap} from 'rxjs/operators'\nimport {deploy} from './datastores/deploy'\nimport {Site, WidgetOptions} from './types'\nimport {stateReducer$} from './reducers'\n\nconst noop = () => undefined\n\nconst INITIAL_PROPS = {\n title: 'Netlify sites',\n sites: [],\n isLoading: true,\n onDeploy: noop,\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\nexport const props$ = (options: WidgetOptions) => {\n const configuredSites = (options.sites || []).map((site) => ({\n id: site.apiId,\n name: site.name,\n title: site.title,\n buildHookId: site.buildHookId,\n url:\n site.url ||\n (site.branch && `https://${site.branch}--${site.name}.netlify.app/`) ||\n (site.name && `https://${site.name}.netlify.app/`),\n adminUrl: site.name && `https://app.netlify.com/sites/${site.name}`,\n branch: site.branch,\n }))\n\n const [onDeploy$, onDeploy] = createEventHandler<Site>()\n const setSitesAction$ = of(configuredSites).pipe(map((sites) => ({type: 'setSites', sites})))\n const deployAction$ = onDeploy$.pipe(map((site) => ({type: 'deploy/started', site})))\n const deployResult$ = onDeploy$.pipe(switchMap((site) => deploy(site)))\n const deployCompletedAction$ = deployResult$.pipe(\n map(\n (result) => ({type: 'deploy/completed', ...result}),\n catchError((error) => of({type: 'deploy/failed', error}))\n )\n )\n\n merge(setSitesAction$, deployAction$, deployCompletedAction$).pipe(stateReducer$).subscribe()\n\n return of(configuredSites).pipe(\n map((sites) => ({\n sites,\n title: options.title || INITIAL_PROPS.title,\n description: options.description,\n isLoading: false,\n onDeploy,\n })),\n startWith(INITIAL_PROPS)\n )\n}\n","import React, {FunctionComponent, PropsWithChildren} from 'react'\n\nconst Link = (props: PropsWithChildren<{url: string}>) => {\n const {url, children} = props\n\n return (\n <span>\n <a href={url} target=\"_blank\" rel=\"noreferrer\">\n {children}\n </a>\n </span>\n )\n}\n\ntype Props = {\n url?: string\n adminUrl?: string\n}\n\nconst Links: FunctionComponent<Props> = (props) => {\n const {url, adminUrl} = props\n\n if (url && adminUrl) {\n return (\n <span>\n (<Link url={url}>view</Link>, <Link url={adminUrl}>admin</Link>)\n </span>\n )\n }\n\n if (url) {\n return <Link url={url}>(view)</Link>\n }\n if (adminUrl) {\n return <Link url={adminUrl}>(admin)</Link>\n }\n return null\n}\n\nexport default Links\n","import React, {FunctionComponent, useCallback, useEffect, useRef, useState} from 'react'\nimport {Button, Flex, Box, Card, Text, Stack, Label} from '@sanity/ui'\nimport {DeployAction, Site} from '../../types'\nimport Links from './Links'\n\ninterface Props {\n site: Site\n onDeploy: DeployAction\n}\n\nexport const IMAGE_PULL_INTERVAL = 10000\n\nconst getImageUrl = (siteId: string, branchName?: string) => {\n const baseUrl = `https://api.netlify.com/api/v1/badges/${siteId}/deploy-status`\n const time = new Date().getTime()\n const branch = `branch=${branchName}`\n\n return branchName ? `${baseUrl}?${time}&${branch}` : `${baseUrl}?${time}`\n}\n\nconst useBadgeImage = (siteId: string, branchName?: string ) => {\n const [src, setSrc] = useState(() => getImageUrl(siteId, branchName))\n const update = useCallback(() => setSrc(getImageUrl(siteId, branchName)), [siteId])\n\n useEffect(() => {\n const interval = window.setInterval(update, IMAGE_PULL_INTERVAL)\n return () => window.clearInterval(interval)\n }, [update])\n\n return [src, update] as const\n}\n\nconst useDeploy = (site: Site, onDeploy: DeployAction, updateBadge: () => void) => {\n const timeoutRef = useRef(-1)\n useEffect(() => () => window.clearTimeout(timeoutRef.current), [])\n\n return useCallback(() => {\n onDeploy(site)\n timeoutRef.current = window.setTimeout(updateBadge, 1000)\n }, [site, onDeploy, updateBadge])\n}\n\nconst SiteItem: FunctionComponent<Props> = (props) => {\n const [hasBadgeError, setHasBadgeError] = useState(false)\n const {site, onDeploy} = props\n const {id, name, title, url, adminUrl, buildHookId, branch} = site\n\n const [badge, updateBadge] = useBadgeImage(id, branch)\n const handleDeploy = useDeploy(site, onDeploy, updateBadge)\n const handleBadgeError = () => {\n setHasBadgeError(true)\n }\n\n return (\n <Flex as=\"li\">\n <Box flex={1} paddingY={2} paddingX={3}>\n <Stack space={2}>\n <Text as=\"h4\">\n {title || name}\n <Links url={url} adminUrl={adminUrl} />\n </Text>\n\n <Flex justify=\"flex-start\">\n {!hasBadgeError && <img src={badge} onError={handleBadgeError} alt=\"Badge\" />}\n {hasBadgeError && <Card tone=\"critical\" radius={2} padding={2}><Label size={0} muted>Failed to load badge</Label></Card>}\n </Flex>\n </Stack>\n </Box>\n\n {buildHookId ? (\n <Box paddingY={2} paddingX={3}>\n <Button mode=\"ghost\" onClick={handleDeploy} text=\"Deploy\" />\n </Box>\n ) : null}\n </Flex>\n )\n}\n\nexport default SiteItem\n","import React from 'react'\nimport {DeployAction, Site} from '../types'\nimport SiteItem from './SiteItem'\nimport {Flex, Box, Card, Text, Spinner, Stack} from '@sanity/ui'\n\ninterface Props {\n isLoading: boolean\n sites?: Site[]\n onDeploy: DeployAction\n}\n\nexport default function SiteList(props: Props) {\n const {isLoading, onDeploy, sites} = props\n if (isLoading) {\n return (\n <Card padding={4}>\n <Flex direction=\"column\" justify=\"center\" align=\"center\">\n <Spinner muted />\n <Box marginTop={3}>\n <Text muted>Loading sites…</Text>\n </Box>\n </Flex>\n </Card>\n )\n }\n if (!sites || (sites && sites.length === 0)) {\n return (\n <Card tone=\"critical\" padding={3}>\n <Text>No sites are defined in the widget options. Please check your config.</Text>\n </Card>\n )\n }\n return (\n <Box paddingY={2}>\n <Stack as=\"ul\" space={2}>\n {sites.map((site, index) => {\n return <SiteItem onDeploy={onDeploy} site={site} key={`site-${index}`} />\n })}\n </Stack>\n </Box>\n )\n}\n","import React from 'react'\nimport {NetlifyWidgetProps} from '../types'\nimport SiteList from './SiteList'\nimport {DashboardWidgetContainer} from '@sanity/dashboard'\nimport {styled} from 'styled-components'\nimport {Button, Flex, Card, Text, Box} from '@sanity/ui'\n\nconst ContentCard = styled(Card)`\n min-height: 66px;\n`\n\nexport default function NetlifyWidget(props: NetlifyWidgetProps) {\n const netlifySitesUrl = 'https://app.netlify.com/account/sites'\n const {title, description, isLoading, sites, onDeploy} = props\n\n const footer = (\n <Flex direction=\"column\" align=\"stretch\">\n <Button\n as=\"a\"\n href={isLoading ? undefined : netlifySitesUrl}\n disabled={isLoading}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage sites at Netlify\"\n loading={isLoading}\n target=\"_blank\"\n />\n </Flex>\n )\n\n return (\n <DashboardWidgetContainer header={title} footer={footer}>\n <ContentCard paddingY={1}>\n {description && (\n <Box paddingY={3} paddingX={3}>\n <Text as=\"p\" size={1} muted>\n <span dangerouslySetInnerHTML={{__html: description}} />\n </Text>\n </Box>\n )}\n <SiteList isLoading={isLoading} onDeploy={onDeploy} sites={sites} />\n </ContentCard>\n </DashboardWidgetContainer>\n )\n}\n","import React from 'react'\nimport {streamingComponent} from 'react-props-stream'\nimport {map, switchMap} from 'rxjs/operators'\nimport {WidgetOptions} from './types'\nimport {props$} from './props'\nimport NetlifyWidget from './components/NetlifyWidget'\n\nexport default streamingComponent<WidgetOptions>((options$) =>\n options$.pipe(\n switchMap((options) =>\n props$(options).pipe(\n map((props) => {\n return <NetlifyWidget {...props} />\n })\n )\n )\n )\n)\n","import React from 'react'\nimport Widget from './widget'\nimport {WidgetOptions} from './types'\nimport {DashboardWidget, LayoutConfig} from '@sanity/dashboard'\n\nexport type NetlifyWidgetConfig = WidgetOptions & {layout?: LayoutConfig}\n\nexport function netlifyWidget(config: NetlifyWidgetConfig): DashboardWidget {\n return {\n name: 'netlify-widget',\n component: () => {\n return <Widget {...config} />\n },\n layout: config.layout ?? {width: 'medium'},\n }\n}\n"],"names":[],"mappings":"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"}
package/sanity.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "parts": [
3
- {
4
- "implements": "part:@sanity/base/sanity-root",
5
- "path": "./v2-incompatible.js"
6
- }
7
- ]
8
- }
@@ -1,47 +0,0 @@
1
- import React from 'react'
2
- import {NetlifyWidgetProps} from '../types'
3
- import SiteList from './SiteList'
4
- import {DashboardWidgetContainer} from '@sanity/dashboard'
5
- import {styled} from 'styled-components'
6
- import {Button, Flex, Card, Text, Box} from '@sanity/ui'
7
-
8
- const ContentCard = styled(Card)`
9
- min-height: 66px;
10
- `
11
-
12
- export default function NetlifyWidget(props: NetlifyWidgetProps) {
13
- const netlifySitesUrl = 'https://app.netlify.com/account/sites'
14
- const {title, description, isLoading, sites, onDeploy} = props
15
-
16
- const footer = (
17
- <Flex direction="column" align="stretch">
18
- <Button
19
- as="a"
20
- href={isLoading ? undefined : netlifySitesUrl}
21
- disabled={isLoading}
22
- paddingX={2}
23
- paddingY={4}
24
- mode="bleed"
25
- tone="primary"
26
- text="Manage sites at Netlify"
27
- loading={isLoading}
28
- target="_blank"
29
- />
30
- </Flex>
31
- )
32
-
33
- return (
34
- <DashboardWidgetContainer header={title} footer={footer}>
35
- <ContentCard paddingY={1}>
36
- {description && (
37
- <Box paddingY={3} paddingX={3}>
38
- <Text as="p" size={1} muted>
39
- <span dangerouslySetInnerHTML={{__html: description}} />
40
- </Text>
41
- </Box>
42
- )}
43
- <SiteList isLoading={isLoading} onDeploy={onDeploy} sites={sites} />
44
- </ContentCard>
45
- </DashboardWidgetContainer>
46
- )
47
- }
@@ -1,40 +0,0 @@
1
- import React, {FunctionComponent, PropsWithChildren} from 'react'
2
-
3
- const Link = (props: PropsWithChildren<{url: string}>) => {
4
- const {url, children} = props
5
-
6
- return (
7
- <span>
8
- <a href={url} target="_blank" rel="noreferrer">
9
- {children}
10
- </a>
11
- </span>
12
- )
13
- }
14
-
15
- type Props = {
16
- url?: string
17
- adminUrl?: string
18
- }
19
-
20
- const Links: FunctionComponent<Props> = (props) => {
21
- const {url, adminUrl} = props
22
-
23
- if (url && adminUrl) {
24
- return (
25
- <span>
26
- (<Link url={url}>view</Link>, <Link url={adminUrl}>admin</Link>)
27
- </span>
28
- )
29
- }
30
-
31
- if (url) {
32
- return <Link url={url}>(view)</Link>
33
- }
34
- if (adminUrl) {
35
- return <Link url={adminUrl}>(admin)</Link>
36
- }
37
- return null
38
- }
39
-
40
- export default Links