@sanity/dashboard 4.0.0 → 4.1.1
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.esm.js +48 -34
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +48 -34
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +48 -34
- package/lib/index.mjs.map +1 -1
- package/package.json +24 -20
- package/src/versionedClient.ts +1 -1
- package/src/widgets/projectInfo/ProjectInfo.tsx +29 -51
- package/src/widgets/projectInfo/index.ts +1 -1
- package/src/widgets/projectInfo/types.ts +28 -0
package/lib/index.esm.js
CHANGED
|
@@ -47,26 +47,39 @@ const Root$3 = styled(Card)`
|
|
|
47
47
|
] });
|
|
48
48
|
});
|
|
49
49
|
function useVersionedClient() {
|
|
50
|
-
return useClient({ apiVersion: "2024-
|
|
50
|
+
return useClient({ apiVersion: "2024-08-01" });
|
|
51
51
|
}
|
|
52
52
|
const DashboardContext = createContext({ widgets: [] });
|
|
53
53
|
function useDashboardConfig() {
|
|
54
54
|
return useContext(DashboardContext);
|
|
55
55
|
}
|
|
56
|
+
var __defProp$2 = Object.defineProperty, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$2 = (a, b) => {
|
|
57
|
+
for (var prop in b || (b = {}))
|
|
58
|
+
__hasOwnProp$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
|
|
59
|
+
if (__getOwnPropSymbols$2)
|
|
60
|
+
for (var prop of __getOwnPropSymbols$2(b))
|
|
61
|
+
__propIsEnum$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
|
|
62
|
+
return a;
|
|
63
|
+
};
|
|
56
64
|
function WidgetContainer(props) {
|
|
57
65
|
const config = useDashboardConfig(), layout = useMemo(
|
|
58
|
-
() => ({
|
|
59
|
-
...props.layout || {},
|
|
60
|
-
...config.layout || {}
|
|
61
|
-
}),
|
|
66
|
+
() => __spreadValues$2(__spreadValues$2({}, props.layout || {}), config.layout || {}),
|
|
62
67
|
[props.layout, config.layout]
|
|
63
68
|
);
|
|
64
69
|
return /* @__PURE__ */ jsx(Card, { shadow: 1, "data-width": layout.width, "data-height": layout.height, children: createElement(props.component, {}) });
|
|
65
70
|
}
|
|
71
|
+
var __defProp$1 = Object.defineProperty, __getOwnPropSymbols$1 = Object.getOwnPropertySymbols, __hasOwnProp$1 = Object.prototype.hasOwnProperty, __propIsEnum$1 = Object.prototype.propertyIsEnumerable, __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$1 = (a, b) => {
|
|
72
|
+
for (var prop in b || (b = {}))
|
|
73
|
+
__hasOwnProp$1.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
|
|
74
|
+
if (__getOwnPropSymbols$1)
|
|
75
|
+
for (var prop of __getOwnPropSymbols$1(b))
|
|
76
|
+
__propIsEnum$1.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
|
|
77
|
+
return a;
|
|
78
|
+
};
|
|
66
79
|
function isUrl(url) {
|
|
67
80
|
return url && /^https?:\/\//.test(`${url}`);
|
|
68
81
|
}
|
|
69
|
-
function
|
|
82
|
+
function getGraphQLUrl(projectId, dataset) {
|
|
70
83
|
return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`;
|
|
71
84
|
}
|
|
72
85
|
function getGroqUrl(projectId, dataset) {
|
|
@@ -77,24 +90,15 @@ function getManageUrl(projectId) {
|
|
|
77
90
|
}
|
|
78
91
|
const NO_EXPERIMENTAL = [], NO_DATA = [];
|
|
79
92
|
function ProjectInfo(props) {
|
|
80
|
-
const { __experimental_before = NO_EXPERIMENTAL, data = NO_DATA } = props, [
|
|
93
|
+
const { __experimental_before = NO_EXPERIMENTAL, data = NO_DATA } = props, [studioApps, setStudioApps] = useState(), [graphQLApi, setGraphQLApi] = useState(), versionedClient = useVersionedClient(), { projectId = "unknown", dataset = "unknown" } = versionedClient.config();
|
|
81
94
|
useEffect(() => {
|
|
82
95
|
const subscriptions = [];
|
|
83
96
|
return subscriptions.push(
|
|
84
|
-
versionedClient.observable.request({ uri:
|
|
85
|
-
next: (result) =>
|
|
86
|
-
var _a;
|
|
87
|
-
if ((_a = result.metadata) != null && _a.externalStudioHost) {
|
|
88
|
-
setStudioHost(result.metadata.externalStudioHost);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
setStudioHost(
|
|
92
|
-
result.studioHost ? `https://${result.studioHost}.sanity.studio` : void 0
|
|
93
|
-
);
|
|
94
|
-
},
|
|
97
|
+
versionedClient.observable.request({ uri: "/user-applications", tag: "dashboard.project-info" }).subscribe({
|
|
98
|
+
next: (result) => setStudioApps(result.filter((app) => app.type === "studio")),
|
|
95
99
|
error: (error) => {
|
|
96
|
-
console.error("Error while
|
|
97
|
-
error: "Something went wrong while
|
|
100
|
+
console.error("Error while resolving user applications", error), setStudioApps({
|
|
101
|
+
error: "Something went wrong while resolving user applications. See console."
|
|
98
102
|
});
|
|
99
103
|
}
|
|
100
104
|
})
|
|
@@ -104,17 +108,17 @@ function ProjectInfo(props) {
|
|
|
104
108
|
uri: `/graphql/${dataset}/default`,
|
|
105
109
|
tag: "dashboard.project-info.graphql-api"
|
|
106
110
|
}).subscribe({
|
|
107
|
-
next: () =>
|
|
111
|
+
next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),
|
|
108
112
|
error: (error) => {
|
|
109
|
-
error.statusCode === 404 ?
|
|
110
|
-
error: "Something went wrong while looking up
|
|
113
|
+
error.statusCode === 404 ? setGraphQLApi(void 0) : (console.error("Error while looking for graphQLApi", error), setGraphQLApi({
|
|
114
|
+
error: "Something went wrong while looking up graphQLApi. See console."
|
|
111
115
|
}));
|
|
112
116
|
}
|
|
113
117
|
})
|
|
114
118
|
), () => {
|
|
115
119
|
subscriptions.forEach((s) => s.unsubscribe());
|
|
116
120
|
};
|
|
117
|
-
}, [dataset, projectId, versionedClient,
|
|
121
|
+
}, [dataset, projectId, versionedClient, setGraphQLApi]);
|
|
118
122
|
const assembleTableRows = useMemo(() => {
|
|
119
123
|
var _a;
|
|
120
124
|
let result = [
|
|
@@ -126,11 +130,13 @@ function ProjectInfo(props) {
|
|
|
126
130
|
]
|
|
127
131
|
}
|
|
128
132
|
];
|
|
129
|
-
const apps =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
const apps = data.filter((item) => item.category === "apps");
|
|
134
|
+
(Array.isArray(studioApps) ? studioApps : []).forEach((app) => {
|
|
135
|
+
apps.push({
|
|
136
|
+
title: app.title || "Studio",
|
|
137
|
+
value: app.urlType === "internal" ? `https://${app.appHost}.sanity.studio` : app.appHost
|
|
138
|
+
});
|
|
139
|
+
}), apps.length > 0 && (result = result.concat([{ title: "Apps", rows: apps }])), result = result.concat(
|
|
134
140
|
[
|
|
135
141
|
{
|
|
136
142
|
title: "APIs",
|
|
@@ -138,7 +144,7 @@ function ProjectInfo(props) {
|
|
|
138
144
|
{ title: "GROQ", value: getGroqUrl(projectId, dataset) },
|
|
139
145
|
{
|
|
140
146
|
title: "GraphQL",
|
|
141
|
-
value: (_a = typeof
|
|
147
|
+
value: (_a = typeof graphQLApi == "object" ? "Error" : graphQLApi) != null ? _a : "Not deployed"
|
|
142
148
|
}
|
|
143
149
|
]
|
|
144
150
|
}
|
|
@@ -151,9 +157,9 @@ function ProjectInfo(props) {
|
|
|
151
157
|
}), Object.keys(otherStuff).forEach((category) => {
|
|
152
158
|
result.push({ title: category, rows: otherStuff[category] });
|
|
153
159
|
}), result;
|
|
154
|
-
}, [
|
|
160
|
+
}, [graphQLApi, studioApps, projectId, dataset, data]);
|
|
155
161
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
156
|
-
__experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsx(WidgetContainer, {
|
|
162
|
+
__experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsx(WidgetContainer, __spreadValues$1({}, widgetConfig), idx)),
|
|
157
163
|
/* @__PURE__ */ jsx(Box, { height: "fill", marginTop: (__experimental_before == null ? void 0 : __experimental_before.length) > 0 ? 4 : 0, children: /* @__PURE__ */ jsx(
|
|
158
164
|
DashboardWidgetContainer,
|
|
159
165
|
{
|
|
@@ -188,7 +194,7 @@ function ProjectInfo(props) {
|
|
|
188
194
|
/* @__PURE__ */ jsx(Text, { weight: "medium", role: "rowheader", children: row.title }),
|
|
189
195
|
typeof row.value == "object" && /* @__PURE__ */ jsx(Text, { size: 1, children: (_a = row.value) == null ? void 0 : _a.error }),
|
|
190
196
|
typeof row.value == "string" && /* @__PURE__ */ jsx(Fragment, { children: isUrl(row.value) ? /* @__PURE__ */ jsx(Text, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: /* @__PURE__ */ jsx("a", { href: row.value, children: row.value }) }) : /* @__PURE__ */ jsx(Code, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: row.value }) })
|
|
191
|
-
] }, row.title);
|
|
197
|
+
] }, `${row.value}-${row.title}`);
|
|
192
198
|
}) })
|
|
193
199
|
] }, item.title))
|
|
194
200
|
] })
|
|
@@ -450,6 +456,14 @@ function sanityTutorialsWidget(config) {
|
|
|
450
456
|
function DashboardLayout(props) {
|
|
451
457
|
return /* @__PURE__ */ jsx(Container, { width: 4, padding: 4, sizing: "border", style: { height: "100%", overflowY: "auto" }, children: props.children });
|
|
452
458
|
}
|
|
459
|
+
var __defProp = Object.defineProperty, __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => {
|
|
460
|
+
for (var prop in b || (b = {}))
|
|
461
|
+
__hasOwnProp.call(b, prop) && __defNormalProp(a, prop, b[prop]);
|
|
462
|
+
if (__getOwnPropSymbols)
|
|
463
|
+
for (var prop of __getOwnPropSymbols(b))
|
|
464
|
+
__propIsEnum.call(b, prop) && __defNormalProp(a, prop, b[prop]);
|
|
465
|
+
return a;
|
|
466
|
+
};
|
|
453
467
|
const media = {
|
|
454
468
|
small: (...args) => css`
|
|
455
469
|
@media (min-width: ${({ theme }) => theme.sanity.media[0]}px) {
|
|
@@ -525,7 +539,7 @@ function WidgetGroup(props) {
|
|
|
525
539
|
gap: 4,
|
|
526
540
|
children: [
|
|
527
541
|
widgets.length ? null : /* @__PURE__ */ jsx(Card, { padding: 4, shadow: 1, tone: "primary", children: /* @__PURE__ */ jsx(Text, { align: "center", children: "Add some widgets to populate this space." }) }),
|
|
528
|
-
widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsx(WidgetContainer, {
|
|
542
|
+
widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsx(WidgetContainer, __spreadValues({}, widgetConfig), index) : /* @__PURE__ */ jsxs(Box, { children: [
|
|
529
543
|
widgetConfig.name,
|
|
530
544
|
" is missing widget component"
|
|
531
545
|
] }, index))
|
package/lib/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/components/DashboardWidgetContainer.tsx","../src/versionedClient.ts","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/widgets/projectInfo/ProjectInfo.tsx","../src/widgets/projectInfo/index.ts","../src/widgets/projectUsers/ProjectUser.tsx","../src/widgets/projectUsers/ProjectUsers.tsx","../src/widgets/projectUsers/index.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../src/widgets/sanityTutorials/dataAdapter.ts","../src/widgets/sanityTutorials/SanityTutorials.tsx","../src/widgets/sanityTutorials/index.ts","../src/components/DashboardLayout.tsx","../src/components/WidgetGroup.tsx","../src/containers/Dashboard.tsx","../src/plugin.tsx"],"sourcesContent":["import React, {forwardRef} from 'react'\nimport {Card, Box, Heading} from '@sanity/ui'\nimport {styled} from 'styled-components'\n\nconst Root = styled(Card)`\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n`\n\nconst Header = styled(Card)`\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n`\n\nconst Footer = styled(Card)`\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n`\n\nconst Content = styled(Box)`\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n overflow-y: auto;\n outline: none;\n }\n`\n\ninterface DashboardWidgetProps {\n header?: string\n children: React.ReactNode\n footer?: React.ReactNode\n}\n\nexport const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer(\n props: DashboardWidgetProps,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {header, children, footer} = props\n\n return (\n <Root radius={3} display=\"flex\" ref={ref}>\n {header && (\n <Header borderBottom paddingX={3} paddingY={4}>\n <Heading size={1} textOverflow=\"ellipsis\">\n {header}\n </Heading>\n </Header>\n )}\n {children && <Content>{children}</Content>}\n {footer && <Footer borderTop>{footer}</Footer>}\n </Root>\n )\n})\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n return useClient({apiVersion: '2024-06-03'})\n}\n","import {createContext, useContext} from 'react'\nimport {DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n return useContext(DashboardContext)\n}\n","import React, {createElement, useMemo} from 'react'\nimport {useDashboardConfig} from './DashboardContext'\nimport {Card} from '@sanity/ui'\nimport {DashboardWidget} from '../types'\n\nexport function WidgetContainer(props: DashboardWidget) {\n const config = useDashboardConfig()\n const layout = useMemo(\n () => ({\n ...(props.layout || {}),\n ...(config.layout || {}),\n }),\n [props.layout, config.layout],\n )\n\n return (\n <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n {createElement(props.component, {})}\n </Card>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Card, Stack, Heading, Grid, Label, Text, Code, Button} from '@sanity/ui'\nimport {useVersionedClient} from '../../versionedClient'\nimport {Subscription} from 'rxjs'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {DashboardWidget} from '../../types'\n\nexport interface ProjectInfoProps {\n __experimental_before?: DashboardWidget[]\n data: ProjectData[]\n}\n\ninterface App {\n title: string\n rows?: App[]\n value?: string | {error: string}\n}\n\ninterface ProjectData {\n title: string\n category?: string\n}\n\nfunction isUrl(url?: string) {\n return url && /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction getGraphQlUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`\n}\n\nfunction getGroqUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`\n}\n\nfunction getManageUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}`\n}\n\nconst NO_EXPERIMENTAL: DashboardWidget[] = []\nconst NO_DATA: ProjectData[] = []\n\nexport function ProjectInfo(props: ProjectInfoProps) {\n const {__experimental_before = NO_EXPERIMENTAL, data = NO_DATA} = props\n const [studioHost, setStudioHost] = useState<string | {error: string} | undefined>()\n const [graphqlApi, setGraphQlApi] = useState<string | {error: string} | undefined>()\n const versionedClient = useVersionedClient()\n const {projectId = 'unknown', dataset = 'unknown'} = versionedClient.config()\n\n useEffect(() => {\n const subscriptions: Subscription[] = []\n\n subscriptions.push(\n versionedClient.observable\n .request<{\n studioHost: string\n metadata?: {externalStudioHost?: string}\n }>({uri: `/projects/${projectId}`, tag: 'dashboard.project-info.studio-host'})\n .subscribe({\n next: (result) => {\n if (result.metadata?.externalStudioHost) {\n setStudioHost(result.metadata.externalStudioHost)\n return\n }\n\n setStudioHost(\n result.studioHost ? `https://${result.studioHost}.sanity.studio` : undefined,\n )\n },\n error: (error) => {\n console.error('Error while looking for studioHost', error)\n setStudioHost({\n error: 'Something went wrong while looking up studioHost. See console.',\n })\n },\n }),\n )\n\n // ping assumed graphql endpoint\n subscriptions.push(\n versionedClient.observable\n .request({\n method: 'HEAD',\n uri: `/graphql/${dataset}/default`,\n tag: 'dashboard.project-info.graphql-api',\n })\n .subscribe({\n next: () => setGraphQlApi(getGraphQlUrl(projectId, dataset)),\n error: (error) => {\n if (error.statusCode === 404) {\n setGraphQlApi(undefined)\n } else {\n console.error('Error while looking for graphqlApi', error)\n setGraphQlApi({\n error: 'Something went wrong while looking up graphqlApi. See console.',\n })\n }\n },\n }),\n )\n\n return () => {\n subscriptions.forEach((s) => s.unsubscribe())\n }\n }, [dataset, projectId, versionedClient, setGraphQlApi, setStudioHost])\n\n const assembleTableRows = useMemo(() => {\n let result: App[] = [\n {\n title: 'Sanity project',\n rows: [\n {title: 'Project ID', value: projectId},\n {title: 'Dataset', value: dataset},\n ],\n },\n ]\n\n // Handle any apps\n const apps: App[] = [\n studioHost ? {title: 'Studio', value: studioHost} : null,\n ...data.filter((item) => item.category === 'apps'),\n ].filter((a): a is App => !!a)\n if (apps.length > 0) {\n result = result.concat([{title: 'Apps', rows: apps}])\n }\n\n // Handle APIs\n result = result.concat(\n [\n {\n title: 'APIs',\n rows: [\n {title: 'GROQ', value: getGroqUrl(projectId, dataset)},\n {\n title: 'GraphQL',\n value: (typeof graphqlApi === 'object' ? 'Error' : graphqlApi) ?? 'Not deployed',\n },\n ],\n },\n ],\n data.filter((item) => item.category === 'apis'),\n )\n\n // Handle whatever else there might be\n const otherStuff: Record<string, ProjectData[]> = {}\n data.forEach((item) => {\n if (item.category && item.category !== 'apps' && item.category !== 'apis') {\n if (!otherStuff[item.category]) {\n otherStuff[item.category] = []\n }\n otherStuff[item.category].push(item)\n }\n })\n Object.keys(otherStuff).forEach((category) => {\n result.push({title: category, rows: otherStuff[category]})\n })\n\n return result\n }, [graphqlApi, studioHost, projectId, dataset, data])\n\n return (\n <>\n {__experimental_before.map((widgetConfig, idx) => (\n <WidgetContainer key={idx} {...widgetConfig} />\n ))}\n <Box height=\"fill\" marginTop={__experimental_before?.length > 0 ? 4 : 0}>\n <DashboardWidgetContainer\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage project\"\n as=\"a\"\n href={getManageUrl(projectId)}\n />\n }\n >\n <Card\n paddingY={4}\n radius={2}\n role=\"table\"\n aria-label=\"Project info\"\n aria-describedby=\"project_info_table\"\n >\n <Stack space={4}>\n <Box paddingX={3} as=\"header\">\n <Heading size={1} as=\"h2\" id=\"project_info_table\">\n Project info\n </Heading>\n </Box>\n {assembleTableRows.map((item) => {\n if (!item || !item.rows) {\n return null\n }\n\n return (\n <Stack key={item.title} space={3}>\n <Card borderBottom padding={3}>\n <Label size={0} muted role=\"columnheader\">\n {item.title}\n </Label>\n </Card>\n <Stack space={4} paddingX={3} role=\"rowgroup\">\n {item.rows.map((row) => {\n return (\n <Grid key={row.title} columns={2} role=\"row\">\n <Text weight=\"medium\" role=\"rowheader\">\n {row.title}\n </Text>\n {typeof row.value === 'object' && (\n <Text size={1}>{row.value?.error}</Text>\n )}\n {typeof row.value === 'string' && (\n <>\n {isUrl(row.value) ? (\n <Text size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n <a href={row.value}>{row.value}</a>\n </Text>\n ) : (\n <Code size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n {row.value}\n </Code>\n )}\n </>\n )}\n </Grid>\n )\n })}\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n </Card>\n </DashboardWidgetContainer>\n </Box>\n </>\n )\n}\n","import {ProjectInfo} from './ProjectInfo'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectInfo,\n layout: config?.layout ?? {width: 'medium'},\n }\n}\n","import React from 'react'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {styled} from 'styled-components'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {RobotIcon} from '@sanity/icons'\n\nconst Root = styled(Flex)`\n height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height\n box-sizing: content-box;\n`\n\nexport interface ProjectUserProps {\n user: User\n isRobot: boolean\n roles: string[]\n}\n\nexport function ProjectUser({user, isRobot, roles}: ProjectUserProps) {\n const listFormat = useListFormat({style: 'narrow'})\n return (\n <Root align=\"center\">\n <Flex align=\"center\" flex={1} gap={2}>\n <Box flex=\"none\">\n {isRobot ? (\n <Text size={2}>\n <RobotIcon />\n </Text>\n ) : (\n <UserAvatar user={user} />\n )}\n </Box>\n\n <Stack flex={1} space={2}>\n <Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n {user.displayName}\n </Text>\n\n <Text muted size={1} textOverflow=\"ellipsis\">\n {listFormat.format(roles)}\n </Text>\n </Stack>\n </Flex>\n </Root>\n )\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {Role, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {ProjectUser} from './ProjectUser'\n\nfunction getInviteUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}/members`\n}\n\ninterface Member {\n id: string\n roles: Role[]\n isRobot: boolean\n isCurrentUser: boolean\n createdAt: string\n}\n\ninterface Project {\n id: string\n members: Member[]\n}\n\nexport function ProjectUsers() {\n const [project, setProject] = useState<Project | undefined>()\n const [users, setUsers] = useState<User[] | undefined>()\n const [error, setError] = useState<Error | undefined>()\n\n const userStore = useUserStore()\n const versionedClient = useVersionedClient()\n\n const fetchData = useCallback(() => {\n const {projectId} = versionedClient.config()\n const subscription = versionedClient.observable\n .request<Project>({\n uri: `/projects/${projectId}`,\n tag: 'dashboard.project-users',\n })\n .pipe(\n switchMap((_project) =>\n from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(\n map((_users) => ({project: _project, users: _users})),\n ),\n ),\n )\n .subscribe({\n next: ({users: _users, project: _project}) => {\n setProject(_project)\n setUsers(\n (Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>\n sortUsersByRobotStatus(userA, userB, _project),\n ),\n )\n },\n error: (e: Error) => setError(e),\n })\n\n return () => subscription.unsubscribe()\n }, [userStore, versionedClient])\n\n useEffect(() => fetchData(), [fetchData])\n\n const handleRetryFetch = useCallback(() => fetchData(), [fetchData])\n\n const isLoading = !users || !project\n\n if (error) {\n return (\n <DashboardWidgetContainer header=\"Project users\">\n <Box padding={4}>\n <Text>\n Something went wrong while fetching data. You could{' '}\n <a onClick={handleRetryFetch} title=\"Retry users fetch\" style={{cursor: 'pointer'}}>\n retry\n </a>\n ..?\n </Text>\n </Box>\n </DashboardWidgetContainer>\n )\n }\n\n return (\n <DashboardWidgetContainer\n header=\"Project users\"\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage members\"\n as=\"a\"\n loading={isLoading}\n href={isLoading ? undefined : getInviteUrl(project.id)}\n />\n }\n >\n {isLoading && (\n <Box paddingY={5} paddingX={2}>\n <Stack space={4}>\n <Text align=\"center\" muted size={1}>\n <Spinner />\n </Text>\n <Text align=\"center\" size={1} muted>\n Loading items…\n </Text>\n </Stack>\n </Box>\n )}\n\n {!isLoading && (\n <Stack space={3} padding={3}>\n {users?.map((user) => {\n const membership = project.members.find((member) => member.id === user.id)\n return (\n <ProjectUser\n key={user.id}\n user={user}\n isRobot={membership?.isRobot ?? false}\n roles={membership?.roles.map((role) => role.title) || []}\n />\n )\n })}\n </Stack>\n )}\n </DashboardWidgetContainer>\n )\n}\n\nfunction sortUsersByRobotStatus(userA: User, userB: User, project: Project) {\n const {members} = project\n const membershipA = members.find((member) => member.id === userA?.id)\n const membershipB = members.find((member) => member.id === userB?.id)\n\n // On ties, sort by when the user was added\n if (membershipA?.isRobot === membershipB?.isRobot) {\n return (membershipA?.createdAt || '') > (membershipB?.createdAt || '') ? 1 : -1\n }\n\n // Robots go to the bottom\n return membershipA?.isRobot ? 1 : -1\n}\n","import {ProjectUsers} from './ProjectUsers'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectUsers,\n layout: config?.layout,\n }\n}\n","import React from 'react'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {PlayIcon} from '@sanity/icons'\nimport {styled} from 'styled-components'\n\nconst PlayIconBox = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ${({theme}) => theme.sanity.color.card.enabled.bg};\n opacity: 0.75;\n }\n`\n\nconst Root = styled(Flex)`\n &:hover {\n ${PlayIconBox} {\n &:before {\n opacity: 1;\n }\n }\n }\n`\n\nconst PosterCard = styled(Card)`\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n`\n\nconst Poster = styled.img`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n`\n\nexport interface TutorialProps {\n title: string\n posterURL?: string\n href: string\n showPlayIcon?: boolean\n presenterName?: string\n presenterSubtitle?: string\n}\n\nexport function Tutorial(props: TutorialProps) {\n const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props\n\n return (\n <Root flex={1}>\n <Card\n sizing=\"border\"\n flex={1}\n padding={2}\n radius={2}\n as=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{position: 'relative'}}\n >\n <Flex direction=\"column\" style={{height: '100%'}}>\n {posterURL && (\n <PosterCard marginBottom={1}>\n <Poster src={posterURL} />\n {showPlayIcon && (\n <PlayIconBox display=\"flex\">\n <Text align=\"center\">\n <PlayIcon />\n </Text>\n </PlayIconBox>\n )}\n </PosterCard>\n )}\n <Flex direction=\"column\" justify=\"space-between\" paddingY={2} flex={1}>\n <Heading as=\"h3\" size={1}>\n {title}\n </Heading>\n <Box marginTop={4}>\n <Stack space={2} flex={1}>\n <Text size={1}>{presenterName}</Text>\n <Text size={0} style={{opacity: 0.7}}>\n {presenterSubtitle}\n </Text>\n </Stack>\n </Box>\n </Flex>\n </Flex>\n </Card>\n </Root>\n )\n}\n","import {useMemo} from 'react'\nimport {useVersionedClient} from '../../versionedClient'\nimport imageUrlBuilder from '@sanity/image-url'\n\nconst tutorialsProjectConfig = {\n projectId: '3do82whm',\n dataset: 'next',\n}\n\nexport interface Guide {\n _type?: string\n slug?: {current: string}\n presenter?: {\n name?: string\n }\n}\n\nexport interface FeedItem {\n _id: string\n title?: string\n poster?: string\n category?: string\n guideOrTutorial?: Guide\n externalLink?: string\n presenter?: {\n name?: string\n }\n hasVideo?: boolean\n}\n\nexport function useDataAdapter() {\n const versionedClient = useVersionedClient()\n return useMemo(\n () => ({\n getFeed: (templateRepoId: string) => {\n const uri = templateRepoId\n ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n : '/addons/dashboard'\n return versionedClient.observable.request<{items: FeedItem[]}>({\n uri,\n tag: 'dashboard.sanity-tutorials',\n withCredentials: false,\n })\n },\n urlBuilder: imageUrlBuilder(tutorialsProjectConfig),\n }),\n [versionedClient],\n )\n}\n","import React, {useEffect, useState} from 'react'\nimport {Flex} from '@sanity/ui'\nimport {Tutorial} from './Tutorial'\nimport {FeedItem, Guide, useDataAdapter} from './dataAdapter'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nfunction createUrl(slug: {current: string}, type?: string) {\n if (type === 'tutorial') {\n return `https://www.sanity.io/docs/tutorials/${slug.current}`\n } else if (type === 'guide') {\n return `https://www.sanity.io/docs/guides/${slug.current}`\n }\n return false\n}\n\nexport interface SanityTutorialsProps {\n templateRepoId: string\n}\n\nexport function SanityTutorials(props: SanityTutorialsProps) {\n const {templateRepoId} = props\n const [feedItems, setFeedItems] = useState<FeedItem[]>([])\n\n const {getFeed, urlBuilder} = useDataAdapter()\n\n useEffect(() => {\n const subscription = getFeed(templateRepoId).subscribe((response) => {\n setFeedItems(response.items)\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [setFeedItems, getFeed, templateRepoId])\n\n const title = 'Learn about Sanity'\n\n return (\n <DashboardWidgetContainer header={title}>\n <Flex as=\"ul\" overflow=\"auto\" align=\"stretch\" paddingY={2}>\n {feedItems?.map((feedItem, index) => {\n if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {\n return null\n }\n const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}\n const subtitle = feedItem.category\n const {guideOrTutorial = {} as Guide} = feedItem\n const href =\n (guideOrTutorial.slug\n ? createUrl(guideOrTutorial.slug, guideOrTutorial._type)\n : feedItem.externalLink) || feedItem.externalLink\n\n return (\n <Flex\n as=\"li\"\n key={feedItem._id}\n paddingRight={index < feedItems?.length - 1 ? 1 : 3}\n paddingLeft={index === 0 ? 3 : 0}\n align=\"stretch\"\n style={{minWidth: 272, width: '30%'}}\n >\n <Tutorial\n title={feedItem.title}\n href={href ?? ''}\n presenterName={presenter.name}\n presenterSubtitle={subtitle}\n showPlayIcon={feedItem.hasVideo}\n posterURL={\n feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined\n }\n />\n </Flex>\n )\n })}\n </Flex>\n </DashboardWidgetContainer>\n )\n}\n","import {SanityTutorials} from './SanityTutorials'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'sanity-tutorials',\n component: SanityTutorials,\n layout: config?.layout ?? {width: 'full'},\n }\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Container} from '@sanity/ui'\n\nexport function DashboardLayout(props: PropsWithChildren<{}>) {\n return (\n <Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n {props.children}\n </Container>\n )\n}\n","import React from 'react'\nimport {styled, css} from 'styled-components'\nimport {Box, Card, Grid, Text} from '@sanity/ui'\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {DashboardConfig, LayoutConfig, DashboardWidget} from '../types'\n\nconst media = {\n small: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n ${css(...args)}\n }\n `,\n medium: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[2]}px) {\n ${css(...args)}\n }\n `,\n}\n\nconst Root = styled(Grid)`\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ${media.small`\n grid-column: span 2;\n `}\n }\n\n & > div[data-width='large'] {\n ${media.small`\n grid-column: span 2;\n `}\n\n ${media.medium`\n grid-column: span 3;\n `}\n }\n\n & > div[data-width='full'] {\n ${media.small`\n grid-column: 1 / -1;\n `}\n }\n\n & > div[data-height='medium'] {\n ${media.small`\n grid-row: span 2;\n `}\n }\n\n & > div[data-height='large'] {\n ${media.small`\n grid-row: span 2;\n `}\n\n ${media.medium`\n grid-row: span 3;\n `}\n }\n\n & > div[data-height='full'] {\n ${media.medium`\n grid-row: 1 / -1;\n `}\n }\n`\n\nexport interface WidgetGroupProps {\n config: Partial<DashboardConfig>\n}\n\nconst NO_WIDGETS: DashboardWidget[] = []\nconst NO_LAYOUT: LayoutConfig = {}\n\nexport function WidgetGroup(props: WidgetGroupProps) {\n const {\n config: {layout = NO_LAYOUT, widgets = NO_WIDGETS},\n } = props\n return (\n <Root\n autoFlow=\"row dense\"\n data-width={layout.width || 'auto'}\n data-height={layout.height || 'auto'}\n gap={4}\n >\n {widgets.length ? null : (\n <Card padding={4} shadow={1} tone=\"primary\">\n <Text align=\"center\">Add some widgets to populate this space.</Text>\n </Card>\n )}\n {widgets.map((widgetConfig, index) => {\n if (widgetConfig.type === '__experimental_group') {\n return <WidgetGroup key={index} config={widgetConfig} />\n }\n if (widgetConfig.component) {\n return <WidgetContainer key={index} {...widgetConfig} />\n }\n return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n })}\n </Root>\n )\n}\n","import React from 'react'\nimport {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {DashboardContext} from './DashboardContext'\nimport {DashboardConfig} from '../types'\n\nexport function Dashboard({config}: {config: DashboardConfig}) {\n if (!config) {\n return null\n }\n\n return (\n <DashboardContext.Provider value={config}>\n <DashboardLayout>\n <WidgetGroup config={config} />\n </DashboardLayout>\n </DashboardContext.Provider>\n )\n}\n","import React, {ComponentType, CSSProperties} from 'react'\nimport {Dashboard} from './containers/Dashboard'\nimport {definePlugin} from 'sanity'\nimport {DashboardConfig, DashboardWidget, LayoutConfig} from './types'\n\nconst strokeStyle: CSSProperties = {\n stroke: 'currentColor',\n strokeWidth: 1.2,\n}\n\nconst DashboardIcon = () => (\n <svg\n data-sanity-icon\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"xMidYMid\"\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M19.5 19.5H5.5V5.5H19.5V19.5Z\" style={strokeStyle} />\n <path d=\"M5.5 12.5H19.5\" style={strokeStyle} />\n <path d=\"M14.5 19.5V12.5M10.5 12.5V5.5\" style={strokeStyle} />\n </svg>\n)\n\nexport interface DashboardPluginConfig {\n /**\n * Dashboard tool title\n */\n title?: string\n /**\n * Dashboard tool name (used in url path)\n */\n name?: string\n /**\n * Dashboard tool icon\n */\n icon?: ComponentType\n widgets?: DashboardWidget[]\n\n /**\n * Will be used for widgets that do not define a layout directly.\n */\n defaultLayout?: LayoutConfig\n}\n\nexport const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {\n const pluginConfig: DashboardConfig = {\n layout: config.defaultLayout ?? {},\n widgets: config.widgets ?? [],\n }\n\n const title = config.title ?? 'Dashboard'\n const name = config.name ?? 'dashboard'\n const icon = config.icon ?? DashboardIcon\n\n return {\n name: 'dashboard',\n tools: (prev, context) => {\n return [\n ...prev,\n {\n title,\n name,\n icon,\n component: () => <Dashboard config={pluginConfig} />,\n },\n ]\n },\n }\n})\n"],"names":["Root"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/components/DashboardWidgetContainer.tsx","../src/versionedClient.ts","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/widgets/projectInfo/ProjectInfo.tsx","../src/widgets/projectInfo/index.ts","../src/widgets/projectUsers/ProjectUser.tsx","../src/widgets/projectUsers/ProjectUsers.tsx","../src/widgets/projectUsers/index.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../src/widgets/sanityTutorials/dataAdapter.ts","../src/widgets/sanityTutorials/SanityTutorials.tsx","../src/widgets/sanityTutorials/index.ts","../src/components/DashboardLayout.tsx","../src/components/WidgetGroup.tsx","../src/containers/Dashboard.tsx","../src/plugin.tsx"],"sourcesContent":["import React, {forwardRef} from 'react'\nimport {Card, Box, Heading} from '@sanity/ui'\nimport {styled} from 'styled-components'\n\nconst Root = styled(Card)`\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n`\n\nconst Header = styled(Card)`\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n`\n\nconst Footer = styled(Card)`\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n`\n\nconst Content = styled(Box)`\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n overflow-y: auto;\n outline: none;\n }\n`\n\ninterface DashboardWidgetProps {\n header?: string\n children: React.ReactNode\n footer?: React.ReactNode\n}\n\nexport const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer(\n props: DashboardWidgetProps,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {header, children, footer} = props\n\n return (\n <Root radius={3} display=\"flex\" ref={ref}>\n {header && (\n <Header borderBottom paddingX={3} paddingY={4}>\n <Heading size={1} textOverflow=\"ellipsis\">\n {header}\n </Heading>\n </Header>\n )}\n {children && <Content>{children}</Content>}\n {footer && <Footer borderTop>{footer}</Footer>}\n </Root>\n )\n})\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n return useClient({apiVersion: '2024-08-01'})\n}\n","import {createContext, useContext} from 'react'\nimport {DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n return useContext(DashboardContext)\n}\n","import React, {createElement, useMemo} from 'react'\nimport {useDashboardConfig} from './DashboardContext'\nimport {Card} from '@sanity/ui'\nimport {DashboardWidget} from '../types'\n\nexport function WidgetContainer(props: DashboardWidget) {\n const config = useDashboardConfig()\n const layout = useMemo(\n () => ({\n ...(props.layout || {}),\n ...(config.layout || {}),\n }),\n [props.layout, config.layout],\n )\n\n return (\n <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n {createElement(props.component, {})}\n </Card>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Card, Stack, Heading, Grid, Label, Text, Code, Button} from '@sanity/ui'\nimport {useVersionedClient} from '../../versionedClient'\nimport {Subscription} from 'rxjs'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {type DashboardWidget} from '../../types'\nimport {type App, type ProjectInfoProps, type ProjectData, UserApplication} from './types'\n\nfunction isUrl(url?: string) {\n return url && /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction getGraphQLUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`\n}\n\nfunction getGroqUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`\n}\n\nfunction getManageUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}`\n}\n\nconst NO_EXPERIMENTAL: DashboardWidget[] = []\nconst NO_DATA: ProjectData[] = []\n\nexport function ProjectInfo(props: ProjectInfoProps) {\n const {__experimental_before = NO_EXPERIMENTAL, data = NO_DATA} = props\n const [studioApps, setStudioApps] = useState<UserApplication[] | {error: string} | undefined>()\n const [graphQLApi, setGraphQLApi] = useState<string | {error: string} | undefined>()\n const versionedClient = useVersionedClient()\n const {projectId = 'unknown', dataset = 'unknown'} = versionedClient.config()\n\n useEffect(() => {\n const subscriptions: Subscription[] = []\n\n subscriptions.push(\n versionedClient.observable\n .request<UserApplication[]>({uri: '/user-applications', tag: 'dashboard.project-info'})\n .subscribe({\n next: (result) => setStudioApps(result.filter((app) => app.type === 'studio')),\n error: (error) => {\n console.error('Error while resolving user applications', error)\n setStudioApps({\n error: 'Something went wrong while resolving user applications. See console.',\n })\n },\n }),\n )\n\n // ping assumed graphql endpoint\n subscriptions.push(\n versionedClient.observable\n .request({\n method: 'HEAD',\n uri: `/graphql/${dataset}/default`,\n tag: 'dashboard.project-info.graphql-api',\n })\n .subscribe({\n next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),\n error: (error) => {\n if (error.statusCode === 404) {\n setGraphQLApi(undefined)\n } else {\n console.error('Error while looking for graphQLApi', error)\n setGraphQLApi({\n error: 'Something went wrong while looking up graphQLApi. See console.',\n })\n }\n },\n }),\n )\n\n return () => {\n subscriptions.forEach((s) => s.unsubscribe())\n }\n }, [dataset, projectId, versionedClient, setGraphQLApi])\n\n const assembleTableRows = useMemo(() => {\n let result: App[] = [\n {\n title: 'Sanity project',\n rows: [\n {title: 'Project ID', value: projectId},\n {title: 'Dataset', value: dataset},\n ],\n },\n ]\n\n const apps: App[] = data.filter((item) => item.category === 'apps')\n\n // Handle studios\n ;(Array.isArray(studioApps) ? studioApps : []).forEach((app) => {\n apps.push({\n title: app.title || 'Studio',\n value: app.urlType === 'internal' ? `https://${app.appHost}.sanity.studio` : app.appHost,\n })\n })\n\n if (apps.length > 0) {\n result = result.concat([{title: 'Apps', rows: apps}])\n }\n\n // Handle APIs\n result = result.concat(\n [\n {\n title: 'APIs',\n rows: [\n {title: 'GROQ', value: getGroqUrl(projectId, dataset)},\n {\n title: 'GraphQL',\n value: (typeof graphQLApi === 'object' ? 'Error' : graphQLApi) ?? 'Not deployed',\n },\n ],\n },\n ],\n data.filter((item) => item.category === 'apis'),\n )\n\n // Handle whatever else there might be\n const otherStuff: Record<string, ProjectData[]> = {}\n data.forEach((item) => {\n if (item.category && item.category !== 'apps' && item.category !== 'apis') {\n if (!otherStuff[item.category]) {\n otherStuff[item.category] = []\n }\n otherStuff[item.category].push(item)\n }\n })\n Object.keys(otherStuff).forEach((category) => {\n result.push({title: category, rows: otherStuff[category]})\n })\n\n return result\n }, [graphQLApi, studioApps, projectId, dataset, data])\n\n return (\n <>\n {__experimental_before.map((widgetConfig, idx) => (\n <WidgetContainer key={idx} {...widgetConfig} />\n ))}\n <Box height=\"fill\" marginTop={__experimental_before?.length > 0 ? 4 : 0}>\n <DashboardWidgetContainer\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage project\"\n as=\"a\"\n href={getManageUrl(projectId)}\n />\n }\n >\n <Card\n paddingY={4}\n radius={2}\n role=\"table\"\n aria-label=\"Project info\"\n aria-describedby=\"project_info_table\"\n >\n <Stack space={4}>\n <Box paddingX={3} as=\"header\">\n <Heading size={1} as=\"h2\" id=\"project_info_table\">\n Project info\n </Heading>\n </Box>\n {assembleTableRows.map((item) => {\n if (!item || !item.rows) {\n return null\n }\n\n return (\n <Stack key={item.title} space={3}>\n <Card borderBottom padding={3}>\n <Label size={0} muted role=\"columnheader\">\n {item.title}\n </Label>\n </Card>\n <Stack space={4} paddingX={3} role=\"rowgroup\">\n {item.rows.map((row) => {\n return (\n <Grid key={`${row.value}-${row.title}`} columns={2} role=\"row\">\n <Text weight=\"medium\" role=\"rowheader\">\n {row.title}\n </Text>\n {typeof row.value === 'object' && (\n <Text size={1}>{row.value?.error}</Text>\n )}\n {typeof row.value === 'string' && (\n <>\n {isUrl(row.value) ? (\n <Text size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n <a href={row.value}>{row.value}</a>\n </Text>\n ) : (\n <Code size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n {row.value}\n </Code>\n )}\n </>\n )}\n </Grid>\n )\n })}\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n </Card>\n </DashboardWidgetContainer>\n </Box>\n </>\n )\n}\n","import {ProjectInfo} from './ProjectInfo'\nimport {type LayoutConfig, type DashboardWidget} from '../../types'\n\nexport function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectInfo,\n layout: config?.layout ?? {width: 'medium'},\n }\n}\n","import React from 'react'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {styled} from 'styled-components'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {RobotIcon} from '@sanity/icons'\n\nconst Root = styled(Flex)`\n height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height\n box-sizing: content-box;\n`\n\nexport interface ProjectUserProps {\n user: User\n isRobot: boolean\n roles: string[]\n}\n\nexport function ProjectUser({user, isRobot, roles}: ProjectUserProps) {\n const listFormat = useListFormat({style: 'narrow'})\n return (\n <Root align=\"center\">\n <Flex align=\"center\" flex={1} gap={2}>\n <Box flex=\"none\">\n {isRobot ? (\n <Text size={2}>\n <RobotIcon />\n </Text>\n ) : (\n <UserAvatar user={user} />\n )}\n </Box>\n\n <Stack flex={1} space={2}>\n <Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n {user.displayName}\n </Text>\n\n <Text muted size={1} textOverflow=\"ellipsis\">\n {listFormat.format(roles)}\n </Text>\n </Stack>\n </Flex>\n </Root>\n )\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {Role, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {ProjectUser} from './ProjectUser'\n\nfunction getInviteUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}/members`\n}\n\ninterface Member {\n id: string\n roles: Role[]\n isRobot: boolean\n isCurrentUser: boolean\n createdAt: string\n}\n\ninterface Project {\n id: string\n members: Member[]\n}\n\nexport function ProjectUsers() {\n const [project, setProject] = useState<Project | undefined>()\n const [users, setUsers] = useState<User[] | undefined>()\n const [error, setError] = useState<Error | undefined>()\n\n const userStore = useUserStore()\n const versionedClient = useVersionedClient()\n\n const fetchData = useCallback(() => {\n const {projectId} = versionedClient.config()\n const subscription = versionedClient.observable\n .request<Project>({\n uri: `/projects/${projectId}`,\n tag: 'dashboard.project-users',\n })\n .pipe(\n switchMap((_project) =>\n from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(\n map((_users) => ({project: _project, users: _users})),\n ),\n ),\n )\n .subscribe({\n next: ({users: _users, project: _project}) => {\n setProject(_project)\n setUsers(\n (Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>\n sortUsersByRobotStatus(userA, userB, _project),\n ),\n )\n },\n error: (e: Error) => setError(e),\n })\n\n return () => subscription.unsubscribe()\n }, [userStore, versionedClient])\n\n useEffect(() => fetchData(), [fetchData])\n\n const handleRetryFetch = useCallback(() => fetchData(), [fetchData])\n\n const isLoading = !users || !project\n\n if (error) {\n return (\n <DashboardWidgetContainer header=\"Project users\">\n <Box padding={4}>\n <Text>\n Something went wrong while fetching data. You could{' '}\n <a onClick={handleRetryFetch} title=\"Retry users fetch\" style={{cursor: 'pointer'}}>\n retry\n </a>\n ..?\n </Text>\n </Box>\n </DashboardWidgetContainer>\n )\n }\n\n return (\n <DashboardWidgetContainer\n header=\"Project users\"\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage members\"\n as=\"a\"\n loading={isLoading}\n href={isLoading ? undefined : getInviteUrl(project.id)}\n />\n }\n >\n {isLoading && (\n <Box paddingY={5} paddingX={2}>\n <Stack space={4}>\n <Text align=\"center\" muted size={1}>\n <Spinner />\n </Text>\n <Text align=\"center\" size={1} muted>\n Loading items…\n </Text>\n </Stack>\n </Box>\n )}\n\n {!isLoading && (\n <Stack space={3} padding={3}>\n {users?.map((user) => {\n const membership = project.members.find((member) => member.id === user.id)\n return (\n <ProjectUser\n key={user.id}\n user={user}\n isRobot={membership?.isRobot ?? false}\n roles={membership?.roles.map((role) => role.title) || []}\n />\n )\n })}\n </Stack>\n )}\n </DashboardWidgetContainer>\n )\n}\n\nfunction sortUsersByRobotStatus(userA: User, userB: User, project: Project) {\n const {members} = project\n const membershipA = members.find((member) => member.id === userA?.id)\n const membershipB = members.find((member) => member.id === userB?.id)\n\n // On ties, sort by when the user was added\n if (membershipA?.isRobot === membershipB?.isRobot) {\n return (membershipA?.createdAt || '') > (membershipB?.createdAt || '') ? 1 : -1\n }\n\n // Robots go to the bottom\n return membershipA?.isRobot ? 1 : -1\n}\n","import {ProjectUsers} from './ProjectUsers'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectUsers,\n layout: config?.layout,\n }\n}\n","import React from 'react'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {PlayIcon} from '@sanity/icons'\nimport {styled} from 'styled-components'\n\nconst PlayIconBox = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ${({theme}) => theme.sanity.color.card.enabled.bg};\n opacity: 0.75;\n }\n`\n\nconst Root = styled(Flex)`\n &:hover {\n ${PlayIconBox} {\n &:before {\n opacity: 1;\n }\n }\n }\n`\n\nconst PosterCard = styled(Card)`\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n`\n\nconst Poster = styled.img`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n`\n\nexport interface TutorialProps {\n title: string\n posterURL?: string\n href: string\n showPlayIcon?: boolean\n presenterName?: string\n presenterSubtitle?: string\n}\n\nexport function Tutorial(props: TutorialProps) {\n const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props\n\n return (\n <Root flex={1}>\n <Card\n sizing=\"border\"\n flex={1}\n padding={2}\n radius={2}\n as=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{position: 'relative'}}\n >\n <Flex direction=\"column\" style={{height: '100%'}}>\n {posterURL && (\n <PosterCard marginBottom={1}>\n <Poster src={posterURL} />\n {showPlayIcon && (\n <PlayIconBox display=\"flex\">\n <Text align=\"center\">\n <PlayIcon />\n </Text>\n </PlayIconBox>\n )}\n </PosterCard>\n )}\n <Flex direction=\"column\" justify=\"space-between\" paddingY={2} flex={1}>\n <Heading as=\"h3\" size={1}>\n {title}\n </Heading>\n <Box marginTop={4}>\n <Stack space={2} flex={1}>\n <Text size={1}>{presenterName}</Text>\n <Text size={0} style={{opacity: 0.7}}>\n {presenterSubtitle}\n </Text>\n </Stack>\n </Box>\n </Flex>\n </Flex>\n </Card>\n </Root>\n )\n}\n","import {useMemo} from 'react'\nimport {useVersionedClient} from '../../versionedClient'\nimport imageUrlBuilder from '@sanity/image-url'\n\nconst tutorialsProjectConfig = {\n projectId: '3do82whm',\n dataset: 'next',\n}\n\nexport interface Guide {\n _type?: string\n slug?: {current: string}\n presenter?: {\n name?: string\n }\n}\n\nexport interface FeedItem {\n _id: string\n title?: string\n poster?: string\n category?: string\n guideOrTutorial?: Guide\n externalLink?: string\n presenter?: {\n name?: string\n }\n hasVideo?: boolean\n}\n\nexport function useDataAdapter() {\n const versionedClient = useVersionedClient()\n return useMemo(\n () => ({\n getFeed: (templateRepoId: string) => {\n const uri = templateRepoId\n ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n : '/addons/dashboard'\n return versionedClient.observable.request<{items: FeedItem[]}>({\n uri,\n tag: 'dashboard.sanity-tutorials',\n withCredentials: false,\n })\n },\n urlBuilder: imageUrlBuilder(tutorialsProjectConfig),\n }),\n [versionedClient],\n )\n}\n","import React, {useEffect, useState} from 'react'\nimport {Flex} from '@sanity/ui'\nimport {Tutorial} from './Tutorial'\nimport {FeedItem, Guide, useDataAdapter} from './dataAdapter'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nfunction createUrl(slug: {current: string}, type?: string) {\n if (type === 'tutorial') {\n return `https://www.sanity.io/docs/tutorials/${slug.current}`\n } else if (type === 'guide') {\n return `https://www.sanity.io/docs/guides/${slug.current}`\n }\n return false\n}\n\nexport interface SanityTutorialsProps {\n templateRepoId: string\n}\n\nexport function SanityTutorials(props: SanityTutorialsProps) {\n const {templateRepoId} = props\n const [feedItems, setFeedItems] = useState<FeedItem[]>([])\n\n const {getFeed, urlBuilder} = useDataAdapter()\n\n useEffect(() => {\n const subscription = getFeed(templateRepoId).subscribe((response) => {\n setFeedItems(response.items)\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [setFeedItems, getFeed, templateRepoId])\n\n const title = 'Learn about Sanity'\n\n return (\n <DashboardWidgetContainer header={title}>\n <Flex as=\"ul\" overflow=\"auto\" align=\"stretch\" paddingY={2}>\n {feedItems?.map((feedItem, index) => {\n if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {\n return null\n }\n const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}\n const subtitle = feedItem.category\n const {guideOrTutorial = {} as Guide} = feedItem\n const href =\n (guideOrTutorial.slug\n ? createUrl(guideOrTutorial.slug, guideOrTutorial._type)\n : feedItem.externalLink) || feedItem.externalLink\n\n return (\n <Flex\n as=\"li\"\n key={feedItem._id}\n paddingRight={index < feedItems?.length - 1 ? 1 : 3}\n paddingLeft={index === 0 ? 3 : 0}\n align=\"stretch\"\n style={{minWidth: 272, width: '30%'}}\n >\n <Tutorial\n title={feedItem.title}\n href={href ?? ''}\n presenterName={presenter.name}\n presenterSubtitle={subtitle}\n showPlayIcon={feedItem.hasVideo}\n posterURL={\n feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined\n }\n />\n </Flex>\n )\n })}\n </Flex>\n </DashboardWidgetContainer>\n )\n}\n","import {SanityTutorials} from './SanityTutorials'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'sanity-tutorials',\n component: SanityTutorials,\n layout: config?.layout ?? {width: 'full'},\n }\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Container} from '@sanity/ui'\n\nexport function DashboardLayout(props: PropsWithChildren<{}>) {\n return (\n <Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n {props.children}\n </Container>\n )\n}\n","import React from 'react'\nimport {styled, css} from 'styled-components'\nimport {Box, Card, Grid, Text} from '@sanity/ui'\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {DashboardConfig, LayoutConfig, DashboardWidget} from '../types'\n\nconst media = {\n small: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n ${css(...args)}\n }\n `,\n medium: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[2]}px) {\n ${css(...args)}\n }\n `,\n}\n\nconst Root = styled(Grid)`\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ${media.small`\n grid-column: span 2;\n `}\n }\n\n & > div[data-width='large'] {\n ${media.small`\n grid-column: span 2;\n `}\n\n ${media.medium`\n grid-column: span 3;\n `}\n }\n\n & > div[data-width='full'] {\n ${media.small`\n grid-column: 1 / -1;\n `}\n }\n\n & > div[data-height='medium'] {\n ${media.small`\n grid-row: span 2;\n `}\n }\n\n & > div[data-height='large'] {\n ${media.small`\n grid-row: span 2;\n `}\n\n ${media.medium`\n grid-row: span 3;\n `}\n }\n\n & > div[data-height='full'] {\n ${media.medium`\n grid-row: 1 / -1;\n `}\n }\n`\n\nexport interface WidgetGroupProps {\n config: Partial<DashboardConfig>\n}\n\nconst NO_WIDGETS: DashboardWidget[] = []\nconst NO_LAYOUT: LayoutConfig = {}\n\nexport function WidgetGroup(props: WidgetGroupProps) {\n const {\n config: {layout = NO_LAYOUT, widgets = NO_WIDGETS},\n } = props\n return (\n <Root\n autoFlow=\"row dense\"\n data-width={layout.width || 'auto'}\n data-height={layout.height || 'auto'}\n gap={4}\n >\n {widgets.length ? null : (\n <Card padding={4} shadow={1} tone=\"primary\">\n <Text align=\"center\">Add some widgets to populate this space.</Text>\n </Card>\n )}\n {widgets.map((widgetConfig, index) => {\n if (widgetConfig.type === '__experimental_group') {\n return <WidgetGroup key={index} config={widgetConfig} />\n }\n if (widgetConfig.component) {\n return <WidgetContainer key={index} {...widgetConfig} />\n }\n return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n })}\n </Root>\n )\n}\n","import React from 'react'\nimport {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {DashboardContext} from './DashboardContext'\nimport {DashboardConfig} from '../types'\n\nexport function Dashboard({config}: {config: DashboardConfig}) {\n if (!config) {\n return null\n }\n\n return (\n <DashboardContext.Provider value={config}>\n <DashboardLayout>\n <WidgetGroup config={config} />\n </DashboardLayout>\n </DashboardContext.Provider>\n )\n}\n","import React, {ComponentType, CSSProperties} from 'react'\nimport {Dashboard} from './containers/Dashboard'\nimport {definePlugin} from 'sanity'\nimport {DashboardConfig, DashboardWidget, LayoutConfig} from './types'\n\nconst strokeStyle: CSSProperties = {\n stroke: 'currentColor',\n strokeWidth: 1.2,\n}\n\nconst DashboardIcon = () => (\n <svg\n data-sanity-icon\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"xMidYMid\"\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M19.5 19.5H5.5V5.5H19.5V19.5Z\" style={strokeStyle} />\n <path d=\"M5.5 12.5H19.5\" style={strokeStyle} />\n <path d=\"M14.5 19.5V12.5M10.5 12.5V5.5\" style={strokeStyle} />\n </svg>\n)\n\nexport interface DashboardPluginConfig {\n /**\n * Dashboard tool title\n */\n title?: string\n /**\n * Dashboard tool name (used in url path)\n */\n name?: string\n /**\n * Dashboard tool icon\n */\n icon?: ComponentType\n widgets?: DashboardWidget[]\n\n /**\n * Will be used for widgets that do not define a layout directly.\n */\n defaultLayout?: LayoutConfig\n}\n\nexport const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {\n const pluginConfig: DashboardConfig = {\n layout: config.defaultLayout ?? {},\n widgets: config.widgets ?? [],\n }\n\n const title = config.title ?? 'Dashboard'\n const name = config.name ?? 'dashboard'\n const icon = config.icon ?? DashboardIcon\n\n return {\n name: 'dashboard',\n tools: (prev, context) => {\n return [\n ...prev,\n {\n title,\n name,\n icon,\n component: () => <Dashboard config={pluginConfig} />,\n },\n ]\n },\n }\n})\n"],"names":["Root","__spreadValues"],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -45,26 +45,39 @@ const Root$3 = styledComponents.styled(ui.Card)`
|
|
|
45
45
|
] });
|
|
46
46
|
});
|
|
47
47
|
function useVersionedClient() {
|
|
48
|
-
return sanity.useClient({ apiVersion: "2024-
|
|
48
|
+
return sanity.useClient({ apiVersion: "2024-08-01" });
|
|
49
49
|
}
|
|
50
50
|
const DashboardContext = react.createContext({ widgets: [] });
|
|
51
51
|
function useDashboardConfig() {
|
|
52
52
|
return react.useContext(DashboardContext);
|
|
53
53
|
}
|
|
54
|
+
var __defProp$2 = Object.defineProperty, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$2 = (a, b) => {
|
|
55
|
+
for (var prop in b || (b = {}))
|
|
56
|
+
__hasOwnProp$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
|
|
57
|
+
if (__getOwnPropSymbols$2)
|
|
58
|
+
for (var prop of __getOwnPropSymbols$2(b))
|
|
59
|
+
__propIsEnum$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
|
|
60
|
+
return a;
|
|
61
|
+
};
|
|
54
62
|
function WidgetContainer(props) {
|
|
55
63
|
const config = useDashboardConfig(), layout = react.useMemo(
|
|
56
|
-
() => ({
|
|
57
|
-
...props.layout || {},
|
|
58
|
-
...config.layout || {}
|
|
59
|
-
}),
|
|
64
|
+
() => __spreadValues$2(__spreadValues$2({}, props.layout || {}), config.layout || {}),
|
|
60
65
|
[props.layout, config.layout]
|
|
61
66
|
);
|
|
62
67
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { shadow: 1, "data-width": layout.width, "data-height": layout.height, children: react.createElement(props.component, {}) });
|
|
63
68
|
}
|
|
69
|
+
var __defProp$1 = Object.defineProperty, __getOwnPropSymbols$1 = Object.getOwnPropertySymbols, __hasOwnProp$1 = Object.prototype.hasOwnProperty, __propIsEnum$1 = Object.prototype.propertyIsEnumerable, __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$1 = (a, b) => {
|
|
70
|
+
for (var prop in b || (b = {}))
|
|
71
|
+
__hasOwnProp$1.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
|
|
72
|
+
if (__getOwnPropSymbols$1)
|
|
73
|
+
for (var prop of __getOwnPropSymbols$1(b))
|
|
74
|
+
__propIsEnum$1.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
|
|
75
|
+
return a;
|
|
76
|
+
};
|
|
64
77
|
function isUrl(url) {
|
|
65
78
|
return url && /^https?:\/\//.test(`${url}`);
|
|
66
79
|
}
|
|
67
|
-
function
|
|
80
|
+
function getGraphQLUrl(projectId, dataset) {
|
|
68
81
|
return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`;
|
|
69
82
|
}
|
|
70
83
|
function getGroqUrl(projectId, dataset) {
|
|
@@ -75,24 +88,15 @@ function getManageUrl(projectId) {
|
|
|
75
88
|
}
|
|
76
89
|
const NO_EXPERIMENTAL = [], NO_DATA = [];
|
|
77
90
|
function ProjectInfo(props) {
|
|
78
|
-
const { __experimental_before = NO_EXPERIMENTAL, data = NO_DATA } = props, [
|
|
91
|
+
const { __experimental_before = NO_EXPERIMENTAL, data = NO_DATA } = props, [studioApps, setStudioApps] = react.useState(), [graphQLApi, setGraphQLApi] = react.useState(), versionedClient = useVersionedClient(), { projectId = "unknown", dataset = "unknown" } = versionedClient.config();
|
|
79
92
|
react.useEffect(() => {
|
|
80
93
|
const subscriptions = [];
|
|
81
94
|
return subscriptions.push(
|
|
82
|
-
versionedClient.observable.request({ uri:
|
|
83
|
-
next: (result) =>
|
|
84
|
-
var _a;
|
|
85
|
-
if ((_a = result.metadata) != null && _a.externalStudioHost) {
|
|
86
|
-
setStudioHost(result.metadata.externalStudioHost);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
setStudioHost(
|
|
90
|
-
result.studioHost ? `https://${result.studioHost}.sanity.studio` : void 0
|
|
91
|
-
);
|
|
92
|
-
},
|
|
95
|
+
versionedClient.observable.request({ uri: "/user-applications", tag: "dashboard.project-info" }).subscribe({
|
|
96
|
+
next: (result) => setStudioApps(result.filter((app) => app.type === "studio")),
|
|
93
97
|
error: (error) => {
|
|
94
|
-
console.error("Error while
|
|
95
|
-
error: "Something went wrong while
|
|
98
|
+
console.error("Error while resolving user applications", error), setStudioApps({
|
|
99
|
+
error: "Something went wrong while resolving user applications. See console."
|
|
96
100
|
});
|
|
97
101
|
}
|
|
98
102
|
})
|
|
@@ -102,17 +106,17 @@ function ProjectInfo(props) {
|
|
|
102
106
|
uri: `/graphql/${dataset}/default`,
|
|
103
107
|
tag: "dashboard.project-info.graphql-api"
|
|
104
108
|
}).subscribe({
|
|
105
|
-
next: () =>
|
|
109
|
+
next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),
|
|
106
110
|
error: (error) => {
|
|
107
|
-
error.statusCode === 404 ?
|
|
108
|
-
error: "Something went wrong while looking up
|
|
111
|
+
error.statusCode === 404 ? setGraphQLApi(void 0) : (console.error("Error while looking for graphQLApi", error), setGraphQLApi({
|
|
112
|
+
error: "Something went wrong while looking up graphQLApi. See console."
|
|
109
113
|
}));
|
|
110
114
|
}
|
|
111
115
|
})
|
|
112
116
|
), () => {
|
|
113
117
|
subscriptions.forEach((s) => s.unsubscribe());
|
|
114
118
|
};
|
|
115
|
-
}, [dataset, projectId, versionedClient,
|
|
119
|
+
}, [dataset, projectId, versionedClient, setGraphQLApi]);
|
|
116
120
|
const assembleTableRows = react.useMemo(() => {
|
|
117
121
|
var _a;
|
|
118
122
|
let result = [
|
|
@@ -124,11 +128,13 @@ function ProjectInfo(props) {
|
|
|
124
128
|
]
|
|
125
129
|
}
|
|
126
130
|
];
|
|
127
|
-
const apps =
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
const apps = data.filter((item) => item.category === "apps");
|
|
132
|
+
(Array.isArray(studioApps) ? studioApps : []).forEach((app) => {
|
|
133
|
+
apps.push({
|
|
134
|
+
title: app.title || "Studio",
|
|
135
|
+
value: app.urlType === "internal" ? `https://${app.appHost}.sanity.studio` : app.appHost
|
|
136
|
+
});
|
|
137
|
+
}), apps.length > 0 && (result = result.concat([{ title: "Apps", rows: apps }])), result = result.concat(
|
|
132
138
|
[
|
|
133
139
|
{
|
|
134
140
|
title: "APIs",
|
|
@@ -136,7 +142,7 @@ function ProjectInfo(props) {
|
|
|
136
142
|
{ title: "GROQ", value: getGroqUrl(projectId, dataset) },
|
|
137
143
|
{
|
|
138
144
|
title: "GraphQL",
|
|
139
|
-
value: (_a = typeof
|
|
145
|
+
value: (_a = typeof graphQLApi == "object" ? "Error" : graphQLApi) != null ? _a : "Not deployed"
|
|
140
146
|
}
|
|
141
147
|
]
|
|
142
148
|
}
|
|
@@ -149,9 +155,9 @@ function ProjectInfo(props) {
|
|
|
149
155
|
}), Object.keys(otherStuff).forEach((category) => {
|
|
150
156
|
result.push({ title: category, rows: otherStuff[category] });
|
|
151
157
|
}), result;
|
|
152
|
-
}, [
|
|
158
|
+
}, [graphQLApi, studioApps, projectId, dataset, data]);
|
|
153
159
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
154
|
-
__experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, {
|
|
160
|
+
__experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, __spreadValues$1({}, widgetConfig), idx)),
|
|
155
161
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { height: "fill", marginTop: (__experimental_before == null ? void 0 : __experimental_before.length) > 0 ? 4 : 0, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
156
162
|
DashboardWidgetContainer,
|
|
157
163
|
{
|
|
@@ -186,7 +192,7 @@ function ProjectInfo(props) {
|
|
|
186
192
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "medium", role: "rowheader", children: row.title }),
|
|
187
193
|
typeof row.value == "object" && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: (_a = row.value) == null ? void 0 : _a.error }),
|
|
188
194
|
typeof row.value == "string" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isUrl(row.value) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: row.value, children: row.value }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Code, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: row.value }) })
|
|
189
|
-
] }, row.title);
|
|
195
|
+
] }, `${row.value}-${row.title}`);
|
|
190
196
|
}) })
|
|
191
197
|
] }, item.title))
|
|
192
198
|
] })
|
|
@@ -448,6 +454,14 @@ function sanityTutorialsWidget(config) {
|
|
|
448
454
|
function DashboardLayout(props) {
|
|
449
455
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { width: 4, padding: 4, sizing: "border", style: { height: "100%", overflowY: "auto" }, children: props.children });
|
|
450
456
|
}
|
|
457
|
+
var __defProp = Object.defineProperty, __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => {
|
|
458
|
+
for (var prop in b || (b = {}))
|
|
459
|
+
__hasOwnProp.call(b, prop) && __defNormalProp(a, prop, b[prop]);
|
|
460
|
+
if (__getOwnPropSymbols)
|
|
461
|
+
for (var prop of __getOwnPropSymbols(b))
|
|
462
|
+
__propIsEnum.call(b, prop) && __defNormalProp(a, prop, b[prop]);
|
|
463
|
+
return a;
|
|
464
|
+
};
|
|
451
465
|
const media = {
|
|
452
466
|
small: (...args) => styledComponents.css`
|
|
453
467
|
@media (min-width: ${({ theme }) => theme.sanity.media[0]}px) {
|
|
@@ -523,7 +537,7 @@ function WidgetGroup(props) {
|
|
|
523
537
|
gap: 4,
|
|
524
538
|
children: [
|
|
525
539
|
widgets.length ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 4, shadow: 1, tone: "primary", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { align: "center", children: "Add some widgets to populate this space." }) }),
|
|
526
|
-
widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsxRuntime.jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, {
|
|
540
|
+
widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsxRuntime.jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, __spreadValues({}, widgetConfig), index) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { children: [
|
|
527
541
|
widgetConfig.name,
|
|
528
542
|
" is missing widget component"
|
|
529
543
|
] }, index))
|