Dropdown fields

This commit is contained in:
James Barnsley
2019-11-07 17:01:27 +13:00
parent 17763f7fe7
commit 33d6c66d96
16 changed files with 10151 additions and 5565 deletions

View File

@ -0,0 +1,17 @@
import React from 'react';
import Icon from '../Icon';
const SelectField = ({ onChange, value, options }) => (
<div className="select-field">
<select
onChange={(e) => onChange(e.target.value)}
value={value}
>
{options.map((option) => <option value={option.value}>{option.label}</option>)}
</select>
<Icon name="arrow_drop_down" className="select-field__icon" />
</div>
);
export default SelectField;

View File

@ -7,7 +7,7 @@ import VolumeControl from './Fields/VolumeControl';
import MuteControl from './Fields/MuteControl';
import LatencyControl from './Fields/LatencyControl';
import TextField from './Fields/TextField';
import Icon from './Icon';
import SelectField from './Fields/SelectField';
import * as helpers from '../helpers';
@ -56,18 +56,14 @@ const SnapcastClients = ({ actions, group, groups, show_disconnected_clients })
Group
</div>
<div className="input">
<select onChange={(e) => actions.setClientGroup(client.id, e.target.value)} value={group.id}>
{
groups.map((group) => (
<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>
<SelectField
onChange={(value) => actions.setClientGroup(client.id, value)}
value={group.id}
options={[
...groups.map((group) => ({ value: group.id, label: group.name })),
{ value: group.id, label: 'New group' },
]}
/>
</div>
</label>
<div className="snapcast__client__volume field">
@ -83,6 +79,7 @@ const SnapcastClients = ({ actions, group, groups, show_disconnected_clients })
<VolumeControl
className="snapcast__volume-control snapcast__client__volume-control"
volume={client.volume}
mute={client.mute}
onVolumeChange={(percent) => actions.setClientVolume(client.id, percent)}
/>
</div>

View File

@ -12,6 +12,7 @@ import Link from './Link';
import * as helpers from '../helpers';
import * as actions from '../services/snapcast/actions';
import SelectField from './Fields/SelectField';
const SnapcastGroups = (props) => {
const {
@ -64,19 +65,13 @@ const SnapcastGroups = (props) => {
Stream
</div>
<div className="input">
<select onChange={(e) => actions.setGroupStream(group.id, e.target.value)} value={group.stream_id}>
{
streamsArray.map((stream) => (
<option value={stream.id} key={stream.id}>
{stream.id}
{' '}
(
{stream.status}
)
</option>
))
}
</select>
<SelectField
onChange={(value) => actions.setGroupStream(group.id, value)}
value={group.stream_id}
options={streamsArray.map((stream) => (
{ value: stream.id, label: `${stream.id} (${stream.status})` }
))}
/>
</div>
</div>
<div className="field">
@ -86,12 +81,13 @@ const SnapcastGroups = (props) => {
<div className="input">
<MuteControl
className="snapcast__group__mute-control snapcast__mute-control"
mute={group.muted}
mute={group.mute}
onMuteChange={(mute) => actions.setGroupMute(group.id, mute)}
/>
<VolumeControl
className="snapcast__group__volume-control snapcast__volume-control"
volume={group_volume}
mute={group.mute}
onVolumeChange={(percent, previousPercent) => actions.setGroupVolume(group.id, percent, previousPercent)}
/>
</div>
@ -156,8 +152,7 @@ const SnapcastGroups = (props) => {
}
return (
<div className="snapcast__groups">
<a name="services-snapcast-groups" />
<div className="snapcast__groups" id="services-snapcast-groups">
<div className="snapcast__groups__menu menu">
<div className="menu__inner">
{groupsArray.map((group) => renderMenuItem(group))}

View File

@ -879,10 +879,6 @@ export const formatGroup = function (data) {
}
}
if (group.name === undefined || group.name === '') {
group.name = `Group ${data.id.substring(0, 3)}`;
}
if (group.mute === undefined && data.mute !== undefined) {
group.mute = data.mute;
}

View File

@ -285,11 +285,10 @@ const SnapcastMiddleware = (function () {
case 'SNAPCAST_GROUPS_LOADED':
var groups_index = { ...snapcast.groups };
var groups_loaded = [];
var clients_loaded = [];
for (const raw_group of action.groups) {
var group = helpers.formatGroup(raw_group);
const groups_loaded = action.groups.map(raw_group => {
let group = helpers.formatGroup(raw_group);
if (groups_index[group.id]) {
group = { ...groups_index[group.id], ...group };
@ -300,8 +299,13 @@ const SnapcastMiddleware = (function () {
clients_loaded = [...clients_loaded, ...raw_group.clients];
}
groups_loaded.push(group);
}
// Create a name (display only) based on it's ID
if (group.name === undefined || group.name === '') {
group.name = `Group ${group.id.substring(0, 3)}`;
}
return group;
});
action.groups = groups_loaded;
@ -462,7 +466,7 @@ const SnapcastMiddleware = (function () {
request(store, 'Group.SetClients', params)
.then(
response => {
store.dispatch(snapcastActions.serverLoaded(response.server));
store.dispatch(snapcastActions.groupsLoaded(response.server.groups, true));
},
error => {
store.dispatch(coreActions.handleException(
@ -557,7 +561,7 @@ const SnapcastMiddleware = (function () {
store.dispatch(snapcastActions.groupLoaded(
{
id: action.id,
muted: response.mute,
mute: response.mute,
},
));
},

View File

@ -73,27 +73,24 @@ class LibraryBrowseDirectory extends React.Component {
const uri_elements = uri.split('/');
return (
<h4>
<h4 className="breadcrumbs">
{uri_elements.map((uri_element, index) => {
// Reconstruct a URL to this element
let uri = 'file://';
for (let i = 0; i <= index; i++) {
uri += `/${uri_elements[i]}`;
}
let uri = 'file://';
for (let i = 0; i <= index; i++) {
uri += `/${uri_elements[i]}`;
}
return (
return (
<span key={uri}>
{index > 0 && (
<span>
<Icon type="fontawesome" name="angle-right" />
{' '}
</span>
<Icon type="fontawesome" name="angle-right" />
)}
<URILink type="browse" uri={uri}>
{decodeURI(uri_element)}
</URILink>
</span>
);
);
})}
</h4>
);

View File

@ -38,6 +38,8 @@
@import 'components/related-artists';
@import 'components/error-message';
@import 'components/sortable';
@import 'components/mute-control';
@import 'components/select-field';
@import 'views/artist';
@import 'views/user';

View File

@ -1 +1,4 @@
.mute-control {
cursor: pointer;
}

View File

@ -0,0 +1,12 @@
.select-field {
display: flex;
position: relative;
&__icon {
position: absolute;
top: 14px;
right: 14px;
pointer-events: none;
}
}

View File

@ -292,6 +292,13 @@ h4 {
margin-bottom: -1px;
margin-top: 0;
}
&.breadcrumbs {
.icon {
padding-left: 10px;
padding-right: 10px;
}
}
}
h5 {