Sortable commands
This commit is contained in:
74
src/js/components/Fields/Commands.js
Normal file
74
src/js/components/Fields/Commands.js
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
import React from 'react'
|
||||
import Sortable from 'react-sortablejs';
|
||||
import Icon from '../Icon';
|
||||
import Link from '../Link';
|
||||
import * as helpers from '../../helpers';
|
||||
|
||||
export default class Commands extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
|
||||
onChange(order){
|
||||
let commands = {};
|
||||
for (let i = 0; i <= order.length; i++){
|
||||
let command = this.props.commands[order[i]];
|
||||
if (command){
|
||||
commands[command.id] = {...command, ...{sort_order: i}};
|
||||
}
|
||||
}
|
||||
|
||||
this.props.onChange(commands);
|
||||
}
|
||||
|
||||
commands(){
|
||||
let commands = [];
|
||||
|
||||
if (this.props.commands){
|
||||
for (let key of Object.keys(this.props.commands)){
|
||||
commands.push({...this.props.commands[key]});
|
||||
}
|
||||
}
|
||||
|
||||
commands = helpers.sortItems(commands, 'sort_order');
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
render(){
|
||||
const commands = this.commands();
|
||||
|
||||
if (!commands){
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Sortable className="list commands-setup" onChange={(order, sortable, e) => {this.onChange(order)}}>
|
||||
{
|
||||
commands.map(command => {
|
||||
return (
|
||||
<div className="list__item commands-setup__item list__item--no-interaction" key={command.id} data-id={command.id}>
|
||||
<div className="col col--w90">
|
||||
<div className="commands__item commands__item--interactive" onClick={e => this.props.runCommand(command.id, true)}>
|
||||
<Icon className="commands__item__icon" name={command.icon} />
|
||||
<span className={command.colour+'-background commands__item__background'}></span>
|
||||
</div>
|
||||
<div className="commands-setup__item__url commands__item__url">
|
||||
{command.name ? command.name : <span className="grey-text">{command.url}</span>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="commands-setup__item__actions">
|
||||
<Link className="commands-setup__item__edit-button action" to={'/edit-command/'+command.id}>
|
||||
<Icon name="edit" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</Sortable>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ import { bindActionCreators } from 'redux';
|
||||
import VolumeControl from './VolumeControl';
|
||||
import MuteControl from './MuteControl';
|
||||
import Icon from '../Icon';
|
||||
import * as helpers from '../../helpers';
|
||||
|
||||
import * as coreActions from '../../services/core/actions';
|
||||
import * as pusherActions from '../../services/pusher/actions';
|
||||
@ -136,6 +137,8 @@ class OutputControl extends React.Component{
|
||||
commands_items.push(this.props.pusher_commands[key]);
|
||||
}
|
||||
}
|
||||
|
||||
commands_items = helpers.sortItems(commands_items, 'sort_order');
|
||||
|
||||
if (commands_items.length > 0){
|
||||
has_outputs = true;
|
||||
|
||||
@ -216,6 +216,13 @@ export function setCommand(command){
|
||||
}
|
||||
}
|
||||
|
||||
export function setCommands(commands){
|
||||
return {
|
||||
type: 'PUSHER_SET_COMMANDS',
|
||||
commands: commands
|
||||
}
|
||||
}
|
||||
|
||||
export function removeCommand(id){
|
||||
return {
|
||||
type: 'PUSHER_REMOVE_COMMAND',
|
||||
|
||||
@ -459,19 +459,23 @@ const PusherMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'PUSHER_SET_COMMAND':
|
||||
var commands_index = Object.assign({}, pusher.commands);
|
||||
var commands = Object.assign({}, pusher.commands);
|
||||
|
||||
if (commands_index[action.command.id]){
|
||||
var command = Object.assign({}, commands_index[action.command.id], action.command);
|
||||
if (commands[action.command.id]){
|
||||
var command = Object.assign({}, commands[action.command.id], action.command);
|
||||
} else {
|
||||
var command = action.command;
|
||||
}
|
||||
commands_index[action.command.id] = command;
|
||||
commands[action.command.id] = command;
|
||||
|
||||
request(store, 'set_commands', {commands: commands_index})
|
||||
store.dispatch(pusherActions.setCommands(commands));
|
||||
break
|
||||
|
||||
case 'PUSHER_SET_COMMANDS':
|
||||
request(store, 'set_commands', {commands: action.commands})
|
||||
.then(
|
||||
response => {
|
||||
// No action required, the change will be broadcast
|
||||
// No action required, the change will be broadcast
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
|
||||
@ -4,22 +4,21 @@ import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
|
||||
import ConfirmationButton from '../components/Fields/ConfirmationButton'
|
||||
import PusherConnectionList from '../components/PusherConnectionList'
|
||||
import SourcesPriority from '../components/Fields/SourcesPriority'
|
||||
import Header from '../components/Header'
|
||||
import Icon from '../components/Icon'
|
||||
import Thumbnail from '../components/Thumbnail'
|
||||
import URILink from '../components/URILink'
|
||||
import Services from '../components/Services'
|
||||
import ConfirmationButton from '../components/Fields/ConfirmationButton';
|
||||
import PusherConnectionList from '../components/PusherConnectionList';
|
||||
import SourcesPriority from '../components/Fields/SourcesPriority';
|
||||
import Commands from '../components/Fields/Commands';
|
||||
import Header from '../components/Header';
|
||||
import Icon from '../components/Icon';
|
||||
import Services from '../components/Services';
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as coreActions from '../services/core/actions'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
import * as pusherActions from '../services/pusher/actions'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
import * as lastfmActions from '../services/lastfm/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
import * as helpers from '../helpers';
|
||||
import * as coreActions from '../services/core/actions';
|
||||
import * as uiActions from '../services/ui/actions';
|
||||
import * as pusherActions from '../services/pusher/actions';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
import * as lastfmActions from '../services/lastfm/actions';
|
||||
import * as spotifyActions from '../services/spotify/actions';
|
||||
|
||||
class Settings extends React.Component {
|
||||
|
||||
@ -142,54 +141,6 @@ class Settings extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderCommands(){
|
||||
var commands = [];
|
||||
if (this.props.pusher.commands){
|
||||
for (var id in this.props.pusher.commands){
|
||||
if (this.props.pusher.commands.hasOwnProperty(id)){
|
||||
var command = Object.assign({}, this.props.pusher.commands[id]);
|
||||
try {
|
||||
command.command = JSON.parse(command.command);
|
||||
} catch(error){
|
||||
command.command = null;
|
||||
}
|
||||
commands.push(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (commands.length <= 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="list commands-setup">
|
||||
{
|
||||
commands.map(command => {
|
||||
return (
|
||||
<div className="list__item commands-setup__item list__item--no-interaction" key={command.id}>
|
||||
<div className="col col--w90">
|
||||
<div className="commands__item commands__item--interactive" onClick={e => this.props.pusherActions.runCommand(command.id, true)}>
|
||||
<Icon className="commands__item__icon" name={command.icon} />
|
||||
<span className={command.colour+'-background commands__item__background'}></span>
|
||||
</div>
|
||||
<div className="commands-setup__item__url commands__item__url">
|
||||
{command.name ? command.name : <span className="grey-text">{command.url}</span>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="commands-setup__item__actions">
|
||||
<Link className="commands-setup__item__edit-button action" to={'/edit-command/'+command.id}>
|
||||
<Icon name="edit" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
var options = (
|
||||
@ -371,7 +322,11 @@ class Settings extends React.Component {
|
||||
Commands
|
||||
</div>
|
||||
<div className="input">
|
||||
{this.renderCommands()}
|
||||
<Commands
|
||||
commands={this.props.pusher.commands}
|
||||
runCommand={(id, notify) => this.props.pusherActions.runCommand(id, notify)}
|
||||
onChange={commands => this.props.pusherActions.setCommands(commands)}
|
||||
/>
|
||||
<Link to={'/edit-command'} className="button button--default">Add new</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user