labo-components
Version:
168 lines (148 loc) • 5.66 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import TimeUtil from '../../../util/TimeUtil';
import FlexPlayerUtil from '../../../util/FlexPlayerUtil';
import { VIEW_LIST, VIEW_WORDCLOUD } from '../ContentAnnotationsColumn';
import TimedList from './TimedList';
import WordCloud from './WordCloud';
import { sanitize } from '../../shared/WordCloudHelpers';
import MediaEvents from '../_MediaEvents';
/*
This component shows Segments in a TimedList or WordCloud
*/
export default class Segments extends React.Component {
constructor(props) {
super(props);
}
/* ----------------------- RENDER LIST -------------------*/
renderList(mediaObject, searchTerm, mediaEvents) {
// convert segments to item list for TimedList
const items = mediaObject.segments
.filter(segment => !segment.programSegment)
.sort((a, b) => a.start - b.start)
.map((segment, index) => ({
id: 'ca_seg_li_' + index,
start:
FlexPlayerUtil.timeRelativeToOnAir(
segment.start,
mediaObject
) * 1000,
end:
FlexPlayerUtil.timeRelativeToOnAir(
segment.end,
mediaObject
) * 1000,
startLabel: TimeUtil.formatMillisToTime(
FlexPlayerUtil.timeRelativeToOnAir(
segment.start,
mediaObject
) * 1000
).replace(/^00:/g, ''), // remove prefixed 00: hours (as most videos are < 1h)
endLabel: TimeUtil.formatMillisToTime(
FlexPlayerUtil.timeRelativeToOnAir(
segment.end,
mediaObject
) * 1000
).replace(/^00:/g, ''), // remove prefixed 00: hours (as most videos are < 1h)
data: segment.title
}));
return (
<TimedList
items={items}
mediaEvents={mediaEvents}
searchTerm={searchTerm}
/>
);
}
/* ----------------------- RENDER WORDCLOUD -------------------*/
renderWordCloud(mediaObject, searchTerm, mediaEvents) {
// prepare segments
const segments = mediaObject.segments
.filter(segment => !segment.programSegment)
.sort((a, b) => a.start - b.start);
// get raw word list from segment titles
const words = segments.reduce(
(w, segment) => w.concat(segment.title.split(' ')),
[]
);
// When click on a word, onSeek the player to the next occurence of the given word
// Start on the start of the ASR item for context
const onWordClick = word => {
// get current player position
const pos = mediaEvents.getData(MediaEvents.PLAYER_POS);
// get next occurence
let hit = null;
segments.some(segment => {
const segmentStart = FlexPlayerUtil.timeRelativeToOnAir(
segment.start,
mediaObject
);
// if segment in the future, or no first hit
if (segmentStart > pos || hit == null) {
// sanitize the words
const words = sanitize(segment.title);
word = word.replace('_', ' ');
// if word exists
if (words.indexOf(word) !== -1) {
// store first hit
if (!hit) {
hit = segment;
}
// if future hit, store and return
if (segmentStart > pos) {
hit = segment;
return true;
}
}
}
return false;
});
// check if an item was hit
if (hit != null) {
// Update player by triggering SET_PLAYER_POS event
this.props.mediaEvents.trigger(
MediaEvents.SET_PLAYER_POS,
FlexPlayerUtil.timeRelativeToOnAir(hit.start, mediaObject)
);
}
};
return (
<WordCloud
words={words}
mediaEvents={mediaEvents}
size={100}
searchTerm={searchTerm}
onClick={onWordClick}
/>
);
}
/* ----------------------- RENDER -------------------*/
render = () => {
const mediaObject = this.props.activeMediaObject;
if (!mediaObject || !mediaObject.segments) {
return null;
}
switch (this.props.view) {
case VIEW_LIST:
return this.renderList(
mediaObject,
this.props.searchTerm,
this.props.mediaEvents
);
case VIEW_WORDCLOUD:
return this.renderWordCloud(
mediaObject,
this.props.searchTerm,
this.props.mediaEvents
);
default:
return null;
}
};
}
Segments.propTypes = {
searchTerm: PropTypes.string.isRequired,
view: PropTypes.string.isRequired,
activeMediaObject: PropTypes.object.isRequired,
mediaEvents: PropTypes.object.isRequired
};