diff --git a/.gitignore b/.gitignore index 8243e4f..053cd8b 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,4 @@ yarn-error.log* .vs/ db.json -package-lock.json \ No newline at end of file +package-lock.json diff --git a/db.json b/db.json new file mode 100644 index 0000000..183e95f --- /dev/null +++ b/db.json @@ -0,0 +1,44 @@ +{ + "videos": [ + { + "id": "cu3K1njbYqs", + "timesWatched": 1, + "lastWatched": "2018-12-02T20:43:18.202Z" + }, + { + "id": "PoSbnAFvqfA", + "timesWatched": 1, + "lastWatched": "2018-12-02T20:43:24.851Z" + }, + { + "id": "rzeLynj1GYM", + "timesWatched": 2, + "lastWatched": "2018-12-02T20:43:45.916Z" + }, + { + "id": "0J2QdDbelmY", + "timesWatched": 1, + "lastWatched": "2018-12-02T20:49:32.498Z" + }, + { + "id": "unRjK82bDLw", + "timesWatched": 2, + "lastWatched": "2018-12-02T20:49:50.769Z" + }, + { + "id": "g2N0TkfrQhY", + "timesWatched": 1, + "lastWatched": "2018-12-02T20:52:07.780Z" + }, + { + "id": "EM4vblG6BVQ", + "timesWatched": 1, + "lastWatched": "2018-12-02T20:52:43.282Z" + }, + { + "id": "tPwqOWK6EFw", + "timesWatched": 1, + "lastWatched": "2018-12-02T20:53:26.049Z" + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 6f1f0a4..b8bcf80 100644 --- a/package.json +++ b/package.json @@ -12,21 +12,25 @@ "lowdb": "^1.0.0", "moment": "^2.23.0", "moment-duration-format": "^2.2.2", + "node-sass": "^4.11.0", "react": "^16.6.1", "react-app-polyfill": "^0.1.3", "react-bootstrap": "^1.0.0-beta.2", "react-dom": "^16.6.1", + "react-height": "^3.0.0", "react-linkify": "^0.2.2", "react-router-dom": "^4.3.1", "react-scripts": "2.1.1", "react-youtube": "^7.8.0", "wikidata-sdk": "^5.15.9", - "wikijs": "^4.8.1" + "wikijs": "^4.8.1", + "youtube-page-token": "^1.0.1" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", + "node": "npm run build && node ./node-entry.js", "eject": "react-scripts eject" }, "eslintConfig": { diff --git a/src/App.js b/src/App.js index c6bb2af..a718772 100644 --- a/src/App.js +++ b/src/App.js @@ -1,30 +1,68 @@ import React from 'react'; -import { Route, Switch, Link } from 'react-router-dom'; // eslint-disable-line no-unused-vars -import 'bootstrap/dist/css/bootstrap.css'; // eslint-disable-line no-unused-vars -import { Row, Col } from 'react-bootstrap'; // eslint-disable-line no-unused-vars -import VideoList from './VideoList'; // eslint-disable-line no-unused-vars -import TopBar from './TopBar'; // eslint-disable-line no-unused-vars -import VideoPlayer from './VideoPlayer'; // eslint-disable-line no-unused-vars +import { Route, Switch } from 'react-router-dom'; +import 'bootstrap/dist/css/bootstrap.css'; +import { Row, Col, Button, Collapse } from 'react-bootstrap'; +import TopBar from './TopBar'; +import VideoPlayer from './VideoPlayer'; import VideoInfo from './VideoInfo'; +import VideoList from './VideoList'; +import Suggestion from './areainfo/Suggestion'; +import { ReactHeight } from 'react-height'; import './css/App.css'; class App extends React.Component { - render() { + constructor(props) { + super(props); + this.state = { + playerHeight: null, + navHeight: null, + blackbgHeight: null, + isInfoToggled: false + }; +} + +render() { return ( - - - - - - + { this.setState({ navHeight: height }); console.log('l', height) }}> + + + this.setState({ blackbgHeight: height })} className="row upperSection p-2 px-5" > + + this.setState({ playerHeight: height })}> + {/* change component to children */} + - - - - - -
URL not found
}/> + +
+ +
+ +
+ +
+
+ + + + + + +
URL not found
} />
diff --git a/src/VideoInfo.js b/src/VideoInfo.js index 115a60f..8234bba 100644 --- a/src/VideoInfo.js +++ b/src/VideoInfo.js @@ -1,213 +1,176 @@ import React, { Component } from 'react'; -// import PropTypes from 'prop-types'; import Wikipedia from './areainfo/Wikipedia'; -import {Col, Tabs, Tab, ListGroup, ListGroupItem} from 'react-bootstrap'; +import { Tabs, Tab, Table } from 'react-bootstrap'; import axios from 'axios'; import Linkify from "react-linkify"; import Card from "react-bootstrap/lib/Card"; -const ytclear = require('@c0b41/ytclear'); +import moment from 'moment'; +import momentDurationFormat from 'moment-duration-format'; +import './css/VideoInfo.scss'; class VideoInfo extends Component { - constructor(props) { - super(props); - this.state={ - error: null, - isLoaded: false, - VideoDetails: {}, - videoId: '0J2QdDbelmY', - comments : [] - }; - - } - - componentWillMount() { - if(this.props.match.params.id){ - if(this.props.match.params.id === this.state.videoId){} - else{ - this.setState({videoId: this.props.match.params.id}); + constructor(props) { + super(props); + this.state = { + error: null, + isLoaded: false, + VideoDetails: {}, + videoId: '0J2QdDbelmY', + comments: [] + }; + this.momentDuration = this.momentDuration.bind(this); + this.ISO_8601parse = this.ISO_8601parse.bind(this); } - } - } - componentDidMount() { - axios.get('https://www.googleapis.com/youtube/v3/videos', { - params: { - 'part': 'snippet,contentDetails,statistics,topicDetails', - 'id': this.state.videoId, - 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' - } - }).then(response => { - this.setState({ - VideoDetails: response.data.items, - others: { - artist: ytclear(response.data.items[0].snippet.title).split('-')[0], - title: ytclear(response.data.items[0].snippet.title).split('-')[1] - }, - isLoaded: true}); - }, error => { - console.error(error); - this.setState({ - isLoaded: true, - error - }); - }); - - //Richiesta per ottenere i commenti del video - axios.get('https://www.googleapis.com/youtube/v3/commentThreads', { - params: { - 'part': 'snippet', - 'videoId': this.state.videoId, //Da sostituire con variabile - 'order': 'relevance', - 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' - } - }).then( - response => { - this.setState({ - comments: response.data.items, - }); - }, - error => { - console.error(error); - } - ) - } - - // componentWillReceiveProps(nextProps) { - - // } - - // shouldComponentUpdate(nextProps, nextState) { - - // } - - componentWillUpdate(nextProps, nextState) { - // console.info('nextProps',nextProps); - // console.info('nextState',nextState); - if(nextProps.match.params.id === this.state.videoId){} - else if( nextProps.match.params.id){ - this.setState({videoId: nextProps.match.params.id}); + momentDuration(duration) { + return moment.duration(duration).format('hh:mm:ss'); + } + ISO_8601parse(a) { + return moment(a, moment.ISO_8601).format('ddd, DD/MM/YYYY hh:mm:ss'); } - } - componentDidUpdate(prevProps, prevState) { - // console.info('prevProps',prevProps); - // console.info('prevState',prevState); - } - // componentWillUnmount() { - // } + componentDidMount() { + console.log('didmount', this.state.videoId) + axios.all([ + axios.get('https://www.googleapis.com/youtube/v3/videos', { //Richiesta per tutte le info sul video + params: { + 'part': 'snippet,contentDetails,statistics,topicDetails', + 'id': this.state.videoId, + 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' + } + }), axios.get('https://www.googleapis.com/youtube/v3/commentThreads', { //Richiesta per ottenere i commenti del video + params: { + 'part': 'snippet', + 'videoId': this.state.videoId, + 'order': 'relevance', + 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' + } + })]) + .then(axios.spread((videosResponse, commentThreadResponse) => { + this.setState({ + VideoDetails: videosResponse.data.items[0], + comments: commentThreadResponse.data.items, + isLoaded: true + }); + }), error => { + console.error(error); + this.setState({ + isLoaded: true, + error + }); + }); + } - render() { - const { error, isLoaded, VideoDetails } = this.state; - if (error) { - return ( - - Error: {error.message} -- Cannot get {error.config.url} - - ); - } else if (!isLoaded) { - return Loading...; - } else { - return ( - - - {/* codice per tabs reccomenders */} - - -
- {this.state.VideoDetails.map(function(item,index){ - return( -
-

{item.snippet.title}

- -
ID Video
{item.id}
-
Publish Time
{item.snippet.publishedAt.replace(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+).000Z/,function(match,p1,p2,p3,p4,p5,p6){ - return(p3+'/'+p2+'/'+p1+' - '+p4+':'+p5+':'+p6); - })} -
-
Channel Name
{item.snippet.channelTitle}
-
Description
{item.snippet.description}
-
Tags
{item.snippet.tags.map(function(element,index){ - return( - {element} - ) - })}
-
-
- ) - } - )} -
-
- -
- {this.state.VideoDetails.map(function (item,index) { - return( -
-

{item.snippet.title}

- -
Duration
{item.contentDetails.duration.replace(/(PT(\d+)H(\d+)M(\d+)S)|(PT(\d+)M(\d+)S)/,function(match,p1,p2,p3,p4,p5,p6,p7){ - if(p1) return(p2+':'+p3+':'+p4); - else return(p6+':'+p7);})} -
-
Definition
{item.contentDetails.definition}
-
Dimension
{item.contentDetails.dimension}
-
Views
{item.statistics.viewCount}
-
Likes
{item.statistics.likeCount}
-
Dislikes
{item.statistics.dislikeCount}
-
-
- ) - })} -
-
- -
    - {this.state.comments.map(function (item,index) { - return( -
    - + componentDidUpdate(prevProps, prevState, snapshot) { + if (!(prevState.videoId === this.state.videoId)) + axios.all([ + axios.get('https://www.googleapis.com/youtube/v3/videos', { //Richiesta per tutte le info sul video + params: { + 'part': 'snippet,contentDetails,statistics,topicDetails', + 'id': this.state.videoId, + 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' + } + }), axios.get('https://www.googleapis.com/youtube/v3/commentThreads', { //Richiesta per ottenere i commenti del video + params: { + 'part': 'snippet', + 'videoId': this.state.videoId, + 'order': 'relevance', + 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' + } + })]) + .then(axios.spread((videosResponse, commentThreadResponse) => { + this.setState({ + VideoDetails: videosResponse.data.items[0], + comments: commentThreadResponse.data.items, + isLoaded: true + }); + }), error => { + console.error(error); + this.setState({ + isLoaded: true, + error + }); + }); + } + + + componentWillReceiveProps(nextProps) { + console.log(nextProps) + if (nextProps.match.params.id && !(nextProps.match.params.id === this.state.videoId)) { + this.setState({ videoId: nextProps.match.params.id }) + } // mindfuck + } + + render() { + const { error, isLoaded, VideoDetails, comments } = this.state; + const momentDuration = this.momentDuration; // bind momentDuration in render to the actual method + const ISO_8601parse = this.ISO_8601parse; // bind momentDuration in render to the actual method + if (error) { + return ( + + Error: {error.message} -- Cannot get {error.config.url} + + ); + } else if (!isLoaded) { + return Loading...; + } else { + return ( + + {VideoDetails.snippet.title} + + +

    + ID Video: {VideoDetails.id}
    + Published: {ISO_8601parse(VideoDetails.snippet.publishedAt)}
    + Channel name: {VideoDetails.snippet.channelTitle}
    + Description: {VideoDetails.snippet.description}
    + Tags: {VideoDetails.snippet.tags ? + VideoDetails.snippet.tags.map(tag => ({tag})) : ""} + {/* tags should be links */} +

    +
    + +

    Duration: {momentDuration(VideoDetails.contentDetails.duration)}
    + Definition: {VideoDetails.contentDetails.definition}
    + Dimension: {VideoDetails.contentDetails.dimension}
    + Views: {VideoDetails.statistics.viewCount}
    + Likes: {VideoDetails.statistics.likeCount}{String.fromCodePoint(0x1F44D)}
    + Dislikes: {VideoDetails.statistics.dislikeCount}{String.fromCodePoint(0x1F44E)} +

    +
    + + {comments.map(function (comment, index) { + return ( + - {item.snippet.topLevelComment.snippet.authorDisplayName} + + + {comment.snippet.topLevelComment.snippet.authorDisplayName} + - {item.snippet.topLevelComment.snippet.textDisplay} + {comment.snippet.topLevelComment.snippet.textOriginal} -
    - ) - })} -
-
- - - -
- - -

2

- -
- ); - } - } -} + ) + })} + + +
+
+
+ + + ); + } + } + +} VideoInfo.propTypes = { }; diff --git a/src/VideoPlayer.js b/src/VideoPlayer.js index e27ab78..6afe48b 100644 --- a/src/VideoPlayer.js +++ b/src/VideoPlayer.js @@ -8,8 +8,8 @@ class VideoPlayer extends Component { super(props); this.state = { opt: { - // height: '390', - // width: '640', + height: '390', + width: '640', playerVars: { // https://developers.google.com/youtube/player_parameters autoplay: 0, @@ -122,7 +122,7 @@ class VideoPlayer extends Component { // local storage logic for recent reccomender clearInterval(timerId1); }, - error => console.info(error) + error => console.error(error) ) .finally(() => this.setState({ promise1: null })); break; diff --git a/src/areainfo/Suggestion.js b/src/areainfo/Suggestion.js index 2185fd8..a0342b6 100644 --- a/src/areainfo/Suggestion.js +++ b/src/areainfo/Suggestion.js @@ -1,7 +1,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import Random from './reccomenders/Random'; -import Related from './reccomenders/Related'; +import { Row, Col, Button, Collapse } from 'react-bootstrap'; +// import Random from './reccomenders/Random'; +// import Related from './reccomenders/Related'; // and so on.. class Suggestion extends Component { @@ -39,10 +40,19 @@ class Suggestion extends Component { } render() { + let a =['','','','','','','','','','','']; return ( -
- -
+ + + + {a.map((x,i) => - video {i})} + + + + {a.map((x,i) => i)} + ?? box utile o superfluo? + + ); } } diff --git a/src/css/App.css b/src/css/App.css index 2890bb5..34f1e8e 100644 --- a/src/css/App.css +++ b/src/css/App.css @@ -1,9 +1,8 @@ -.bg-black{ -background-color:#000000; +.upperSection{ + background-color:#000000; } -.scrollable{ - overflow: auto !important; - height: 40vh; - margin-top: 2vh; +.downSection{ + overflow-y: auto; + overflow-x: hidden; } \ No newline at end of file diff --git a/src/css/VideoInfo.scss b/src/css/VideoInfo.scss new file mode 100644 index 0000000..7c87b79 --- /dev/null +++ b/src/css/VideoInfo.scss @@ -0,0 +1,10 @@ +// Required +@import "~bootstrap/scss/functions"; +@import "~bootstrap/scss/variables"; +@import "~bootstrap/scss/mixins"; +// To extend +@import '~bootstrap/scss/utilities/text'; + +a[aria-selected=false]{ + @extend .text-white; +} \ No newline at end of file diff --git a/src/reccomenders/Random.js b/src/reccomenders/Random.js index 8b7e7e4..3dbec24 100644 --- a/src/reccomenders/Random.js +++ b/src/reccomenders/Random.js @@ -1,9 +1,9 @@ import React, { Component } from 'react'; -import './App.css'; import 'bootstrap/dist/css/bootstrap.css'; import axios from "axios"; import createpageToken from 'youtube-page-token'; -import YouTube from "react-youtube"; +import {Card} from "react-bootstrap"; +import {Link} from "react-router-dom"; class RecommenderRandom extends Component{ constructor(props){ @@ -24,7 +24,7 @@ class RecommenderRandom extends Component{ 'part': 'snippet', 'topicId' : '/m/04rlf', //Filtro per la musica.In questo caso il valore รจ quello della parent directory 'type' : 'video', //che contiene tutti i generi di musica - 'maxResults': '20', + 'maxResults': '21', 'pageToken' : pageToken, 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' } @@ -41,31 +41,33 @@ class RecommenderRandom extends Component{ } render(){ - const opts = { - height: '250', - width: '250', - playerVars: { - autoplay: 0 - } - }; return ( -
+
{this.state.items.map(function (item,index) { return( -
- -
-

{item.snippet.title}

-

{item.snippet.channelTitle} - {item.snippet.publishedAt.replace(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+).000Z/,function(match,p1,p2,p3,p4,p5,p6){ - return(p3+'/'+p2+'/'+p1+' at '+p4+':'+p5+':'+p6); //Funzione che trasforma la data e ora di pubblicazione dal formato ISO nel normale formato da cristiani - })} -

-

{item.snippet.description}
~Recommended as a Random Video~

-
-
+
+ + + + + + {item.snippet.title}
+ {item.snippet.channelTitle} - {item.snippet.publishedAt.replace(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+).000Z/,function(match,p1,p2,p3,p4,p5,p6){ + return(p3+'/'+p2+'/'+p1+' at '+p4+':'+p5+':'+p6); //Funzione che trasforma la data e ora di pubblicazione dal formato ISO nel normale formato da cristiani + })} +
+
+ +
+
) })}
diff --git a/src/reccomenders/Related.js b/src/reccomenders/Related.js index 2a2e085..197e9a3 100644 --- a/src/reccomenders/Related.js +++ b/src/reccomenders/Related.js @@ -1,99 +1,88 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import axios from 'axios'; -import YouTube from "react-youtube"; import {Link} from "react-router-dom"; import {Card} from "react-bootstrap"; -import CardGroup from "react-bootstrap/es/CardGroup"; class Related extends Component { - constructor(props) { - super(props); - this.state={ - videoId : '0J2QdDbelmY', - items : [] + constructor(props) { + super(props); + this.state={ + videoId : '0J2QdDbelmY', + items : [] + } } - } - componentWillMount() { - if(this.props.match.params.id){ - if(this.props.match.params.id === this.state.videoId){} - else{ - this.setState({videoId: this.props.match.params.id}); - } - } - } + componentWillMount() { + if(this.props.match.params.id){ + if(this.props.match.params.id === this.state.videoId){} + else{ + this.setState({videoId: this.props.match.params.id}); + } + } + } - componentDidMount() { - axios.get("https://www.googleapis.com/youtube/v3/search",{ - params:{ - 'part': 'snippet', - 'relatedToVideoId' : this.state.videoId, - 'type' : 'video', - 'maxResults' : '21', - 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' - } - }).then( + componentDidMount() { + axios.get("https://www.googleapis.com/youtube/v3/search",{ + params:{ + 'part': 'snippet', + 'relatedToVideoId' : this.state.videoId, + 'type' : 'video', + 'maxResults' : '21', + 'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig' + } + }).then( response => { - this.setState({ - items: response.data.items, - }) - console.log(response); + this.setState({ + items: response.data.items, + }) + console.log(response); }, error => { - console.error(error); + console.error(error); } ) - } + } - //componentWillReceiveProps(nextProps) {} + componentWillUpdate(nextProps, nextState) { + if(nextProps.match.params.id === this.state.videoId){} + else if( nextProps.match.params.id){ + this.setState({videoId: nextProps.match.params.id}); + } + } - //shouldComponentUpdate(nextProps, nextState) {} - - componentWillUpdate(nextProps, nextState) { - if(nextProps.match.params.id === this.state.videoId){} - else if( nextProps.match.params.id){ - this.setState({videoId: nextProps.match.params.id}); - } - } - - //componentDidUpdate(prevProps, prevState) {} - - //componentWillUnmount() {} - - render() { - return ( -
- {this.state.items.map(function (item,index) { - return( -
- - - - - - {item.snippet.title}
- {item.snippet.channelTitle} - {item.snippet.publishedAt.replace(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+).000Z/,function(match,p1,p2,p3,p4,p5,p6){ + render() { + return ( +
+ {this.state.items.map(function (item,index) { + return( +
+ + + + + + {item.snippet.title}
+ {item.snippet.channelTitle} - {item.snippet.publishedAt.replace(/(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+).000Z/,function(match,p1,p2,p3,p4,p5,p6){ return(p3+'/'+p2+'/'+p1+' at '+p4+':'+p5+':'+p6); //Funzione che trasforma la data e ora di pubblicazione dal formato ISO nel normale formato da cristiani })} -
-
- -
-
- ) - })} -
- ); - } +
+
+ +
+
+ ) + })} +
+ ); + } } Related.propTypes = {