Remapping store
This commit is contained in:
@ -74,25 +74,6 @@ class Snapcast extends React.Component{
|
||||
{
|
||||
group.clients.map(client => {
|
||||
var name = client.config.name ? client.config.name : client.host.name;
|
||||
var groups_dropdown = [];
|
||||
for (var i = 0; i < groups.length; i++){
|
||||
|
||||
// Don't add our existing group
|
||||
if (groups[i].id !== group.id){
|
||||
groups_dropdown.push({
|
||||
label: (groups[i].name ? groups[i].name : 'Group '+groups[i].id.substring(0,3)),
|
||||
value: groups[i].id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// And append with 'New group' (which is actually
|
||||
// the existing group and middleware handles the behavior shift)
|
||||
groups_dropdown.push({
|
||||
label: 'New group',
|
||||
value: group.id,
|
||||
className: 'grey-text'
|
||||
});
|
||||
|
||||
var class_name = "list__item snapcast__client";
|
||||
if (client.connected){
|
||||
@ -104,58 +85,118 @@ class Snapcast extends React.Component{
|
||||
if (this.state.clients_expanded.includes(client.id)){
|
||||
return (
|
||||
<div className={class_name+" snapcast__client--expanded"} key={client.id}>
|
||||
<div className="snapcast__client__expander" onClick={e => this.toggleClientExpanded(client.id)}>
|
||||
<Icon name="check" />
|
||||
<div className="snapcast__client__header" onClick={e => this.toggleClientExpanded(client.id)}>
|
||||
{name}
|
||||
<div className="snapcast__client__header__icons">
|
||||
{!client.connected ? <Icon name="power_off" className="disconnected" /> : null}
|
||||
<Icon name="expand_less" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__name">
|
||||
<TextField
|
||||
onChange={value => this.props.snapcastActions.setClientName(client.id, value)}
|
||||
value={name}
|
||||
/>
|
||||
<DropdownField
|
||||
className="snapcast__client__group-field"
|
||||
icon="folder"
|
||||
name="Group"
|
||||
no_label
|
||||
no_status_icon
|
||||
value={group.id}
|
||||
options={groups_dropdown}
|
||||
uid={group.id+"_"+client.id}
|
||||
handleChange={value => {this.props.snapcastActions.setClientGroup(client.id, value); this.props.uiActions.hideContextMenu()}}
|
||||
/>
|
||||
</div>
|
||||
<div className="snapcast__client__volume">
|
||||
<VolumeControl
|
||||
className="snapcast__client__volume-control"
|
||||
volume={client.config.volume.percent}
|
||||
mute={client.config.volume.muted}
|
||||
onVolumeChange={percent => this.props.snapcastActions.setClientVolume(client.id, percent)}
|
||||
onMuteChange={mute => this.props.snapcastActions.setClientMute(client.id, mute)}
|
||||
/>
|
||||
</div>
|
||||
<div className="snapcast__client__latency">
|
||||
<LatencyControl
|
||||
max="100"
|
||||
value={client.config.latency}
|
||||
onChange={value => this.props.snapcastActions.setClientLatency(client.id, parseInt(value))}
|
||||
/>
|
||||
<TextField
|
||||
className="tiny"
|
||||
type="number"
|
||||
onChange={value => this.props.snapcastActions.setClientLatency(client.id, parseInt(value))}
|
||||
value={String(client.config.latency)}
|
||||
/>
|
||||
<div className="snapcast__client__details">
|
||||
<div className="field">
|
||||
<div className="name">
|
||||
Name
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={value => this.props.snapcastActions.setClientName(client.id, value)}
|
||||
value={name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field dropdown">
|
||||
<div className="name">
|
||||
Group
|
||||
</div>
|
||||
<div className="input">
|
||||
<select onChange={e => this.props.snapcastActions.setClientGroup(client.id, e.target.value)} value={group.id}>
|
||||
{
|
||||
groups.map(group => {
|
||||
return (
|
||||
<option value={group.id} key={group.id}>
|
||||
{group.name ? group.name : 'Group '+group.id.substring(0,3)}
|
||||
</option>
|
||||
);
|
||||
})
|
||||
}
|
||||
<option value={group.id}>
|
||||
New group
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__volume field">
|
||||
<div className="name">
|
||||
Volume
|
||||
</div>
|
||||
<div className="input">
|
||||
<VolumeControl
|
||||
className="snapcast__client__volume-control"
|
||||
volume={client.config.volume.percent}
|
||||
mute={client.config.volume.muted}
|
||||
onVolumeChange={percent => this.props.snapcastActions.setClientVolume(client.id, percent)}
|
||||
onMuteChange={mute => this.props.snapcastActions.setClientMute(client.id, mute)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__latency field">
|
||||
<div className="name">
|
||||
Latency
|
||||
</div>
|
||||
<div className="input">
|
||||
<LatencyControl
|
||||
max="100"
|
||||
value={client.config.latency}
|
||||
onChange={value => this.props.snapcastActions.setClientLatency(client.id, parseInt(value))}
|
||||
/>
|
||||
<TextField
|
||||
className="tiny"
|
||||
type="number"
|
||||
onChange={value => this.props.snapcastActions.setClientLatency(client.id, parseInt(value))}
|
||||
value={String(client.config.latency)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name tooltip">
|
||||
Power on command
|
||||
<span className="tooltip__content">
|
||||
Fire this HTTP request to turn power on
|
||||
</span>
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={value => console.log(value)}
|
||||
value="http://localhost:8080/sendCommand/power_on"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name tooltip">
|
||||
Power off command
|
||||
<span className="tooltip__content">
|
||||
Fire this HTTP request to turn power off
|
||||
</span>
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={value => console.log(value)}
|
||||
value="http://localhost:8080/sendCommand/power_off"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={class_name} key={client.id}>
|
||||
<div className="snapcast__client__expander" onClick={e => this.toggleClientExpanded(client.id)}>
|
||||
<Icon name="edit" />
|
||||
</div>
|
||||
<div className="snapcast__client__name">
|
||||
<div className={class_name+" snapcast__client--collapsed"} key={client.id}>
|
||||
<div className="snapcast__client__header" onClick={e => this.toggleClientExpanded(client.id)}>
|
||||
{name}
|
||||
<div className="snapcast__client__header__icons">
|
||||
{!client.connected ? <Icon name="power_off" className="disconnected" /> : null}
|
||||
<Icon name="expand_more" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -50,13 +50,6 @@ export function getServer(){
|
||||
}
|
||||
}
|
||||
|
||||
export function serverLoaded(server){
|
||||
return {
|
||||
type: 'SNAPCAST_SERVER_LOADED',
|
||||
server: server
|
||||
}
|
||||
}
|
||||
|
||||
export function setClientName(id, name){
|
||||
return {
|
||||
type: 'SNAPCAST_SET_CLIENT_NAME',
|
||||
@ -129,3 +122,51 @@ export function setGroupVolume(id, percent, old_percent = 0){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Record loaders
|
||||
*
|
||||
* We've got a loaded record, now we just need to plug it in to our state and stores.
|
||||
**/
|
||||
|
||||
export function serverLoaded(server){
|
||||
return serversLoaded([server]);
|
||||
}
|
||||
export function serversLoaded(servers){
|
||||
return {
|
||||
type: 'SNAPCAST_SERVERS_LOADED',
|
||||
servers: servers
|
||||
}
|
||||
}
|
||||
|
||||
export function clientLoaded(client){
|
||||
return clientsLoaded([client]);
|
||||
}
|
||||
export function clientsLoaded(clients){
|
||||
return {
|
||||
type: 'SNAPCAST_CLIENTS_LOADED',
|
||||
clients: clients
|
||||
}
|
||||
}
|
||||
|
||||
export function groupLoaded(group){
|
||||
return groupsLoaded([group]);
|
||||
}
|
||||
export function groupsLoaded(groups){
|
||||
return {
|
||||
type: 'SNAPCAST_SERVERS_LOADED',
|
||||
servers: group
|
||||
}
|
||||
}
|
||||
|
||||
export function streamLoaded(stream){
|
||||
return streamsLoaded([stream]);
|
||||
}
|
||||
export function streamsLoaded(streams){
|
||||
return {
|
||||
type: 'SNAPCAST_STREAMS_LOADED',
|
||||
streams: streams
|
||||
}
|
||||
}
|
||||
@ -2,31 +2,27 @@
|
||||
export default function reducer(snapcast = {}, action){
|
||||
switch (action.type){
|
||||
|
||||
case 'SNAPCAST_SERVER_LOADED':
|
||||
return Object.assign({}, snapcast, {
|
||||
streams: action.streams,
|
||||
groups: action.groups,
|
||||
clients: action.clients
|
||||
});
|
||||
case 'SNAPCAST_CLIENTS_LOADED':
|
||||
var clients = Object.assign({}, snapcast.clients);
|
||||
for (var client of action.clients){
|
||||
clients[client.uri] = client;
|
||||
}
|
||||
return Object.assign({}, snapcast, { clients: clients });
|
||||
|
||||
case 'SNAPCAST_GROUP_UPDATED':
|
||||
case 'SNAPCAST_SOURCES_LOADED':
|
||||
var sources = Object.assign({}, snapcast.sources);
|
||||
for (var source of action.sources){
|
||||
sources[source.uri] = source;
|
||||
}
|
||||
return Object.assign({}, snapcast, { sources: sources });
|
||||
|
||||
case 'SNAPCAST_GROUPS_LOADED':
|
||||
var groups = Object.assign({}, snapcast.groups);
|
||||
var group = groups[action.key];
|
||||
groups[action.key] = Object.assign({}, group, action.group);
|
||||
for (var group of action.groups){
|
||||
groups[group.uri] = group;
|
||||
}
|
||||
return Object.assign({}, snapcast, { groups: groups });
|
||||
|
||||
case 'SNAPCAST_CLIENT_UPDATED':
|
||||
var clients = Object.assign({}, snapcast.clients);
|
||||
var client = clients[action.key];
|
||||
client.config = Object.assign({}, client.config, action.client.config);
|
||||
clients[action.key] = client;
|
||||
return Object.assign({}, snapcast, { clients: clients });
|
||||
|
||||
case 'SNAPCAST_CLIENT_REMOVED':
|
||||
var clients = Object.assign({}, snapcast.clients);
|
||||
delete clients[action.key];
|
||||
return Object.assign({}, snapcast, { clients: clients });
|
||||
|
||||
default:
|
||||
return snapcast
|
||||
}
|
||||
|
||||
@ -44,43 +44,55 @@
|
||||
|
||||
&__client {
|
||||
@include clearfix();
|
||||
position: relative;
|
||||
padding: 14px 10px;
|
||||
padding: 0;
|
||||
|
||||
&--disconnected {
|
||||
opacity: 0.5;
|
||||
.snapcast__client__header {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
&--expanded {
|
||||
.snapcast__client__name {
|
||||
margin-top: -10px;
|
||||
margin-right: 30px;
|
||||
margin-left: -14px;
|
||||
margin-bottom: 20px;
|
||||
background: rgba(255,255,255,0.1);
|
||||
|
||||
.light-theme & {
|
||||
background: rgba(0,0,0,0.1);
|
||||
}
|
||||
}
|
||||
|
||||
&__name {
|
||||
margin-right: 40px;
|
||||
padding-right: 50px;
|
||||
position: relative;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
&--collapsed {
|
||||
.snapcast__client__header:hover {
|
||||
background: rgba(255,255,255,0.03);
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding-right: 30px;
|
||||
.light-theme & {
|
||||
background: rgba(0,0,0,0.03);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__expander {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 14px;
|
||||
&__header {
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
padding: 14px 10px;
|
||||
|
||||
&__icons {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
padding: 14px 10px;
|
||||
|
||||
.icon {
|
||||
padding-left: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__details {
|
||||
position: relative;
|
||||
padding: 0 14px 14px 14px;
|
||||
}
|
||||
|
||||
&__group-field {
|
||||
@ -93,11 +105,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__volume {
|
||||
width: 49%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
&__volume-control {
|
||||
padding-top: 11px;
|
||||
padding-right: 10px;
|
||||
@ -118,11 +125,6 @@
|
||||
}
|
||||
|
||||
&__latency {
|
||||
@include clearfix();
|
||||
width: 49%;
|
||||
padding-left: 2%;
|
||||
float: left;
|
||||
|
||||
input[type="number"] {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user