sanity-plugin-wistia-input
Version:
Wistia input for Sanity v3
316 lines (315 loc) • 12.6 kB
JavaScript
import { setIfMissing, set, definePlugin } from "sanity";
import { jsx, jsxs } from "react/jsx-runtime";
import { useState, useEffect, useCallback } from "react";
import { Box, Card, Text, Menu, Flex, Spinner, MenuItem, Tooltip, Heading, MenuButton, MenuDivider, Button, useToast, Dialog } from "@sanity/ui";
import { LockIcon, SearchIcon, ClipboardIcon, ResetIcon, EllipsisVerticalIcon, PlayIcon, DocumentVideoIcon, ChevronLeftIcon } from "@sanity/icons";
const wistiaMedia = {
name: "wistiaMedia",
type: "object",
title: "Wistia media",
fields: [
{
type: "number",
name: "id"
},
{
type: "string",
name: "hashed_id"
}
],
preview: {
select: {
title: "id"
},
prepare({ title }) {
return {
title: `Wistia video ID: ${title}`
};
}
}
}, WistiaProjectsComponent = ({
onProjectClick,
config
}) => {
const [wistiaProjects, setWistiaProjects] = useState([]), [loading, setLoading] = useState(!1), [error, setError] = useState(""), handleProjectClick = (projectId) => {
onProjectClick(projectId);
};
return useEffect(() => {
setLoading(!0);
const apiUrl = "https://api.wistia.com/v1/projects.json?sort_by=updated&sort_direction=0", headers = new Headers({
Authorization: `Bearer ${config.token}`
});
fetch(apiUrl, {
method: "GET",
headers
}).then((response) => (response.ok || (response?.status === 401 ? setError("401 Not authorised - check your API key permissions.") : setError(`${response?.status} error`)), setLoading(!1), response.json())).then((data) => setWistiaProjects(data)).catch((error2) => console.error(error2));
}, []), error ? /* @__PURE__ */ jsx(Box, { padding: 3, children: /* @__PURE__ */ jsx(Card, { padding: [3, 3, 4], radius: 2, shadow: 1, tone: "critical", children: /* @__PURE__ */ jsx(Text, { align: "center", children: error }) }) }) : /* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsxs(Menu, { children: [
loading && /* @__PURE__ */ jsx(Card, { padding: 4, children: /* @__PURE__ */ jsxs(Flex, { align: "center", direction: "column", gap: 3, height: "fill", justify: "center", children: [
/* @__PURE__ */ jsx(Spinner, { muted: !0 }),
/* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: "Loading projects from Wistia\u2026" })
] }) }),
wistiaProjects?.length ? wistiaProjects?.map((project) => /* @__PURE__ */ jsx(
MenuItem,
{
style: { cursor: "pointer" },
onClick: () => handleProjectClick(project.id),
children: /* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsxs(Flex, { justify: "space-between", gap: 2, children: [
/* @__PURE__ */ jsxs(Text, { weight: "semibold", children: [
project.name,
!project.public && /* @__PURE__ */ jsx(
Tooltip,
{
content: /* @__PURE__ */ jsx(Box, { padding: 2, children: /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: "This project is private" }) }),
fallbackPlacements: ["right", "left"],
placement: "top",
portal: !0,
children: /* @__PURE__ */ jsx(LockIcon, { style: { marginLeft: 5 } })
}
)
] }),
/* @__PURE__ */ jsx(Text, { muted: !0, children: project.mediaCount })
] }) })
},
project.id
)) : !loading && /* @__PURE__ */ jsx(Card, { padding: 4, children: /* @__PURE__ */ jsx(Text, { align: "center", muted: !0, size: 1, children: "No projects found." }) })
] }) });
}, groupBy = (array, key) => array.reduce((rv, x) => ((rv[x[key]] = rv[x[key]] || []).push(x), rv), {}), wistiaMediasComponent = ({
onVideoClick,
projectId,
config
}) => {
const [wistiaMedias, setwistiaMedias] = useState({}), [loading, setLoading] = useState(!1), handleVideoClick = (media) => {
onVideoClick(media);
};
return useEffect(() => {
if (projectId) {
setLoading(!0);
const apiUrl = `https://api.wistia.com/v1/medias.json?project_id=${projectId}&sort_by=name`, headers = new Headers({
Authorization: `Bearer ${config.token}`
});
fetch(apiUrl, {
method: "GET",
headers
}).then((response) => response.json()).then((data) => {
setLoading(!1);
let grouped = groupBy(data, "section");
return setwistiaMedias(grouped);
}).catch((error) => console.error(error));
}
}, []), /* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsxs(Menu, { children: [
!projectId && /* @__PURE__ */ jsx("div", { children: "Error loading project" }),
loading && /* @__PURE__ */ jsx(Card, { padding: 4, children: /* @__PURE__ */ jsxs(Flex, { align: "center", direction: "column", gap: 3, height: "fill", justify: "center", children: [
/* @__PURE__ */ jsx(Spinner, { muted: !0 }),
/* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: "Loading media from Wistia\u2026" })
] }) }),
Object.keys(wistiaMedias)?.length ? Object.keys(wistiaMedias)?.map((section, index) => /* @__PURE__ */ jsxs("div", { children: [
section !== "undefined" && /* @__PURE__ */ jsx(Card, { padding: 3, children: /* @__PURE__ */ jsx(Heading, { as: "h2", size: 1, children: section }) }),
wistiaMedias[section].map((media) => /* @__PURE__ */ jsx(
MenuItem,
{
paddingX: 3,
paddingY: 2,
style: { cursor: "pointer" },
onClick: () => handleVideoClick({ id: media.id, hashed_id: media.hashed_id }),
children: /* @__PURE__ */ jsxs(Flex, { gap: 3, align: "center", children: [
/* @__PURE__ */ jsx("img", { src: media.thumbnail.url, width: "70", style: { borderRadius: 3 } }),
/* @__PURE__ */ jsx(Text, { size: 1, weight: "semibold", align: "left", children: media.name }),
/* @__PURE__ */ jsx(Text, { size: 1, style: { marginLeft: "auto" }, muted: !0, children: new Date(media.duration * 1e3).toISOString().slice(11, 19) })
] })
},
media.id
))
] }, projectId + index)) : !loading && /* @__PURE__ */ jsx(Card, { padding: 4, children: /* @__PURE__ */ jsx(Text, { align: "center", muted: !0, size: 1, children: "No media found." }) })
] }) });
}, playerUrl = (videoUrl) => {
let params = new URLSearchParams(), wistiaSettings = {
playbar: !0,
playButton: !0,
seo: !1,
controlsVisibleOnLoad: !0,
autoPlay: !1,
doNotTrack: !0,
preload: "none",
volumeControl: !0,
copyLinkAndThumbnailEnabled: !0,
fullscreenButton: !0
};
for (let key in wistiaSettings)
params.append(key, wistiaSettings[key]);
return `${videoUrl}?${params.toString()}`;
};
function Player({ videoUrl }) {
return /* @__PURE__ */ jsx(
"div",
{
style: {
position: "relative",
paddingTop: "56.25%",
height: "0"
},
children: /* @__PURE__ */ jsx(
"iframe",
{
allow: "autoplay; fullscreen",
style: {
width: "100%",
height: "100%",
position: "absolute",
top: "0",
right: "0",
bottom: "0",
left: "0",
border: "0",
display: "block",
borderRadius: "3px"
},
src: playerUrl(videoUrl) || ""
}
)
}
);
}
function AssetMenu({ onAction }) {
return /* @__PURE__ */ jsx(
MenuButton,
{
button: /* @__PURE__ */ jsx(Button, { padding: 2, mode: "ghost", icon: EllipsisVerticalIcon, tone: "default" }),
id: "asset-menu",
menu: /* @__PURE__ */ jsxs(Menu, { children: [
/* @__PURE__ */ jsx(
MenuItem,
{
text: "Replace media",
icon: SearchIcon,
onClick: () => {
onAction({ type: "select" });
}
}
),
/* @__PURE__ */ jsx(
MenuItem,
{
text: "Copy embed URL",
icon: ClipboardIcon,
onClick: () => {
onAction({ type: "copyUrl" });
}
}
),
/* @__PURE__ */ jsx(MenuDivider, {}),
/* @__PURE__ */ jsx(
MenuItem,
{
text: "Clear field",
icon: ResetIcon,
tone: "critical",
onClick: () => {
onAction({ type: "delete" });
}
}
)
] })
}
);
}
const WistiaInputComponent = (props) => {
const {
value,
onChange,
config,
schemaType
} = props, [isModalOpen, setIsModalOpen] = useState(!1), [selectedProjectId, setSelectedProjectId] = useState(0), handleChange = useCallback(
(newValue) => {
setIsModalOpen(!1), onChange([
setIfMissing({
_type: schemaType.name
}),
set(newValue.hashed_id, ["hashed_id"]),
set(newValue.id, ["id"])
]);
},
[onChange, schemaType]
), handleProjectClick = (projectId) => {
setSelectedProjectId(projectId);
}, handleAssetMenu = (action) => {
switch (action?.type) {
case "copyUrl":
handleCopyURL();
break;
case "delete":
handleChange({});
break;
case "select":
setIsModalOpen(!0);
break;
}
}, videoUrl = value?.hashed_id ? `https://fast.wistia.net/embed/iframe/${value.hashed_id}` : null, { push: pushToast } = useToast(), handleCopyURL = useCallback(() => {
navigator.clipboard.writeText(videoUrl || ""), pushToast({ closable: !0, status: "success", title: "The URL is copied to the clipboard" });
}, [pushToast, videoUrl]), toggleModal = () => {
setIsModalOpen(!isModalOpen);
};
return config?.token?.length ? /* @__PURE__ */ jsxs("div", { style: { padding: 1 }, children: [
videoUrl ? /* @__PURE__ */ jsxs(Card, { radius: 2, shadow: 1, padding: 2, children: [
/* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", gap: 2, marginBottom: 2, children: [
/* @__PURE__ */ jsxs(Text, { size: 1, weight: "semibold", cellPadding: 2, children: [
/* @__PURE__ */ jsx(PlayIcon, { style: { marginLeft: 3, marginRight: 3 } }),
"Wistia video ID: ",
value?.id
] }),
/* @__PURE__ */ jsx(AssetMenu, { onAction: handleAssetMenu })
] }),
/* @__PURE__ */ jsx(Player, { videoUrl: videoUrl || "" })
] }) : /* @__PURE__ */ jsx(Card, { tone: "inherit", border: !0, padding: [3, 5], style: { borderStyle: "dashed" }, children: /* @__PURE__ */ jsxs(Flex, { align: "center", direction: "column", gap: 4, children: [
/* @__PURE__ */ jsx(Text, { muted: !0, children: /* @__PURE__ */ jsx(DocumentVideoIcon, {}) }),
/* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "Select a media from Wistia" }),
/* @__PURE__ */ jsx(Button, { mode: "ghost", text: "Select media", onClick: toggleModal })
] }) }),
isModalOpen && /* @__PURE__ */ jsx(
Dialog,
{
header: selectedProjectId ? "Select media" : "Select project",
id: "wistia-projects",
onClose: toggleModal,
width: 1,
children: selectedProjectId ? /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(Card, { tone: "default", borderBottom: !0, padding: 4, children: /* @__PURE__ */ jsx(
Button,
{
icon: ChevronLeftIcon,
onClick: () => handleProjectClick(0),
mode: "ghost",
text: "Back to projects"
}
) }),
/* @__PURE__ */ jsx(wistiaMediasComponent, { config, projectId: selectedProjectId, onVideoClick: handleChange })
] }) : /* @__PURE__ */ jsx(WistiaProjectsComponent, { config, onProjectClick: handleProjectClick })
}
)
] }) : /* @__PURE__ */ jsx(Card, { padding: [3, 3, 4], radius: 2, shadow: 1, tone: "critical", children: /* @__PURE__ */ jsxs(Text, { align: "center", children: [
"Missing required API token in Sanity config.",
" ",
/* @__PURE__ */ jsx("a", { href: "https://wistia.com/support/developers/making-api-requests", children: "See Wistia documentation." })
] }) });
};
function wistiaMediaRender(config) {
return {
components: {
input: (props) => /* @__PURE__ */ jsx(WistiaInputComponent, { config, ...props })
}
};
}
const wistiaInput = definePlugin((config) => ({
name: "sanity-plugin-wistia-input",
schema: {
types: [
{
...wistiaMedia,
...wistiaMediaRender(config)
}
]
}
}));
export {
wistiaInput
};
//# sourceMappingURL=index.mjs.map