Skip to content

Commit

Permalink
✨ Fetch from quickchannel #2849
Browse files Browse the repository at this point in the history
  • Loading branch information
padms committed Mar 4, 2025
1 parent 248bf05 commit 803db37
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 140 deletions.
273 changes: 134 additions & 139 deletions sanityv3/schemas/components/VideoSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
import { ReactNode, useState, useCallback, useRef, forwardRef, useEffect } from 'react'
import { ReactNode, useState, forwardRef, useEffect } from 'react'
import { MemberField, set, unset } from 'sanity'
import { createPortal } from 'react-dom'
import type { ObjectInputProps } from 'sanity'
import { Buffer } from 'buffer'
import { UploadIcon, ResetIcon, EllipsisVerticalIcon, ComponentIcon } from '@sanity/icons'
import { Button, Dialog, Text, Label, Menu, MenuButton, MenuDivider, MenuItem, Stack, Card, Box } from '@sanity/ui'
import {
Button,
Dialog,
Text,
TextInput,
Label,
Menu,
MenuButton,
MenuDivider,
MenuItem,
Stack,
Card,
Box,
useToast,
} from '@sanity/ui'
import HLSPlayer from './HLSPlayer'
import { baseUrl } from '../../resolveProductionUrl'
import { getObjectMemberField } from './utils/getObjectMemberField'
Expand All @@ -20,12 +34,6 @@ type VideoSelectorProps = {
children?: ReactNode
} & ObjectInputProps

const MEDIABANK_DOMAIN = 'https://communicationtoolbox.equinor.com'
const MEDIABANK_URL =
MEDIABANK_DOMAIN +
'/dam2/archive?p_com_id=12366&p_oty_id=146867&p_ptl_id=16613&p_lae_id=2&p_mode=plugin_object&p_filter=status:1;sort:obt_id%20desc;type:AND;viewers:VIDEO_VIEWER;localCategories:822833'
const MEDIABANK_IMPORT_TYPE = 'dam:assets-imported'

