[wip] video player page

This commit is contained in:
Sanjay Bhangar 2018-12-08 00:01:09 +02:00
parent f0dc1e4f35
commit 86a90ca8da
10 changed files with 98 additions and 22 deletions

View File

@ -19,7 +19,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>858</title>
</head>
<body>
<noscript>

View File

@ -1,4 +1,9 @@
// Topics Action Types
export const START_LOADING_ALL_TOPICS = 'START_LOADING_ALL_TOPICS';
export const LOADED_ALL_TOPICS = 'LOADED_ALL_TOPICS';
export const START_LOADING_RANDOM_TOPIC = 'START_LOADING_RANDOM_TOPIC';
export const LOADED_RANDOM_TOPIC = 'LOADED_RANDOM_TOPIC';
// Videos Action Types
export const ADD_VIDEOS_TO_STATE = 'ADD_VIDEOS_TO_STATE';

View File

@ -2,6 +2,7 @@ import { fetchAllTopics, fetchVideosByTopic } from '../utils/api';
import { APIError } from './errors';
import { getItem, setItem } from '../utils/safe-storage';
import getRandomTopic from '../utils/get-random-topic';
import { addVideosToState } from './videos';
import {
START_LOADING_ALL_TOPICS,
LOADED_ALL_TOPICS,
@ -42,6 +43,7 @@ export function getRandomTopicVideos(allTopics, numVideos=4) {
dispatch(loadingRandomTopicVideos());
fetchVideosByTopic(randomTopic.name, 0, 4)
.then(videos => {
dispatch(addVideosToState(videos));
dispatch(loadedRandomTopicVideos(randomTopic, videos));
});
};

8
src/actions/videos.js Normal file
View File

@ -0,0 +1,8 @@
import { ADD_VIDEOS_TO_STATE } from './action_types';
export function addVideosToState(videos) {
return {
type: ADD_VIDEOS_TO_STATE,
payload: videos
};
}

View File

@ -1,16 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
import { getThumbnail } from '../utils/video';
class VideoItem extends React.Component {
render() {
const videoLink = `/videos/${this.props.id}`;
return (
<section className="video-item">
<section className="video-thumbnail-container">
<img className="video-thumbnail" src={ getThumbnail(this.props.id) } alt=""/>
<Link to={ videoLink }>
<section className="video-item">
<section className="video-thumbnail-container">
<img className="video-thumbnail" src={ getThumbnail(this.props.id) } alt=""/>
</section>
<h3 className="video-title">{ this.props.title }</h3>
</section>
<h3 className="video-title">{ this.props.title }</h3>
</section>
</Link>
)
}
}

View File

@ -1,5 +1,7 @@
import React from 'react';
import Grid from 'react-css-grid';
import PropTyes from 'prop-types';
import { getVideo } from '../utils/video';
class VideoPlayer extends React.Component {
render() {
@ -8,19 +10,13 @@ class VideoPlayer extends React.Component {
<Grid width={450}
gap={16}>
<section>
<h2>Title</h2>
<video src="https://video22.858.ma/BUR/240p3.mp4" controls>
<h2>{ this.props.title }</h2>
<video src={ getVideo(this.props.id) } controls>
</video>
<h3>date mm/dd/yy </h3>
<h3>date { this.props.date } </h3>
</section>
<section className="text-left">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of
Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like
Aldus
PageMaker including versions of Lorem Ipsum.</p>
<p>{ this.props.description }</p>
</section>
</Grid>
@ -28,4 +24,10 @@ class VideoPlayer extends React.Component {
}
}
export default (VideoPlayer);
VideoPlayer.propTypes = {
title: PropTypes.string,
date: PropType.string,
description: PropTypes.string
};
export default VideoPlayer;

View File

@ -1,14 +1,47 @@
import React from 'react';
import {connect} from 'react-redux';
import VideoPlayer from "../components/VideoPlayer";
class Video extends React.Component {
getInitialState() {
return {
currentVideo: null
};
}
componentDidMount() {
// get videoId from the URL
const videoId = this.props.match.params.id;
// if data for videoId is already part of allVideos, setState to currentVideo
if (this.props.allVideos.hasOwnProperty(videoId)) {
const currentVideo = this.props.allVideos[videoId];
this.setState({'currentVideo': currentVideo});
} else {
// TODO: get video data if not available in cache
}
}
render() {
const video = this.state.currentVideo;
return (
<section>
<VideoPlayer/>
{ video &&
<VideoPlayer
id={ video.id }
title={ video.title }
date = { video.date }
description={ video.description }
/>
}
</section>
);
}
}
export default (Video);
const mapStateToProps = state => {
allVideos: this.state.allVideos;
};
export default connect(mapStateToProps)(Video);

View File

@ -1,9 +1,11 @@
import { combineReducers } from 'redux';
import TopicsReducer from './topics'
import TopicsReducer from './topics';
import VideosReducer from './videos';
const rootReducer = combineReducers({
topics: TopicsReducer
topics: TopicsReducer,
videos: VideosReducer
});
export default rootReducer;

20
src/reducers/videos.js Normal file
View File

@ -0,0 +1,20 @@
import {
ADD_VIDEOS_TO_STATE
} from '../actions/action_types';
export default function(state={}, action) {
switch (action.type) {
case ADD_VIDEOS_TO_STATE:
let clonedState = Object.assign({}, state);
if (!clonedState.allVideos) {
clonedState.allVideos = {};
}
const videosToAdd = action.payload;
videosToAdd.forEach(video => {
if (!clonedState.allVideos.hasOwnProperty(video.id)) {
clonedState.allVideos[video.id] = video;
}
});
return clonedState;
}
}

View File

@ -98,7 +98,7 @@ export function fetchAllDates(startRange=0, endRange=1000) {
*/
export function fetchVideosByX(key, value, startRange, endRange, sortKey='random') {
const data = {
"keys": ["editable", "modified", "title", "source", "project", "topic", "language", "duration", "id"],
"keys": ["editable", "modified", "title", "source", "project", "topic", "language", "duration", "id", "description", "date"],
"query": {
"conditions": [{
"key": key,