Archived
potete chiudere l'internet PORCODIO
This commit is contained in:
+103
-5
@@ -43,10 +43,62 @@ low(new FileAsync(__dirname + '/db.json')) // production
|
||||
});
|
||||
|
||||
// ==============
|
||||
// OPTIONS /globpop
|
||||
app.options('/globpop', (req, res) => {
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': ' GET, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
'Access-Control-Max-Age': 600
|
||||
})
|
||||
res.status(200).end();
|
||||
})
|
||||
|
||||
// GET /globpop
|
||||
app.get('/globpop', (req, res) => {
|
||||
req.query.id ? res.send(req.query.id) : res.status(400).send('Bad Request');
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
});
|
||||
const videos1 = db.get('videos');
|
||||
let videos = JSON.parse(JSON.stringify(videos1.values()));
|
||||
if (req.query.id) {
|
||||
let tmpRes;
|
||||
let row = videos1.getById(req.query.id);
|
||||
if (row.value()) {
|
||||
let tmpA = videos.filter(x => x.id !== req.query.id).map(x => {
|
||||
return {
|
||||
"videoID": x.id,
|
||||
"timesWatched": x.timesWatched,
|
||||
"prevalentReason": x.reason.sort((a, b) => a.timesWatched - b.timesWatched).reverse()[0].reason,
|
||||
"lastSelected": x.lastWatched
|
||||
}
|
||||
})
|
||||
tmpRes = {
|
||||
"site": "site1854.tw.cs.unibo.it",
|
||||
"recommender": req.query.id.toString(),
|
||||
"lastWatched": row.value().lastWatched,
|
||||
"recomended": tmpA
|
||||
}
|
||||
}
|
||||
else {
|
||||
let tmpA = videos.map(x => {
|
||||
return {
|
||||
"videoID": x.id,
|
||||
"timesWatched": x.timesWatched,
|
||||
"prevalentReason": x.reason.sort((a, b) => a.timesWatched - b.timesWatched).reverse()[0].reason,
|
||||
"lastSelected": x.lastWatched
|
||||
}
|
||||
})
|
||||
tmpRes = {
|
||||
"site": "site1854.tw.cs.unibo.it",
|
||||
"recommender": req.query.id.toString(),
|
||||
"lastWatched": "Never Watched",
|
||||
"recomended": tmpA
|
||||
}
|
||||
}
|
||||
res.send(tmpRes)
|
||||
} else
|
||||
res.status(400).send('Bad Request');
|
||||
});
|
||||
|
||||
// OPTIONS /videotrack
|
||||
@@ -62,8 +114,32 @@ low(new FileAsync(__dirname + '/db.json')) // production
|
||||
|
||||
// GET /videotrack
|
||||
app.get('/videotrack', (req, res) => {
|
||||
const videos = db.get('videos');
|
||||
req.query.id ? res.send(videos.getById(req.query.id).value()) : res.send(videos.value())
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
});
|
||||
const videos1 = db.get('videos').values();
|
||||
let videos = JSON.parse(JSON.stringify(videos1));
|
||||
console.log(req.query.prevId)
|
||||
if (req.query.prevId) {
|
||||
console.log(videos.length)
|
||||
let tmp = [];
|
||||
for (let i = 0; i < videos.length; i++) {
|
||||
console.log(videos[i]);
|
||||
for (let j = 0; j < videos[i].reason.length; j++) {
|
||||
console.log(videos[i].reason[j])
|
||||
if (videos[i].reason[j].prevId === req.query.prevId) {
|
||||
let tmp2 = {
|
||||
...videos[i].reason[j],
|
||||
'id': videos[i].id
|
||||
}
|
||||
tmp.push(tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.send(tmp)
|
||||
} else {
|
||||
res.send(videos)
|
||||
}
|
||||
});
|
||||
|
||||
// POST /videotrack
|
||||
@@ -71,21 +147,40 @@ low(new FileAsync(__dirname + '/db.json')) // production
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
});
|
||||
let setReason = function (reason = 'Starter', oldArr = [], prevId) {
|
||||
let j = oldArr.findIndex(el => el.prevId === prevId && el.reason === reason)
|
||||
if (j >= 0) {
|
||||
++oldArr[j].timesWatched;
|
||||
return oldArr
|
||||
}
|
||||
else {
|
||||
let tmp = {
|
||||
prevId,
|
||||
reason,
|
||||
timesWatched: 1
|
||||
}
|
||||
oldArr.push(tmp)
|
||||
return oldArr
|
||||
}
|
||||
}
|
||||
|
||||
const videos = db.get('videos');
|
||||
const row = videos.getById(req.body.id);
|
||||
if (row.value()) {
|
||||
row
|
||||
.update('timesWatched', (n) => ++n)
|
||||
.update('lastWatched', () => new Date().toISOString())
|
||||
.update('reason', (n) => setReason(req.body.reason, n, req.body.prevId))
|
||||
.write()
|
||||
.then(output => res.send(output))
|
||||
.then(output => res.send(200, output))
|
||||
} else {
|
||||
let newRow = {
|
||||
"id": req.body.id.toString(),
|
||||
"timesWatched": 1,
|
||||
"lastWatched": new Date().toISOString(),
|
||||
"reason": setReason(req.body.reason, [], req.body.prevId)
|
||||
}
|
||||
videos.push(newRow).last().write().then(output => res.send(200,output))
|
||||
videos.push(newRow).last().write().then(output => res.send(200, output))
|
||||
}
|
||||
});
|
||||
|
||||
@@ -94,5 +189,8 @@ low(new FileAsync(__dirname + '/db.json')) // production
|
||||
})
|
||||
.then(() => {
|
||||
app.use(express.static(__dirname + '/build')); // serve static build site
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(__dirname + '/build/index.html');
|
||||
});
|
||||
app.listen(8000, () => console.log('listen on 8000')); // bind to port 8000 as required from specs
|
||||
});
|
||||
|
||||
Generated
+8
-22
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hazetv-alfatube-1",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -5879,13 +5879,11 @@
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -5898,18 +5896,15 @@
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@@ -6012,8 +6007,7 @@
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@@ -6023,7 +6017,6 @@
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@@ -6036,20 +6029,17 @@
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
@@ -6066,7 +6056,6 @@
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@@ -6139,8 +6128,7 @@
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@@ -6150,7 +6138,6 @@
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@@ -6256,7 +6243,6 @@
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not ie <= 8",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 66 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 88 KiB |
+23
-7
@@ -2,25 +2,41 @@ import React, { Component } from 'react'
|
||||
import { Container, Row, Col, Image } from 'react-bootstrap';
|
||||
import './css/AboutUs.css';
|
||||
|
||||
export default class Home extends Component {
|
||||
export default class AboutUs extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Container>
|
||||
<Row className="show-Container text-center">
|
||||
<Col xs={12} sm={4} className="person-wrapper">
|
||||
<Image src="assets/person-1.jpg" roundedCircle className="profile-pic"/>
|
||||
<Image src="assets/person-1.jpg" roundedCircle className="profile-pic" />
|
||||
<h3>Matteo Scorzafava</h3>
|
||||
<p>That's a crooked tree. We'll send him to Washington. These little son of a guns hide in your brush and you just have to push them out.</p>
|
||||
Wikipedia <br/>
|
||||
Gestione 15 secondi <br/>
|
||||
Recommender Search <br/>
|
||||
Back-end per popolarità <br/>
|
||||
Recommender similarityArtist <br/>
|
||||
|
||||
|
||||
<p></p>
|
||||
</Col>
|
||||
<Col xs={12} sm={4} className="person-wrapper">
|
||||
<Image src="assets/person-2.jpg" roundedCircle className="profile-pic"/>
|
||||
<Image src="assets/person-2.jpg" roundedCircle className="profile-pic" />
|
||||
<h3>Simone Ferrari</h3>
|
||||
<p>That's a crooked tree. We'll send him to Washington. These little son of a guns hide in your brush and you just have to push them out.</p>
|
||||
<p>Recommender Random<br/>
|
||||
Recommender Related<br/>
|
||||
Recommender Similarity Genere<br/>
|
||||
Box delle informazioni relative al video
|
||||
</p>
|
||||
</Col>
|
||||
<Col xs={12} sm={4} className="person-wrapper">
|
||||
<Image src="assets/person-3.jpg" roundedCircle className="profile-pic"/>
|
||||
<Image src="assets/person-3.jpg" roundedCircle className="profile-pic" />
|
||||
<h3>Gregorio Giacchetti</h3>
|
||||
<p>That's a crooked tree. We'll send him to Washington. These little son of a guns hide in your brush and you just have to push them out.</p>
|
||||
<p>Recommender Recent<br/>
|
||||
Recommender fvitali<br/>
|
||||
Gestione della barra dei recommender<br/>
|
||||
AboutUs <br/>
|
||||
Recommender similarityArtist
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
|
||||
+18
-18
@@ -34,19 +34,17 @@ class App extends React.Component {
|
||||
exact: true,
|
||||
strict: false
|
||||
});
|
||||
if (prevState.videoId !== null){
|
||||
if (idMatch && idMatch.params.id !== prevState.videoId) {
|
||||
localStorage.setItem('prevId', prevState.videoId)
|
||||
localStorage.setItem('lastId', idMatch.params.id)
|
||||
return { videoId: idMatch.params.id };
|
||||
}
|
||||
else{
|
||||
if (idMatch && idMatch.params.id !== prevState.videoId) {
|
||||
localStorage.setItem('lastId', idMatch.params.id)
|
||||
return { videoId: idMatch.params.id };
|
||||
else {
|
||||
return null;
|
||||
|
||||
}
|
||||
return null;
|
||||
}}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
@@ -58,19 +56,21 @@ class App extends React.Component {
|
||||
<Row className="upperSection">
|
||||
<Col
|
||||
xs="12"
|
||||
lg={this.state.isInfoToggled ? { span: 6, offset: 0, order: 2 } : { span: 7, offset: 1, order: 2 }}
|
||||
className="align-content-center pt-2 p-1 pr-2">
|
||||
<ReactHeight onHeightReady={height => { this.setState({ playerHeight: height }) }}>
|
||||
<VideoPlayer videoId={this.state.videoId} />
|
||||
</ReactHeight>
|
||||
lg={this.state.isInfoToggled ? { span: 8, offset: 0, order: 2 } : { span: 9, offset: 0, order: 2 }}
|
||||
className="blackBg align-content-center">
|
||||
<Col xs="12" lg={this.state.isInfoToggled ? { span: 10, offset: 1 } : { span: 10, offset: 1 }}>
|
||||
<ReactHeight onHeightReady={height => { this.setState({ playerHeight: height }) }}>
|
||||
<VideoPlayer videoId={this.state.videoId} />
|
||||
</ReactHeight>
|
||||
</Col>
|
||||
</Col>
|
||||
<Col
|
||||
xs="12"
|
||||
lg={this.state.isInfoToggled ? { span: 5, order: 1 } : { span: 3, order: 1 }}
|
||||
className="p-0 p-xs-0"
|
||||
style={window.innerWidth < 992 ?
|
||||
{ 'overflow': "auto", 'display': 'fixed', 'maxHeight': this.state.playerHeight * 1.4 + 'px' } :
|
||||
{ 'overflow': "auto", 'maxHeight': `${this.state.playerHeight}px` }}>
|
||||
lg={this.state.isInfoToggled ? { span: 4, order: 1 } : { span: 3, order: 1 }}
|
||||
className={this.state.isInfoToggled ? "" : "blackBg"}
|
||||
style={window.innerWidth < 992 ?
|
||||
{ 'overflow': "auto", 'display': 'fixed', 'maxHeight': this.state.playerHeight * 1.4 + 'px' } :
|
||||
{ 'overflow': "auto", 'maxHeight': `${this.state.playerHeight}px` }}>
|
||||
{/* true = style for xs ;; false = style for lg */}
|
||||
<div className="d-flex justify-content-center">
|
||||
<Button
|
||||
@@ -89,7 +89,7 @@ class App extends React.Component {
|
||||
</Collapse>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ "maxHeight": `calc(98vh - ${this.state.playerHeight}px - 46px)` }} className='mt-1 downSection'>
|
||||
<Row style={{ "maxHeight": `calc(98vh - ${this.state.playerHeight}px - 40px)` }} className='mt-2 downSection'>
|
||||
<Switch>
|
||||
<Route exact path='/' component={VideoList} />
|
||||
<Route path={"/video/:id"} component={Suggestion} />
|
||||
|
||||
+16
-13
@@ -1,5 +1,4 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Row } from 'react-bootstrap';
|
||||
import { Switch, Route } from 'react-router';
|
||||
import Random from './reccomenders/Random';
|
||||
import Related from './reccomenders/Related';
|
||||
@@ -7,16 +6,19 @@ import Search from './reccomenders/Search';
|
||||
import fvitali from './reccomenders/fvitali';
|
||||
import popGlobaleAssoluta from './reccomenders/popGlobaleAssoluta';
|
||||
import Recent from './reccomenders/Recent';
|
||||
import similarityArtist from './reccomenders/similarityArtist';
|
||||
import popLocaleAss from './reccomenders/popLocaleAss';
|
||||
import PopRelLoc from './reccomenders/popRelLoc';
|
||||
import genreSimilarity from './reccomenders/genreSimilarity';
|
||||
|
||||
// and so on..
|
||||
|
||||
class Suggestion extends Component {
|
||||
|
||||
// static getDerivedStateFromProps(nextProps, prevState) {
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// componentDidMount() {
|
||||
|
||||
// }
|
||||
@@ -36,18 +38,19 @@ class Suggestion extends Component {
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row>
|
||||
<Switch>
|
||||
<Route path='/video/:id/vitali' component={fvitali} />
|
||||
<Route path='/search/:query' component={Search} />
|
||||
<Route path='/video/:id/random' component={Random} />
|
||||
<Route path='/video/:id/popGlobalAssoluta' component={popGlobaleAssoluta} />
|
||||
<Route path='/video/:id/recent' component={Recent} />
|
||||
<Route path='/video/:id/popRelLoc' component={PopRelLoc} />
|
||||
{/* lasciare questo per ultimo */}
|
||||
<Route component={Related} />
|
||||
<Route path='/video/:id/genreSimilarity' component={genreSimilarity} />
|
||||
<Route path='/video/:id/vitali' component={fvitali} />
|
||||
<Route path='/search/:query' component={Search} />
|
||||
<Route path='/video/:id/random' component={Random} />
|
||||
<Route path='/video/:id/popGlobalAssoluta' component={popGlobaleAssoluta} />
|
||||
<Route path='/video/:id/popLocaleAss' component={popLocaleAss} />
|
||||
<Route path='/video/:id/recent' component={Recent} />
|
||||
<Route path='/video/:id/similarityArtist' component={similarityArtist} />
|
||||
<Route path='/video/:id/popRelLoc' component={PopRelLoc} />
|
||||
{/* lasciare questo per ultimo */}
|
||||
<Route component={Related} />
|
||||
</Switch>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
+20
-32
@@ -22,15 +22,15 @@ class TopBar extends Component {
|
||||
}
|
||||
handleSubmit = event => {
|
||||
event.preventDefault();
|
||||
event.target.reset();
|
||||
// event.target.reset();
|
||||
this.props.history.push('/search/' + this.state.query);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Navbar bg="dark" className="py-0 px-1 w-100" expand="md">
|
||||
<Navbar bg="primary" varian="dark" className="py-0 px-1 w-100" expand="md">
|
||||
<Navbar.Brand>
|
||||
<Link to="/">HazeTV</Link>
|
||||
<Link className="text-light" to="/">HazeTV</Link>
|
||||
</Navbar.Brand>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
@@ -41,43 +41,31 @@ class TopBar extends Component {
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/random` }} className="text-light nav-link">Random</Link>
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/related` }} className="text-light nav-link">Related</Link>
|
||||
{<NavDropdown title="Similarity" id="basic-nav-dropdown" >
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/...` }} className="text-dark nav-link">
|
||||
Artist
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/similarityArtist` }} className="text-light nav-link">
|
||||
Artist
|
||||
</Link>
|
||||
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/...` }} className="text-dark nav-link">
|
||||
Genre
|
||||
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/genreSimilarity` }} className="text-light nav-link">
|
||||
Genre
|
||||
</Link>
|
||||
|
||||
|
||||
</NavDropdown>}
|
||||
{<NavDropdown title="Popolarità locale" id="basic-nav-dropdown" >
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/...` }} className="text-dark nav-link">
|
||||
Assoluta
|
||||
</Link>
|
||||
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/popRelLoc` }} className="text-dark nav-link">
|
||||
Relativa
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/popLocaleAss` }} className="text-light nav-link">
|
||||
Assoluta
|
||||
</Link>
|
||||
|
||||
</NavDropdown>}
|
||||
{<NavDropdown title="Popolarità globale" id="basic-nav-dropdown" >
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/popGlobalAssoluta` }} className="text-dark nav-link">
|
||||
Assoluta
|
||||
</Link>
|
||||
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/...` }} className="text-dark nav-link">
|
||||
Relativa
|
||||
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/popRelLoc` }} className="text-light nav-link">
|
||||
Relativa
|
||||
</Link>
|
||||
|
||||
|
||||
</NavDropdown>}
|
||||
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/progetti` }} className="text-light nav-link">Progetti</Link>
|
||||
<Link to={{ pathname: `/video/${localStorage['lastId']}/popGlobalAssoluta` }} className="text-light nav-link">popGlobalAssoluta</Link>
|
||||
|
||||
</Nav>
|
||||
<form className="form-inline" onSubmit={this.handleSubmit}>
|
||||
@@ -87,7 +75,7 @@ class TopBar extends Component {
|
||||
className="mr-sm-2"
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<Button type="submit" variant="outline-success">Search</Button>
|
||||
<Button type="submit" variant="secondary">Search</Button>
|
||||
</form>
|
||||
</Navbar.Collapse>
|
||||
</Navbar>
|
||||
|
||||
+10
-4
@@ -50,11 +50,14 @@ class VideoInfo extends React.Component {
|
||||
comments: commentThreadResponse.data.items,
|
||||
isLoaded: true
|
||||
});
|
||||
let index = videosResponse.data.items[0].topicDetails.relevantTopicIds.indexOf('/m/04rlf');
|
||||
videosResponse.data.items[0].topicDetails.relevantTopicIds.splice(index, 1);
|
||||
localStorage.setItem('lastTopic', videosResponse.data.items[0].topicDetails.relevantTopicIds);
|
||||
}), error => {
|
||||
console.error(error);
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
error
|
||||
error,
|
||||
isLoaded: true
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -64,14 +67,17 @@ class VideoInfo extends React.Component {
|
||||
const momentDuration = this.momentDuration;
|
||||
const ISO_8601parse = this.ISO_8601parse;
|
||||
if (error) {
|
||||
let htmlRegEx = /<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[\^'">\s]+))?)+\s*|\s*)\/?>/gm;
|
||||
return (
|
||||
<span className="text-white">
|
||||
<span>{}</span>
|
||||
Error: {error.message} -- Cannot get {error.config.url}
|
||||
Error: {error.message} -- {error.response.data && error.response.data.error.message.replace(htmlRegEx, '')}
|
||||
</span>
|
||||
);
|
||||
} else if (!isLoaded) {
|
||||
return <span className="text-white">Loading...</span>;
|
||||
return <div className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</div>;
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
|
||||
+72
-47
@@ -1,48 +1,48 @@
|
||||
import React from 'react';
|
||||
import { Col, ListGroup, Card, CardDeck } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import { Col, ListGroup, Card, CardDeck, Media } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import axios from 'axios'; // eslint-disable-line no-unused-vars
|
||||
import { Link } from 'react-router-dom'; // eslint-disable-line no-unused-vars
|
||||
/*eslint no-console: ["error", { allow: ["warn", "error", "info"] }] */
|
||||
|
||||
class VideoList extends React.Component {
|
||||
state = {
|
||||
error: null,
|
||||
isLoaded: false,
|
||||
items: [],
|
||||
headers: null
|
||||
};
|
||||
error: null,
|
||||
isLoaded: false,
|
||||
items: [],
|
||||
headers: null
|
||||
};
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
localStorage['fixedVideoList'] ?
|
||||
this.setState({
|
||||
items: this.shuffleArray(JSON.parse(localStorage.getItem('fixedVideoList'))),
|
||||
isLoaded: true
|
||||
}) :
|
||||
axios.get('http://site1825.tw.cs.unibo.it/video.json').then(
|
||||
response => {
|
||||
this.shuffleArray(response.data);
|
||||
this.getThumbnails(response.data)
|
||||
.then(videoList => localStorage.setItem('fixedVideoList',JSON.stringify(videoList)));
|
||||
},
|
||||
// Note: it's important to handle errors here
|
||||
// instead of a catch() block so that we don't swallow
|
||||
// exceptions from actual bugs in components.
|
||||
error => {
|
||||
console.error(error);
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
error
|
||||
});
|
||||
}
|
||||
)
|
||||
this.setState({
|
||||
items: this.shuffleArray(JSON.parse(localStorage.getItem('fixedVideoList'))),
|
||||
isLoaded: true
|
||||
}) :
|
||||
axios.get('http://site1825.tw.cs.unibo.it/video.json').then(
|
||||
response => {
|
||||
this.shuffleArray(response.data);
|
||||
this.getThumbnails(response.data)
|
||||
.then(videoList => localStorage.setItem('fixedVideoList', JSON.stringify(videoList)));
|
||||
},
|
||||
// Note: it's important to handle errors here
|
||||
// instead of a catch() block so that we don't swallow
|
||||
// exceptions from actual bugs in components.
|
||||
error => {
|
||||
console.error(error);
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
error
|
||||
});
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// METODI
|
||||
getThumbnails(videoItems) {
|
||||
let idToLookFor = videoItems.map(item => item.videoID);
|
||||
let finalChunk = (videoItems.length % 50) + 100;
|
||||
return axios
|
||||
return axios
|
||||
.all([
|
||||
// chain 3 parallel get
|
||||
axios.get('https://www.googleapis.com/youtube/v3/videos', {
|
||||
@@ -74,22 +74,24 @@ class VideoList extends React.Component {
|
||||
])
|
||||
.then(
|
||||
axios.spread((res1, res2, res3) => {
|
||||
[...res1.data.items,...res2.data.items,...res3.data.items]
|
||||
.map(resCurrentValue =>
|
||||
Object.defineProperty(
|
||||
videoItems.find(videoItem => {
|
||||
return videoItem.videoID === resCurrentValue.id;
|
||||
}),
|
||||
'thumbnail',
|
||||
{ value: resCurrentValue.snippet.thumbnails.medium.url,
|
||||
enumerable: true }
|
||||
)
|
||||
);
|
||||
[...res1.data.items, ...res2.data.items, ...res3.data.items]
|
||||
.map(resCurrentValue =>
|
||||
Object.defineProperty(
|
||||
videoItems.find(videoItem => {
|
||||
return videoItem.videoID === resCurrentValue.id;
|
||||
}),
|
||||
'thumbnail',
|
||||
{
|
||||
value: resCurrentValue.snippet.thumbnails.medium.url,
|
||||
enumerable: true
|
||||
}
|
||||
)
|
||||
);
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
items: videoItems
|
||||
});
|
||||
return new Promise((resolve, reject) => resolve(videoItems))
|
||||
return new Promise((resolve, reject) => resolve(videoItems))
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -113,13 +115,9 @@ class VideoList extends React.Component {
|
||||
</React.Fragment>
|
||||
);
|
||||
} else if (!isLoaded) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Col>
|
||||
<p className="text-center">Loading...</p>
|
||||
</Col>
|
||||
</React.Fragment>
|
||||
);
|
||||
return <Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>;
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
@@ -152,6 +150,33 @@ class VideoList extends React.Component {
|
||||
</Col>
|
||||
))}
|
||||
</React.Fragment>
|
||||
|
||||
|
||||
// <ul className="list-unstyled">{
|
||||
// items.map(item => (
|
||||
// <Link
|
||||
// key={item.videoId}
|
||||
// as="li" className="media mx-5 my-1 suggItem"
|
||||
// to={{
|
||||
// pathname: '/video/' + item.videoID,
|
||||
// state: {
|
||||
// artist: item.artist,
|
||||
// title: item.title
|
||||
// }
|
||||
// }}>
|
||||
// <img
|
||||
// width={240}
|
||||
// height={120}
|
||||
// className="align-self-center mr-3"
|
||||
// src={item.thumbnail}
|
||||
// alt={'Thumbnail of ' + item.title}
|
||||
// />
|
||||
// <Media.Body>
|
||||
// <h5>{item.artist} - {item.title}</h5>
|
||||
// <p>{item.category}</p>
|
||||
// </Media.Body>
|
||||
// </Link>
|
||||
// ))}</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+84
-88
@@ -6,48 +6,48 @@ import { withRouter } from 'react-router-dom';
|
||||
|
||||
class VideoPlayer extends React.Component {
|
||||
state = {
|
||||
opt: {
|
||||
// height: '390',
|
||||
// width: '640',
|
||||
playerVars: {
|
||||
// https://developers.google.com/youtube/player_parameters
|
||||
autoplay: 0,
|
||||
modestbranding: 1,
|
||||
fs: 0,
|
||||
iv_load_policy:3,
|
||||
rel: 0,
|
||||
origin//: 'http://site1854.tw.cs.unibo.it'
|
||||
}
|
||||
},
|
||||
promise1: null,
|
||||
promise2: null,
|
||||
outsideReject1: null,
|
||||
outsideReject2: null
|
||||
};
|
||||
|
||||
opt: {
|
||||
// height: '390',
|
||||
// width: '640',
|
||||
playerVars: {
|
||||
// https://developers.google.com/youtube/player_parameters
|
||||
autoplay: 0,
|
||||
modestbranding: 1,
|
||||
fs: 0,
|
||||
iv_load_policy: 3,
|
||||
rel: 0,
|
||||
origin//: 'http://site1854.tw.cs.unibo.it'
|
||||
}
|
||||
},
|
||||
promise1: null,
|
||||
promise2: Promise,
|
||||
outsideReject1: null,
|
||||
outsideReject2: null
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<YouTube
|
||||
opts={this.state.opt}
|
||||
videoId={this.props.videoId}
|
||||
onReady={this._onReady}
|
||||
onPlay={this._onPlay}
|
||||
onError={this._onError}
|
||||
onStateChange={this._onStateChange}
|
||||
className="embed-responsive-item"
|
||||
containerClassName="embed-responsive embed-responsive-16by9"
|
||||
/>
|
||||
<YouTube
|
||||
opts={this.state.opt}
|
||||
videoId={this.props.videoId}
|
||||
onReady={this._onReady}
|
||||
onPlay={this._onPlay}
|
||||
onError={this._onError}
|
||||
onStateChange={this._onStateChange}
|
||||
className="embed-responsive-item"
|
||||
containerClassName="embed-responsive embed-responsive-16by9"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// access to player in all event handlers via event.target
|
||||
_onError(event) {
|
||||
console.error('Player error: ', event);
|
||||
}
|
||||
|
||||
_onPlay(event) {}
|
||||
_onPlay(event) { }
|
||||
|
||||
_onReady(event) {}
|
||||
_onReady(event) { }
|
||||
|
||||
_onStateChange(event) {
|
||||
let timerId1, timerId2;
|
||||
@@ -78,7 +78,7 @@ class VideoPlayer extends React.Component {
|
||||
timerId1 = window.setInterval(() => {
|
||||
if (event.target.getCurrentTime() > 15)
|
||||
resolve(event.target.getVideoData().video_id);
|
||||
}, 1000);
|
||||
}, 500);
|
||||
this.setState({ outsideReject1: reject });
|
||||
})
|
||||
});
|
||||
@@ -86,83 +86,79 @@ class VideoPlayer extends React.Component {
|
||||
.then(
|
||||
videoIdWatched => {
|
||||
// post request to local db
|
||||
let reason = new URLSearchParams(this.props.location.search).get("ref");
|
||||
axios
|
||||
.post('http://site1854.tw.cs.unibo.it/videotrack', {
|
||||
id: videoIdWatched.toString()
|
||||
id: videoIdWatched.toString(),
|
||||
reason: reason || undefined,
|
||||
prevId: localStorage['prevId']
|
||||
})
|
||||
.then(
|
||||
response => console.info(response.data),
|
||||
error => this.setState({error})//console.error(error, videoIdWatched.toString())
|
||||
error => this.setState({ error })//console.error(error, videoIdWatched.toString())
|
||||
);
|
||||
// local storage logic for recent reccomender//tmp è il video che devo inserire sulla lista
|
||||
let tmp = JSON.parse(localStorage.getItem('lastWatched'))
|
||||
let j=tmp.findIndex(el=>el.id.toString()===videoIdWatched.toString())
|
||||
if (j<0) {
|
||||
// local storage logic for recent reccomender
|
||||
let tmp = JSON.parse(localStorage.getItem('lastWatched'))
|
||||
let j = tmp.findIndex(el => el.id.toString() === videoIdWatched.toString())
|
||||
if (j < 0) {
|
||||
|
||||
if (localStorage['prevId']==='1')
|
||||
{
|
||||
//per primo video
|
||||
tmp.push({
|
||||
'id': videoIdWatched.toString(),
|
||||
'lastWatched' : new Date(),
|
||||
'timesWatched' : 1,
|
||||
'prevVideos': []
|
||||
})
|
||||
}
|
||||
else {
|
||||
//Prima volta video generico
|
||||
tmp.push({
|
||||
'id': videoIdWatched.toString(),
|
||||
'lastWatched' : new Date(),
|
||||
'timesWatched' : 1,
|
||||
'prevVideos' : [{id:[localStorage["prevId"]].toString()}]
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if (tmp[j].id=='0J2QdDbelmY'){
|
||||
// tmp[j].timesWatched++;
|
||||
// tmp[j].lastWatched= new Date();
|
||||
// let z=tmp[j].prevVideos.findIndex(el=>el.id === localStorage["prevId"].toString())
|
||||
// if (z<0){
|
||||
// tmp[j].prevVideos.push({
|
||||
// 'id': localStorage["prevId"].toString()
|
||||
// })}
|
||||
// } else {
|
||||
//altre volte
|
||||
tmp[j].timesWatched++;
|
||||
tmp[j].lastWatched= new Date();
|
||||
let z=tmp[j].prevVideos.findIndex(el=>el.id === localStorage["prevId"].toString())
|
||||
if (z<0){
|
||||
tmp[j].prevVideos.push({
|
||||
'id': localStorage["prevId"].toString()
|
||||
})}
|
||||
|
||||
//}
|
||||
if (localStorage['prevId'] === '1') {
|
||||
//per primo video
|
||||
tmp.push({
|
||||
'id': videoIdWatched.toString(),
|
||||
'lastWatched': new Date(),
|
||||
'timesWatched': 1,
|
||||
'prevVideos': []
|
||||
})
|
||||
}
|
||||
else {
|
||||
//Prima volta video generico
|
||||
tmp.push({
|
||||
'id': videoIdWatched.toString(),
|
||||
'lastWatched': new Date(),
|
||||
'timesWatched': 1,
|
||||
'prevVideos': [{ id: [localStorage["prevId"]].toString() }]
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
//altre volte
|
||||
tmp[j].timesWatched++;
|
||||
tmp[j].lastWatched = new Date();
|
||||
let z = tmp[j].prevVideos.findIndex(el => el.id === localStorage["prevId"].toString())
|
||||
if (z < 0) {
|
||||
tmp[j].prevVideos.push({
|
||||
'id': localStorage["prevId"].toString()
|
||||
})
|
||||
}
|
||||
|
||||
tmp.sort((a, b) => new Date(b.lastWatched).getTime() - new Date(a.lastWatched).getTime());
|
||||
}
|
||||
|
||||
|
||||
|
||||
localStorage.setItem('lastWatched', JSON.stringify(tmp));
|
||||
tmp.sort((a, b) => new Date(b.lastWatched).getTime() - new Date(a.lastWatched).getTime());
|
||||
|
||||
|
||||
|
||||
localStorage.setItem('lastWatched', JSON.stringify(tmp));
|
||||
//.finally(()=>{})
|
||||
clearInterval(timerId1);
|
||||
return new Promise ((resolve,reject) => resolve(videoIdWatched))
|
||||
},
|
||||
error => console.error(error)
|
||||
)
|
||||
|
||||
.finally(() => this.setState({ promise1: null, outsideReject1: null }));
|
||||
break;
|
||||
.finally((id) => this.setState({ promise1: null, outsideReject1: null }));
|
||||
break;
|
||||
case 5:
|
||||
if (this.state.promise1)
|
||||
if (this.state.promise1)
|
||||
this.state.outsideReject1('Video changed');
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return new Promise ((resolve,reject) => resolve('ok'))
|
||||
})
|
||||
.finally(()=>{this.setState({promise2: null, outsideReject2: null})});
|
||||
.finally((res) => { this.setState({ promise2: null, outsideReject2: null }) });
|
||||
}
|
||||
}
|
||||
_onStateChange = this._onStateChange.bind(this);
|
||||
|
||||
+155
-114
@@ -3,9 +3,10 @@ import { Link } from 'react-router-dom';
|
||||
import wikijs from 'wikijs';
|
||||
import wdk from 'wikidata-sdk';
|
||||
import axios from 'axios';
|
||||
import { Table } from 'react-bootstrap';
|
||||
import { Table, Col } from 'react-bootstrap';
|
||||
import moment from 'moment';
|
||||
import "./css/Wikipedia.css"
|
||||
/*eslint no-console: ["error", { allow: ["warn", "error"] }] */
|
||||
|
||||
class Wikipedia extends Component {
|
||||
|
||||
@@ -38,11 +39,91 @@ class Wikipedia extends Component {
|
||||
case "P2624": // metrolyrics id
|
||||
return (<a target="_blank" rel="noopener noreferrer" href={`http://www.metrolyrics.com/${value}`}>{`${value}`}</a>)
|
||||
case "P1651": // youtubeid
|
||||
return ( <Link to={{pathname:`/video/${value}`}}>{`${value}`}</Link>)
|
||||
return (<Link to={{ pathname: `/video/${value}` }}>{`${value}`}</Link>)
|
||||
case "P2581":
|
||||
return (<a target="_blank" rel="noopener noreferrer" href={`https://babelnet.org/synset?word=bn:${value}`}>{`${value}`}</a>)
|
||||
return (<a target="_blank" rel="noopener noreferrer" href={`https://babelnet.org/synset?word=bn:${value}`}>{value}</a>)
|
||||
case "P1827":
|
||||
return (<a target="_blank" rel="noopener noreferrer" href={`https://musicbrainz.org/iswc/${value}`}>{value}</a>)
|
||||
default:
|
||||
return(`${value}`)
|
||||
return (`${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
getMusicBrainzFromWData = (P175, P435=undefined) => { // P175 = artist P435 = workid
|
||||
const musicbrainzBaseUrl = "https://musicbrainz.org/ws/2"; // more readable
|
||||
let artist = this.props.artist || this.props.artist2;
|
||||
let title = this.props.title || this.props.title2;
|
||||
if (P175.toLowerCase() === artist.trim().toLowerCase()) {
|
||||
axios
|
||||
.get(`https://musicbrainz.org/ws/2/recording`, {
|
||||
params: {
|
||||
'query': `${title.trim()} AND artistname:${artist.trim()}`, //AND release:${P361}
|
||||
'limit': 1,
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(resP175EqArtist => {
|
||||
axios
|
||||
.get(`${musicbrainzBaseUrl}/recording/${resP175EqArtist.data.recordings[0].id}`, {
|
||||
params: {
|
||||
'inc': 'work-rels+artists+releases',
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(resRecordingQuery => {
|
||||
let musicbrainzWorkId = resRecordingQuery.data.relations.map(x => x['target-type'] === 'work' ? x.work.id.toString() : "") || P435.toString();
|
||||
axios.get(`${musicbrainzBaseUrl}/work/${musicbrainzWorkId}`, {
|
||||
params:{
|
||||
'inc': 'artist-rels url-rels',
|
||||
'limit': 1,
|
||||
'offset': 0,
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(musicbrainzWorkRes => {
|
||||
this.setState({ musicbrainz: musicbrainzWorkRes.data, isMBLoaded: true })
|
||||
},
|
||||
error => console.error(error))
|
||||
}, err => { console.error(err) })
|
||||
}
|
||||
, err => console.error(err))
|
||||
}
|
||||
else if (P175.toLowerCase() === title.trim().toLowerCase()) { // video title was title - artist
|
||||
axios
|
||||
.get(`https://musicbrainz.org/ws/2/recording`, {
|
||||
params: {
|
||||
'query': `"${artist.trim()}" AND artistname:"${title.trim()}"`, //AND release:${P361}
|
||||
'limit': 1,
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(resP175EqTitle => {
|
||||
axios
|
||||
.get(`${musicbrainzBaseUrl}/recording/${resP175EqTitle.data.recordings[0].id}`, {
|
||||
params: {
|
||||
'inc': 'work-rels+artists+releases',
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(resRecordingQuery => {
|
||||
let musicbrainzWorkId = resRecordingQuery.data.relations.map(x => x['target-type'] === 'work' ? x.work.id.toString() : "") || P435.toString();
|
||||
axios.get(`${musicbrainzBaseUrl}/work/${musicbrainzWorkId}`, {
|
||||
params:{
|
||||
'inc': 'artist-rels url-rels',
|
||||
'limit': 1,
|
||||
'offset': 0,
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(musicbrainzWorkRes => {
|
||||
this.setState({ musicbrainz: musicbrainzWorkRes.data, isMBLoaded: true })
|
||||
},
|
||||
error => console.error(error))
|
||||
}, err => { console.error(err) })
|
||||
}
|
||||
, err => console.error(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,44 +141,53 @@ class Wikipedia extends Component {
|
||||
.map(x => wikidatatmp.claims[x][0].mainsnak.datavalue.value.id)
|
||||
.filter(x => typeof x === 'string'), 'en'))
|
||||
])
|
||||
.then(axios.spread((resKey, resQ) => {
|
||||
this.setState({
|
||||
wikidatakeys: Object.entries(resKey.data.entities),
|
||||
wikidataQ: resQ.data.entities,
|
||||
isWDataLoaded: true
|
||||
})
|
||||
}))
|
||||
.then(
|
||||
axios.spread((resKey, resQ) => {
|
||||
this.setState({
|
||||
wikidatakeys: Object.entries(resKey.data.entities),
|
||||
wikidataQ: resQ.data.entities,
|
||||
isWDataLoaded: true
|
||||
})
|
||||
try{
|
||||
this.getMusicBrainzFromWData(
|
||||
resQ.data.entities[wikidatatmp.claims.P175[0].mainsnak.datavalue.value.id].labels.en.value,
|
||||
wikidatatmp.claims.P435[0].mainsnak.datavalue.value
|
||||
);
|
||||
}
|
||||
catch(e){
|
||||
console.error(e)
|
||||
this.getMusicBrainzFromWData(
|
||||
resQ.data.entities[wikidatatmp.claims.P175[0].mainsnak.datavalue.value.id].labels.en.value
|
||||
);
|
||||
}
|
||||
}))
|
||||
if (wikidatatmp.sitelinks.enwiki)
|
||||
wikijs()
|
||||
.page(wikidatatmp.sitelinks.enwiki.title)
|
||||
.then(page => Promise.all([page.fullInfo(), page.summary()]))
|
||||
.then(page => Promise.all([page.fullInfo()]))
|
||||
.then(wikipediaRes => this.setState({
|
||||
wikipedia: {
|
||||
"desc": wikipediaRes[1],
|
||||
// "desc": wikipediaRes[1],
|
||||
"info": wikipediaRes[0].general
|
||||
},
|
||||
wikipediakeys: Object.keys(wikipediaRes[0].general),
|
||||
isWikiLoaded: true
|
||||
}))
|
||||
else {
|
||||
console.info('called here')
|
||||
this.findWikiPage();
|
||||
}
|
||||
}, error => console.error(error))
|
||||
}
|
||||
|
||||
findWikiPage = () => {
|
||||
let wikiquery = `${'undefined' === typeof this.props.title ? this.props.title2.trim() : this.props.title.trim()} (${'undefined' === typeof this.props.artist ? this.props.artist2.trim() : this.props.artist.trim()} song)`;
|
||||
console.info(wikiquery)
|
||||
let wikiquery = `${'undefined' === typeof this.props.title ? ('undefined' === typeof this.props.title2 ? this.props.artist2 : this.props.title2) : this.props.title.trim()} ${'undefined' === typeof this.props.title && 'undefined' === typeof this.props.title2 ? "" : `(${'undefined' === typeof this.props.artist ? this.props.artist2.trim() : this.props.artist.trim()} song)`}`;
|
||||
return wikijs()
|
||||
.find(wikiquery)
|
||||
.then(res => {
|
||||
console.info(res, 'a');
|
||||
return Promise.all([res.fullInfo(), res.summary()]);
|
||||
return Promise.all([res.fullInfo()]);
|
||||
}) // find by props.title (props.artist song)
|
||||
.then(wikipediaRes => this.setState({
|
||||
wikipedia: {
|
||||
"desc": wikipediaRes[1],
|
||||
"info": wikipediaRes[0].general
|
||||
},
|
||||
wikipediakeys: Object.keys(wikipediaRes[0].general),
|
||||
@@ -106,99 +196,50 @@ class Wikipedia extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const musicbrainzBaseUrl = "https://musicbrainz.org/ws/2"; // more readable
|
||||
// let timerId1;
|
||||
let timerId1;
|
||||
axios.get(wdk.getReverseClaims('P1651', this.props.videoId)) // P1651 is youtube_video_id property
|
||||
.then(wikidataP1651Res => {
|
||||
if (wikidataP1651Res.data.results.bindings.length) { // got a match
|
||||
if (wikidataP1651Res.data.results.bindings.length) // got a match
|
||||
this.getWikidataPage(wdk.simplify.sparqlResults(wikidataP1651Res.data))// set in state wikidata
|
||||
.then(() => {
|
||||
if (this.state.wikidata.claims.P435) { // p435 == musicbrainzWorkId
|
||||
axios.get(`${musicbrainzBaseUrl}/work/${this.state.wikidata.claims.P435[0].mainsnak.datavalue.value}`, { // get musicbrainz info
|
||||
params: {
|
||||
'inc': 'artist-rels url-rels',
|
||||
'limit': 15,
|
||||
'offset': 0,
|
||||
'fmt': 'json'
|
||||
}
|
||||
}).then(
|
||||
musicbrainzRes1 =>
|
||||
this.setState({ musicbrainz: musicbrainzRes1.data, isMBLoaded: true })
|
||||
);
|
||||
}
|
||||
else {//oof P435 not found in wikidata
|
||||
axios.get(`${musicbrainzBaseUrl}/work`, { // search on mb by wikidata title
|
||||
params: {
|
||||
'query': `work:${this.state.wikidata.labels.en.value}`,
|
||||
'limit': 1,
|
||||
'offset': 0,
|
||||
'fmt': 'json'
|
||||
}
|
||||
}).then(musicbrainzRes2 => {
|
||||
axios.get(`${musicbrainzBaseUrl}/work/${musicbrainzRes2.data.works[0].id}`,
|
||||
{ // get musicbrainz info on track by previous id
|
||||
params: {
|
||||
'inc': 'artist-rels url-rels',
|
||||
'limit': 15,
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
(musicbrainzWorkRes2) =>
|
||||
this.setState({ musicbrainz: musicbrainzWorkRes2.data, isMBLoaded: true })
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else { //oof
|
||||
axios.get(`${musicbrainzBaseUrl}/work`, {
|
||||
params: {
|
||||
'query': 'undefined' === typeof this.props.title ? this.props.title2 : this.props.title,
|
||||
'limit': 1,
|
||||
'offset': 0,
|
||||
'fmt': 'json'
|
||||
else { //oof -- no P1651 :(
|
||||
let title = this.props.title || this.props.title2;
|
||||
axios.get(wdk.searchEntities(`${title.trim()}`))
|
||||
.then(wikidataSearchRes => {
|
||||
try{
|
||||
this.getWikidataPage(wikidataSearchRes.data.search[0].title)
|
||||
}
|
||||
catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
}).then(musicbrainzRes => {
|
||||
axios.all([
|
||||
axios.get(wdk.getReverseClaims('P435', musicbrainzRes.data.works[0].id)), // P435 is musicbrainz id
|
||||
axios.get(`${musicbrainzBaseUrl}/work/${musicbrainzRes.data.works[0].id}`, { // get musicbrainz info
|
||||
params: {
|
||||
'inc': 'artist-rels url-rels',
|
||||
'limit': 15,
|
||||
'fmt': 'json'
|
||||
}
|
||||
})
|
||||
]).then(
|
||||
axios.spread((wikidataP435Res, musicbrainzWorkRes) => {
|
||||
this.setState({
|
||||
musicbrainz: musicbrainzWorkRes.data,
|
||||
isMBLoaded: true
|
||||
});
|
||||
if (wikidataP435Res.data.results.bindings.length) // found a match
|
||||
this.getWikidataPage(wdk.simplify.sparqlResults(wikidataP435Res.data)); // set the result in the state
|
||||
else if (musicbrainzWorkRes.data.relations.find(currentRel => currentRel.type === "wikidata")) { // found wikidata on music brainz
|
||||
let wikidataUrl = musicbrainzWorkRes.data.relations.find(currentRel => currentRel.type === "wikidata");
|
||||
let wikidataEntityRegEx = new RegExp("[^/]+$"); // match last part of url https://regex101.com/r/0wCQHY/1
|
||||
this.getWikidataPage(wikidataEntityRegEx.exec(wikidataUrl.url.resource)) //.then(() => this.setState({ isWikiLoaded: true }));
|
||||
}
|
||||
else { // oof
|
||||
this.findWikiPage()
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
}).finally(() => {
|
||||
// let tmp = JSON.parse(localStorage['currentVideoInfo']);
|
||||
// tmp.id = this.props.videoId;
|
||||
// tmp.artist = this.state.wikipedia.info.artist;
|
||||
// tmp.genre = this.state.wikidataQ[this.state.wikidata.claims["P136"][0].mainsnak.datavalue.value.id].labels.en.value;
|
||||
// console.info(tmp)
|
||||
// // localStorage.setItem('currentVideoInfo',JSON.stringify(tmp));
|
||||
this.setState({ isLoaded: true })
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
timerId1 = window.setInterval(() => {
|
||||
if (this.state.wikidataQ == undefined || this.state.wikidata == undefined) { }
|
||||
else{
|
||||
try {
|
||||
resolve({
|
||||
artist: this.state.wikidataQ[this.state.wikidata.claims["P175"][0].mainsnak.datavalue.value.id].labels.en.value.toString(),
|
||||
genre: this.state.wikidataQ[this.state.wikidata.claims["P136"][0].mainsnak.datavalue.value.id].labels.en.value.toString()
|
||||
})
|
||||
}
|
||||
catch{
|
||||
resolve({ artist: null, genre: null })
|
||||
}
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
}).then((res) => {
|
||||
let tmp = JSON.parse(localStorage['currentVideoInfo']);
|
||||
window.clearInterval(timerId1);
|
||||
tmp = {
|
||||
id: this.props.videoId.toString(),
|
||||
artist: res.artist,
|
||||
genre: res.genre
|
||||
}
|
||||
localStorage.setItem('currentVideoInfo', JSON.stringify(tmp));
|
||||
})
|
||||
.finally(() => this.setState({ isLoaded: true }));
|
||||
}
|
||||
|
||||
|
||||
@@ -220,11 +261,12 @@ class Wikipedia extends Component {
|
||||
if (error) {
|
||||
return <React.Fragment>Error: {error.message}</React.Fragment>;
|
||||
} else if (!this.state.isLoaded) {
|
||||
return <React.Fragment>Loading...</React.Fragment>;
|
||||
return <Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>;
|
||||
} else {
|
||||
return (<>
|
||||
{/* {isWikiLoaded && wikipedia.desc} */}
|
||||
<Table bordered variant="dark" hover size="sm">
|
||||
return (
|
||||
<Table size="sm">
|
||||
<tbody>
|
||||
{isWikiLoaded &&
|
||||
this.state.wikipediakeys.map(key => (
|
||||
@@ -241,9 +283,9 @@ class Wikipedia extends Component {
|
||||
${key[1].labels.en ? key[1].labels.en.value : ""} `}
|
||||
</td>
|
||||
<td>{
|
||||
typeof wikidata.claims[key[0]][0].mainsnak.datavalue.value === "string" ?
|
||||
this.getExternalLink(key[0],wikidata.claims[key[0]][0].mainsnak.datavalue.value) :
|
||||
typeof wikidata.claims[key[0]][0].mainsnak.datavalue.value.id === "string" ?
|
||||
typeof wikidata.claims[key[0]][0].mainsnak.datavalue.value === "string" ? // wikidata external
|
||||
this.getExternalLink(key[0], wikidata.claims[key[0]][0].mainsnak.datavalue.value) :
|
||||
typeof wikidata.claims[key[0]][0].mainsnak.datavalue.value.id === "string" ? // wikidata Q
|
||||
<><a target="_blank" rel="noopener noreferrer" href={`https://www.wikidata.org/wiki/${wikidata.claims[key[0]][0].mainsnak.datavalue.value.id}`}>
|
||||
{`${this.state.wikidataQ[wikidata.claims[key[0]][0].mainsnak.datavalue.value.id].labels.en ?
|
||||
this.state.wikidataQ[wikidata.claims[key[0]][0].mainsnak.datavalue.value.id].labels.en.value :
|
||||
@@ -274,7 +316,6 @@ class Wikipedia extends Component {
|
||||
}
|
||||
</tbody>
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+74
-2
@@ -1,9 +1,81 @@
|
||||
.upperSection{
|
||||
background-color:#000000;
|
||||
display: fixed;
|
||||
}
|
||||
|
||||
.blackBg{
|
||||
background-color:#000000;
|
||||
}
|
||||
|
||||
.downSection{
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.suggItem:hover{
|
||||
background-color: #213241;
|
||||
text-decoration: none;
|
||||
/* color: */
|
||||
}
|
||||
.suggItem:hover h5{
|
||||
color: #DF691A;
|
||||
}
|
||||
.suggItem p{
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* LOADING ANIMATION */
|
||||
.lds-ellipsis {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
.lds-ellipsis div {
|
||||
position: absolute;
|
||||
top: 27px;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
||||
}
|
||||
.lds-ellipsis div:nth-child(1) {
|
||||
left: 6px;
|
||||
animation: lds-ellipsis1 0.6s infinite;
|
||||
}
|
||||
.lds-ellipsis div:nth-child(2) {
|
||||
left: 6px;
|
||||
animation: lds-ellipsis2 0.6s infinite;
|
||||
}
|
||||
.lds-ellipsis div:nth-child(3) {
|
||||
left: 26px;
|
||||
animation: lds-ellipsis2 0.6s infinite;
|
||||
}
|
||||
.lds-ellipsis div:nth-child(4) {
|
||||
left: 45px;
|
||||
animation: lds-ellipsis3 0.6s infinite;
|
||||
}
|
||||
@keyframes lds-ellipsis1 {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes lds-ellipsis3 {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
@keyframes lds-ellipsis2 {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(19px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
a[target=_blank]{
|
||||
background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAXklEQVQoka2QwQ3AMAwCs1N28k7eiZ3oI7IcU6efBomXOREyxhUZ2brTdNAcVB2BaJgCVcDAalJLXsB+iLAjm1pAwzHWHD3gWMcMg/ERMjKfFOHVqMEGqEM/gKP/6gE2f+h+Z5P45wAAAABJRU5ErkJggg==') center right no-repeat;
|
||||
padding-right: 14px;
|
||||
|
||||
|
||||
}
|
||||
tbody a{
|
||||
color: #DF691A !important;
|
||||
}
|
||||
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+12
File diff suppressed because one or more lines are too long
+13
-10
@@ -1,21 +1,24 @@
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
// import 'bootstrap/dist/css/bootstrap.css';
|
||||
// import './css/bootswatch/darkly/bootstrap.min.css'
|
||||
import './css/bootswatch/superhero/bootstrap.min.css'
|
||||
import 'react-app-polyfill/ie9';
|
||||
//import '@babel/polyfill';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
import { HashRouter, BrowserRouter } from 'react-router-dom'; // eslint-disable-line
|
||||
import { HashRouter, BrowserRouter } from 'react-router-dom'; // eslint-disable-line
|
||||
|
||||
localStorage['lastWatched'] ? function (){}() : localStorage.setItem('lastWatched', JSON.stringify([]))
|
||||
localStorage['first'] ? function (){}() : localStorage.setItem('first', JSON.stringify([]))
|
||||
localStorage['lastId'] ? function (){}() : localStorage.setItem('lastId','0J2QdDbelmY')
|
||||
localStorage['prevId'] ? function (){}() : localStorage.setItem('prevId','1')
|
||||
localStorage['currentVideoInfo']? function(){}() : localStorage.setItem('currentVideoInfo', JSON.stringify({
|
||||
'id':'0J2QdDbelmY',
|
||||
'artist':'Seven Nation Army',
|
||||
'genre':'Rock'
|
||||
localStorage['lastWatched'] ? function () { }() : localStorage.setItem('lastWatched', JSON.stringify([]))
|
||||
localStorage['first'] ? function () { }() : localStorage.setItem('first', JSON.stringify([]))
|
||||
localStorage['prevId'] ? function () { }() : localStorage.setItem('prevId', '1')
|
||||
localStorage['lastId'] ? function () { }() : localStorage.setItem('lastId', '0J2QdDbelmY')
|
||||
localStorage['currentVideoInfo'] ? function () { }() : localStorage.setItem('currentVideoInfo', JSON.stringify({
|
||||
'id': '0J2QdDbelmY',
|
||||
'artist': 'Seven Nation Army',
|
||||
'genre': 'Rock'
|
||||
}));
|
||||
localStorage['lastTopic'] ? function () { }() : localStorage.setItem('lastTopic', '/m/04rlf');
|
||||
|
||||
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
|
||||
registerServiceWorker();
|
||||
|
||||
+68
-38
@@ -1,20 +1,20 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from "axios";
|
||||
import createpageToken from 'youtube-page-token';
|
||||
import {Card,Col} from "react-bootstrap";
|
||||
import {Link} from "react-router-dom";
|
||||
import { Card, Col, Media } from "react-bootstrap";
|
||||
import { Link } from "react-router-dom";
|
||||
import moment from "moment";
|
||||
|
||||
class RecommenderRandom extends Component{
|
||||
state={
|
||||
items : [],
|
||||
}
|
||||
class RecommenderRandom extends Component {
|
||||
state = {
|
||||
items: [],
|
||||
}
|
||||
|
||||
ISO_8601parse(a) {
|
||||
return moment(a, moment.ISO_8601).format('ddd, DD/MM/YYYY hh:mm:ss');
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
componentDidMount() {
|
||||
let pos = Math.floor(Math.random() * 500);
|
||||
let pageToken = createpageToken(pos); /* createPageToken(pos) restituisce il pageToken relativo al numero
|
||||
di pagina che gli viene passato(in questo caso pos) che verrai poi usato
|
||||
@@ -23,16 +23,16 @@ class RecommenderRandom extends Component{
|
||||
axios.get("https://www.googleapis.com/youtube/v3/search", {
|
||||
params: {
|
||||
'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
|
||||
'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': '21',
|
||||
'pageToken' : pageToken,
|
||||
'pageToken': pageToken,
|
||||
'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig'
|
||||
}
|
||||
}).then(
|
||||
response => {
|
||||
this.setState({
|
||||
items : response.data.items,
|
||||
items: response.data.items,
|
||||
})
|
||||
},
|
||||
error => {
|
||||
@@ -41,34 +41,64 @@ class RecommenderRandom extends Component{
|
||||
)
|
||||
}
|
||||
|
||||
render(){
|
||||
render() {
|
||||
const ISO_8601parse = this.ISO_8601parse;
|
||||
if (window.innerWidth < 992) {
|
||||
return (<React.Fragment>
|
||||
{this.state.items.map(function (item,index) {
|
||||
return(
|
||||
<Col key={index} md='4'>
|
||||
<Card>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.snippet.title}<br/>
|
||||
{item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</React.Fragment> );
|
||||
}
|
||||
{this.state.items.map(function (item, index) {
|
||||
return (
|
||||
<Col key={index} md='4'>
|
||||
<Card>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=Random"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.snippet.title}<br />
|
||||
{item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}<br />
|
||||
<span>Reccomender: Random</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</React.Fragment>);
|
||||
}else{
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: `/video/${item.id.videoId}`,
|
||||
search: '?ref=Random'
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3 img-fluid"
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.snippet.title}</h5>
|
||||
<p> {item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}</p>
|
||||
<p>Reccomender: Random</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}}
|
||||
}
|
||||
export default RecommenderRandom;
|
||||
+55
-30
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Col, ListGroup, Card, CardDeck } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import { Col, Card, Media } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import axios from 'axios'; // eslint-disable-line no-unused-vars
|
||||
import { Link } from 'react-router-dom'; // eslint-disable-line no-unused-vars
|
||||
/*eslint no-console: ["error", { allow: ["warn", "error", "info"] }] */
|
||||
@@ -55,7 +55,6 @@ class Recent extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
const { error, isLoaded, items } = this.state;
|
||||
if (error) {
|
||||
@@ -65,41 +64,67 @@ class Recent extends React.Component {
|
||||
</React.Fragment>
|
||||
);
|
||||
} else if (!isLoaded) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Col>
|
||||
<p className="text-center">Loading...</p>
|
||||
</Col>
|
||||
</React.Fragment>
|
||||
);
|
||||
return <Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>;
|
||||
} else {
|
||||
if (window.innerWidth < 992) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{items.map(item => (
|
||||
<Col md="4">
|
||||
<Card key={item.id}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br />
|
||||
{item.lastSelected}
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
<Col key={item.id} md="4">
|
||||
<Card >
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
search: "?ref=Recent"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br />
|
||||
<span>Ultima volta visto: {this.ISO_8601parse(item.lastWatched)} </span><br />
|
||||
<span>Reccomender: Recent</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
|
||||
</Col>))}
|
||||
|
||||
</Col>))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}else{
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.name}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: `/video/${item.name}`,
|
||||
search: '?ref=Recent'
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3 img-fluid"
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.name}</h5><br />
|
||||
<p>Ultima volta visto: {this.ISO_8601parse(item.lastWatched)} </p><br />
|
||||
<p>Reccomender: Recent</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+53
-23
@@ -1,15 +1,15 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios';
|
||||
import {Link} from "react-router-dom";
|
||||
import {Card,Col} from "react-bootstrap";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Card, Col, Media } from "react-bootstrap";
|
||||
import moment from "moment";
|
||||
|
||||
|
||||
class Related extends Component {
|
||||
state={
|
||||
videoId : localStorage['lastId'],
|
||||
items : []
|
||||
}
|
||||
state = {
|
||||
videoId: localStorage['lastId'],
|
||||
items: []
|
||||
}
|
||||
|
||||
|
||||
ISO_8601parse(a) {
|
||||
@@ -17,12 +17,12 @@ class Related extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
axios.get("https://www.googleapis.com/youtube/v3/search",{
|
||||
params:{
|
||||
axios.get("https://www.googleapis.com/youtube/v3/search", {
|
||||
params: {
|
||||
'part': 'snippet',
|
||||
'relatedToVideoId' : this.props.match.params.id,
|
||||
'type' : 'video',
|
||||
'maxResults' : '22',
|
||||
'relatedToVideoId': this.props.match.params.id,
|
||||
'type': 'video',
|
||||
'maxResults': '22',
|
||||
'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig'
|
||||
}
|
||||
}).then(
|
||||
@@ -37,14 +37,14 @@ class Related extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps,prevState){
|
||||
if (prevProps.match.params.id !== this.props.match.params.id){
|
||||
axios.get("https://www.googleapis.com/youtube/v3/search",{
|
||||
params:{
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.match.params.id !== this.props.match.params.id) {
|
||||
axios.get("https://www.googleapis.com/youtube/v3/search", {
|
||||
params: {
|
||||
'part': 'snippet',
|
||||
'relatedToVideoId' : this.props.match.params.id,
|
||||
'type' : 'video',
|
||||
'maxResults' : '22',
|
||||
'relatedToVideoId': this.props.match.params.id,
|
||||
'type': 'video',
|
||||
'maxResults': '22',
|
||||
'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig'
|
||||
}
|
||||
}).then(
|
||||
@@ -62,15 +62,17 @@ class Related extends Component {
|
||||
|
||||
render() {
|
||||
const ISO_8601parse = this.ISO_8601parse;
|
||||
if (window.innerWidth < 992) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.state.items.map(function (item,index) {
|
||||
return(
|
||||
{this.state.items.map(function (item, index) {
|
||||
return (
|
||||
<Col key={index} md="4">
|
||||
<Card>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=Related"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
@@ -79,8 +81,9 @@ class Related extends Component {
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.snippet.title}<br/>
|
||||
{item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}
|
||||
{item.snippet.title}<br />
|
||||
{item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}<br />
|
||||
<span>Reccomender: Related</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
@@ -90,7 +93,34 @@ class Related extends Component {
|
||||
})}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}else{
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: `/video/${item.id.videoId}`,
|
||||
search: '?ref=Related'
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3 img-fluid"
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.snippet.title}</h5>
|
||||
<p> {item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}</p>
|
||||
<p>Reccomender: Related</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}}
|
||||
}
|
||||
|
||||
Related.propTypes = {
|
||||
|
||||
+45
-10
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Card, Col } from 'react-bootstrap';
|
||||
import { Col, Media, Card } from 'react-bootstrap';
|
||||
|
||||
class Search extends React.Component {
|
||||
|
||||
@@ -44,7 +44,8 @@ class Search extends React.Component {
|
||||
// }
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevProps.match.params.query !== this.props.match.params.query)
|
||||
if (prevProps.match.params.query !== this.props.match.params.query) {
|
||||
this.setState({ isLoaded: false })
|
||||
if (new RegExp("[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]").test(this.props.match.params.query.toString()))
|
||||
axios.get('https://www.googleapis.com/youtube/v3/videos', {
|
||||
params: {
|
||||
@@ -68,6 +69,8 @@ class Search extends React.Component {
|
||||
)
|
||||
else
|
||||
this.youtubeSearch();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// componentWillUnmount() {
|
||||
@@ -86,7 +89,7 @@ class Search extends React.Component {
|
||||
'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig'
|
||||
}
|
||||
}).then(
|
||||
res =>
|
||||
res =>
|
||||
this.setState({
|
||||
res: res.data,
|
||||
isLoaded: true
|
||||
@@ -102,15 +105,46 @@ class Search extends React.Component {
|
||||
if (this.state.error) {
|
||||
return <React.Fragment>{this.state.error.message} -- {this.state.error.response.data.error.errors[0].reason} </React.Fragment>;
|
||||
} else if (!this.state.isLoaded) {
|
||||
return <React.Fragment>Loading...</React.Fragment>;
|
||||
return <Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>;
|
||||
} else {
|
||||
if (window.innerWidth > 992) {
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.res.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=Search"
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3"
|
||||
src={item.snippet.thumbnails.medium.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.snippet.title}</h5>
|
||||
<p>{item.snippet.description}</p>
|
||||
<p>Reccomender: Search</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}else{
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.state.res.items.map(item => (<Col key={item.id.videoId} md="4">
|
||||
<Card>
|
||||
{this.state.res.items.map(item => (<Col md="4">
|
||||
<Card key={item.id.videoId}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=Search"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
@@ -119,16 +153,17 @@ class Search extends React.Component {
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.snippet.title}
|
||||
<p>{item.snippet.title}</p>
|
||||
<p className='small'>{item.lastSelected}</p>
|
||||
<p className='small'>Reccomender: Search</p>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Col>))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+84
-57
@@ -1,25 +1,24 @@
|
||||
import React from 'react';
|
||||
import { Col, Card } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import { Col, Card, Media } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import axios from 'axios'; // eslint-disable-line no-unused-vars
|
||||
import { Link } from 'react-router-dom'; // eslint-disable-line no-unused-vars
|
||||
/*eslint no-console: ["error", { allow: ["warn", "error", "info"] }] */
|
||||
|
||||
|
||||
class fvitali extends React.Component {
|
||||
state = {
|
||||
error: null,
|
||||
isLoaded: false,
|
||||
items: [],
|
||||
};
|
||||
|
||||
|
||||
state = {
|
||||
error: null,
|
||||
isLoaded: false,
|
||||
items: [],
|
||||
};
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
axios.get('http://site1825.tw.cs.unibo.it/TW/globpop', {
|
||||
'params':{
|
||||
'id':this.props.match.params.id //se 'id'=>'Id', allora tutti video random, sennò anche per genere simile
|
||||
'params': {
|
||||
'id': this.props.match.params.id //se 'id'=>'Id', allora tutti video random, sennò anche per genere simile
|
||||
}
|
||||
}).then(
|
||||
response => {
|
||||
response => {
|
||||
this.getThumbnailsNames(response.data.recommended);
|
||||
},
|
||||
error => {
|
||||
@@ -32,33 +31,33 @@ class fvitali extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// METODI
|
||||
getThumbnailsNames(reccomended) {
|
||||
let idToLookFor = reccomended.map(item => item.videoID);
|
||||
axios.get('https://www.googleapis.com/youtube/v3/videos', {
|
||||
params: {
|
||||
part: 'snippet',
|
||||
id: idToLookFor.toString(),
|
||||
key: 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig',
|
||||
fields: 'items(id,snippet/thumbnails/medium,snippet/title)'
|
||||
}
|
||||
})
|
||||
axios.get('https://www.googleapis.com/youtube/v3/videos', {
|
||||
params: {
|
||||
part: 'snippet',
|
||||
id: idToLookFor.toString(),
|
||||
key: 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig',
|
||||
fields: 'items(id,snippet/thumbnails/medium,snippet/title)'
|
||||
}
|
||||
})
|
||||
|
||||
.then(
|
||||
res1 => {
|
||||
res1.data.items.map(resCurrentValue =>
|
||||
res1.data.items.map(resCurrentValue =>
|
||||
Object.defineProperties(
|
||||
reccomended.find(videoItem => {
|
||||
return videoItem.videoID === resCurrentValue.id;
|
||||
}),
|
||||
{
|
||||
'thumbnail':
|
||||
{ value: resCurrentValue.snippet.thumbnails.medium.url },
|
||||
'name':
|
||||
{value: resCurrentValue.snippet.title}
|
||||
})
|
||||
'thumbnail':
|
||||
{ value: resCurrentValue.snippet.thumbnails.medium.url },
|
||||
'name':
|
||||
{ value: resCurrentValue.snippet.title }
|
||||
})
|
||||
);
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
@@ -79,38 +78,66 @@ class fvitali extends React.Component {
|
||||
);
|
||||
} else if (!isLoaded) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Col>
|
||||
<p className="text-center">Loading...</p>
|
||||
</Col>
|
||||
</React.Fragment>
|
||||
<Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{items.map(item=>( <Col md="4">
|
||||
<Card key={item.videoID}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.videoID,
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br/>
|
||||
{item.lastSelected}
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>))}
|
||||
|
||||
</React.Fragment>
|
||||
);
|
||||
if (window.innerWidth < 992) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{items.map(item => (<Col md="4">
|
||||
<Card key={item.videoID}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.videoID,
|
||||
search: "?ref=fvitali"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
<span>{item.name}</span> <br/>
|
||||
|
||||
<span>Reccomender: fvitali</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>))}
|
||||
</React.Fragment>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
items.map(item => (
|
||||
<Link
|
||||
key={item.videoID}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: `/video/${item.videoID}`,
|
||||
search: '?ref=fvitali'
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3 img-fluid"
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.name}</h5>
|
||||
|
||||
<p>Reccomender: fvitali</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios';
|
||||
import { Card, Col, Media } from "react-bootstrap";
|
||||
import createpageToken from 'youtube-page-token';
|
||||
import { Link } from "react-router-dom";
|
||||
import moment from "moment";
|
||||
|
||||
class genreSimilarity extends Component {
|
||||
state = {
|
||||
items: []
|
||||
};
|
||||
|
||||
ISO_8601parse(a) {
|
||||
return moment(a, moment.ISO_8601).format('ddd, DD/MM/YYYY hh:mm:ss');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let pos = Math.floor(Math.random() * 100);
|
||||
let pageToken = createpageToken(pos);
|
||||
|
||||
axios.get("https://www.googleapis.com/youtube/v3/search", {
|
||||
params: {
|
||||
'part': 'snippet',
|
||||
'topicId': localStorage['lastTopic'],
|
||||
'type': 'video',
|
||||
'maxResults': '21',
|
||||
'order': 'viewCount',
|
||||
'pageToken': pageToken,
|
||||
'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig'
|
||||
}
|
||||
}).then(
|
||||
response => {
|
||||
this.setState({
|
||||
items: response.data.items,
|
||||
})
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const ISO_8601parse = this.ISO_8601parse;
|
||||
if (window.innerWidth < 992){
|
||||
return (<React.Fragment>
|
||||
{this.state.items.map(function (item, index) {
|
||||
return (
|
||||
<Col key={index} md='4'>
|
||||
<Card>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=genreSimilarity"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.snippet.title}<br />
|
||||
{item.snippet.channelTitle}<br />
|
||||
<span>Reccomender: similarityArtist</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</React.Fragment>);
|
||||
}else {
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: `/video/${item.id.videoId}`,
|
||||
search: '?ref=genreSimilarity'
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3 img-fluid"
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.snippet.title}</h5>
|
||||
<p> {item.snippet.channelTitle} - {ISO_8601parse(item.snippet.publishedAt)}</p>
|
||||
<p>Reccomender: genreSimilarity</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}}
|
||||
}
|
||||
|
||||
export default genreSimilarity;
|
||||
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Col, ListGroup, Card, CardDeck } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import { Col, Media, Card } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import axios from 'axios'; // eslint-disable-line no-unused-vars
|
||||
import { Link } from 'react-router-dom'; // eslint-disable-line no-unused-vars
|
||||
import moment from "moment";
|
||||
var _ = require('lodash');
|
||||
|
||||
class popGlobaleAssoluta extends React.Component {
|
||||
state = {
|
||||
@@ -13,70 +14,54 @@ class popGlobaleAssoluta extends React.Component {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
// listSiti.map(
|
||||
// sito =>
|
||||
// axios.get(`http://site${sito}.tw.cs.unibo.it/globpop`, {
|
||||
// 'params': {
|
||||
// 'id': this.props.match.params.id
|
||||
// }
|
||||
// })
|
||||
// )
|
||||
|
||||
|
||||
// let listSiti = ['1828', '1829', '1838', '1839', '1846', '1822', '1847', '1831', '1827', '1848', '1824', '1830', '1836', '1850', '1849', '1851', '1861', '1823', '1863', '1834', '1904', '1906', '1901', '1862', '1859'];
|
||||
let listSiti = ['1828', '1838', '1839', '1846', '1847', '1831', '1827', '1849', '1823', '1863', '1834', '1901', '1859'];
|
||||
let axiosReq = [];
|
||||
for(let i=0; i<listSiti.length; i++){
|
||||
console.log(`http://site${listSiti[i]}.tw.cs.unibo.it/globpop`)
|
||||
axiosReq.push(axios.get(`http://site${listSiti[i]}.tw.cs.unibo.it/globpop`, {
|
||||
'params': {
|
||||
'id': this.props.match.params.id
|
||||
}
|
||||
}))
|
||||
}
|
||||
Promise.all(axiosReq)
|
||||
.then(axios.spread((...res) => {
|
||||
console.log(res.map(x=>x.data))
|
||||
})
|
||||
)
|
||||
}
|
||||
// let listSiti = ['1828', '1829', '1838', '1839', '1846', '1822', '1847', '1831', '1827', '1848', '1824', '1830', '1836', '1850', '1849', '1851', '1861', '1823', '1863', '1834', '1904', '1906', '1901', '1862', '1859', '1841', '1905', '1864', '1840', '1860', '1858', '1835', '1911', '1913', '1826', '1855', '1907', '1912', '1903', '1915', '1854', '1910'];
|
||||
let listSiti = ['1828', '1838','1839', '1846', '1831', '1827', '1823', '1863', '1834', '1901'];//, '1859', '1841', '1905', '1864', '1860', '1858', '1913', '1855', '1912', '1915', '1854', '1910'];
|
||||
Promise.all(
|
||||
listSiti.map(
|
||||
el => fetch(`http://site${el}.tw.cs.unibo.it/globpop?id=${this.props.match.params.id}`)
|
||||
.then(res =>
|
||||
res.json()
|
||||
)
|
||||
)
|
||||
).then(res => {
|
||||
/* do something with res here... */
|
||||
console.log(res)
|
||||
let tmp = res.map(x => x.recommended);
|
||||
//let tmp2 =tmp.filter(el=>el.length > 0).map(el => el.map(el1 => el1.videoID || el1.videoId) )
|
||||
console.log(...tmp)
|
||||
this.getThumbnailsNames(tmp);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
// METODI
|
||||
getThumbnailsNames(reccomended) {
|
||||
let idToLookFor = reccomended.map(item => item.videoID);
|
||||
console.log(reccomended)
|
||||
let tmp2 =reccomended.filter(el=>el.length > 0).map(el => el.map(el1 => el1.videoID || el1.videoId) )
|
||||
let idToLookFor =[].concat(...tmp2);
|
||||
idToLookFor.filter(el=>el.videoID !== undefined || el.videoId !== undefined)
|
||||
axios.get('https://www.googleapis.com/youtube/v3/videos', {
|
||||
params: {
|
||||
part: 'snippet',
|
||||
id: idToLookFor.toString(),
|
||||
id: _.uniq(idToLookFor).slice(0,50).toString(),
|
||||
key: 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig',
|
||||
fields: 'items(id,snippet/thumbnails/medium,snippet/title)'
|
||||
fields: 'items(id,snippet/thumbnails/high,snippet/title)'
|
||||
}
|
||||
})
|
||||
|
||||
.then(
|
||||
res1 => {
|
||||
res1.data.items.map(resCurrentValue => {
|
||||
Object.defineProperties(
|
||||
reccomended.find(videoItem => {
|
||||
return videoItem.videoID === resCurrentValue.id;
|
||||
}),
|
||||
{
|
||||
'thumbnail':
|
||||
{ value: resCurrentValue.snippet.thumbnails.medium.url },
|
||||
'name':
|
||||
{ value: resCurrentValue.snippet.title }
|
||||
});
|
||||
});
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
items: reccomended
|
||||
items: res1.data.items,
|
||||
isLoaded: true,
|
||||
});
|
||||
console.log(res1)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { error, isLoaded, items, headers } = this.state;
|
||||
const { error, isLoaded, items } = this.state;
|
||||
if (error) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
@@ -91,7 +76,7 @@ class popGlobaleAssoluta extends React.Component {
|
||||
</Col>
|
||||
</React.Fragment>
|
||||
);
|
||||
} else {
|
||||
} else { if (window.innerWidth < 992){
|
||||
return (
|
||||
<React.Fragment>
|
||||
{items.map(item => (<Col md="4">
|
||||
@@ -99,16 +84,18 @@ class popGlobaleAssoluta extends React.Component {
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.videoID,
|
||||
search: "?ref=popGlobaleAssoluta"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
<Card.Img
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br />
|
||||
{item.lastSelected}
|
||||
{item.snippet.title}<br />
|
||||
{item.snippet.channelTitle}<br />
|
||||
<span>Reccomender: popGlobaleAssoluta</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
@@ -117,7 +104,34 @@ class popGlobaleAssoluta extends React.Component {
|
||||
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}else {
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.videoID}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: `/video/${item.videoID}`,
|
||||
search: '?ref=popGlobaleAssoluta'
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3 img-fluid"
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.snippet.title}</h5>
|
||||
<p> {item.snippet.channelTitle}</p>
|
||||
<p>Reccomender: popGlobaleAssoluta</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import React from 'react';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Col, Media, Card } from 'react-bootstrap';
|
||||
|
||||
class popLocaleAss extends React.Component {
|
||||
|
||||
state = {
|
||||
isLoaded: false,
|
||||
error: null,
|
||||
res: null
|
||||
}
|
||||
|
||||
// static getDerivedStateFromProps(nextProps, prevState) {
|
||||
|
||||
// }
|
||||
|
||||
componentDidMount() {
|
||||
axios
|
||||
.get('http://site1854.tw.cs.unibo.it/videotrack')
|
||||
.then(res => {
|
||||
this.getThumbnailsNames(res.data.sort((a, b) => a.timesWatched - b.timesWatched).reverse());
|
||||
}
|
||||
, error => this.setState({ error }))
|
||||
}
|
||||
|
||||
// shouldComponentUpdate(nextProps, nextState) {
|
||||
|
||||
// }
|
||||
|
||||
// componentDidUpdate(prevProps, prevState) {
|
||||
// if (prevProps.match.params !== this.props.match.params) {
|
||||
// this.setState({ isLoaded: false })
|
||||
// }
|
||||
// }
|
||||
|
||||
// componentWillUnmount() {
|
||||
|
||||
// }
|
||||
|
||||
getThumbnailsNames(reccomended) {
|
||||
let idToLookFor = reccomended.map(item => item.id);
|
||||
axios.get('https://www.googleapis.com/youtube/v3/videos', {
|
||||
params: {
|
||||
part: 'snippet',
|
||||
id: idToLookFor.toString(),
|
||||
key: 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig',
|
||||
fields: 'items(id,snippet/thumbnails/medium,snippet/title,snippet/description)'
|
||||
}
|
||||
})
|
||||
|
||||
.then(
|
||||
res1 => {
|
||||
res1.data.items.map(resCurrentValue =>
|
||||
Object.defineProperties(
|
||||
reccomended.find(videoItem => {
|
||||
return videoItem.id === resCurrentValue.id;
|
||||
}),
|
||||
{
|
||||
'thumbnail':
|
||||
{ value: resCurrentValue.snippet.thumbnails.medium.url },
|
||||
'name':
|
||||
{ value: resCurrentValue.snippet.title },
|
||||
'description':
|
||||
{ value: resCurrentValue.snippet.description }
|
||||
})
|
||||
);
|
||||
this.setState({
|
||||
isLoaded: true,
|
||||
items: reccomended
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return <React.Fragment>{this.state.error.message} -- {this.state.error.response.data.error.errors[0].reason} </React.Fragment>;
|
||||
} else if (!this.state.isLoaded) {
|
||||
return <Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>;
|
||||
} else {
|
||||
if (window.innerWidth > 992){
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
search: "?ref=popLocaleAss"
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3"
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.name}</h5>
|
||||
<p>{item.description.substring(0, 200)}</p>
|
||||
<p>Visto: {item.timesWatched} volt{item.timesWatched === 1 ?"a":"e"} </p>
|
||||
<p> Reccomender: popLocaleAss </p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}else {return (<React.Fragment>
|
||||
{this.state.items.map(function (item, index) {
|
||||
return (
|
||||
<Col key={index} md='4'>
|
||||
<Card>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
search: "?ref=popLocaleAss"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br />
|
||||
<span>Visto: {item.timesWatched} volt{item.timesWatched === 1 ?"a":"e"} </span><br />
|
||||
<span> Reccomender: popLocaleAss </span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</React.Fragment>);
|
||||
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
export default popLocaleAss;
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Col, ListGroup, Card, CardDeck } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import { Col, Card, Media } from 'react-bootstrap'; // eslint-disable-line no-unused-vars
|
||||
import axios from 'axios'; // eslint-disable-line no-unused-vars
|
||||
import { Link } from 'react-router-dom'; // eslint-disable-line no-unused-vars
|
||||
/*eslint no-console: ["error", { allow: ["warn", "error", "info"] }] */
|
||||
@@ -18,16 +18,20 @@ class PopRelLoc extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let tmp = JSON.parse(localStorage.getItem('lastWatched'));
|
||||
let j=tmp.findIndex(el=>el.id === localStorage["lastId"]);
|
||||
//this.getThumbnailsNames(tmp[j].prevVideos);
|
||||
if (tmp.length === 0 || localStorage["prevId"] === '1')
|
||||
{this.getThumbnailsNames(JSON.parse(localStorage.getItem('first')))}
|
||||
else
|
||||
{this.getThumbnailsNames(tmp[j].prevVideos)}
|
||||
|
||||
axios.get("http://site1854.tw.cs.unibo.it/videotrack",{
|
||||
params: {
|
||||
"prevId" : localStorage['lastId']
|
||||
}
|
||||
}).then(res=>{
|
||||
this.getThumbnailsNames(res.data)
|
||||
this.setState({
|
||||
items : res.data
|
||||
})
|
||||
},
|
||||
error=>console.error(error))
|
||||
|
||||
}
|
||||
|
||||
|
||||
// METODI
|
||||
getThumbnailsNames(listVideo) {
|
||||
let idToLookFor = listVideo.map(item => item.id);
|
||||
@@ -80,33 +84,63 @@ class PopRelLoc extends React.Component {
|
||||
</React.Fragment>
|
||||
);
|
||||
} else {
|
||||
if (window.innerWidth < 992) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{items.map(item => (
|
||||
<Col md="4">
|
||||
<Card key={item.id}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br />
|
||||
{item.lastSelected}
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
<Col md="4">
|
||||
<Card key={item.id}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
search: "?ref=popRelLoc"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.name}<br />
|
||||
<span>Visto: {item.timesWatched} volt{item.timesWatched === 1 ?"a":"e"} </span><br />
|
||||
<span> Reccomender: popRelLoc </span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
|
||||
</Col>))}
|
||||
|
||||
</Col>))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}else{
|
||||
return (
|
||||
<ul className="list-unstyled">{
|
||||
this.state.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: '/video/' + item.id,
|
||||
search: "?ref=popRelLoc"
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3"
|
||||
src={item.thumbnail}
|
||||
alt={'Thumbnail of ' + item.name}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.name}</h5>
|
||||
<p>Visto: {item.timesWatched} volt{item.timesWatched === 1 ?"a":"e"} </p>
|
||||
<p> Reccomender: popRelLoc </p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
);
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import React from 'react';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Col, Media, Card } from 'react-bootstrap';
|
||||
|
||||
class similarityArtist extends React.Component {
|
||||
|
||||
state = {
|
||||
isLoaded: false,
|
||||
error: null,
|
||||
res: null
|
||||
}
|
||||
|
||||
// static getDerivedStateFromProps(nextProps, prevState) {
|
||||
|
||||
// }
|
||||
|
||||
componentDidMount() {
|
||||
let timerId1;
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
timerId1 = window.setInterval(() => {
|
||||
if (localStorage['lastId'] === JSON.parse(localStorage['currentVideoInfo']).id)
|
||||
resolve(true)
|
||||
}, 1000)
|
||||
})
|
||||
promise.then(() => {
|
||||
window.clearInterval(timerId1);
|
||||
this.setState({ artist: JSON.parse(localStorage['currentVideoInfo']).artist })
|
||||
axios.get('https://www.googleapis.com/youtube/v3/search', {
|
||||
params: {
|
||||
'part': 'snippet',
|
||||
'q': JSON.parse(localStorage['currentVideoInfo']).artist,
|
||||
'videoEmbeddable': 'true',
|
||||
'type': 'video',
|
||||
'maxResults': 15,
|
||||
'topicId': '/m/04rlf, /m/02jjt',
|
||||
'key': 'AIzaSyA21Odw9UdfiOJnxvA_eDfOW0OxuUfHKig'
|
||||
}
|
||||
}).then(
|
||||
res => {
|
||||
let j = res.data.items.findIndex(el => el.id.videoId === localStorage['lastId'])
|
||||
if (j >= 0)
|
||||
res.data.items.splice(j, 1);
|
||||
this.setState({
|
||||
res: res.data,
|
||||
isLoaded: true
|
||||
})
|
||||
console.log(res);
|
||||
}
|
||||
|
||||
,
|
||||
|
||||
error => this.setState({
|
||||
error
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// shouldComponentUpdate(nextProps, nextState) {
|
||||
|
||||
// }
|
||||
|
||||
// componentDidUpdate(prevProps, prevState) {
|
||||
// if (prevProps.match.params !== this.props.match.params) {
|
||||
// this.setState({ isLoaded: false })
|
||||
// }
|
||||
// }
|
||||
|
||||
// componentWillUnmount() {
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return <React.Fragment>{this.state.error.message} -- {this.state.error.response.data.error.errors[0].reason} </React.Fragment>;
|
||||
} else if (!this.state.isLoaded) {
|
||||
return <Col className="text-center">
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</Col>;
|
||||
} else {
|
||||
if (window.innerWidth > 992) {
|
||||
return (
|
||||
<>
|
||||
<h4>Artist Similarity: {this.state.artist}</h4>
|
||||
<ul className="list-unstyled">{
|
||||
this.state.res.items.map(item => (
|
||||
<Link
|
||||
key={item.id.videoId}
|
||||
as="li" className="media mx-5 my-1 suggItem"
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=similarityArtist"
|
||||
}}>
|
||||
<img
|
||||
width={240}
|
||||
height={120}
|
||||
className="align-self-center mr-3"
|
||||
src={item.snippet.thumbnails.medium.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Media.Body>
|
||||
<h5>{item.snippet.title}</h5>
|
||||
<p>{item.snippet.description}</p>
|
||||
<p>Reccomender: similarityArtist</p>
|
||||
</Media.Body>
|
||||
</Link>
|
||||
))
|
||||
}</ul>
|
||||
</>
|
||||
);
|
||||
}else{
|
||||
return (<React.Fragment>
|
||||
{this.state.res.items.map(function (item, index) {
|
||||
return (
|
||||
<Col key={index} md='4'>
|
||||
<Card>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/video/' + item.id.videoId,
|
||||
search: "?ref=similarityArtist"
|
||||
}}
|
||||
>
|
||||
<Card.Img
|
||||
src={item.snippet.thumbnails.high.url}
|
||||
alt={'Thumbnail of ' + item.snippet.title}
|
||||
/>
|
||||
<Card.ImgOverlay>
|
||||
<Card.Title className="bg-dark d-inline text-white">
|
||||
{item.snippet.title}<br />
|
||||
{item.snippet.channelTitle}<br />
|
||||
<span>Reccomender: similarityArtist</span>
|
||||
</Card.Title>
|
||||
</Card.ImgOverlay>
|
||||
</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</React.Fragment>);
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
export default similarityArtist;
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export default function register() {
|
||||
@@ -30,7 +30,7 @@ export default function register() {
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL?process.env.PUBLIC_URL:'http://localhost:8000'}/service-worker.js`;
|
||||
const swUrl = `${process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'http://localhost:8000'}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Lets check if a service worker still exists or not.
|
||||
@@ -41,7 +41,7 @@ export default function register() {
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
||||
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user