const SCREEN9_ACCOUNT_ID = process.env.SANITY_STUDIO_SCREEN9_ACCOUNT_ID
const SCREEN9_TOKEN = process.env.SANITY_STUDIO_SCREEN9_TOKEN
const SCREEN9_AUTH = Buffer.from(`${SCREEN9_ACCOUNT_ID}:${SCREEN9_TOKEN}`).toString('base64')
Expand All @@ -34,6 +42,8 @@ const VideoSelector = forwardRef(function VideoSelector(
props: VideoSelectorProps,
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const toast = useToast()
const [open, setIsOpen] = useState(false)
const [container, setContainer] = useState<HTMLDivElement | null>(null)
const [error, setError] = useState('')
const { value, members, children, renderField, renderInput, renderItem, renderPreview, onChange } = props
Expand All @@ -42,91 +52,50 @@ const VideoSelector = forwardRef(function VideoSelector(
setContainer(document.createElement('div'))
}, [])

const closeModal = () => {
newWindow?.current?.close()
window.removeEventListener('message', handleMediaBankEvent)
}

const handleMediaBankEvent = useCallback(
async (event: MessageEvent) => {
if (!event || !event.data || event.origin !== MEDIABANK_DOMAIN) return false

const message = JSON.parse(event.data)

if (message?.type === MEDIABANK_IMPORT_TYPE) {
const file = message.data.assets[0]

if (file.viewer === 'VIDEO_VIEWER' && file.screen9Connected) {
const videoId = file.flvVideoRef
const endpoint = `${baseUrl}/api/screen9/${SCREEN9_ACCOUNT_ID}/videos/${videoId}/streams?ssl=true`

const data = await fetch(endpoint, {
headers: {
Authorization: `Basic ${SCREEN9_AUTH}`,
},
})
.then((res) =>
res.status !== 200
? setError('Could not retrieve url from Screen9. Please report the error to the dev team.')
: res.json(),
)
.catch((error) => {
setError(`Could not retrieve url from Screen9. Please report the error to the dev team. Error: ${error}`)
})

if (!data.error) {
const video = {
id: videoId,
title: file.title,
url: data.streams.hls,
}
// save to document
onChange(set(video))
}
} else {
setError('File is not supported. Please select a equinor.com video file.')
const handleOpenModal = async () => {
if (value?.id) {
setIsOpen(true)
const videoId = value.id
const endpoint = `${baseUrl}/api/screen9/${SCREEN9_ACCOUNT_ID}/videos/${videoId}/meta,streams?ssl=true`

const data = await fetch(endpoint, {
headers: {
Authorization: `Basic ${SCREEN9_AUTH}`,
},
})
.then((res) =>
res.status !== 200
? setError('Could not retrieve url from Screen9. Please report the error to the dev team.')
: res.json(),
)
.catch((error) => {
setError(`Could not retrieve url from Screen9. Please report the error to the dev team. Error: ${error}`)
})

if (!data.error) {
const video = {
id: videoId,
title: data.meta.title,
url: data.streams.hls,
}
closeModal()
}
},
[onChange],
)

const handleOpenModal = () => {
const height = 800
const width = 1200

const left = window.screen.width / 2 - width / 2
const top = window.screen.height / 2 - height / 2

if (container) {
newWindow.current = window.open(
MEDIABANK_URL,
'Media Bank',
`height=${height},width=${width},left=${left},top=${top}`,
)

if (newWindow.current) {
newWindow.current.document.body.appendChild(container)
window.addEventListener('message', handleMediaBankEvent)
// save to document
onChange(set(video))
setIsOpen(false)
}
} else {
toast.push({
status: 'error',
title: 'Enter media id of the video',
})
}
}

const handleReset = () => {
onChange(unset())
}

const newWindow = useRef<Window | null>(null)

const title = getObjectMemberField(members, 'title')

useEffect(() => {
// Clean up event listener when unmounting component
return () => {
window.removeEventListener('message', handleMediaBankEvent)
}
}, [handleMediaBankEvent])
const id = getObjectMemberField(members, 'id')

return (
<>
Expand All @@ -138,73 +107,99 @@ const VideoSelector = forwardRef(function VideoSelector(
</Box>
</Dialog>
)}
{!value ? (
<Stack>
{open && error.length != 0 && (
<Dialog header="Fetch video from Quickchannel" id="fetch-video" onClose={() => setIsOpen(false)} zOffset={1000}>
<Box padding={4}>
<Text>Fetching video url... {(id?.field?.value as string) || (open && !error)} </Text>
</Box>
</Dialog>
)}
{!value?.url ? (
<Stack space={2}>
{id && (
<MemberField
member={id}
renderInput={renderInput}
renderField={renderField}
renderItem={renderItem}
renderPreview={renderPreview}
/>
)}
<Button
icon={UploadIcon}
mode="ghost"
type="button"
onClick={handleOpenModal}
text="Import from Media Bank"
text="Fetch video from QuickChannel"
/>
</Stack>
) : (
<Stack space={4} marginTop={2}>
<Stack space={3}>
<Label as="label" htmlFor="text-input" size={1}>
Title
</Label>
{title && (
<MemberField
member={title}
renderInput={renderInput}
renderField={renderField}
renderItem={renderItem}
renderPreview={renderPreview}
/>
)}
</Stack>
<Stack space={3}>
<Label as="label" htmlFor="asset" size={1}>
Asset
</Label>
<div ref={forwardedRef} id="asset" style={{ position: 'relative' }}>
<Card border paddingX={6} tone="transparent">
<HLSPlayer
src={value.url}
controls={true}
width="100%"
height="350px"
style={{ marginBottom: '-5px', background: 'black' }}
/>
</Card>

<div style={{ position: 'absolute', top: '8px', right: '8px' }}>
<MenuButton
button={<Button icon={EllipsisVerticalIcon} mode="ghost" />}
id="menu-video"
menu={
<Menu>
<MenuItem as="div">
<Label size={2}>Replace</Label>
</MenuItem>
<MenuItem
as="button"
icon={ComponentIcon}
type="button"
onClick={handleOpenModal}
text="Media Bank"
/>
<MenuDivider />
<MenuItem as="button" icon={ResetIcon} text="Clear field" tone="critical" onClick={handleReset} />
</Menu>
}
popover={{ portal: true }}
value.url && (
<Stack space={4} marginTop={2}>
<Stack space={3}>
<Label as="label" htmlFor="text-input" size={1}>
Title
</Label>
{title && (
<MemberField
member={title}
renderInput={renderInput}
renderField={renderField}
renderItem={renderItem}
renderPreview={renderPreview}
/>
)}
</Stack>

<Stack space={3}>
<Label as="label" htmlFor="asset" size={1}>
Asset
</Label>

<div ref={forwardedRef} id="asset" style={{ position: 'relative' }}>
<Card border paddingX={6} tone="transparent">
<HLSPlayer
src={value.url}
controls={true}
width="100%"
height="350px"
style={{ marginBottom: '-5px', background: 'black' }}
/>
</Card>

<div style={{ position: 'absolute', top: '8px', right: '8px' }}>
<MenuButton
button={<Button icon={EllipsisVerticalIcon} mode="ghost" />}
id="menu-video"
menu={
<Menu>
<MenuItem as="div">
<Label size={2}>Replace</Label>
</MenuItem>
<MenuItem
as="button"
icon={ComponentIcon}
type="button"
onClick={handleOpenModal}
text="Media Bank"
/>
<MenuDivider />
<MenuItem
as="button"
icon={ResetIcon}
text="Clear field"
tone="critical"
onClick={handleReset}
/>
</Menu>
}
popover={{ portal: true }}
/>
</div>
</div>
</div>
</Stack>
</Stack>
</Stack>
)
)}
</>
)
Expand Down
2 changes: 1 addition & 1 deletion sanityv3/schemas/objects/hlsVideo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
{
name: 'id',
type: 'string',
hidden: true,
// hidden: true,
},
{
name: 'title',
Expand Down

0 comments on commit 803db37

Please sign in to comment.