Working on known bugs
See issue #16 * Add basic settings view * Fix play next song when playlist is on * Add timer styling on webplayer * Fix wrong albums being linked in songs table
This commit is contained in:
parent
23aa8b52ab
commit
198d50aec5
26
app/components/Settings.jsx
Normal file
26
app/components/Settings.jsx
Normal file
@ -0,0 +1,26 @@
|
||||
// NPM imports
|
||||
import React, { Component } from "react";
|
||||
import CSSModules from "react-css-modules";
|
||||
import { injectIntl, intlShape } from "react-intl";
|
||||
|
||||
// Styles
|
||||
import css from "../styles/Songs.scss";
|
||||
|
||||
|
||||
/**
|
||||
* A single row for a single song in the songs table.
|
||||
*/
|
||||
class SettingsCSSIntl extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h2>Settings</h2>
|
||||
<p>TODO</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
SettingsCSSIntl.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
export default injectIntl(CSSModules(SettingsCSSIntl, css));
|
@ -58,8 +58,8 @@ class SongsTableRowCSSIntl extends Component {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
const length = formatLength(this.props.song.get("time"));
|
||||
const linkToArtist = "/artist/" + this.props.song.getIn(["artist", "id"]);
|
||||
const linkToAlbum = "/album/" + this.props.song.getIn(["album", "id"]);
|
||||
const linkToArtist = "/artist/" + this.props.song.getIn(["artist", "id"]) + "-" + encodeURIComponent(this.props.song.getIn(["artist", "name"]));
|
||||
const linkToAlbum = linkToArtist + "/album/" + this.props.song.getIn(["album", "id"]) + "-" + encodeURIComponent(this.props.song.getIn(["album", "name"]));
|
||||
|
||||
return (
|
||||
<tr>
|
||||
|
@ -118,6 +118,7 @@ class WebPlayerCSSIntl extends Component {
|
||||
<div className="col-xs-12">
|
||||
<div className="row" styleName="artRow" onMouseOver={this.artOpacityHandler} onMouseOut={this.artOpacityHandler}>
|
||||
<div className="col-xs-12">
|
||||
<div styleName="artTimer"></div>
|
||||
<img src={art} width="200" height="200" alt={formatMessage(webplayerMessages["app.common.art"])} ref="art" styleName="art" />
|
||||
<div ref="artText">
|
||||
{
|
||||
@ -166,6 +167,7 @@ class WebPlayerCSSIntl extends Component {
|
||||
<button styleName={randomBtnStyles.join(" ")} aria-label={formatMessage(webplayerMessages["app.webplayer.random"])} title={formatMessage(webplayerMessages["app.webplayer.random"])} aria-pressed={this.props.isRandom} onClick={onRandom} ref="randomBtn">
|
||||
<FontAwesome name="random" />
|
||||
</button>
|
||||
{ /* TODO: If already on playlist page, should go back. */ }
|
||||
<Link to="/playlist" styleName={playlistBtnStyles.join(" ")} aria-label={formatMessage(webplayerMessages["app.webplayer.playlist"])} title={formatMessage(webplayerMessages["app.webplayer.playlist"])}>
|
||||
<FontAwesome name="list" />
|
||||
</Link>
|
||||
|
@ -133,12 +133,13 @@ export default createReducer(initialState, {
|
||||
}
|
||||
},
|
||||
[PLAY_NEXT_SONG]: (state) => {
|
||||
const newIndex = state.get("currentIndex") + 1;
|
||||
let newIndex = state.get("currentIndex") + 1;
|
||||
if (newIndex >= state.get("playlist").size) {
|
||||
// If there is an overflow
|
||||
if (state.get("isRepeat")) {
|
||||
// TODO: Handle repeat
|
||||
return state.set("error", null);
|
||||
// If we are at the end of the playlist and repeat mode is on,
|
||||
// just play back first song.
|
||||
newIndex = 0;
|
||||
} else {
|
||||
// Just stop playback
|
||||
return (
|
||||
|
@ -18,6 +18,7 @@ import LoginPage from "./views/LoginPage";
|
||||
import LogoutPage from "./views/LogoutPage";
|
||||
import PlaylistPage from "./views/PlaylistPage";
|
||||
import SongsPage from "./views/SongsPage";
|
||||
import SettingsPage from "./views/SettingsPage";
|
||||
|
||||
export default (
|
||||
<Route path="/" component={App}> // Main container is App
|
||||
@ -35,6 +36,7 @@ export default (
|
||||
<Route path="artist/:artist/album/:album" component={ArtistPage} />
|
||||
<Route path="songs" component={SongsPage} />
|
||||
<Route path="playlist" component={PlaylistPage} />
|
||||
<Route path="settings" component={SettingsPage} />
|
||||
<IndexRoute component={HomePage} />
|
||||
</Route>
|
||||
</Route>
|
||||
|
@ -19,6 +19,15 @@ $controlsMarginTop: 10px;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.artTimer {
|
||||
position: absolute;
|
||||
width: 50px;
|
||||
height: 200px;
|
||||
background-color: black;
|
||||
opacity: 0.75;
|
||||
z-index: -9;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls
|
||||
*/
|
||||
|
@ -1,6 +1,3 @@
|
||||
/**
|
||||
* TODO: Scroll to album if /album/:id is passed.
|
||||
*/
|
||||
// NPM imports
|
||||
import React, { Component, PropTypes } from "react";
|
||||
import { bindActionCreators } from "redux";
|
||||
|
18
app/views/SettingsPage.jsx
Normal file
18
app/views/SettingsPage.jsx
Normal file
@ -0,0 +1,18 @@
|
||||
// NPM imports
|
||||
import React, { Component } from "react";
|
||||
|
||||
// Components
|
||||
import Settings from "../components/Settings";
|
||||
|
||||
/**
|
||||
* Paginated table of available songs
|
||||
*/
|
||||
class SettingsPage extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Settings />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SettingsPage;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
||||
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="./",t(0)}({0:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(636);Object.keys(r).forEach(function(e){"default"!==e&&"__esModule"!==e&&Object.defineProperty(t,e,{enumerable:!0,get:function(){return r[e]}})})},636:function(e,t){!function(t,n){function r(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;return n.innerHTML="x<style>"+t+"</style>",r.insertBefore(n.lastChild,r.firstChild)}function a(){var e=b.elements;return"string"==typeof e?e.split(" "):e}function o(e,t){var n=b.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof e&&(e=e.join(" ")),b.elements=n+" "+e,s(t)}function c(e){var t=E[e[v]];return t||(t={},y++,e[v]=y,E[y]=t),t}function i(e,t,r){if(t||(t=n),f)return t.createElement(e);r||(r=c(t));var a;return a=r.cache[e]?r.cache[e].cloneNode():g.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e),!a.canHaveChildren||p.test(e)||a.tagUrn?a:r.frag.appendChild(a)}function l(e,t){if(e||(e=n),f)return e.createDocumentFragment();t=t||c(e);for(var r=t.frag.cloneNode(),o=0,i=a(),l=i.length;o<l;o++)r.createElement(i[o]);return r}function u(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return b.shivMethods?i(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+a().join().replace(/[\w\-:]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(b,t.frag)}function s(e){e||(e=n);var t=c(e);return!b.shivCSS||d||t.hasCSS||(t.hasCSS=!!r(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),f||u(e,t),e}var d,f,m="3.7.3-pre",h=t.html5||{},p=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,g=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",y=0,E={};!function(){try{var e=n.createElement("a");e.innerHTML="<xyz></xyz>",d="hidden"in e,f=1==e.childNodes.length||function(){n.createElement("a");var e=n.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(t){d=!0,f=!0}}();var b={elements:h.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:h.shivCSS!==!1,supportsUnknownElements:f,shivMethods:h.shivMethods!==!1,type:"default",shivDocument:s,createElement:i,createDocumentFragment:l,addElements:o};t.html5=b,s(n),"object"==typeof e&&e.exports&&(e.exports=b)}("undefined"!=typeof window?window:this,document)}});
|
||||
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="./",t(0)}({0:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(638);Object.keys(r).forEach(function(e){"default"!==e&&"__esModule"!==e&&Object.defineProperty(t,e,{enumerable:!0,get:function(){return r[e]}})})},638:function(e,t){!function(t,n){function r(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;return n.innerHTML="x<style>"+t+"</style>",r.insertBefore(n.lastChild,r.firstChild)}function a(){var e=b.elements;return"string"==typeof e?e.split(" "):e}function o(e,t){var n=b.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof e&&(e=e.join(" ")),b.elements=n+" "+e,s(t)}function c(e){var t=E[e[v]];return t||(t={},y++,e[v]=y,E[y]=t),t}function i(e,t,r){if(t||(t=n),f)return t.createElement(e);r||(r=c(t));var a;return a=r.cache[e]?r.cache[e].cloneNode():g.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e),!a.canHaveChildren||p.test(e)||a.tagUrn?a:r.frag.appendChild(a)}function l(e,t){if(e||(e=n),f)return e.createDocumentFragment();t=t||c(e);for(var r=t.frag.cloneNode(),o=0,i=a(),l=i.length;o<l;o++)r.createElement(i[o]);return r}function u(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return b.shivMethods?i(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+a().join().replace(/[\w\-:]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(b,t.frag)}function s(e){e||(e=n);var t=c(e);return!b.shivCSS||d||t.hasCSS||(t.hasCSS=!!r(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),f||u(e,t),e}var d,f,m="3.7.3-pre",h=t.html5||{},p=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,g=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",y=0,E={};!function(){try{var e=n.createElement("a");e.innerHTML="<xyz></xyz>",d="hidden"in e,f=1==e.childNodes.length||function(){n.createElement("a");var e=n.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(t){d=!0,f=!0}}();var b={elements:h.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:h.shivCSS!==!1,supportsUnknownElements:f,shivMethods:h.shivMethods!==!1,type:"default",shivDocument:s,createElement:i,createDocumentFragment:l,addElements:o};t.html5=b,s(n),"object"==typeof e&&e.exports&&(e.exports=b)}("undefined"!=typeof window?window:this,document)}});
|
||||
//# sourceMappingURL=fix.ie9.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user