Dropzones; Dropzone super-basic behavior
This commit is contained in:
30
src/js/components/Dropzone.js
Executable file
30
src/js/components/Dropzone.js
Executable file
@ -0,0 +1,30 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
|
||||
import Icon from './Icon'
|
||||
|
||||
export default class Dropzone extends React.Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleMouseUp(e){
|
||||
// TODO: sanity check if this is a valid dropzone
|
||||
|
||||
return this.props.handleMouseUp(e)
|
||||
}
|
||||
|
||||
render(){
|
||||
if( !this.props.data ) return null
|
||||
|
||||
return (
|
||||
<div className="dropzone" onMouseUp={ e => this.handleMouseUp(e) }>
|
||||
<Icon className="white" name={ this.props.data.icon } />
|
||||
<span className="title">{ this.props.data.title }</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
89
src/js/components/Dropzones.js
Executable file
89
src/js/components/Dropzones.js
Executable file
@ -0,0 +1,89 @@
|
||||
|
||||
import React, { PropTypes } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
|
||||
import Dropzone from './Dropzone'
|
||||
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
|
||||
class Dropzones extends React.Component{
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this._zones = [
|
||||
{
|
||||
title: 'Add to queue',
|
||||
icon: 'play',
|
||||
action: 'enqueue'
|
||||
},
|
||||
{
|
||||
title: 'Add to library',
|
||||
icon: 'music',
|
||||
action: 'add_to_library',
|
||||
accepts: ['track','album','playlist','artist']
|
||||
},
|
||||
{
|
||||
title: 'Add to playlist',
|
||||
icon: 'playlist',
|
||||
action: 'add_to_playlist',
|
||||
accepts: ['tltrack','track','album','playlist','artist']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
handleMouseMove(e){
|
||||
if( !this.props.dragger || !this.props.dragger.dragging ) return null;
|
||||
this.props.uiActions.dragMove( e )
|
||||
}
|
||||
|
||||
handleMouseUp(e, index){
|
||||
var target = this._zones[index]
|
||||
var victims = this.props.dragger.victims
|
||||
var uris = []
|
||||
for( var i = 0; i < victims.length; i++ ){
|
||||
uris.push( victims[i].uri )
|
||||
}
|
||||
|
||||
switch( target.action ){
|
||||
|
||||
case 'enqueue':
|
||||
this.props.mopidyActions.enqueueTracks( uris )
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
if( !this.props.dragger || !this.props.dragger.dragging ) return null
|
||||
|
||||
return (
|
||||
<div className="dropzones">
|
||||
{
|
||||
this._zones.map( (zone, index) => {
|
||||
return <Dropzone key={index} data={zone} handleMouseUp={ e => this.handleMouseUp(e, index) }/>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
dragger: state.ui.dragger
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Dropzones)
|
||||
@ -8,6 +8,7 @@ import MiniPlayer from './MiniPlayer'
|
||||
import Icon from './Icon'
|
||||
import Thumbnail from './Thumbnail'
|
||||
import SearchForm from './SearchForm'
|
||||
import Dropzones from './Dropzones'
|
||||
|
||||
import FontAwesome from 'react-fontawesome'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
@ -18,18 +19,6 @@ class Sidebar extends React.Component{
|
||||
super(props);
|
||||
}
|
||||
|
||||
renderDropzones(){
|
||||
if( !this.props.dragger || !this.props.dragger.dragging ) return null
|
||||
|
||||
return (
|
||||
<div className="dropzones">
|
||||
<div className="zone">
|
||||
<div className="title">Zone</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<aside>
|
||||
@ -101,8 +90,7 @@ class Sidebar extends React.Component{
|
||||
|
||||
</nav>
|
||||
|
||||
{ this.renderDropzones() }
|
||||
|
||||
<Dropzones />
|
||||
<MiniPlayer />
|
||||
|
||||
</aside>
|
||||
|
||||
@ -57,6 +57,10 @@ export function dragMove( e ){
|
||||
}
|
||||
}
|
||||
|
||||
export function dragCancel(){
|
||||
return { type: 'DRAG_CANCEL' }
|
||||
}
|
||||
|
||||
export function dragEnd(){
|
||||
return { type: 'DRAG_END' }
|
||||
}
|
||||
|
||||
@ -55,6 +55,15 @@ export default function reducer(ui = {}, action){
|
||||
}
|
||||
});
|
||||
|
||||
case 'DRAG_CANCEL':
|
||||
return Object.assign({}, ui, {
|
||||
dragger: {
|
||||
dragging: false,
|
||||
context: false,
|
||||
victims: false
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -63,7 +63,7 @@ class App extends React.Component{
|
||||
|
||||
shouldTriggerShortcut(e){
|
||||
var ignoreNodes = ['INPUT', 'TEXTAREA'];
|
||||
var keyCodes = [32];
|
||||
var keyCodes = [32,27];
|
||||
|
||||
if( ignoreNodes.indexOf(e.target.nodeName) > -1 ){
|
||||
return false;
|
||||
@ -82,13 +82,20 @@ class App extends React.Component{
|
||||
handleKeyUp(e){
|
||||
if( !this.shouldTriggerShortcut(e) ) return;
|
||||
|
||||
switch(e.keyCode){
|
||||
switch(e.keyCode){
|
||||
|
||||
case 32: // spacebar
|
||||
if( this.props.play_state == 'playing' ){
|
||||
this.props.mopidyActions.pause();
|
||||
}else{
|
||||
this.props.mopidyActions.play();
|
||||
}
|
||||
break;
|
||||
|
||||
case 27: // esc
|
||||
if( this.props.dragger.dragging ){
|
||||
this.props.uiActions.dragCancel();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
|
||||
|
||||
@import 'vendor/font-awesome/index';
|
||||
|
||||
@import 'global/variables';
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
|
||||
.dragging * {
|
||||
cursor: grabbing !important;
|
||||
cursor: -moz-grabbing !important;
|
||||
cursor: -webkit-grabbing !important;
|
||||
}
|
||||
|
||||
.dragger {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
@ -19,12 +25,23 @@
|
||||
z-index: 9998;
|
||||
background: rgba(25, 25, 25, 0.9);
|
||||
|
||||
.zone {
|
||||
.dropzone {
|
||||
@include animate();
|
||||
margin: 15px;
|
||||
padding: 50px 20px;
|
||||
background: $turquoise;
|
||||
padding: 40px 20px;
|
||||
background: $dark_grey;
|
||||
color: #FFFFFF;
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
margin: 0 auto 10px;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $turquoise;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user