sanity-plugin-dashboard-widget-netlify 2.0.1 → 2.0.2
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/lib/index.d.ts +45 -0
- package/lib/index.js +171 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +176 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +21 -25
- package/src/components/NetlifyWidget.tsx +1 -1
- package/lib/index.esm.js +0 -2
- package/lib/index.esm.js.map +0 -1
- /package/lib/{src/index.d.ts → index.d.mts} +0 -0
package/LICENSE
CHANGED
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
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
CHANGED
|
@@ -1,2 +1,172 @@
|
|
|
1
|
-
"use strict";
|
|
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;
|
|
2
172
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/http/utils/createAbortController.ts","../src/http/statusCodeRequest.ts","../src/reducers.ts","../src/props.ts","../src/datastores/deploy.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 {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 {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 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":["statusCodeRequest","input","init","Observable","subscriber","controller","window","AbortController","AbortControllerPolyfill","fetch","_objectSpread","signal","then","res","status","Error","concat","statusText","next","complete","err","name","error","abort","stateReducer$","scan","state","action","type","sites","map","site","id","INITIAL_PROPS","title","isLoading","onDeploy","props$","options","configuredSites","apiId","buildHookId","url","branch","adminUrl","onDeploy$","createEventHandler","setSitesAction$","of","pipe","deployAction$","deployCompletedAction$","switchMap","method","result","deploy","catchError","merge","subscribe","description","startWith","Link","props","children","jsx","href","target","rel","Links","jsxs","getImageUrl","siteId","branchName","baseUrl","time","Date","getTime","SiteItem","hasBadgeError","setHasBadgeError","useState","badge","updateBadge","src","setSrc","update","useCallback","useEffect","interval","setInterval","clearInterval","useBadgeImage","handleDeploy","timeoutRef","useRef","clearTimeout","current","setTimeout","useDeploy","Flex","as","Box","flex","paddingY","paddingX","Stack","space","Text","justify","onError","alt","Card","tone","radius","padding","Label","size","muted","Button","mode","onClick","text","SiteList","direction","align","Spinner","marginTop","length","index","ContentCard","styled","_templateObject","NetlifyWidget","footer","disabled","loading","DashboardWidgetContainer","header","dangerouslySetInnerHTML","__html","Widget","streamingComponent","options$","config","_a","component","layout","width"],"mappings":"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"}
|
|
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
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-dashboard-widget-netlify",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Sanity Studio Dashboard Widget for triggering Netlify builds",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -19,20 +19,19 @@
|
|
|
19
19
|
},
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"author": "Sanity.io <hello@sanity.io>",
|
|
22
|
+
"type": "commonjs",
|
|
22
23
|
"exports": {
|
|
23
24
|
".": {
|
|
24
|
-
"types": "./lib/src/index.d.ts",
|
|
25
25
|
"source": "./src/index.ts",
|
|
26
|
-
"import": "./lib/index.
|
|
26
|
+
"import": "./lib/index.mjs",
|
|
27
27
|
"require": "./lib/index.js",
|
|
28
|
-
"default": "./lib/index.
|
|
28
|
+
"default": "./lib/index.js"
|
|
29
29
|
},
|
|
30
30
|
"./package.json": "./package.json"
|
|
31
31
|
},
|
|
32
32
|
"main": "./lib/index.js",
|
|
33
|
-
"module": "./lib/index.
|
|
34
|
-
"
|
|
35
|
-
"types": "./lib/src/index.d.ts",
|
|
33
|
+
"module": "./lib/index.mjs",
|
|
34
|
+
"types": "./lib/index.d.ts",
|
|
36
35
|
"files": [
|
|
37
36
|
"src",
|
|
38
37
|
"lib",
|
|
@@ -41,18 +40,16 @@
|
|
|
41
40
|
],
|
|
42
41
|
"scripts": {
|
|
43
42
|
"__test": "jest --coverage",
|
|
44
|
-
"
|
|
45
|
-
"build": "pkg-utils build --strict",
|
|
43
|
+
"build": "plugin-kit verify-package --silent && pkg-utils build --strict --check --clean",
|
|
46
44
|
"clean": "rimraf lib",
|
|
47
45
|
"compile": "tsc --noEmit",
|
|
48
46
|
"link-watch": "plugin-kit link-watch",
|
|
49
47
|
"lint": "eslint .",
|
|
50
48
|
"prepare": "husky install",
|
|
51
49
|
"prepublishOnly": "npm run compile && npm run build",
|
|
52
|
-
"test": "echo 'tests disabled for now'",
|
|
53
50
|
"test:prod": "npm run lint && npm run test -- --no-cache",
|
|
54
51
|
"test:watch": "jest --coverage --watch",
|
|
55
|
-
"watch": "pkg-utils watch"
|
|
52
|
+
"watch": "pkg-utils watch --strict"
|
|
56
53
|
},
|
|
57
54
|
"prettier": {
|
|
58
55
|
"bracketSpacing": false,
|
|
@@ -61,8 +58,8 @@
|
|
|
61
58
|
"singleQuote": true
|
|
62
59
|
},
|
|
63
60
|
"dependencies": {
|
|
64
|
-
"@sanity/incompatible-plugin": "^1.0.
|
|
65
|
-
"@sanity/ui": "^
|
|
61
|
+
"@sanity/incompatible-plugin": "^1.0.5",
|
|
62
|
+
"@sanity/ui": "^2.16.4",
|
|
66
63
|
"abort-controller": "^2.0.3",
|
|
67
64
|
"react-props-stream": "^1.0.1",
|
|
68
65
|
"rxjs": "^6.6.7"
|
|
@@ -72,9 +69,9 @@
|
|
|
72
69
|
"@babel/preset-react": "^7.18.6",
|
|
73
70
|
"@commitlint/cli": "^17.2.0",
|
|
74
71
|
"@commitlint/config-conventional": "^17.2.0",
|
|
75
|
-
"@sanity/dashboard": "^
|
|
76
|
-
"@sanity/pkg-utils": "^
|
|
77
|
-
"@sanity/plugin-kit": "^
|
|
72
|
+
"@sanity/dashboard": "^4.1.4",
|
|
73
|
+
"@sanity/pkg-utils": "^7.9.3",
|
|
74
|
+
"@sanity/plugin-kit": "^4.0.19",
|
|
78
75
|
"@sanity/semantic-release-preset": "^2.0.2",
|
|
79
76
|
"@testing-library/jest-dom": "^5.16.5",
|
|
80
77
|
"@testing-library/react": "^13.4.0",
|
|
@@ -82,7 +79,6 @@
|
|
|
82
79
|
"@types/node": "^18.11.9",
|
|
83
80
|
"@types/react": "^18",
|
|
84
81
|
"@types/react-dom": "^18",
|
|
85
|
-
"@types/styled-components": "^5.1.26",
|
|
86
82
|
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
|
87
83
|
"@typescript-eslint/parser": "^5.42.0",
|
|
88
84
|
"eslint": "^8.26.0",
|
|
@@ -102,19 +98,19 @@
|
|
|
102
98
|
"react-dom": "^18",
|
|
103
99
|
"rimraf": "^3.0.2",
|
|
104
100
|
"sanity": "^3.0.0",
|
|
105
|
-
"styled-components": "^
|
|
101
|
+
"styled-components": "^6.1.19",
|
|
106
102
|
"ts-jest": "^29.0.3",
|
|
107
|
-
"typescript": "
|
|
103
|
+
"typescript": "5.8.3"
|
|
108
104
|
},
|
|
109
105
|
"peerDependencies": {
|
|
110
|
-
"@sanity/dashboard": "^
|
|
111
|
-
"react": "^18",
|
|
112
|
-
"react-dom": "^18",
|
|
113
|
-
"sanity": "^3.0.0",
|
|
114
|
-
"styled-components": "^
|
|
106
|
+
"@sanity/dashboard": "^4.1.4",
|
|
107
|
+
"react": "^18.3 || ^19",
|
|
108
|
+
"react-dom": "^18.3 || ^19",
|
|
109
|
+
"sanity": "^3 || ^4.0.0-0",
|
|
110
|
+
"styled-components": "^6.1"
|
|
115
111
|
},
|
|
116
112
|
"engines": {
|
|
117
|
-
"node": ">=
|
|
113
|
+
"node": ">=18"
|
|
118
114
|
},
|
|
119
115
|
"publishConfig": {
|
|
120
116
|
"access": "public"
|
|
@@ -2,7 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import {NetlifyWidgetProps} from '../types'
|
|
3
3
|
import SiteList from './SiteList'
|
|
4
4
|
import {DashboardWidgetContainer} from '@sanity/dashboard'
|
|
5
|
-
import styled from 'styled-components'
|
|
5
|
+
import {styled} from 'styled-components'
|
|
6
6
|
import {Button, Flex, Card, Text, Box} from '@sanity/ui'
|
|
7
7
|
|
|
8
8
|
const ContentCard = styled(Card)`
|
package/lib/index.esm.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var e;function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function r(e){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?t(Object(i),!0).forEach((function(t){n(e,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(i)):t(Object(i)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(i,t))}))}return e}function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}import{jsxs as i,jsx as o}from"react/jsx-runtime";import{createEventHandler as a,streamingComponent as c}from"react-props-stream";import{map as s,scan as l,switchMap as d,catchError as p,startWith as u}from"rxjs/operators";import{Observable as m,of as h,merge as f}from"rxjs";import y from"abort-controller";import{useState as g,useCallback as b,useEffect as w,useRef as O}from"react";import{Flex as j,Box as v,Stack as D,Text as P,Card as k,Label as x,Button as I,Spinner as T}from"@sanity/ui";import{DashboardWidgetContainer as H}from"@sanity/dashboard";import E from"styled-components";const L=(e,t)=>new m((n=>{const i="AbortController"in window?new AbortController:new y;return fetch(e,r(r({},t),{},{signal:i.signal})).then((e=>{if(e.status<200||e.status>299)throw new Error("HTTP Error ".concat(e.status,": ").concat(e.statusText));return e.status})).then((e=>{n.next(e),n.complete()}),(e=>{"AbortError"===e.name?n.complete():n.error(e)})),()=>{i.abort()}}));const S=l(((e,t)=>{switch(t.type){case"setSites":return r(r({},e),{},{sites:t.sites||[]});case"deploy/started":return r(r({},e),{},{sites:e.sites.map((e=>t.site&&e.id===t.site.id?r({},e):e))});case"deploy/failed":return r(r({},e),{},{error:t.error});case"deploy/completed":return r(r({},e),{},{sites:e.sites.map((e=>t.site&&e.id===t.site.id?r(r({},e),{},{error:t.error}):e))});default:return e}})),Y={title:"Netlify sites",sites:[],isLoading:!0,onDeploy:()=>{}},_=e=>{const t=(e.sites||[]).map((e=>({id:e.apiId,name:e.name,title:e.title,buildHookId:e.buildHookId,url:e.url||e.branch&&"https://".concat(e.branch,"--").concat(e.name,".netlify.app/")||e.name&&"https://".concat(e.name,".netlify.app/"),adminUrl:e.name&&"https://app.netlify.com/sites/".concat(e.name),branch:e.branch}))),[n,i]=a(),o=h(t).pipe(s((e=>({type:"setSites",sites:e})))),c=n.pipe(s((e=>({type:"deploy/started",site:e})))),l=n.pipe(d((e=>function(e){return e.buildHookId?L("https://api.netlify.com/build_hooks/".concat(e.buildHookId),{method:"POST"}).pipe(s((t=>({result:t,site:e})))):h(new Error("Site missing buildHookId"))}(e)))).pipe(s((e=>r({type:"deploy/completed"},e)),p((e=>h({type:"deploy/failed",error:e})))));return f(o,c,l).pipe(S).subscribe(),h(t).pipe(s((t=>({sites:t,title:e.title||Y.title,description:e.description,isLoading:!1,onDeploy:i}))),u(Y))},z=e=>{const{url:t,children:r}=e;return o("span",{children:o("a",{href:t,target:"_blank",rel:"noreferrer",children:r})})},U=e=>{const{url:t,adminUrl:r}=e;return t&&r?i("span",{children:["(",o(z,{url:t,children:"view"}),", ",o(z,{url:r,children:"admin"}),")"]}):t?o(z,{url:t,children:"(view)"}):r?o(z,{url:r,children:"(admin)"}):null},X=(e,t)=>{const r="https://api.netlify.com/api/v1/badges/".concat(e,"/deploy-status"),n=(new Date).getTime(),i="branch=".concat(t);return t?"".concat(r,"?").concat(n,"&").concat(i):"".concat(r,"?").concat(n)},A=e=>{const[t,r]=g(!1),{site:n,onDeploy:a}=e,{id:c,name:s,title:l,url:d,adminUrl:p,buildHookId:u,branch:m}=n,[h,f]=((e,t)=>{const[r,n]=g((()=>X(e,t))),i=b((()=>n(X(e,t))),[e]);return w((()=>{const e=window.setInterval(i,1e4);return()=>window.clearInterval(e)}),[i]),[r,i]})(c,m),y=((e,t,r)=>{const n=O(-1);return w((()=>()=>window.clearTimeout(n.current)),[]),b((()=>{t(e),n.current=window.setTimeout(r,1e3)}),[e,t,r])})(n,a,f);return i(j,{as:"li",children:[o(v,{flex:1,paddingY:2,paddingX:3,children:i(D,{space:2,children:[i(P,{as:"h4",children:[l||s,o(U,{url:d,adminUrl:p})]}),i(j,{justify:"flex-start",children:[!t&&o("img",{src:h,onError:()=>{r(!0)},alt:"Badge"}),t&&o(k,{tone:"critical",radius:2,padding:2,children:o(x,{size:0,muted:!0,children:"Failed to load badge"})})]})]})}),u?o(v,{paddingY:2,paddingX:3,children:o(I,{mode:"ghost",onClick:y,text:"Deploy"})}):null]})};function C(e){const{isLoading:t,onDeploy:r,sites:n}=e;return t?o(k,{padding:4,children:i(j,{direction:"column",justify:"center",align:"center",children:[o(T,{muted:!0}),o(v,{marginTop:3,children:o(P,{muted:!0,children:"Loading sites…"})})]})}):!n||n&&0===n.length?o(k,{tone:"critical",padding:3,children:o(P,{children:"No sites are defined in the widget options. Please check your config."})}):o(v,{paddingY:2,children:o(D,{as:"ul",space:2,children:n.map(((e,t)=>o(A,{onDeploy:r,site:e},"site-".concat(t))))})})}const N=E(k)(e||(M=["\n min-height: 66px;\n"],B||(B=M.slice(0)),e=Object.freeze(Object.defineProperties(M,{raw:{value:Object.freeze(B)}}))));var M,B;function F(e){const{title:t,description:r,isLoading:n,sites:a,onDeploy:c}=e;return o(H,{header:t,footer:o(j,{direction:"column",align:"stretch",children:o(I,{as:"a",href:n?void 0:"https://app.netlify.com/account/sites",disabled:n,paddingX:2,paddingY:4,mode:"bleed",tone:"primary",text:"Manage sites at Netlify",loading:n,target:"_blank"})}),children:i(N,{paddingY:1,children:[r&&o(v,{paddingY:3,paddingX:3,children:o(P,{as:"p",size:1,muted:!0,children:o("span",{dangerouslySetInnerHTML:{__html:r}})})}),o(C,{isLoading:n,onDeploy:c,sites:a})]})})}var q=c((e=>e.pipe(d((e=>_(e).pipe(s((e=>o(F,r({},e))))))))));function G(e){var t;return{name:"netlify-widget",component:()=>o(q,r({},e)),layout:null!=(t=e.layout)?t:{width:"medium"}}}export{G as netlifyWidget};
|
|
2
|
-
//# sourceMappingURL=index.esm.js.map
|
package/lib/index.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/http/utils/createAbortController.ts","../src/http/statusCodeRequest.ts","../src/reducers.ts","../src/props.ts","../src/datastores/deploy.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 {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 {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 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":["statusCodeRequest","input","init","Observable","subscriber","controller","window","AbortController","AbortControllerPolyfill","fetch","_objectSpread","signal","then","res","status","Error","concat","statusText","next","complete","err","name","error","abort","stateReducer$","scan","state","action","type","sites","map","site","id","INITIAL_PROPS","title","isLoading","onDeploy","props$","options","configuredSites","apiId","buildHookId","url","branch","adminUrl","onDeploy$","createEventHandler","setSitesAction$","of","pipe","deployAction$","deployCompletedAction$","switchMap","method","result","deploy","catchError","merge","subscribe","description","startWith","Link","props","children","jsx","href","target","rel","Links","jsxs","getImageUrl","siteId","branchName","baseUrl","time","Date","getTime","SiteItem","hasBadgeError","setHasBadgeError","useState","badge","updateBadge","src","setSrc","update","useCallback","useEffect","interval","setInterval","clearInterval","useBadgeImage","handleDeploy","timeoutRef","useRef","clearTimeout","current","setTimeout","useDeploy","Flex","as","Box","flex","paddingY","paddingX","Stack","space","Text","justify","onError","alt","Card","tone","radius","padding","Label","size","muted","Button","mode","onClick","text","SiteList","direction","align","Spinner","marginTop","length","index","ContentCard","styled","_templateObject","NetlifyWidget","DashboardWidgetContainer","header","footer","disabled","loading","dangerouslySetInnerHTML","__html","Widget","streamingComponent","options$","netlifyWidget","config","_a","component","layout","width"],"mappings":"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"}
|
|
File without changes
|