Playlist and album views
This commit is contained in:
@ -2919,18 +2919,29 @@ main h1 {
|
|||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main h2 {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
main h3 {
|
main h3 {
|
||||||
|
font-weight: 100;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main h4 {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
main h3.underline {
|
main h4.underline {
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
border-bottom: 1px solid #000000;
|
border-bottom: 1px solid #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
main h3:not(:first-child) {
|
main h4:not(:first-child) {
|
||||||
padding-top: 40px;
|
padding-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3665,7 +3676,7 @@ main header h1 {
|
|||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
background: #DDDDDD;
|
background: #EEEEEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-view .intro .thumbnail {
|
.album-view .intro .thumbnail {
|
||||||
@ -3673,12 +3684,132 @@ main header h1 {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-view .intro h1 {
|
.album-view .intro .details {
|
||||||
padding-top: 30px;
|
padding: 30px;
|
||||||
|
color: #AAAAAA;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .intro .artist-grid {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .intro .artist-grid .grid-item {
|
||||||
|
margin: 0;
|
||||||
|
width: 50%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .intro .artist-grid .grid-item .thumbnail .image {
|
||||||
|
background-color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .intro .artist-grid .grid-item .name {
|
||||||
|
-webkit-transition: all 0.2s ease-in-out;
|
||||||
|
-moz-transition: all 0.2s ease-in-out;
|
||||||
|
-o-transition: all 0.2s ease-in-out;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
position: absolute;
|
||||||
|
top: 35%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 2;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .intro .artist-grid .grid-item:hover .name {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-view .main {
|
.album-view .main {
|
||||||
padding-left: 300px;
|
padding-left: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.album-view .main .title {
|
||||||
|
padding: 30px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .main .title h3 {
|
||||||
|
color: #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-view .main .title h3 a:hover {
|
||||||
|
color: #777777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 300px;
|
||||||
|
background: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .thumbnail {
|
||||||
|
float: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .details {
|
||||||
|
padding: 30px;
|
||||||
|
color: #AAAAAA;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .artist-grid {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .artist-grid .grid-item {
|
||||||
|
margin: 0;
|
||||||
|
width: 50%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .artist-grid .grid-item .thumbnail .image {
|
||||||
|
background-color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .artist-grid .grid-item .name {
|
||||||
|
-webkit-transition: all 0.2s ease-in-out;
|
||||||
|
-moz-transition: all 0.2s ease-in-out;
|
||||||
|
-o-transition: all 0.2s ease-in-out;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
position: absolute;
|
||||||
|
top: 35%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 2;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .intro .artist-grid .grid-item:hover .name {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .main {
|
||||||
|
padding-left: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .main .title {
|
||||||
|
padding: 30px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .main .title h3 {
|
||||||
|
color: #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-view .main .title h3 a:hover {
|
||||||
|
color: #777777;
|
||||||
|
}
|
||||||
|
|
||||||
/*# sourceMappingURL=app.css.map*/
|
/*# sourceMappingURL=app.css.map*/
|
||||||
File diff suppressed because one or more lines are too long
@ -5958,6 +5958,13 @@
|
|||||||
_reactRouter.browserHistory.push(this.props.link);
|
_reactRouter.browserHistory.push(this.props.link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'renderThumbnail',
|
||||||
|
value: function renderThumbnail() {
|
||||||
|
if (this.props.item.images) return _react2.default.createElement(_Thumbnail2.default, { size: 'medium', images: this.props.item.images });
|
||||||
|
if (this.props.item.icons) return _react2.default.createElement(_Thumbnail2.default, { size: 'medium', images: this.props.item.icons });
|
||||||
|
return _react2.default.createElement(_Thumbnail2.default, { size: 'medium', images: [] });
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'render',
|
key: 'render',
|
||||||
value: function render() {
|
value: function render() {
|
||||||
@ -5973,8 +5980,7 @@
|
|||||||
{ className: 'grid-item', onClick: function onClick(e) {
|
{ className: 'grid-item', onClick: function onClick(e) {
|
||||||
return _this2.handleClick(e);
|
return _this2.handleClick(e);
|
||||||
} },
|
} },
|
||||||
item.images ? _react2.default.createElement(_Thumbnail2.default, { size: 'medium', images: item.images }) : null,
|
this.renderThumbnail(),
|
||||||
item.icons ? _react2.default.createElement(_Thumbnail2.default, { size: 'medium', images: item.icons }) : null,
|
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'name' },
|
{ className: 'name' },
|
||||||
@ -7514,9 +7520,15 @@
|
|||||||
'div',
|
'div',
|
||||||
{ className: className },
|
{ className: className },
|
||||||
this.props.albums.map(function (album, index) {
|
this.props.albums.map(function (album, index) {
|
||||||
var link = album.uri;
|
|
||||||
if (album.album) link = album.album.uri;
|
// handle nested album objects (as in Album Library)
|
||||||
return _react2.default.createElement(_GridItem2.default, { item: album, key: index, link: '/album/' + link });
|
if (album.album) {
|
||||||
|
var flatAlbum = album.album;
|
||||||
|
flatAlbum.added_at = album.added_at;
|
||||||
|
album = flatAlbum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _react2.default.createElement(_GridItem2.default, { item: album, key: index, link: '/album/' + album.uri });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -10581,7 +10593,7 @@
|
|||||||
/* 95 */
|
/* 95 */
|
||||||
/***/ function(module, exports, __webpack_require__) {
|
/***/ function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
var __WEBPACK_AMD_DEFINE_RESULT__;var require;/* WEBPACK VAR INJECTION */(function(process) {/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
var require;var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(process) {/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
||||||
/** @author Brian Cavalier */
|
/** @author Brian Cavalier */
|
||||||
/** @author John Hann */
|
/** @author John Hann */
|
||||||
|
|
||||||
@ -11288,6 +11300,10 @@
|
|||||||
|
|
||||||
var _AlbumLink2 = _interopRequireDefault(_AlbumLink);
|
var _AlbumLink2 = _interopRequireDefault(_AlbumLink);
|
||||||
|
|
||||||
|
var _Dater = __webpack_require__(379);
|
||||||
|
|
||||||
|
var _Dater2 = _interopRequireDefault(_Dater);
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
@ -11329,36 +11345,16 @@
|
|||||||
// notify our tracklist
|
// notify our tracklist
|
||||||
this.props.handleContextMenu(e);
|
this.props.handleContextMenu(e);
|
||||||
}
|
}
|
||||||
}, {
|
|
||||||
key: 'formatDuration',
|
|
||||||
value: function formatDuration() {
|
|
||||||
if (typeof this.props.track.duration_ms !== 'undefined') {
|
|
||||||
var ms = this.props.track.duration_ms;
|
|
||||||
} else if (typeof this.props.track.length !== 'undefined') {
|
|
||||||
var ms = this.props.track.length;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var time = new Date(ms);
|
|
||||||
var min = time.getMinutes();
|
|
||||||
var sec = time.getSeconds();
|
|
||||||
if (sec < 10) sec = '0' + sec;
|
|
||||||
return min + ':' + sec;
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
key: 'render',
|
key: 'render',
|
||||||
value: function render() {
|
value: function render() {
|
||||||
var _this2 = this;
|
var _this2 = this;
|
||||||
|
|
||||||
var className = 'list-item track';
|
var track = this.props.track;
|
||||||
if (typeof this.props.track.selected !== 'undefined' && this.props.track.selected) {
|
|
||||||
className += ' selected';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.track.playing) {
|
var className = 'list-item track';
|
||||||
className += ' playing';
|
if (typeof track.selected !== 'undefined' && track.selected) className += ' selected';
|
||||||
}
|
if (track.playing) className += ' playing';
|
||||||
|
|
||||||
return _react2.default.createElement(
|
return _react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
@ -11377,22 +11373,23 @@
|
|||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'span',
|
'span',
|
||||||
{ className: 'col name' },
|
{ className: 'col name' },
|
||||||
this.props.track.name
|
track.name
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'span',
|
'span',
|
||||||
{ className: 'col artists' },
|
{ className: 'col artists' },
|
||||||
this.props.track.artists ? _react2.default.createElement(_ArtistSentence2.default, { artists: this.props.track.artists }) : null
|
track.artists ? _react2.default.createElement(_ArtistSentence2.default, { artists: track.artists }) : null
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'span',
|
'span',
|
||||||
{ className: 'col album' },
|
{ className: 'col album' },
|
||||||
this.props.track.album ? _react2.default.createElement(_AlbumLink2.default, { album: this.props.track.album }) : null
|
track.album ? _react2.default.createElement(_AlbumLink2.default, { album: track.album }) : null
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'span',
|
'span',
|
||||||
{ className: 'col duration' },
|
{ className: 'col duration' },
|
||||||
this.formatDuration()
|
track.duration_ms ? _react2.default.createElement(_Dater2.default, { type: 'length', data: track.duration_ms }) : null,
|
||||||
|
track.length ? _react2.default.createElement(_Dater2.default, { type: 'length', data: track.length }) : null
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -19117,6 +19114,8 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
case 'MOPIDY_CURRENTTLTRACK':
|
case 'MOPIDY_CURRENTTLTRACK':
|
||||||
|
if (!action.data) return mopidy;
|
||||||
|
|
||||||
var tracks = [];
|
var tracks = [];
|
||||||
Object.assign(tracks, mopidy.tracks);
|
Object.assign(tracks, mopidy.tracks);
|
||||||
|
|
||||||
@ -19566,6 +19565,14 @@
|
|||||||
|
|
||||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||||
|
|
||||||
|
var _ArtistGrid = __webpack_require__(155);
|
||||||
|
|
||||||
|
var _ArtistGrid2 = _interopRequireDefault(_ArtistGrid);
|
||||||
|
|
||||||
|
var _Dater = __webpack_require__(379);
|
||||||
|
|
||||||
|
var _Dater2 = _interopRequireDefault(_Dater);
|
||||||
|
|
||||||
var _actions = __webpack_require__(11);
|
var _actions = __webpack_require__(11);
|
||||||
|
|
||||||
var spotifyActions = _interopRequireWildcard(_actions);
|
var spotifyActions = _interopRequireWildcard(_actions);
|
||||||
@ -19611,32 +19618,66 @@
|
|||||||
this.props.spotifyActions.getAlbum(nextProps.params.uri);
|
this.props.spotifyActions.getAlbum(nextProps.params.uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'totalTime',
|
||||||
|
value: function totalTime() {
|
||||||
|
if (!this.props.spotify.album) return null;
|
||||||
|
var tracks = this.props.spotify.tracks.items;
|
||||||
|
var duration = 0;
|
||||||
|
for (var i = 0; i < tracks.length; i++) {
|
||||||
|
duration += tracks[i].duration_ms;
|
||||||
|
}
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'render',
|
key: 'render',
|
||||||
value: function render() {
|
value: function render() {
|
||||||
if (this.props.spotify.album) {
|
if (this.props.spotify.album) {
|
||||||
|
var album = this.props.spotify.album;
|
||||||
return _react2.default.createElement(
|
return _react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'view album-view' },
|
{ className: 'view album-view' },
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'intro' },
|
{ className: 'intro' },
|
||||||
_react2.default.createElement(_Thumbnail2.default, { size: 'large', images: this.props.spotify.album.images })
|
_react2.default.createElement(_Thumbnail2.default, { size: 'large', images: album.images }),
|
||||||
|
_react2.default.createElement(_ArtistGrid2.default, { artists: album.artists }),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'details' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
null,
|
||||||
|
album.tracks.total,
|
||||||
|
' tracks, ',
|
||||||
|
this.totalTime
|
||||||
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
null,
|
||||||
|
'Released ',
|
||||||
|
_react2.default.createElement(_Dater2.default, { type: 'date', data: album.release_date })
|
||||||
|
)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'main' },
|
{ className: 'main' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'title' },
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h1',
|
'h1',
|
||||||
null,
|
null,
|
||||||
this.props.spotify.album.name
|
album.name
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h3',
|
||||||
null,
|
null,
|
||||||
_react2.default.createElement(_ArtistSentence2.default, { artists: this.props.spotify.album.artists })
|
_react2.default.createElement(_ArtistSentence2.default, { artists: album.artists })
|
||||||
|
)
|
||||||
),
|
),
|
||||||
_react2.default.createElement(_TrackList2.default, { tracks: this.props.spotify.album.tracks.items })
|
_react2.default.createElement(_TrackList2.default, { tracks: album.tracks.items })
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -19805,12 +19846,6 @@
|
|||||||
null,
|
null,
|
||||||
this.props.children
|
this.props.children
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
|
||||||
'footer',
|
|
||||||
null,
|
|
||||||
'Iris by James Barnsley \xA0|\xA0 v',
|
|
||||||
this.props.pusher.version.current
|
|
||||||
),
|
|
||||||
this.props.ui.context_menu.test,
|
this.props.ui.context_menu.test,
|
||||||
_react2.default.createElement(_ContextMenu2.default, { state: this.props.ui.context_menu })
|
_react2.default.createElement(_ContextMenu2.default, { state: this.props.ui.context_menu })
|
||||||
);
|
);
|
||||||
@ -19954,7 +19989,7 @@
|
|||||||
'div',
|
'div',
|
||||||
{ className: 'col w70' },
|
{ className: 'col w70' },
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
{ className: 'left-padding' },
|
{ className: 'left-padding' },
|
||||||
'Top tracks'
|
'Top tracks'
|
||||||
),
|
),
|
||||||
@ -19965,7 +20000,7 @@
|
|||||||
'div',
|
'div',
|
||||||
{ className: 'col w25' },
|
{ className: 'col w25' },
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
null,
|
null,
|
||||||
'Related artists'
|
'Related artists'
|
||||||
),
|
),
|
||||||
@ -19973,7 +20008,7 @@
|
|||||||
),
|
),
|
||||||
_react2.default.createElement('div', { className: 'cf' }),
|
_react2.default.createElement('div', { className: 'cf' }),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
{ className: 'left-padding' },
|
{ className: 'left-padding' },
|
||||||
'Albums'
|
'Albums'
|
||||||
),
|
),
|
||||||
@ -20029,9 +20064,13 @@
|
|||||||
|
|
||||||
var _TrackList2 = _interopRequireDefault(_TrackList);
|
var _TrackList2 = _interopRequireDefault(_TrackList);
|
||||||
|
|
||||||
var _Header = __webpack_require__(18);
|
var _Thumbnail = __webpack_require__(31);
|
||||||
|
|
||||||
var _Header2 = _interopRequireDefault(_Header);
|
var _Thumbnail2 = _interopRequireDefault(_Thumbnail);
|
||||||
|
|
||||||
|
var _Dater = __webpack_require__(379);
|
||||||
|
|
||||||
|
var _Dater2 = _interopRequireDefault(_Dater);
|
||||||
|
|
||||||
var _actions = __webpack_require__(11);
|
var _actions = __webpack_require__(11);
|
||||||
|
|
||||||
@ -20083,14 +20122,42 @@
|
|||||||
value: function render() {
|
value: function render() {
|
||||||
if (this.props.spotify.playlist) {
|
if (this.props.spotify.playlist) {
|
||||||
|
|
||||||
|
var playlist = this.props.spotify.playlist;
|
||||||
var context = null;
|
var context = null;
|
||||||
if (this.props.spotify.playlist.owner.id == this.props.spotify.me.id) context = 'editable-playlist';
|
if (playlist.owner.id == this.props.spotify.me.id) context = 'editable-playlist';
|
||||||
|
|
||||||
return _react2.default.createElement(
|
return _react2.default.createElement(
|
||||||
'div',
|
'div',
|
||||||
{ className: 'view playlist-view' },
|
{ className: 'view playlist-view' },
|
||||||
_react2.default.createElement(_Header2.default, { icon: 'playlist', title: this.props.spotify.playlist.name }),
|
_react2.default.createElement(
|
||||||
_react2.default.createElement(_TrackList2.default, { context: context, tracks: this.props.spotify.playlist.tracks.items })
|
'div',
|
||||||
|
{ className: 'intro' },
|
||||||
|
_react2.default.createElement(_Thumbnail2.default, { size: 'large', images: playlist.images }),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'details' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
null,
|
||||||
|
playlist.tracks.total,
|
||||||
|
' tracks'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'main' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'div',
|
||||||
|
{ className: 'title' },
|
||||||
|
_react2.default.createElement(
|
||||||
|
'h1',
|
||||||
|
null,
|
||||||
|
playlist.name
|
||||||
|
)
|
||||||
|
),
|
||||||
|
_react2.default.createElement(_TrackList2.default, { context: context, tracks: playlist.tracks.items })
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -20426,7 +20493,7 @@
|
|||||||
'section',
|
'section',
|
||||||
null,
|
null,
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
{ className: 'underline' },
|
{ className: 'underline' },
|
||||||
'Mopidy'
|
'Mopidy'
|
||||||
),
|
),
|
||||||
@ -20480,7 +20547,7 @@
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
{ className: 'underline' },
|
{ className: 'underline' },
|
||||||
'Pusher'
|
'Pusher'
|
||||||
),
|
),
|
||||||
@ -20533,7 +20600,7 @@
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
{ className: 'underline' },
|
{ className: 'underline' },
|
||||||
'Spotify'
|
'Spotify'
|
||||||
),
|
),
|
||||||
@ -20589,7 +20656,7 @@
|
|||||||
),
|
),
|
||||||
_react2.default.createElement(_SpotifyAuthenticationFrame2.default, null),
|
_react2.default.createElement(_SpotifyAuthenticationFrame2.default, null),
|
||||||
_react2.default.createElement(
|
_react2.default.createElement(
|
||||||
'h3',
|
'h4',
|
||||||
{ className: 'underline' },
|
{ className: 'underline' },
|
||||||
'Advanced'
|
'Advanced'
|
||||||
),
|
),
|
||||||
@ -48675,6 +48742,85 @@
|
|||||||
module.exports = isPlainObject;
|
module.exports = isPlainObject;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ },
|
||||||
|
/* 371 */,
|
||||||
|
/* 372 */,
|
||||||
|
/* 373 */,
|
||||||
|
/* 374 */,
|
||||||
|
/* 375 */,
|
||||||
|
/* 376 */,
|
||||||
|
/* 377 */,
|
||||||
|
/* 378 */,
|
||||||
|
/* 379 */
|
||||||
|
/***/ function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||||
|
|
||||||
|
var _react = __webpack_require__(2);
|
||||||
|
|
||||||
|
var _react2 = _interopRequireDefault(_react);
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
|
|
||||||
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||||
|
|
||||||
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||||||
|
|
||||||
|
var Dater = function (_React$Component) {
|
||||||
|
_inherits(Dater, _React$Component);
|
||||||
|
|
||||||
|
function Dater(props) {
|
||||||
|
_classCallCheck(this, Dater);
|
||||||
|
|
||||||
|
return _possibleConstructorReturn(this, (Dater.__proto__ || Object.getPrototypeOf(Dater)).call(this, props));
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(Dater, [{
|
||||||
|
key: 'calculate',
|
||||||
|
value: function calculate() {
|
||||||
|
switch (this.props.type) {
|
||||||
|
|
||||||
|
case 'length':
|
||||||
|
var time = new Date(this.props.data);
|
||||||
|
var min = time.getMinutes();
|
||||||
|
var sec = time.getSeconds();
|
||||||
|
if (sec < 10) sec = '0' + sec;
|
||||||
|
return min + ':' + sec;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'date':
|
||||||
|
// TODO: nice date formatting
|
||||||
|
return this.props.data;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'render',
|
||||||
|
value: function render() {
|
||||||
|
return _react2.default.createElement(
|
||||||
|
'span',
|
||||||
|
{ className: 'dater' },
|
||||||
|
this.calculate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return Dater;
|
||||||
|
}(_react2.default.Component);
|
||||||
|
|
||||||
|
exports.default = Dater;
|
||||||
|
|
||||||
/***/ }
|
/***/ }
|
||||||
/******/ ])));
|
/******/ ])));
|
||||||
//# sourceMappingURL=app.js.map
|
//# sourceMappingURL=app.js.map
|
||||||
File diff suppressed because one or more lines are too long
@ -17,9 +17,15 @@ export default class AlbumGrid extends React.Component{
|
|||||||
{
|
{
|
||||||
this.props.albums.map(
|
this.props.albums.map(
|
||||||
(album, index) => {
|
(album, index) => {
|
||||||
var link = album.uri;
|
|
||||||
if( album.album ) link = album.album.uri;
|
// handle nested album objects (as in Album Library)
|
||||||
return <GridItem item={album} key={index} link={'/album/'+link} />
|
if( album.album ){
|
||||||
|
var flatAlbum = album.album;
|
||||||
|
flatAlbum.added_at = album.added_at;
|
||||||
|
album = flatAlbum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <GridItem item={album} key={index} link={'/album/'+album.uri} />
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class Artist extends React.Component{
|
|||||||
if( this.props.spotify.artist ){
|
if( this.props.spotify.artist ){
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3>{ this.props.spotify.artist.name }</h3>
|
<h4>{ this.props.spotify.artist.name }</h4>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/js/components/Dater.js
Executable file
34
src/js/components/Dater.js
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
import React, { PropTypes } from 'react'
|
||||||
|
|
||||||
|
export default class Dater extends React.Component{
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate(){
|
||||||
|
switch(this.props.type){
|
||||||
|
|
||||||
|
case 'length':
|
||||||
|
var time = new Date( this.props.data );
|
||||||
|
var min = time.getMinutes();
|
||||||
|
var sec = time.getSeconds();
|
||||||
|
if( sec < 10 ) sec = '0'+sec;
|
||||||
|
return min+':'+sec;
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'date':
|
||||||
|
// TODO: nice date formatting
|
||||||
|
return this.props.data
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(){
|
||||||
|
return <span className="dater">{ this.calculate() }</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,6 +17,12 @@ export default class GridItem extends React.Component{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderThumbnail(){
|
||||||
|
if( this.props.item.images ) return <Thumbnail size="medium" images={this.props.item.images} />
|
||||||
|
if( this.props.item.icons ) return <Thumbnail size="medium" images={this.props.item.icons} />
|
||||||
|
return <Thumbnail size="medium" images={[]} />
|
||||||
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
var item = this.props.item;
|
var item = this.props.item;
|
||||||
if( typeof(item.album) !== 'undefined' ){
|
if( typeof(item.album) !== 'undefined' ){
|
||||||
@ -25,8 +31,7 @@ export default class GridItem extends React.Component{
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="grid-item" onClick={ (e) => this.handleClick(e) }>
|
<div className="grid-item" onClick={ (e) => this.handleClick(e) }>
|
||||||
{ item.images ? <Thumbnail size="medium" images={item.images} /> : null }
|
{ this.renderThumbnail() }
|
||||||
{ item.icons ? <Thumbnail size="medium" images={item.icons} /> : null }
|
|
||||||
<div className="name">{ item.name }</div>
|
<div className="name">{ item.name }</div>
|
||||||
<div className="secondary">
|
<div className="secondary">
|
||||||
{ item.artists ? <ArtistSentence artists={ item.artists } /> : null }
|
{ item.artists ? <ArtistSentence artists={ item.artists } /> : null }
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import React, { PropTypes } from 'react'
|
|||||||
import FontAwesome from 'react-fontawesome'
|
import FontAwesome from 'react-fontawesome'
|
||||||
import ArtistSentence from './ArtistSentence'
|
import ArtistSentence from './ArtistSentence'
|
||||||
import AlbumLink from './AlbumLink'
|
import AlbumLink from './AlbumLink'
|
||||||
|
import Dater from './Dater'
|
||||||
|
|
||||||
export default class Track extends React.Component{
|
export default class Track extends React.Component{
|
||||||
|
|
||||||
@ -31,32 +32,12 @@ export default class Track extends React.Component{
|
|||||||
this.props.handleContextMenu(e);
|
this.props.handleContextMenu(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatDuration(){
|
|
||||||
if( typeof(this.props.track.duration_ms) !== 'undefined' ){
|
|
||||||
var ms = this.props.track.duration_ms;
|
|
||||||
}else if( typeof(this.props.track.length) !== 'undefined' ){
|
|
||||||
var ms = this.props.track.length;
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var time = new Date(ms);
|
|
||||||
var min = time.getMinutes();
|
|
||||||
var sec = time.getSeconds();
|
|
||||||
if( sec < 10 ) sec = '0'+sec;
|
|
||||||
return min+':'+sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
|
var track = this.props.track;
|
||||||
|
|
||||||
var className = 'list-item track';
|
var className = 'list-item track';
|
||||||
if( typeof(this.props.track.selected) !== 'undefined' && this.props.track.selected ){
|
if( typeof(track.selected) !== 'undefined' && track.selected ) className += ' selected';
|
||||||
className += ' selected';
|
if( track.playing ) className += ' playing';
|
||||||
}
|
|
||||||
|
|
||||||
if( this.props.track.playing ){
|
|
||||||
className += ' playing';
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -66,16 +47,17 @@ export default class Track extends React.Component{
|
|||||||
onContextMenu={ (e) => this.handleContextMenu(e) }>
|
onContextMenu={ (e) => this.handleContextMenu(e) }>
|
||||||
{ this.props.track.selected ? <FontAwesome name="check" className="select-state" fixedWidth /> : null }
|
{ this.props.track.selected ? <FontAwesome name="check" className="select-state" fixedWidth /> : null }
|
||||||
<span className="col name">
|
<span className="col name">
|
||||||
{this.props.track.name}
|
{track.name}
|
||||||
</span>
|
</span>
|
||||||
<span className="col artists">
|
<span className="col artists">
|
||||||
{ this.props.track.artists ? <ArtistSentence artists={this.props.track.artists} /> : null }
|
{ track.artists ? <ArtistSentence artists={track.artists} /> : null }
|
||||||
</span>
|
</span>
|
||||||
<span className="col album">
|
<span className="col album">
|
||||||
{ this.props.track.album ? <AlbumLink album={this.props.track.album} /> : null }
|
{ track.album ? <AlbumLink album={track.album} /> : null }
|
||||||
</span>
|
</span>
|
||||||
<span className="col duration">
|
<span className="col duration">
|
||||||
{ this.formatDuration() }
|
{ track.duration_ms ? <Dater type="length" data={track.duration_ms} /> : null }
|
||||||
|
{ track.length ? <Dater type="length" data={track.length} /> : null }
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -53,6 +53,8 @@ export default function reducer(mopidy = {}, action){
|
|||||||
});
|
});
|
||||||
|
|
||||||
case 'MOPIDY_CURRENTTLTRACK':
|
case 'MOPIDY_CURRENTTLTRACK':
|
||||||
|
if( !action.data ) return mopidy;
|
||||||
|
|
||||||
var tracks = [];
|
var tracks = [];
|
||||||
Object.assign(tracks, mopidy.tracks);
|
Object.assign(tracks, mopidy.tracks);
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import TrackList from '../components/TrackList'
|
|||||||
import Thumbnail from '../components/Thumbnail'
|
import Thumbnail from '../components/Thumbnail'
|
||||||
import Parallax from '../components/Parallax'
|
import Parallax from '../components/Parallax'
|
||||||
import ArtistSentence from '../components/ArtistSentence'
|
import ArtistSentence from '../components/ArtistSentence'
|
||||||
|
import ArtistGrid from '../components/ArtistGrid'
|
||||||
|
import Dater from '../components/Dater'
|
||||||
|
|
||||||
import * as spotifyActions from '../services/spotify/actions'
|
import * as spotifyActions from '../services/spotify/actions'
|
||||||
import * as mopidyActions from '../services/mopidy/actions'
|
import * as mopidyActions from '../services/mopidy/actions'
|
||||||
@ -29,17 +31,35 @@ class Album extends React.Component{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
totalTime(){
|
||||||
|
if( !this.props.spotify.album ) return null
|
||||||
|
var tracks = this.props.spotify.tracks.items;
|
||||||
|
var duration = 0;
|
||||||
|
for( var i = 0; i < tracks.length; i++ ){
|
||||||
|
duration += tracks[i].duration_ms;
|
||||||
|
}
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
if( this.props.spotify.album ){
|
if( this.props.spotify.album ){
|
||||||
|
var album = this.props.spotify.album;
|
||||||
return (
|
return (
|
||||||
<div className="view album-view">
|
<div className="view album-view">
|
||||||
<div className="intro">
|
<div className="intro">
|
||||||
<Thumbnail size="large" images={ this.props.spotify.album.images } />
|
<Thumbnail size="large" images={ album.images } />
|
||||||
|
<ArtistGrid artists={ album.artists } />
|
||||||
|
<div className="details">
|
||||||
|
<div>{ album.tracks.total } tracks, { this.totalTime }</div>
|
||||||
|
<div>Released <Dater type="date" data={ album.release_date } /></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<h1>{ this.props.spotify.album.name }</h1>
|
<div className="title">
|
||||||
<h3><ArtistSentence artists={ this.props.spotify.album.artists } /></h3>
|
<h1>{ album.name }</h1>
|
||||||
<TrackList tracks={this.props.spotify.album.tracks.items} />
|
<h3><ArtistSentence artists={ album.artists } /></h3>
|
||||||
|
</div>
|
||||||
|
<TrackList tracks={ album.tracks.items } />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -77,9 +77,6 @@ class App extends React.Component{
|
|||||||
<main>
|
<main>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
|
||||||
Iris by James Barnsley | v{ this.props.pusher.version.current }
|
|
||||||
</footer>
|
|
||||||
{ this.props.ui.context_menu.test }
|
{ this.props.ui.context_menu.test }
|
||||||
<ContextMenu state={this.props.ui.context_menu} />
|
<ContextMenu state={this.props.ui.context_menu} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -43,20 +43,20 @@ class Artist extends React.Component{
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col w70">
|
<div className="col w70">
|
||||||
<h3 className="left-padding">Top tracks</h3>
|
<h4 className="left-padding">Top tracks</h4>
|
||||||
{ this.props.spotify.artist.tracks ? <TrackList tracks={ this.props.spotify.artist.tracks } /> : null }
|
{ this.props.spotify.artist.tracks ? <TrackList tracks={ this.props.spotify.artist.tracks } /> : null }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col w5"></div>
|
<div className="col w5"></div>
|
||||||
|
|
||||||
<div className="col w25">
|
<div className="col w25">
|
||||||
<h3>Related artists</h3>
|
<h4>Related artists</h4>
|
||||||
{ this.props.spotify.artist.related_artists ? <ArtistList artists={ this.props.spotify.artist.related_artists.slice(0,6) } /> : null }
|
{ this.props.spotify.artist.related_artists ? <ArtistList artists={ this.props.spotify.artist.related_artists.slice(0,6) } /> : null }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="cf"></div>
|
<div className="cf"></div>
|
||||||
|
|
||||||
<h3 className="left-padding">Albums</h3>
|
<h4 className="left-padding">Albums</h4>
|
||||||
{ this.props.spotify.artist_albums ? <AlbumGrid className="no-top-padding" albums={ this.props.spotify.artist_albums.items } /> : null }
|
{ this.props.spotify.artist_albums ? <AlbumGrid className="no-top-padding" albums={ this.props.spotify.artist_albums.items } /> : null }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,7 +4,8 @@ import { connect } from 'react-redux'
|
|||||||
import { bindActionCreators } from 'redux'
|
import { bindActionCreators } from 'redux'
|
||||||
|
|
||||||
import TrackList from '../components/TrackList'
|
import TrackList from '../components/TrackList'
|
||||||
import Header from '../components/Header'
|
import Thumbnail from '../components/Thumbnail'
|
||||||
|
import Dater from '../components/Dater'
|
||||||
|
|
||||||
import * as spotifyActions from '../services/spotify/actions'
|
import * as spotifyActions from '../services/spotify/actions'
|
||||||
import * as mopidyActions from '../services/mopidy/actions'
|
import * as mopidyActions from '../services/mopidy/actions'
|
||||||
@ -30,13 +31,24 @@ class Playlist extends React.Component{
|
|||||||
render(){
|
render(){
|
||||||
if( this.props.spotify.playlist ){
|
if( this.props.spotify.playlist ){
|
||||||
|
|
||||||
|
var playlist = this.props.spotify.playlist;
|
||||||
var context = null;
|
var context = null;
|
||||||
if( this.props.spotify.playlist.owner.id == this.props.spotify.me.id ) context = 'editable-playlist'
|
if( playlist.owner.id == this.props.spotify.me.id ) context = 'editable-playlist'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="view playlist-view">
|
<div className="view playlist-view">
|
||||||
<Header icon="playlist" title={ this.props.spotify.playlist.name } />
|
<div className="intro">
|
||||||
<TrackList context={context} tracks={this.props.spotify.playlist.tracks.items} />
|
<Thumbnail size="large" images={ playlist.images } />
|
||||||
|
<div className="details">
|
||||||
|
<div>{ playlist.tracks.total } tracks</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="main">
|
||||||
|
<div className="title">
|
||||||
|
<h1>{ playlist.name }</h1>
|
||||||
|
</div>
|
||||||
|
<TrackList context={context} tracks={ playlist.tracks.items } />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class Settings extends React.Component{
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
<h3 className="underline">Mopidy</h3>
|
<h4 className="underline">Mopidy</h4>
|
||||||
<form onSubmit={(e) => this.setMopidyConfig(e)}>
|
<form onSubmit={(e) => this.setMopidyConfig(e)}>
|
||||||
<label>
|
<label>
|
||||||
<div className="label">Host</div>
|
<div className="label">Host</div>
|
||||||
@ -88,7 +88,7 @@ class Settings extends React.Component{
|
|||||||
<button type="submit" className="secondary">Apply</button>
|
<button type="submit" className="secondary">Apply</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3 className="underline">Pusher</h3>
|
<h4 className="underline">Pusher</h4>
|
||||||
<form>
|
<form>
|
||||||
<label>
|
<label>
|
||||||
<div className="label">Username</div>
|
<div className="label">Username</div>
|
||||||
@ -112,7 +112,7 @@ class Settings extends React.Component{
|
|||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3 className="underline">Spotify</h3>
|
<h4 className="underline">Spotify</h4>
|
||||||
<form onSubmit={(e) => this.setSpotifyConfig(e)}>
|
<form onSubmit={(e) => this.setSpotifyConfig(e)}>
|
||||||
<label>
|
<label>
|
||||||
<div className="label">Country</div>
|
<div className="label">Country</div>
|
||||||
@ -138,7 +138,7 @@ class Settings extends React.Component{
|
|||||||
|
|
||||||
<SpotifyAuthenticationFrame />
|
<SpotifyAuthenticationFrame />
|
||||||
|
|
||||||
<h3 className="underline">Advanced</h3>
|
<h4 className="underline">Advanced</h4>
|
||||||
<label>
|
<label>
|
||||||
<div className="label">Version</div>
|
<div className="label">Version</div>
|
||||||
<div className="input">
|
<div className="input">
|
||||||
|
|||||||
@ -17,4 +17,5 @@
|
|||||||
|
|
||||||
@import 'views/artist';
|
@import 'views/artist';
|
||||||
@import 'views/album';
|
@import 'views/album';
|
||||||
|
@import 'views/playlist';
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,18 @@ main {
|
|||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
|
font-weight: 100;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
$turquoise: #08d58f;
|
$turquoise: #08d58f;
|
||||||
|
$faint_grey: #EEEEEE;
|
||||||
$light_grey: #DDDDDD;
|
$light_grey: #DDDDDD;
|
||||||
$mid_grey: #AAAAAA;
|
$mid_grey: #AAAAAA;
|
||||||
$dark_grey: #333333;
|
$dark_grey: #333333;
|
||||||
|
|||||||
@ -6,19 +6,67 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
background: $light_grey;
|
background: $faint_grey;
|
||||||
|
|
||||||
.thumbnail {
|
.thumbnail {
|
||||||
float: none;
|
float: none;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
.details {
|
||||||
padding-top: 30px;
|
padding: 30px;
|
||||||
|
color: $mid_grey;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artist-grid {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.grid-item {
|
||||||
|
margin: 0;
|
||||||
|
width: 50%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.thumbnail .image {
|
||||||
|
background-color: $secondary_grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
@include animate();
|
||||||
|
position: absolute;
|
||||||
|
top: 35%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 2;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.name {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 30px 40px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: $mid_grey;
|
||||||
|
a:hover {
|
||||||
|
color: darken($mid_grey, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
padding-left: 300px;
|
padding-left: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,72 @@
|
|||||||
|
|
||||||
.album-view {
|
.playlist-view {
|
||||||
.intro {
|
.intro {
|
||||||
@include clearfix;
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
color: #FFFFFF;
|
|
||||||
padding: 20px;
|
|
||||||
height: 40vh;
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
.parallax {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 100%;
|
bottom: 0;
|
||||||
z-index: -1;
|
width: 300px;
|
||||||
}
|
background: $faint_grey;
|
||||||
|
|
||||||
.thumbnail {
|
.thumbnail {
|
||||||
float: none;
|
float: none;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 160px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
.details {
|
||||||
padding-top: 30px;
|
padding: 30px;
|
||||||
|
color: $mid_grey;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.artist-grid {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.grid-item {
|
||||||
|
margin: 0;
|
||||||
|
width: 50%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.thumbnail .image {
|
||||||
|
background-color: $secondary_grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
@include animate();
|
||||||
|
position: absolute;
|
||||||
|
top: 35%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFFFF;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 2;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.name {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 30px 40px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: $mid_grey;
|
||||||
|
a:hover {
|
||||||
|
color: darken($mid_grey, 20%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
padding-left: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user