Build issue; Grid items

This commit is contained in:
James Barnsley
2016-10-25 14:09:53 +13:00
parent 3f055df3f2
commit 5372cd0334
17 changed files with 195 additions and 125 deletions

9
build.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash
if [ ! -d production ]; then
mkdir production;
fi
cp src/index.html production/index.html
cp src/.htaccess production/.htaccess
cp -R src/fonts production/fonts

View File

@ -1,40 +0,0 @@
0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/nodejs', '/usr/bin/npm', 'run', 'dev' ]
2 info using npm@2.15.8
3 info using node@v4.4.7
4 verbose run-script [ 'predev', 'dev', 'postdev' ]
5 info predev iris@1.0.0
6 info dev iris@1.0.0
7 verbose unsafe-perm in lifecycle true
8 info iris@1.0.0 Failed to exec dev script
9 verbose stack Error: iris@1.0.0 dev: `mkdir production & cp src/index.html production/index.html & cp -R src/fonts production/fonts & NODE_ENV=development webpack & sass src/scss/app.scss production/app.css`
9 verbose stack Exit status 65
9 verbose stack at EventEmitter.<anonymous> (/usr/lib/node_modules/npm/lib/utils/lifecycle.js:217:16)
9 verbose stack at emitTwo (events.js:87:13)
9 verbose stack at EventEmitter.emit (events.js:172:7)
9 verbose stack at ChildProcess.<anonymous> (/usr/lib/node_modules/npm/lib/utils/spawn.js:24:14)
9 verbose stack at emitTwo (events.js:87:13)
9 verbose stack at ChildProcess.emit (events.js:172:7)
9 verbose stack at maybeClose (internal/child_process.js:827:16)
9 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)
10 verbose pkgid iris@1.0.0
11 verbose cwd /var/www/iris
12 error Linux 3.16.0-4-amd64
13 error argv "/usr/bin/nodejs" "/usr/bin/npm" "run" "dev"
14 error node v4.4.7
15 error npm v2.15.8
16 error code ELIFECYCLE
17 error iris@1.0.0 dev: `mkdir production & cp src/index.html production/index.html & cp -R src/fonts production/fonts & NODE_ENV=development webpack & sass src/scss/app.scss production/app.css`
17 error Exit status 65
18 error Failed at the iris@1.0.0 dev script 'mkdir production & cp src/index.html production/index.html & cp -R src/fonts production/fonts & NODE_ENV=development webpack & sass src/scss/app.scss production/app.css'.
18 error This is most likely a problem with the iris package,
18 error not with npm itself.
18 error Tell the author that this fails on your system:
18 error mkdir production & cp src/index.html production/index.html & cp -R src/fonts production/fonts & NODE_ENV=development webpack & sass src/scss/app.scss production/app.css
18 error You can get information on how to open an issue for this project with:
18 error npm bugs iris
18 error Or if that isn't available, you can get their info via:
18 error
18 error npm owner ls iris
18 error There is likely additional logging output above.
19 verbose exit [ 1, true ]

View File

@ -34,7 +34,7 @@
"react-fontawesome": "*"
},
"scripts": {
"dev": "mkdir production & cp src/index.html production/index.html & cp -R src/fonts production/fonts & NODE_ENV=development webpack & sass src/scss/app.scss production/app.css",
"dev": "./build.sh & NODE_ENV=development webpack & sass src/scss/app.scss production/app.css",
"prod": "NODE_ENV=production webpack"
},
"author": "James Barnsley",

6
src/.htaccess Executable file
View File

@ -0,0 +1,6 @@
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

View File

