Skip to content

Commit 439b51c

Browse files
committed
Full features implementation
1 parent 3d0f999 commit 439b51c

File tree

11 files changed

+310
-40
lines changed

11 files changed

+310
-40
lines changed
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 3.2.7 on 2021-10-01 01:32
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('api', '0002_alter_room_code'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='room',
15+
name='current_song',
16+
field=models.CharField(max_length=50, null=True),
17+
),
18+
migrations.AddField(
19+
model_name='room',
20+
name='votes',
21+
field=models.IntegerField(default=0),
22+
),
23+
]

api/models.py

+2
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ class Room(models.Model):
1818
guest_can_pause = models.BooleanField(null=False, default=False)
1919
votes_to_skip = models.IntegerField(null=False, default=1)
2020
created_at = models.DateTimeField(auto_now_add=True)
21+
votes = models.IntegerField(default=0)
22+
current_song = models.CharField(max_length=50, null=True)

api/views.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from rest_framework.response import Response
55
from django.http import JsonResponse
66
from .models import Room
7+
from spotify.utils import skip_song
78

89

910
bad_header = 'Bad Request'
@@ -88,7 +89,7 @@ def post(self, request):
8889
self.request.session.pop('room_code')
8990
host_id = self.request.session.session_key
9091
room_results = Room.objects.filter(host=host_id)
91-
if len(room_results) > 0:
92+
if room_results.exists():
9293
room = room_results[0]
9394
room.delete()
9495
return Response({'message': 'Sucess'}, status=status.HTTP_200_OK)
@@ -115,6 +116,8 @@ def patch(self, request):
115116
room.guest_can_pause = guest_can_pause
116117
room.votes_to_skip = votes_to_skip
117118
room.save(update_fields=['guest_can_pause', 'votes_to_skip'])
119+
if room.votes >= votes_to_skip:
120+
skip_song(room.host)
118121
return Response(RoomSerializer(room).data, status=status.HTTP_200_OK)
119122
return Response({bad_header: "Invalid Data"}, status=status.HTTP_400_BAD_REQUEST)
120123

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React, { Component } from 'react';
2+
import { Grid, Typography, Card, IconButton, LinearProgress } from '@material-ui/core';
3+
import PlayArrowIcon from '@material-ui/icons/PlayArrow'
4+
import PauseIcon from '@material-ui/icons/Pause'
5+
import SkipNextIcon from '@material-ui/icons/SkipNext'
6+
7+
8+
export default class MusicPlayer extends Component{
9+
constructor(props) {
10+
super(props);
11+
}
12+
pauseSong() {
13+
const requestOptions = {
14+
method: 'PUT',
15+
headers: {"Content-Type": "application/json"}
16+
};
17+
fetch("/spotify/pause/", requestOptions);
18+
}
19+
playSong() {
20+
const requestOptions = {
21+
method: 'PUT',
22+
headers: {"Content-Type": "application/json"}
23+
};
24+
fetch("/spotify/play/", requestOptions);
25+
}
26+
skipSong() {
27+
const requestOptions = {
28+
method: "POST",
29+
headers: {"Content-Type": "application/json"}
30+
};
31+
fetch("/spotify/skip/", requestOptions)
32+
}
33+
render() {
34+
let songProgress = (this.props.time / this.props.duration) * 100;
35+
return (
36+
<Card>
37+
<Grid container alignItems="center">
38+
<Grid item align="center" xs={4}>
39+
<img src={this.props.image_url} height="100%" width="100%"/>
40+
</Grid>
41+
<Grid item align="center" xs={8}>
42+
<Typography component="h5" variant="h5">
43+
{this.props.title}
44+
</Typography>
45+
<Typography color="TextSecondary" variant="subtitle1">
46+
{this.props.artist}
47+
</Typography>
48+
<div>
49+
<IconButton onClick={ () => {this.props.is_playing ? this.pauseSong() : this.playSong();}}>
50+
{this.props.is_playing ? <PauseIcon/> : <PlayArrowIcon/>}
51+
</IconButton>
52+
<IconButton onClick={ () => {this.skipSong()}}>
53+
<SkipNextIcon/>
54+
</IconButton>
55+
<Typography color="TextSecondary" variant="subtitle1">
56+
{this.props.votes} / {this.props.votes_required}
57+
</Typography>
58+
</div>
59+
</Grid>
60+
</Grid>
61+
<LinearProgress variant="determinate" value={songProgress}/>
62+
</Card>
63+
)
64+
}
65+
}

frontend/src/components/Room.js

+28-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { Component } from 'react';
22
import { Grid, Button, Typography } from '@material-ui/core';
33
import CreateRoomPage from "./CreateRoomPage";
4+
import MusicPlayer from "./MusicPlayer";
5+
46

