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
}/>
+
+
+ this.setState({ isInfoToggled: !this.state.isInfoToggled })}
+ className="pt-1 "
+ aria-controls="infovideo-collapse"
+ aria-expanded={this.state.isInfoToggled}>
+ {this.state.isInfoToggled ? "Nascondi informazioni" : "Mostra informazioni"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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 = {