Edit client modal... we'll need a server one too
This commit is contained in:
@ -4279,7 +4279,7 @@ input[type="submit"] {
|
||||
opacity: 0.5; }
|
||||
|
||||
.snapcast .group .clients .client > .inner {
|
||||
padding: 5px 5px 5px 20px;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #383734; }
|
||||
|
||||
.snapcast .group .clients .client .name {
|
||||
@ -4288,24 +4288,22 @@ input[type="submit"] {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 0; }
|
||||
.snapcast .group .clients .client .name.editing {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
letter-spacing: -0.01rem;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004); }
|
||||
|
||||
.snapcast .group .clients .client .volume-control .mute-control {
|
||||
.snapcast .group .clients .client .controls .edit {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
cursor: pointer; }
|
||||
|
||||
.snapcast .group .clients .client .controls .volume-control .mute-control {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
padding: 0 10px;
|
||||
border: 0; }
|
||||
|
||||
.snapcast .group .clients .client .volume-control .slider-wrapper {
|
||||
padding-left: 30px; }
|
||||
.snapcast .group .clients .client .controls .volume-control .slider-wrapper {
|
||||
margin-left: 40px; }
|
||||
|
||||
.snapcast .group .clients .client .volume-control.muted .slider .progress {
|
||||
.snapcast .group .clients .client .controls .volume-control.muted .slider .progress {
|
||||
background: #a3a19f; }
|
||||
|
||||
aside {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -38,7 +38,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1521657991";
|
||||
var build = "1521786595";
|
||||
var version = "3.14.2";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
62
src/js/components/Modal/EditSnapcastClientModal.js
Executable file
62
src/js/components/Modal/EditSnapcastClientModal.js
Executable file
@ -0,0 +1,62 @@
|
||||
|
||||
import React, { PropTypes } from 'react';
|
||||
import FontAwesome from 'react-fontawesome';
|
||||
|
||||
import Icon from '../Icon';
|
||||
import * as helpers from '../../helpers';
|
||||
|
||||
export default class EditSnapcastClientModal extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
var client = this.props.clients[this.props.data.id];
|
||||
this.state = {
|
||||
id: client.id,
|
||||
name: client.config.name,
|
||||
latency: client.config.latency.toString()
|
||||
};
|
||||
}
|
||||
|
||||
handleSave(e){
|
||||
this.props.pusherActions.setSnapcastClientName(this.state.id, this.state.name);
|
||||
this.props.pusherActions.setSnapcastClientLatency(this.state.id, parseInt(this.state.latency));
|
||||
this.props.uiActions.closeModal();
|
||||
}
|
||||
|
||||
handleDelete(e){
|
||||
this.props.pusherActions.deleteSnapcastClient(this.state.id);
|
||||
this.props.uiActions.closeModal();
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
<h1>Edit speaker</h1>
|
||||
<h2 className="grey-text">Description</h2>
|
||||
|
||||
<form>
|
||||
<div className="field text">
|
||||
<span className="label">Name</span>
|
||||
<input
|
||||
type="text"
|
||||
onChange={e => this.setState({name: e.target.value})}
|
||||
value={this.state.name} />
|
||||
</div>
|
||||
<div className="field text">
|
||||
<span className="label">Latency (ms)</span>
|
||||
<input
|
||||
type="number"
|
||||
onChange={e => this.setState({latency: e.target.value})}
|
||||
value={this.state.latency} />
|
||||
</div>
|
||||
</form>
|
||||
<form>
|
||||
<div className="actions centered-text">
|
||||
<button className="destructive large" onClick={e => this.handleDelete(e)}>Delete</button>
|
||||
<button className="primary large" onClick={e => this.handleSave(e)}>Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ import AddToQueueModal from './AddToQueueModal'
|
||||
import CreatePlaylistModal from './CreatePlaylistModal'
|
||||
import EditPlaylistModal from './EditPlaylistModal'
|
||||
import EditRadioModal from './EditRadioModal'
|
||||
import EditSnapcastClientModal from './EditSnapcastClientModal'
|
||||
import ImageZoomModal from './ImageZoomModal'
|
||||
import KioskModeModal from './KioskModeModal'
|
||||
import SearchURISchemesModal from './SearchURISchemesModal'
|
||||
@ -115,6 +116,13 @@ class Modal extends React.Component{
|
||||
artists={this.props.artists}
|
||||
tracks={this.props.tracks} /> : null }
|
||||
|
||||
{ this.props.modal.name == 'edit_snapcast_client' ? <EditSnapcastClientModal
|
||||
uiActions={this.props.uiActions}
|
||||
pusherActions={this.props.pusherActions}
|
||||
data={this.props.modal.data}
|
||||
clients={this.props.snapcast_clients}
|
||||
groups={this.props.snapcast_groups} /> : null }
|
||||
|
||||
{ this.props.modal.name == 'image_zoom' ? <ImageZoomModal
|
||||
uiActions={this.props.uiActions}
|
||||
data={this.props.modal.data} /> : null }
|
||||
@ -159,7 +167,9 @@ const mapStateToProps = (state, ownProps) => {
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
spotify_authorized: state.spotify.authorization,
|
||||
spotify_library_playlists: state.spotify.library_playlists,
|
||||
mopidy_library_playlists: state.mopidy.library_playlists
|
||||
mopidy_library_playlists: state.mopidy.library_playlists,
|
||||
snapcast_groups: state.pusher.snapcast_groups,
|
||||
snapcast_clients: state.pusher.snapcast_clients
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,26 +40,6 @@ class Snapcast extends React.Component{
|
||||
this.setState({editing_client: null});
|
||||
}
|
||||
|
||||
renderClientName(client){
|
||||
if (this.state.editing_client && this.state.editing_client.id == client.id){
|
||||
return (
|
||||
<input
|
||||
className="name editing"
|
||||
value={this.state.editing_client.name}
|
||||
onChange={e => this.setState({editing_client: {id: client.id, name: e.target.value}})}
|
||||
onBlur={e => this.saveEditingClient()}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
var name = client.config.name ? client.config.name : client.host.name;
|
||||
return (
|
||||
<div className="name" onClick={e => this.setState({editing_client: {id: client.id, name: name}})}>
|
||||
{name} {!client.connected ? '(disconnected)' : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
if (!this.props.snapcast_clients || !this.props.snapcast_groups){
|
||||
return null;
|
||||
@ -103,11 +83,17 @@ class Snapcast extends React.Component{
|
||||
<div className="clients">
|
||||
{
|
||||
group.clients.map(client => {
|
||||
var name = client.config.name ? client.config.name : client.host.name;
|
||||
return (
|
||||
<div className={"client "+(client.connected ? 'connected' : 'disconnected')} key={client.id}>
|
||||
<div className="inner">
|
||||
{this.renderClientName(client)}
|
||||
<div className="name">
|
||||
{name} {!client.connected ? '(disconnected)' : null}
|
||||
</div>
|
||||
<div className="controls">
|
||||
<div className="control edit" onClick={e => this.props.uiActions.openModal('edit_snapcast_client',{id: client.id})}>
|
||||
<FontAwesome name="cog" />
|
||||
</div>
|
||||
<VolumeControl
|
||||
volume={client.config.volume.percent}
|
||||
mute={client.config.volume.muted}
|
||||
|
||||
@ -200,3 +200,28 @@ export function setSnapcastClientName(id, name){
|
||||
}
|
||||
}
|
||||
|
||||
export function setSnapcastClientLatency(id, latency){
|
||||
return {
|
||||
type: 'PUSHER_SET_SNAPCAST_CLIENT_LATENCY',
|
||||
data: {
|
||||
method: 'Client.SetLatency',
|
||||
params: {
|
||||
id: id,
|
||||
latency: latency
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteSnapcastClient(id){
|
||||
return {
|
||||
type: 'PUSHER_DELETE_SNAPCAST_CLIENT',
|
||||
data: {
|
||||
method: 'Server.DeleteClient',
|
||||
params: {
|
||||
id: id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -525,8 +525,8 @@ const PusherMiddleware = (function(){
|
||||
var clients_ids = [];
|
||||
|
||||
// And now this groups' clients
|
||||
for (var i = 0; i < group.clients.length; i++){
|
||||
var client = group.clients[i];
|
||||
for (var j = 0; j < group.clients.length; j++){
|
||||
var client = group.clients[j];
|
||||
clients[client.id] = client;
|
||||
clients_ids.push(client.id);
|
||||
}
|
||||
@ -544,7 +544,7 @@ const PusherMiddleware = (function(){
|
||||
type: 'PUSHER_SNAPCAST',
|
||||
snapcast_clients: clients,
|
||||
snapcast_groups: groups
|
||||
})
|
||||
});
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
@ -604,6 +604,49 @@ const PusherMiddleware = (function(){
|
||||
);
|
||||
break
|
||||
|
||||
case 'PUSHER_SET_SNAPCAST_CLIENT_LATENCY':
|
||||
request(store, 'snapcast_instruct', action.data)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch({
|
||||
type: 'PUSHER_SNAPCAST_CLIENT_UPDATED',
|
||||
key: action.data.params.id,
|
||||
client: {
|
||||
config: {
|
||||
latency: response.latency
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message
|
||||
));
|
||||
}
|
||||
);
|
||||
break
|
||||
|
||||
case 'PUSHER_DELETE_SNAPCAST_CLIENT':
|
||||
request(store, 'snapcast_instruct', action.data)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch({
|
||||
type: 'PUSHER_SNAPCAST_CLIENT_REMOVED',
|
||||
key: action.data.params.id
|
||||
})
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message
|
||||
));
|
||||
}
|
||||
);
|
||||
break
|
||||
|
||||
// This action is irrelevant to us, pass it on to the next middleware
|
||||
default:
|
||||
return next(action);
|
||||
|
||||
@ -61,6 +61,11 @@ export default function reducer(pusher = {}, action){
|
||||
snapcast_clients[action.key] = client;
|
||||
return Object.assign({}, pusher, { snapcast_clients: snapcast_clients });
|
||||
|
||||
case 'PUSHER_SNAPCAST_CLIENT_REMOVED':
|
||||
var snapcast_clients = Object.assign({}, pusher.snapcast_clients);
|
||||
delete snapcast_clients[action.key];
|
||||
return Object.assign({}, pusher, { snapcast_clients: snapcast_clients });
|
||||
|
||||
default:
|
||||
return pusher
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
& > .inner {
|
||||
padding: 5px 5px 5px 20px;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid $grey;
|
||||
}
|
||||
|
||||
@ -29,32 +29,32 @@
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
|
||||
&.editing {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
letter-spacing: -0.01rem;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004);
|
||||
}
|
||||
}
|
||||
|
||||
.volume-control {
|
||||
.mute-control {
|
||||
.controls {
|
||||
|
||||
.edit {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
padding: 0 10px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.slider-wrapper {
|
||||
padding-left: 30px;
|
||||
}
|
||||
.volume-control {
|
||||
.mute-control {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
padding: 0 10px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&.muted {
|
||||
.slider .progress {
|
||||
background: $mid_grey;
|
||||
.slider-wrapper {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
&.muted {
|
||||
.slider .progress {
|
||||
background: $mid_grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user