57
export default class Room extends Component {
68
constructor(props) {
@@ -11,6 +13,7 @@ export default class Room extends Component {
1113
is_host: false,
1214
show_setting: false,
1315
spotify_authenticated: false,
16+
song: {},
1417
};
1518
this.RoomCode = this.props.match.params.RoomCode;
1619
this.getRoomDetails();
@@ -20,7 +23,15 @@ export default class Room extends Component {
2023
this.renderSettingsButton = this.renderSettingsButton.bind(this);
2124
this.getRoomDetails = this.getRoomDetails.bind(this);
2225
this.authenticateSpotify = this.authenticateSpotify.bind(this);
23-
this.getRoomDetails();
26+
this.getCurrentSong = this.getCurrentSong.bind(this);
27+
}
28+
29+
componentDidMount() {
30+
this.interval = setInterval(this.getCurrentSong, 1000)
31+
}
32+
33+
componentWillUnmount() {
34+
clearInterval(this.interval)
2435
}
2536

2637
getRoomDetails() {
@@ -38,25 +49,35 @@ export default class Room extends Component {
3849
is_host: data.is_host
3950
});
4051
if (this.state.is_host) {
41-
console.log('getRoomDetails')
4252
this.authenticateSpotify();
4353
}
4454
});
4555
}
4656
authenticateSpotify() {
47-
console.log('authenticateSpotify')
4857
fetch('/spotify/is-authenticated').then((_response) => _response.json()).then((data) => {
4958
this.setState({ spotifyAuthenticated: data.status });
50-
console.log(data.status);
5159
if (!data.status) {
5260
fetch('/spotify/get-auth-url')
5361
.then((response) => response.json())
54-
.then((data) => {
55-
window.location.replace(data.url);
62+
.then((_data) => {
63+
window.location.replace(_data.url);
5664
})
5765
}
5866
});
5967
}
68+
getCurrentSong() {
69+
fetch('/spotify/current-song')
70+
.then((response) => {
71+
if (!response.ok) {
72+
return {};
73+
} else {
74+
return response.json();
75+
}
76+
}).then((data) => {
77+
this.setState({song: data});
78+
console.log(data)
79+
})
80+
}
6081
leaveButtonPressed() {
6182
const requestOptions = {
6283
method: "POST",
@@ -115,21 +136,7 @@ export default class Room extends Component {
115136
Code: {this.RoomCode}
116137
</Typography>
117138
</Grid>
118-
<Grid item xs={12} align="center">
119-
<Typography variant="h6" component="h6">
120-
Votes: {this.state.votes_to_skip}
121-
</Typography>
122-
</Grid>
123-
<Grid item xs={12} align="center">
124-
<Typography variant="h6" component="h6">
125-
Guest can pause: {this.state.guest_can_pause.toString()}
126-
</Typography>
127-
</Grid>
128-
<Grid item xs={12} align="center">
129-
<Typography variant="h6" component="h6">
130-
Host: {this.state.is_host.toString()}
131-
</Typography>
132-
</Grid>
139+
<MusicPlayer {...this.state.song}/>
133140
{this.state.is_host ? this.renderSettingsButton() : null}
134141
<Grid item xs={12} align="center">
135142
<Button variant="contained" color="secondary" onClick={this.leaveButtonPressed}>

frontend/static/frontend/main.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/static/frontend/main.js.LICENSE.txt

+56
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
!*** ../node_modules/react/index.js ***!
1919
\**************************************/
2020

21+
/*!***************************************!*\
22+
!*** ./src/components/MusicPlayer.js ***!
23+
\***************************************/
24+
2125
/*!****************************************!*\
2226
!*** ../node_modules/isarray/index.js ***!
2327
\****************************************/
@@ -74,6 +78,10 @@
7478
!*** ../node_modules/path-to-regexp/index.js ***!
7579
\***********************************************/
7680

81+
/*!***************************************************!*\
82+
!*** ../node_modules/@material-ui/icons/Pause.js ***!
83+
\***************************************************/
84+
7785
/*!****************************************************!*\
7886
!*** ../node_modules/is-in-browser/dist/module.js ***!
7987
\****************************************************/
@@ -82,10 +90,22 @@
8290
!*** ../node_modules/hyphenate-style-name/index.js ***!
8391
\*****************************************************/
8492

93+
/*!******************************************************!*\
94+
!*** ../node_modules/@material-ui/icons/SkipNext.js ***!
95+
\******************************************************/
96+
8597
/*!******************************************************!*\
8698
!*** ../node_modules/value-equal/esm/value-equal.js ***!
8799
\******************************************************/
88100

101+
/*!*******************************************************!*\
102+
!*** ../node_modules/@material-ui/icons/PlayArrow.js ***!
103+
\*******************************************************/
104+
105+
/*!********************************************************!*\
106+
!*** ../node_modules/@babel/runtime/helpers/typeof.js ***!
107+
\********************************************************/
108+
89109
/*!********************************************************!*\
90110
!*** ../node_modules/@material-ui/system/esm/merge.js ***!
91111
\********************************************************/
@@ -102,6 +122,10 @@
102122
!*** ../node_modules/react/cjs/react.production.min.js ***!
103123
\*********************************************************/
104124

125+
/*!**********************************************************!*\
126+
!*** ../node_modules/@material-ui/core/esm/Card/Card.js ***!
127+
\**********************************************************/
128+
105129
/*!**********************************************************!*\
106130
!*** ../node_modules/@material-ui/core/esm/Grid/Grid.js ***!
107131
\**********************************************************/
@@ -170,6 +194,10 @@
170194
!*** ../node_modules/@material-ui/core/esm/colors/pink.js ***!
171195
\************************************************************/
172196

197+
/*!************************************************************!*\
198+
!*** ../node_modules/@material-ui/core/esm/utils/index.js ***!
199+
\************************************************************/
200+
173201
/*!************************************************************!*\
174202
!*** ../node_modules/react-transition-group/esm/config.js ***!
175203
\************************************************************/
@@ -302,6 +330,10 @@
302330
!*** ../node_modules/@material-ui/core/esm/utils/useForkRef.js ***!
303331
\*****************************************************************/
304332

333+
/*!*****************************************************************!*\
334+
!*** ../node_modules/@material-ui/icons/utils/createSvgIcon.js ***!
335+
\*****************************************************************/
336+
305337
/*!*****************************************************************!*\
306338
!*** ../node_modules/react-dom/cjs/react-dom.production.min.js ***!
307339
\*****************************************************************/
@@ -490,6 +522,10 @@
490522
!*** ../node_modules/@material-ui/core/esm/Typography/Typography.js ***!
491523
\**********************************************************************/
492524

525+
/*!**********************************************************************!*\
526+
!*** ../node_modules/@material-ui/core/esm/utils/unsupportedProp.js ***!
527+
\**********************************************************************/
528+
493529
/*!**********************************************************************!*\
494530
!*** ../node_modules/@material-ui/styles/esm/jssPreset/jssPreset.js ***!
495531
\**********************************************************************/
@@ -506,6 +542,10 @@
506542
!*** ../node_modules/@babel/runtime/helpers/esm/toConsumableArray.js ***!
507543
\***********************************************************************/
508544

545+
/*!***********************************************************************!*\
546+
!*** ../node_modules/@babel/runtime/helpers/interopRequireDefault.js ***!
547+
\***********************************************************************/
548+
509549
/*!***********************************************************************!*\
510550
!*** ../node_modules/@material-ui/core/esm/ButtonBase/TouchRipple.js ***!
511551
\***********************************************************************/
@@ -538,6 +578,10 @@
538578
!*** ./node_modules/@material-ui/lab/esm/internal/svg-icons/Close.js ***!
539579
\***********************************************************************/
540580

581+
/*!************************************************************************!*\
582+
!*** ../node_modules/@babel/runtime/helpers/interopRequireWildcard.js ***!
583+
\************************************************************************/
584+
541585
/*!************************************************************************!*\
542586
!*** ../node_modules/@material-ui/core/esm/ButtonGroup/ButtonGroup.js ***!
543587
\************************************************************************/
@@ -586,6 +630,14 @@
586630
!*** ../node_modules/@material-ui/core/esm/styles/createBreakpoints.js ***!
587631
\*************************************************************************/
588632

633+
/*!*************************************************************************!*\
634+
!*** ../node_modules/@material-ui/core/esm/utils/deprecatedPropType.js ***!
635+
\*************************************************************************/
636+
637+
/*!*************************************************************************!*\
638+
!*** ../node_modules/@material-ui/core/esm/utils/requirePropFactory.js ***!
639+
\*************************************************************************/
640+
589641
/*!**************************************************************************!*\
590642
!*** ../node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js ***!
591643
\**************************************************************************/
@@ -654,6 +706,10 @@
654706
!*** ../node_modules/@material-ui/core/esm/FormHelperText/FormHelperText.js ***!
655707
\******************************************************************************/
656708

709+
/*!******************************************************************************!*\
710+
!*** ../node_modules/@material-ui/core/esm/LinearProgress/LinearProgress.js ***!
711+
\******************************************************************************/
712+
657713
/*!******************************************************************************!*\
658714
!*** ../node_modules/@material-ui/styles/esm/getThemeProps/getThemeProps.js ***!
659715
\******************************************************************************/

spotify/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ class SpotifyToken(models.Model):
55
user = models.CharField(max_length=50, unique=True)
66
created_at = models.DateTimeField(auto_now_add=True)
77
refresh_token = models.CharField(max_length=150)
8-
acces_token = models.CharField(max_length=150)
8+
access_token = models.CharField(max_length=150)
99
expires_in = models.DateTimeField()
1010
token_type = models.CharField(max_length=50)

spotify/urls.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from django.urls import path
2-
from .views import AuthURL, spotify_callback, IsAuthenticated
2+
from .views import AuthURL, spotify_callback, IsAuthenticated, CurrentSong, PauseSong, PlaySong, SkipSong
33

44
urlpatterns = [
55
path('get-auth-url/', AuthURL.as_view()),
66
path('redirect/', spotify_callback),
77
path('is-authenticated/', IsAuthenticated.as_view()),
8+
path('current-song/', CurrentSong.as_view()),
9+
path('pause/', PauseSong.as_view()),
10+
path('play/', PlaySong.as_view()),
11+
path('skip/', SkipSong.as_view()),
812
]

0 commit comments

Comments
 (0)