import React from 'react'; import superagent from 'superagent'; import ReactPlayer from 'react-player' import DraggableTableRow from '../Util/DraggableTableRow.jsx'; import constants from '../CloudApi/Constants.js'; import { Container, Segment, Grid, Header, Image, Icon, Button, Table, Form, Label, Message, Menu, Tab, Dropdown, Modal, Card, Divider} from 'semantic-ui-react' import MoviesTVWrapper from './MoviesTVWrapper.jsx'; const Views = { Loading: "Loading", Channels: "Channels", ChannelEditor: "ChannelEditor", ChannelGroups: "ChannelGroups", ChannelGroupEditor: "ChannelGroupEditor" } class TVDashboard extends React.Component { constructor(props) { super(props); this.state = { query: null, currentChannel: null, currentChannelGroup: null, channels: [], channelGroups: [], selectedChannelId: null, plutoChannelQueries: null, currentVideoUri: null, view: Views.Loading, nextContent: constants.ContentQueryTypes[0].value, imageLoading: false, loading: false }; } async componentDidMount() { if (this.props.match.params.channelId) { this.setState({ view: Views.Loading }); try { const mediaProductTrailersRes = await superagent.get(`/api/admin/media/products?entitlementClass=FREE_FOR_ALL`).accept('json'); const freeMediaProductOptions = mediaProductTrailersRes.body.map(mediaProduct => { return { "key": mediaProduct.bigMediaId, "value": mediaProduct.bigMediaId, "text": `${mediaProduct.title}`, "image": { src: mediaProduct.marketingData["en-US"].unityPosterTexture && mediaProduct.marketingData["en-US"].unityPosterTexture["src"] } } }); this.setState({ mediaProductTrailers: mediaProductTrailersRes.body, freeMediaProductOptions }); const response = await superagent.get("/api/admin/tv/channel/" + this.props.match.params.channelId); this.setState({ currentChannel: response.body, view: Views.ChannelEditor, loading: false }); } catch (e) { console.log(e); } } else if (this.props.match.params.channelGroupId) { this.setState({ view: Views.Loading }); try { const channelsResponse = await superagent.get("/api/admin/tv/channels"); const response = await superagent.get("/api/admin/tv/channel_group/" + this.props.match.params.channelGroupId); this.setState({ channels: channelsResponse.body, currentChannelGroup: response.body, view: Views.ChannelGroupEditor, loading: false }); } catch (e) { console.log(e); } } else if (this.props.view) { if (this.props.view === Views.ChannelGroups) { await this.onShowChannelGroups(); } else if (this.props.views === Views.Channels) { await this.onShowChannels(); } else { await this.onShowChannels(); } } else { await this.onShowChannels(); } await this.getChannelQueryOptions(); } refreshData() { } onChange(e, { name, value }) { this.setState({ [name]: value }) } onChangeCurrentChannel(e, { name, value }) { if (this.state.currentChannel) { const _currentChannel = this.state.currentChannel; _currentChannel[name] = value; this.setState({ currentChannel: _currentChannel }); } } onChangeCurrentChannelRoomSettings(e, { name, value }) { if (this.state.currentChannel) { const _currentChannel = this.state.currentChannel; if (!_currentChannel.roomSettings) { _currentChannel.roomSettings = {}; } _currentChannel.roomSettings[name] = value; console.log(_currentChannel); this.setState({ currentChannel: _currentChannel }); } } onChangeCurrentChannelGroup(e, { name, value }) { if (this.state.currentChannelGroup) { const _currentChannelGroup = this.state.currentChannelGroup; _currentChannelGroup[name] = value; this.setState({ currentChannelGroup: _currentChannelGroup }); } } async onShowChannels(e) { this.setState({ loading: true }); const response = await superagent.get("/api/admin/tv/channels"); this.setState({ channels: response.body, view: Views.Channels, loading: false }); } onCreateChannel(e) { this.setState({ currentChannel: { geo: [], streams: [], queries: [], roomSettings: {} }, view: Views.ChannelEditor }); } async onShowChannelGroups(e) { this.setState({ loading: true }); const response = await superagent.get("/api/admin/tv/channel_groups"); this.setState({ channelGroups: response.body, view: Views.ChannelGroups, loading: false }); } async getChannelQueryOptions(e) { this.setState({ plutoChannelQueries: null }); const response = await superagent.get("/api/admin/tv/channel_query/pluto"); const options = response.body.map(nv => { return {"key": nv.value, "value": nv.value, "text": nv.name}}); this.setState({ plutoChannelQueries: options }); } onCreateChannelGroup(e) { this.setState({ currentChannelGroup: { channels: [] }, view: Views.ChannelGroupEditor }); } async onSaveChannel(e) { try { this.setState({ loading: true }); if (this.state.currentChannel) { if (this.state.currentChannel.id) { const result = await superagent.put("/api/admin/tv/channel").send(this.state.currentChannel); this.setState({ currentChannel: result.body, loading: false }); } else { const result = await superagent.post("/api/admin/tv/channel").send(this.state.currentChannel); this.setState({ currentChannel: result.body, loading: false }); } } } catch (e) { console.log(e); } } onAddStream(e) { e.preventDefault(); let currentChannel = this.state.currentChannel; currentChannel.streams.push({ type: this.state.nextContent, uri: "" }); this.setState({currentChannel}); } onAddQuery(e) { e.preventDefault(); let currentChannel = this.state.currentChannel; currentChannel.queries.push({ name: "twitch", value: "" }); this.setState({currentChannel}); } renderChannelEditor() { const geo = (this.state.currentChannel.geo.length == 0) ? : (
{this.state.currentChannel.geo.map(geo => { return ( ) })}
); const details = (
); const extraDetail = (

{geo}

); const roomSettings = (
Room Settings
); const channelContent = (
Channel Content
Queries
{(this.state.currentChannel.queries.length > 0) && ( Priority Source Value Edit )} {this.state.currentChannel.queries.map((query, queryIndex) => { let onQueryChange = function(e, { name, value }) { let currentChannel = this.state.currentChannel; currentChannel.queries[queryIndex][name] = value; this.setState({currentChannel}); } let onRemoveQuery = function(e) { let currentChannel = this.state.currentChannel; currentChannel.queries.splice(queryIndex, 1); this.setState({currentChannel}); } let queryElement =
; if (query.name === "pluto") { queryElement = ( ); } else if (query.name === "twitch") { queryElement = ( ); } else if (query.name === "youtube") { queryElement = (
); } else if (query.name === "BigMediaProduct") { queryElement = ( ); } return ( Query #{queryIndex + 1} {queryElement} ) })}
Streams
{(this.state.currentChannel.streams.length > 0) && ( Priority Data Preview Edit )} {this.state.currentChannel.streams.map((stream, streamIndex) => { let onStreamEntryChange = function(e, { name, value }) { let currentChannel = this.state.currentChannel; currentChannel.streams[streamIndex][name] = value; this.setState({currentChannel}); } let onMutedChanged = function(e) { let currentChannel = this.state.currentChannel; currentChannel.streams[streamIndex].isMuted = !currentChannel.streams[streamIndex].isMuted; this.setState({currentChannel}); } let onIsStaticFile = function(e) { let currentChannel = this.state.currentChannel; currentChannel.streams[streamIndex].onIsStaticFile = !currentChannel.streams[streamIndex].onIsStaticFile; this.setState({currentChannel}); } let onStereoChanged = function(e, { name, value }) { let currentChannel = this.state.currentChannel; if (value === 0) { currentChannel.streams[streamIndex].isStereo = false; currentChannel.streams[streamIndex].stereoPacking = "None"; } else if (value === 1) { currentChannel.streams[streamIndex].isStereo = true; currentChannel.streams[streamIndex].stereoPacking = "LeftRight"; } else if (value === 2) { currentChannel.streams[streamIndex].isStereo = true; currentChannel.streams[streamIndex].stereoPacking = "OverUnder"; } this.setState({currentChannel}); } let onRemoveStream = function(e) { let currentChannel = this.state.currentChannel; currentChannel.streams.splice(streamIndex, 1); this.setState({currentChannel}); } return ( ) })}
) const panes = [ { menuItem: 'Details', render: () => {details}{extraDetail} }, { menuItem: 'Room Settings', render: () => {roomSettings} }, { menuItem: 'Content', render: () => {channelContent} } ]; const tabs = ( ); // return (
{(!this.state.currentChannel.id) && details} {(this.state.currentChannel.id) && ( (this.state.currentChannel.streams.length == 0 && this.state.currentChannel.queries.length == 0) && ( This channel does not have any content!

Nobody will see the channel until you add a query or a stream

) )} {(this.state.currentChannel.id) && tabs} {(!this.state.currentChannel.id) &&
) } onSelectChannel(channel, e) { this.props.history.push({pathname: `/tv/channel/${channel.id}`}); } onSorted(clickedColumn) { const { channels, channelDirection } = this.state; const newChannelDirection = channelDirection === 'ascending' ? 'descending' : 'ascending'; const sortedChannels = _.sortBy(channels, [clickedColumn]); if (newChannelDirection === "descending") { sortedChannels.reverse(); } this.setState({ channels: sortedChannels, channelDirection: newChannelDirection }); } renderChannels() { return (
Name Display title + description Geography Room Settings Active Streams Content Queries {this.state.channels.map((channel, channelIndex) => { const streamData = channel.streams.length > 0 ? `${channel.streams.length} streams (${channel.streams[0].type})` : ""; const queryData = channel.queries.length > 0 ? `(${channel.queries[0].name})` : ""; const geo = (channel.geo.length == 0) ? : (
{channel.geo.map(geo => { return ( ) })}
) return ( {channel.name}
{channel.title}
{channel.description}
{(channel.streams.length === 0 && channel.queries.length === 0) && }
{geo} {(channel.roomSettings) &&
{channel.roomSettings.environment} (Size: {channel.roomSettings.size})
}
{streamData} {queryData}
) })}
) } onSelectChannelGroup(channelGroup, e) { this.props.history.push({pathname: `/tv/channel_group/${channelGroup.id}`}); } renderChannelGroups() { return (
Name Published Notes Display title Number of Channels {this.state.channelGroups.map((channelGroup, channelGroupIndex) => { return ( {channelGroup.name} {(channelGroup.isPublished === false) && ()} {(channelGroup.channels.length === 0) && } {channelGroup.title} {channelGroup.channels.length} ) })}
) } async onSaveChannelGroup(e) { try { this.setState({ loading: true }); await superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); this.setState({ loading: false }); } catch (e) { console.log(e); } } /** * The unity texture asset takes a while to generate - keep trying to load it until it shows up. */ async tryLoadImage() { try { this.setState({ imageLoading: true }); const result = await superagent.get(this.state.currentChannelGroup.textures[0].url); this.setState({ imageLoading: false }); } catch (e) { setTimeout(this.tryLoadImage.bind(this), 500); } } renderChannelGroupEditor() { const channelSelectionList = this.state.channels.map(chan => { return { "key": chan.id, "value": chan.id, "text": `${chan.title} (${chan.name})` } }); let onChannelSelectionChanged = function(e, { name, value }) { this.setState({selectedChannelId: value}); } let onAddChannelToList = async function (e) { e.preventDefault(); if (this.state.selectedChannelId) { const channel = _.find(this.state.channels, ["id", this.state.selectedChannelId]); const currentChannelGroup = this.state.currentChannelGroup; currentChannelGroup.channelIds.push(this.state.selectedChannelId); currentChannelGroup.channels.push(channel); this.setState({ currentChannelGroup }); superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); } } let onRebuildChannelGroup = async function onRebuildChannelGroup() { try { this.setState({ loading: true }); const result = await superagent.get("/api/admin/tv/rebuild_channel_group/" + this.state.currentChannelGroup.id); this.setState({ currentChannelGroup: result.body, loading: false }); await this.tryLoadImage(); } catch (e) { console.log(e); } } let onRemoveChannelFromList = async function(channelIndex, e) { e.preventDefault(); if (this.state.currentChannelGroup) { const currentChannelGroup = this.state.currentChannelGroup; currentChannelGroup.channelIds.splice(channelIndex, 1); currentChannelGroup.channels.splice(channelIndex, 1); this.setState({ currentChannelGroup }); superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); } } let onMoveChannelUp = async function(channelIndex, e) { e.preventDefault(); if (this.state.currentChannelGroup) { const currentChannelGroup = this.state.currentChannelGroup; if(channelIndex > currentChannelGroup.channels.length || channelIndex == 0){ alert("top"); return; } const movedChannelId = currentChannelGroup.channelIds[channelIndex]; const movedChannel = currentChannelGroup.channels[channelIndex]; currentChannelGroup.channelIds.splice(channelIndex, 1); currentChannelGroup.channels.splice(channelIndex, 1); currentChannelGroup.channelIds.splice(channelIndex-1, 0, movedChannelId); currentChannelGroup.channels.splice(channelIndex-1, 0, movedChannel); this.setState({ currentChannelGroup }); superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); } } let onMoveChannelDown = async function(channelIndex, e) { e.preventDefault(); if (this.state.currentChannelGroup) { const currentChannelGroup = this.state.currentChannelGroup; if(channelIndex > currentChannelGroup.channels.length || channelIndex+1 == currentChannelGroup.channels.length){ alert('already bottom'); return; } const movedChannelId = currentChannelGroup.channelIds[channelIndex]; const movedChannel = currentChannelGroup.channels[channelIndex]; currentChannelGroup.channelIds.splice(channelIndex, 1); currentChannelGroup.channels.splice(channelIndex, 1); currentChannelGroup.channelIds.splice(channelIndex+1, 0, movedChannelId); currentChannelGroup.channels.splice(channelIndex+1, 0, movedChannel); this.setState({ currentChannelGroup }); superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); } } let onMoveChannelToTop = async function(channelIndex, e) { e.preventDefault(); if (this.state.currentChannelGroup) { const currentChannelGroup = this.state.currentChannelGroup; if(channelIndex > currentChannelGroup.channels.length || channelIndex == 0){ return; } const movedChannelId = currentChannelGroup.channelIds[channelIndex]; const movedChannel = currentChannelGroup.channels[channelIndex]; currentChannelGroup.channelIds.splice(channelIndex, 1); currentChannelGroup.channels.splice(channelIndex, 1); currentChannelGroup.channelIds.splice(0, 0, movedChannelId); currentChannelGroup.channels.splice(0, 0, movedChannel); this.setState({ currentChannelGroup }); superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); } } let onChannelSwap = async function(channelIndexA, channelIndexB) { //e.preventDefault(); if (channelIndexA >= this.state.currentChannelGroup.channelIds.length || channelIndexA < 0) { return; } console.log("dest", channelIndexA, "src", channelIndexB); if (this.state.currentChannelGroup) { const currentChannelGroup = this.state.currentChannelGroup; const movedChannelId = currentChannelGroup.channelIds[channelIndexB]; currentChannelGroup.channelIds.splice(channelIndexB, 1); currentChannelGroup.channelIds.splice(channelIndexA, 0, movedChannelId); const movedChannel = currentChannelGroup.channels[channelIndexB]; currentChannelGroup.channels.splice(channelIndexB, 1); currentChannelGroup.channels.splice(channelIndexA, 0, movedChannel); //currentChannelGroup.channelIds[channelIndexA] = currentChannelGroup.channelIds.splice(channelIndexB, 1, currentChannelGroup.channelIds)[0]; //currentChannelGroup.channels[channelIndexA] = currentChannelGroup.channels.splice(channelIndexB, 1, currentChannelGroup.channels)[0]; this.setState({ currentChannelGroup }); superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup); } } // return (
{(this.state.currentChannelGroup.id) && {(this.state.imageLoading === false && this.state.currentChannelGroup.textures[0] && this.state.currentChannelGroup.textures[0].url) && } )} {(!this.state.currentChannelGroup.id) &&
) } render() { let contents = null; let title = null; if (this.state.view === Views.Channels) { title = "Channels"; contents = this.renderChannels(); } else if (this.state.view === Views.ChannelGroups) { title = "All Channel Groups"; contents = this.renderChannelGroups(); } else if (this.state.view === Views.ChannelEditor) { title = (this.state.currentChannel.id) ? this.state.currentChannel.name : "Create Channel"; contents = this.renderChannelEditor(); } else if (this.state.view === Views.ChannelGroupEditor) { title = (this.state.currentChannelGroup.id) ? "Edit Channel Group" : "Create Channel Group"; contents = this.renderChannelGroupEditor(); } else if (this.state.view === Views.Loading) { contents = (
Loading...
) } return ( {contents} ); } } export default TVDashboard;