@ -1,6 +1,6 @@
import React, { PropTypes } from 'react'
import AlbumGridItem from './AlbumGridItem'
import GridItem from './GridItem'
export default class AlbumGrid extends React.Component{
@ -15,7 +15,9 @@ export default class AlbumGrid extends React.Component{
{
this.props.items.items.map(
(album, index) => {
return <AlbumGridItem item={album} key={index} />
var link = album.uri;
if( album.album ) link = album.album.uri;
return <GridItem item={album} key={index} link={'/album/'+link} />
}
)
}

View File

@ -1,26 +0,0 @@
import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import Thumbnail from './Thumbnail'
export default class AlbumGridItem extends React.Component{
constructor(props) {
super(props);
}
render(){
var item = this.props.item;
if( typeof(item.album) !== 'undefined' ){
item.album.added_at = item.added_at;
item = item.album;
}
var link = '/album/' + item.uri;
return (
<Link to={link} className="grid-item album-grid-item">
{ item.images ? <Thumbnail size="medium" images={item.images} /> : item.name }
</Link>
);
}
}

28
src/js/components/ArtistGrid.js Executable file
View File

@ -0,0 +1,28 @@
import React, { PropTypes } from 'react'
import AlbumGridItem from './AlbumGridItem'
export default class AlbumGrid extends React.Component{
constructor(props) {
super(props);
}
render(){
if( this.props.items ){
return (
<ul className="grid album-grid">
{
this.props.items.items.map(
(album, index) => {
return <AlbumGridItem item={album} key={index} />
}
)
}
</ul>
);
}
return null;
}
}

37
src/js/components/GridItem.js Executable file
View File

@ -0,0 +1,37 @@
import React, { PropTypes } from 'react'
import { Link, browserHistory } from 'react-router'
import Thumbnail from './Thumbnail'
import ArtistList from './ArtistList'
export default class GridItem extends React.Component{
constructor(props) {
super(props);
}
handleClick(e){
if( e.target.tagName.toLowerCase() !== 'a' ){
browserHistory.push( this.props.link );
}
}
render(){
var item = this.props.item;
if( typeof(item.album) !== 'undefined' ){
item.album.added_at = item.added_at;
item = item.album;
}
return (
<div className="grid-item" onClick={ (e) => this.handleClick(e) }>
{ item.images ? <Thumbnail size="medium" images={item.images} /> : item.name }
<div className="name">{ item.name }</div>
<div className="secondary">
{ item.artists ? <ArtistList artists={ item.artists } /> : null }
</div>
</div>
);
}
}

View File

@ -40,9 +40,7 @@ export default class Track extends React.Component{
render(){
var className = 'list-item track';
var selectedIcon = 'square-o';
if( typeof(this.props.track.selected) !== 'undefined' && this.props.track.selected ){
selectedIcon = 'check-square-o';
className += ' selected';
}
@ -55,12 +53,12 @@ export default class Track extends React.Component{
className={className}
onDoubleClick={ (e) => this.handleDoubleClick(e) }
onClick={ (e) => this.handleClick(e) }>
<FontAwesome name={selectedIcon} className="select-state" fixedWidth />
{ this.props.track.selected ? <FontAwesome name="check" className="select-state" fixedWidth /> : null }
<span className="col name">
{this.props.track.name}
</span>
<span className="col artists">
<ArtistList artists={this.props.track.artists} />
{ this.props.track.artists ? <ArtistList artists={this.props.track.artists} /> : null }
</span>
<span className="col album">
{ this.props.track.album ? <AlbumLink album={this.props.track.album} /> : null }

View File

@ -19,18 +19,6 @@ export default function reducer(mopidy = {}, action){
tlid: action.tlid
});
case 'MOPIDY_HIGHLIGHT_CURRENT_TLTRACK':
if( !action.data ) return mopidy;
for( var i = 0; i < mopidy.tracks.length; i++ ){
if( mopidy.tracks[i].tlid == action.data.tlid ){
action.data.track.playing = true;
Object.assign(mopidy.tracks[i], action.data);
}else{
mopidy.tracks[i].track.playing = false;
}
}
return Object.assign({}, mopidy, { tracks: mopidy.tracks });
case 'MOPIDY_PLAYLISTS_LOADED':
if( !action.data ) return mopidy;
return Object.assign({}, mopidy, { playlists: action.data });
@ -65,8 +53,16 @@ export default function reducer(mopidy = {}, action){
});
case 'MOPIDY_CURRENTTLTRACK':
var tracks = [];
Object.assign(tracks, mopidy.tracks);
for( var i = 0; i < tracks.length; i++ ){
Object.assign(tracks[i].track, { playing: ( tracks[i].tlid == action.data.tlid ) });
}
return Object.assign({}, mopidy, {
currentTlTrack: action.data
currentTlTrack: action.data,
tracks: tracks
});
case 'MOPIDY_VOLUME':

View File

@ -46,35 +46,39 @@ class Settings extends React.Component{
title="Settings"
/>
<h4>Mopidy</h4>
<form onSubmit={() => this.setMopidyConfig()}>
<label>
<span className="label">Host</span>
<input onChange={ e => this.setState({ mopidy_host: e.target.value })} value={ this.state.mopidy_host } />
</label>
<label>
<span className="label">Port</span>
<input onChange={ e => this.setState({ mopidy_port: e.target.value })} value={ this.state.mopidy_port } />
</label>
<button type="submit">Apply</button>
</form>
<section>
<h4>Spotify</h4>
<form onSubmit={() => this.setSpotifyConfig()}>
<label>
<span className="label">Country</span>
<input onChange={ e => this.setState({ spotify_country: e.target.value })} value={ this.state.spotify_country } />
</label>
<label>
<span className="label">Locale</span>
<input onChange={ e => this.setState({ spotify_locale: e.target.value })} value={ this.state.spotify_locale } />
</label>
<button type="submit">Apply</button>
</form>
<h3>Mopidy</h3>
<form onSubmit={() => this.setMopidyConfig()}>
<label>
<span className="label">Host</span>
<input onChange={ e => this.setState({ mopidy_host: e.target.value })} value={ this.state.mopidy_host } />
</label>
<label>
<span className="label">Port</span>
<input onChange={ e => this.setState({ mopidy_port: e.target.value })} value={ this.state.mopidy_port } />
</label>
<button type="submit">Apply</button>
</form>
<SpotifyAuthenticationFrame />
<h3>Spotify</h3>
<form onSubmit={() => this.setSpotifyConfig()}>
<label>
<span className="label">Country</span>
<input onChange={ e => this.setState({ spotify_country: e.target.value })} value={ this.state.spotify_country } />
</label>
<label>
<span className="label">Locale</span>
<input onChange={ e => this.setState({ spotify_locale: e.target.value })} value={ this.state.spotify_locale } />
</label>
<button type="submit">Apply</button>
</form>
<ConfirmationButton content="Reset all settings" confirmingContent="Are you sure?" onConfirm={() => this.resetAllSettings()} />
<SpotifyAuthenticationFrame />
<ConfirmationButton content="Reset all settings" confirmingContent="Are you sure?" onConfirm={() => this.resetAllSettings()} />
</section>
</div>
);
}

View File

@ -10,5 +10,6 @@
@import 'components/icon';
@import 'components/sidebar';
@import 'components/lists';
@import 'components/grid';
@import 'components/header';

37
src/scss/components/_grid.scss Executable file
View File

@ -0,0 +1,37 @@
.grid {
padding: 40px 20px;
.grid-item {
width: 16%;
margin: 0 2% 3%;
display: inline-block;
vertical-align: top;
border-bottom: 0;
.thumbnail {
max-width: 100%;
}
.name {
@include one_line_text;
padding-top: 8px;
}
.secondary {
@include one_line_text;
padding-top: 2px;
color: $secondary_grey;
}
&:nth-child(5)::after {
@include clear;
}
&:hover{
cursor: pointer;
opacity: 0.75;
}
}
}

View File

@ -10,7 +10,7 @@
display: block;
position: relative;
padding: 8px 10px 8px 30px;
padding: 9px 10px 9px 40px;
border-top: 1px solid #EEEEEE;
border-bottom: 1px solid #EEEEEE;
margin-bottom: -1px;
@ -22,9 +22,7 @@
}
&::after {
content: '';
clear: both;
display: block;
@include clear;
}
&.selected {
@ -57,12 +55,13 @@
.select-state {
position: absolute;
top: 10px;
left: 10px;
top: 12px;
left: 15px;
font-size: 10px;
}
&.playing {
font-weight: 500;
font-weight: 600;
}
}

View File

@ -5,10 +5,11 @@ aside{
top: 0;
left: 0;
bottom: 0;
background: #333333;
background: #111111;
width: 200px;
overflow: hidden;
box-shadow: inset -20px 0px 30px -20px rgba(0, 0, 0, 0.5);
.thumbnail {
position: absolute;
top: 0;
@ -36,11 +37,11 @@ aside{
&.active {
border-color: $turquoise;
background: rgba( 0,0,0,0.1 );
background: rgba( 0, 0, 0, 0.5 );
}
&:hover {
background: rgba( 255,255,255,0.1 );
background: rgba( 255, 255, 255, 0.1 );
}
}
@ -73,13 +74,13 @@ aside{
color: #FFFFFF;
.title {
@include one_line_text
@include one_line_text;
}
.artist-list {
opacity: 0.5;
display: block;
@include one_line_text
@include one_line_text;
.artist a {
color: inherit;

View File

@ -27,4 +27,15 @@ main {
}
}
section {
padding: 40px;
}
h3 {
font-size: 14px;
margin-bottom: 14px;
padding-bottom: 4px;
border-bottom: 1px solid #000000;
text-transform: uppercase;
}
}

View File

@ -1,8 +1,15 @@
$turquoise: #08d58f;
$secondary_grey: #888888;
@mixin one_line_text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@mixin clear {
content: '';
clear: both;
display: block;
}