Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@ -26,6 +26,7 @@ import {
|
||||
sourceIcon,
|
||||
} from '../util/helpers';
|
||||
import { collate } from '../util/format';
|
||||
import Button from '../components/Button';
|
||||
|
||||
export class Album extends React.Component {
|
||||
componentDidMount = () => {
|
||||
@ -66,12 +67,10 @@ export class Album extends React.Component {
|
||||
componentDidUpdate = ({
|
||||
uri: prevUri,
|
||||
album: prevAlbum,
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
}) => {
|
||||
const {
|
||||
uri,
|
||||
album,
|
||||
mopidy_connected,
|
||||
coreActions: {
|
||||
loadAlbum,
|
||||
},
|
||||
@ -82,15 +81,11 @@ export class Album extends React.Component {
|
||||
|
||||
if (uri !== prevUri) {
|
||||
loadAlbum(uri);
|
||||
} else if (!prev_mopidy_connected && mopidy_connected) {
|
||||
if (uriSource(uri) !== 'spotify') {
|
||||
loadAlbum(uri);
|
||||
}
|
||||
}
|
||||
|
||||
// We have just received our full album or our album artists
|
||||
if ((!prevAlbum && album) || (!prevAlbum.artists && album.artists)) {
|
||||
if (album.wiki === undefined && album.artists.length > 0) {
|
||||
if (album.artists && album.wiki === undefined) {
|
||||
getAlbum(album.uri, album.artists[0].name, album.name);
|
||||
}
|
||||
}
|
||||
@ -260,12 +255,15 @@ export class Album extends React.Component {
|
||||
</div>
|
||||
|
||||
<div className="actions">
|
||||
<button type="button" className="button button--primary" onClick={this.play}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.play}
|
||||
tracking={{ category: 'Album', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
</Button>
|
||||
{uriSource(uri) === 'spotify' && (
|
||||
<FollowButton
|
||||
className="secondary"
|
||||
uri={uri}
|
||||
is_following={this.inLibrary()}
|
||||
/>
|
||||
@ -320,7 +318,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
spotify_library_albums: state.spotify.library_albums,
|
||||
local_library_albums: state.mopidy.library_albums,
|
||||
spotify_authorized: state.spotify.authorization,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -33,6 +33,8 @@ import {
|
||||
import { collate } from '../util/format';
|
||||
import { sortItems, applyFilter } from '../util/arrays';
|
||||
import { i18n, I18n } from '../locale';
|
||||
import Button from '../components/Button';
|
||||
import { trackEvent } from '../components/Trackable';
|
||||
|
||||
class Artist extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -42,12 +44,10 @@ class Artist extends React.Component {
|
||||
|
||||
componentDidUpdate = ({
|
||||
uri: prevUri,
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
artist: prevArtist,
|
||||
}) => {
|
||||
const {
|
||||
uri,
|
||||
mopidy_connected,
|
||||
artist,
|
||||
coreActions: {
|
||||
loadArtist,
|
||||
@ -56,10 +56,6 @@ class Artist extends React.Component {
|
||||
|
||||
if (uri !== prevUri) {
|
||||
loadArtist(uri);
|
||||
} else if (!prev_mopidy_connected && mopidy_connected) {
|
||||
if (uriSource(uri) !== 'spotify') {
|
||||
loadArtist(uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (!prevArtist && artist) this.setWindowTitle(artist);
|
||||
@ -69,12 +65,14 @@ class Artist extends React.Component {
|
||||
onResetFilters = () => {
|
||||
this.onChangeFilter(null);
|
||||
this.onChangeSort(null);
|
||||
trackEvent({ category: 'Artist', action: 'FilterAlbums', label: 'Reset' });
|
||||
}
|
||||
|
||||
onChangeFilter = (value) => {
|
||||
const { uiActions: { set, hideContextMenu } } = this.props;
|
||||
set({ artist_albums_filter: value });
|
||||
hideContextMenu();
|
||||
trackEvent({ category: 'Artist', action: 'FilterAlbums', label: value });
|
||||
}
|
||||
|
||||
onChangeSort = (value) => {
|
||||
@ -88,7 +86,7 @@ class Artist extends React.Component {
|
||||
} = this.props;
|
||||
|
||||
let reverse = false;
|
||||
if (value !== null && sort == value) {
|
||||
if (value !== null && sort === value) {
|
||||
reverse = !sort_reverse;
|
||||
}
|
||||
|
||||
@ -97,6 +95,7 @@ class Artist extends React.Component {
|
||||
artist_albums_sort: value,
|
||||
});
|
||||
hideContextMenu();
|
||||
trackEvent({ category: 'Artist', action: 'SortAlbums', label: `${value} ${reverse ? 'DESC' : 'ASC'}` });
|
||||
}
|
||||
|
||||
onPlay = () => {
|
||||
@ -192,38 +191,38 @@ class Artist extends React.Component {
|
||||
const sort_options = [
|
||||
{
|
||||
value: null,
|
||||
label: 'Default',
|
||||
label: i18n('artist.albums.sort.default'),
|
||||
},
|
||||
{
|
||||
value: 'name',
|
||||
label: 'Name',
|
||||
label: i18n('artist.albums.sort.name'),
|
||||
},
|
||||
{
|
||||
value: 'release_date',
|
||||
label: 'Date',
|
||||
label: i18n('artist.albums.sort.release_date'),
|
||||
},
|
||||
{
|
||||
value: 'tracks_uris.length',
|
||||
label: 'Tracks',
|
||||
label: i18n('artist.albums.sort.track_count'),
|
||||
},
|
||||
];
|
||||
|
||||
const filter_options = [
|
||||
{
|
||||
value: null,
|
||||
label: 'All',
|
||||
label: i18n('artist.albums.filter.all'),
|
||||
},
|
||||
{
|
||||
value: 'album',
|
||||
label: 'Albums',
|
||||
label: i18n('artist.albums.filter.albums'),
|
||||
},
|
||||
{
|
||||
value: 'single',
|
||||
label: 'Singles',
|
||||
label: i18n('artist.albums.filter.singles'),
|
||||
},
|
||||
{
|
||||
value: 'compilation',
|
||||
label: 'Compilations',
|
||||
label: i18n('artist.albums.filter.compilations'),
|
||||
},
|
||||
];
|
||||
|
||||
@ -254,13 +253,12 @@ class Artist extends React.Component {
|
||||
uiActions={uiActions}
|
||||
/>
|
||||
</div>
|
||||
<Link
|
||||
<Button
|
||||
to={`/artist/${encodeURIComponent(uri)}/related-artists`}
|
||||
scrollTo="#sub-views-menu"
|
||||
className="button button--default"
|
||||
>
|
||||
<I18n path="artist.overview.related_artists.more" />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -288,10 +286,15 @@ class Artist extends React.Component {
|
||||
handleChange={this.onChangeFilter}
|
||||
/>
|
||||
{(sort || filter) && (
|
||||
<a className="button button--discrete button--destructive button--small" onClick={this.onResetFilters}>
|
||||
<Button
|
||||
discrete
|
||||
type="destructive"
|
||||
size="small"
|
||||
onClick={this.onResetFilters}
|
||||
>
|
||||
<Icon name="clear" />
|
||||
<I18n path="actions.reset" />
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</h4>
|
||||
|
||||
@ -497,9 +500,13 @@ class Artist extends React.Component {
|
||||
<div className="heading__content">
|
||||
<h1>{this.props.artist ? this.props.artist.name : null}</h1>
|
||||
<div className="actions">
|
||||
<button className="button button--primary" onClick={this.onPlay}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.onPlay}
|
||||
tracking={{ category: 'Artist', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
</Button>
|
||||
{is_spotify && (
|
||||
<FollowButton
|
||||
uri={uri}
|
||||
@ -596,7 +603,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
sort: (state.ui.artist_albums_sort ? state.ui.artist_albums_sort : null),
|
||||
sort_reverse: (!!state.ui.artist_albums_sort_reverse),
|
||||
spotify_authorized: state.spotify.authorization,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import Header from '../components/Header';
|
||||
import Icon from '../components/Icon';
|
||||
import Button from '../components/Button';
|
||||
import * as uiActions from '../services/ui/actions';
|
||||
import * as pusherActions from '../services/pusher/actions';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
@ -85,12 +85,16 @@ class Debug extends React.Component {
|
||||
pusher_data,
|
||||
snapcast_data,
|
||||
} = this.state;
|
||||
|
||||
|
||||
const options = (
|
||||
<a className="button button--discrete button--no-hover" onClick={this.onBack}>
|
||||
<Button
|
||||
onClick={this.onBack}
|
||||
noHover
|
||||
discrete
|
||||
>
|
||||
<Icon name="keyboard_backspace" />
|
||||
<I18n path="actions.back" />
|
||||
</a>
|
||||
</Button>
|
||||
);
|
||||
|
||||
return (
|
||||
@ -107,17 +111,14 @@ class Debug extends React.Component {
|
||||
<div className="field checkbox">
|
||||
<div className="name">Test mode</div>
|
||||
<div className="input">
|
||||
{toggling_test_mode && (
|
||||
<span className="button button--working">Applying...</span>
|
||||
)}
|
||||
{!toggling_test_mode && (
|
||||
<span
|
||||
className={`button button--${test_mode ? 'destructive' : 'default'}`}
|
||||
onClick={this.toggleTestMode}
|
||||
>
|
||||
<I18n path={`actions.${test_mode ? 'disable' : 'enable'}`} />
|
||||
</span>
|
||||
)}
|
||||
<Button
|
||||
type={test_mode ? 'destructive' : null}
|
||||
working={toggling_test_mode}
|
||||
onClick={this.toggleTestMode}
|
||||
tracking={{ category: 'Debug', action: 'TestMode', label: test_mode ? 'Disable' : 'Enable' }}
|
||||
>
|
||||
<I18n path={`actions.${test_mode ? 'disable' : 'enable'}`} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field checkbox">
|
||||
@ -178,9 +179,24 @@ class Debug extends React.Component {
|
||||
<div className="field">
|
||||
<div className="name" />
|
||||
<div className="input">
|
||||
<a className="button button--default" onClick={(e) => this.props.uiActions.createNotification({ content: 'Test notification' })}><I18n path="debug.create_notification" /></a>
|
||||
<a className="button button--default" onClick={(e) => this.props.uiActions.startProcess('test_process', "Test process", {remaining: 68, total: 100})}><I18n path="debug.create_process" /></a>
|
||||
<a className="button button--default" onClick={(e) => this.props.pusherActions.request('test')}><I18n path="debug.run_test" /></a>
|
||||
<Button
|
||||
onClick={() => this.props.uiActions.createNotification({ content: 'Test notification' })}
|
||||
tracking={{ category: 'Debug', action: 'Test notification' }}
|
||||
>
|
||||
<I18n path="debug.create_notification" />
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => this.props.uiActions.startProcess('test_process', "Test process", {remaining: 68, total: 100})}
|
||||
tracking={{ category: 'Debug', action: 'Test process' }}
|
||||
>
|
||||
<I18n path="debug.create_process" />
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => this.props.pusherActions.request('test')}
|
||||
tracking={{ category: 'Debug', action: 'Run test process' }}
|
||||
>
|
||||
<I18n path="debug.run_test" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -221,7 +237,12 @@ class Debug extends React.Component {
|
||||
<div className="field">
|
||||
<div className="name" />
|
||||
<div className="input">
|
||||
<button type="submit" className="button button--default">Send</button>
|
||||
<Button
|
||||
submit
|
||||
tracking={{ category: 'Debug', action: 'Mopidy', label: 'Send' }}
|
||||
>
|
||||
<I18n path="actions.send" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -258,7 +279,12 @@ class Debug extends React.Component {
|
||||
<div className="field">
|
||||
<div className="name" />
|
||||
<div className="input">
|
||||
<button type="submit" className="button button--default"><I18n path="actions.send" /></button>
|
||||
<Button
|
||||
submit
|
||||
tracking={{ category: 'Debug', action: 'Pusher', label: 'Send' }}
|
||||
>
|
||||
<I18n path="actions.send" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -277,7 +303,12 @@ class Debug extends React.Component {
|
||||
<div className="field">
|
||||
<div className="name" />
|
||||
<div className="input">
|
||||
<button type="submit" className="button button--default"><I18n path="actions.send" /></button>
|
||||
<Button
|
||||
submit
|
||||
tracking={{ category: 'Debug', action: 'Snapcast', label: 'Send' }}
|
||||
>
|
||||
<I18n path="actions.send" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -2,13 +2,12 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import ReactGA from 'react-ga';
|
||||
import ErrorMessage from '../components/ErrorMessage';
|
||||
import Link from '../components/Link';
|
||||
import Button from '../components/Button';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import Parallax from '../components/Parallax';
|
||||
import NiceNumber, { nice_number } from '../components/NiceNumber';
|
||||
import PinButton from '../components/Fields/PinButton';
|
||||
import { nice_number } from '../components/NiceNumber';
|
||||
import { Dater, dater } from '../components/Dater';
|
||||
import LazyLoadListener from '../components/LazyLoadListener';
|
||||
import FollowButton from '../components/Fields/FollowButton';
|
||||
@ -53,12 +52,10 @@ class Playlist extends React.Component {
|
||||
componentDidUpdate = ({
|
||||
uri: prevUri,
|
||||
playlist: prevPlaylist,
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
}) => {
|
||||
const {
|
||||
uri,
|
||||
playlist,
|
||||
mopidy_connected,
|
||||
coreActions: {
|
||||
loadPlaylist,
|
||||
},
|
||||
@ -73,10 +70,6 @@ class Playlist extends React.Component {
|
||||
|
||||
if (uri !== prevUri) {
|
||||
loadPlaylist(uri);
|
||||
} else if (!prev_mopidy_connected && mopidy_connected) {
|
||||
if (uriSource(uri) !== 'spotify') {
|
||||
loadPlaylist(uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (!prevPlaylist && playlist) this.setWindowTitle(playlist);
|
||||
@ -183,27 +176,49 @@ class Playlist extends React.Component {
|
||||
return library.indexOf(uri) > -1;
|
||||
}
|
||||
|
||||
togglePinned = () => {
|
||||
const {
|
||||
uri,
|
||||
coreActions: {
|
||||
addPinned,
|
||||
removePinned,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (this.isPinned()) {
|
||||
removePinned(uri);
|
||||
} else {
|
||||
addPinned(uri);
|
||||
}
|
||||
}
|
||||
|
||||
renderActions = () => {
|
||||
const {
|
||||
uri,
|
||||
playlist: {
|
||||
can_edit,
|
||||
name,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
switch (uriSource(this.props.uri)) {
|
||||
switch (uriSource(uri)) {
|
||||
case 'm3u':
|
||||
return (
|
||||
<div className="actions">
|
||||
<button className="button button--primary" onClick={this.play}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.play}
|
||||
tracking={{ category: 'Playlist', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
<Link
|
||||
className="button button--default"
|
||||
</Button>
|
||||
<Button
|
||||
to={`/playlist/${encodeURIComponent(uri)}/edit`}
|
||||
tracking={{ category: 'Playlist', action: 'Edit' }}
|
||||
>
|
||||
<I18n path="actions.edit" />
|
||||
</Link>
|
||||
</Button>
|
||||
<PinButton item={{ uri, name }} />
|
||||
<ContextMenuTrigger onTrigger={this.handleContextMenu} />
|
||||
</div>
|
||||
);
|
||||
@ -212,28 +227,38 @@ class Playlist extends React.Component {
|
||||
if (can_edit) {
|
||||
return (
|
||||
<div className="actions">
|
||||
<button className="button button--primary" onClick={this.play}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.play}
|
||||
tracking={{ category: 'Playlist', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
<Link
|
||||
className="button button--default"
|
||||
</Button>
|
||||
<Button
|
||||
to={`/playlist/${encodeURIComponent(uri)}/edit`}
|
||||
tracking={{ category: 'Playlist', action: 'Edit' }}
|
||||
>
|
||||
<I18n path="actions.edit" />
|
||||
</Link>
|
||||
</Button>
|
||||
<PinButton item={{ uri, name }} />
|
||||
<ContextMenuTrigger onTrigger={this.handleContextMenu} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="actions">
|
||||
<button className="button button--primary" onClick={this.play}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.play}
|
||||
tracking={{ category: 'Playlist', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
</Button>
|
||||
<FollowButton
|
||||
uri={uri}
|
||||
is_following={this.inLibrary()}
|
||||
/>
|
||||
<PinButton item={{ uri, name }} />
|
||||
<ContextMenuTrigger onTrigger={this.handleContextMenu} />
|
||||
</div>
|
||||
);
|
||||
@ -241,12 +266,14 @@ class Playlist extends React.Component {
|
||||
default:
|
||||
return (
|
||||
<div className="actions">
|
||||
<button
|
||||
className="button button--primary"
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.play}
|
||||
tracking={{ category: 'Playlist', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
</Button>
|
||||
<PinButton item={{ uri, name }} />
|
||||
<ContextMenuTrigger onTrigger={this.handleContextMenu} />
|
||||
</div>
|
||||
);
|
||||
@ -386,7 +413,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
me = {},
|
||||
} = {},
|
||||
mopidy: {
|
||||
connected: mopidy_connected,
|
||||
library_playlists: local_library_playlists,
|
||||
} = {},
|
||||
} = state;
|
||||
@ -404,7 +430,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
playlist: (playlists[uri] !== undefined ? playlists[uri] : false),
|
||||
spotify_library_playlists,
|
||||
local_library_playlists,
|
||||
mopidy_connected,
|
||||
spotify_authorized,
|
||||
spotify_userid: (me && me.id) || null,
|
||||
};
|
||||
|
||||
@ -21,6 +21,7 @@ import {
|
||||
uriType,
|
||||
} from '../util/helpers';
|
||||
import { i18n, I18n } from '../locale';
|
||||
import Button from '../components/Button';
|
||||
|
||||
const Artwork = ({
|
||||
image,
|
||||
@ -236,19 +237,19 @@ class Queue extends React.Component {
|
||||
const options = (
|
||||
<span>
|
||||
{this.props.spotify_enabled && (
|
||||
<Link className="button button--no-hover" to="/queue/radio">
|
||||
<Button noHover discrete to="/queue/radio">
|
||||
<Icon name="radio" />
|
||||
<I18n path="now_playing.context_actions.radio" />
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
<Link className="button button--no-hover" to="/queue/history">
|
||||
<Button noHover discrete to="/queue/history">
|
||||
<Icon name="history" />
|
||||
<I18n path="now_playing.context_actions.history" />
|
||||
</Link>
|
||||
<Link className="button button--no-hover" to="/queue/add-uri">
|
||||
</Button>
|
||||
<Button noHover discrete to="/queue/add-uri">
|
||||
<Icon name="playlist_add" />
|
||||
<I18n path="actions.add" />
|
||||
</Link>
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import * as pusherActions from '../services/pusher/actions';
|
||||
import * as spotifyActions from '../services/spotify/actions';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
import { i18n, I18n } from '../locale';
|
||||
import Button from '../components/Button';
|
||||
|
||||
class QueueHistory extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -18,19 +19,18 @@ class QueueHistory extends React.Component {
|
||||
this.loadHistory();
|
||||
}
|
||||
|
||||
componentDidUpdate = ({ mopidy_connected: prev_mopidy_connected }) => {
|
||||
const { mopidy_connected } = this.props;
|
||||
if (!prev_mopidy_connected && mopidy_connected) this.loadHistory();
|
||||
componentDidUpdate = () => {
|
||||
this.loadHistory();
|
||||
}
|
||||
|
||||
loadHistory = (props = this.props) => {
|
||||
loadHistory = () => {
|
||||
const {
|
||||
mopidyActions: { getQueueHistory },
|
||||
mopidyActions: {
|
||||
getQueueHistory,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (props.mopidy_connected) {
|
||||
getQueueHistory();
|
||||
}
|
||||
getQueueHistory();
|
||||
}
|
||||
|
||||
onBack = () => {
|
||||
@ -46,12 +46,16 @@ class QueueHistory extends React.Component {
|
||||
} = this.props;
|
||||
|
||||
const options = (
|
||||
<a className="button button--no-hover" onClick={this.onBack}>
|
||||
<Button
|
||||
onClick={this.onBack}
|
||||
noHover
|
||||
tracking={{ category: 'QueueHistory', action: 'Back' }}
|
||||
>
|
||||
<I18n path="actions.back">
|
||||
<Icon name="keyboard_backspace" />
|
||||
{' '}
|
||||
</I18n>
|
||||
</a>
|
||||
</Button>
|
||||
);
|
||||
|
||||
const tracks = queue_history.map((item) => ({
|
||||
@ -82,7 +86,6 @@ class QueueHistory extends React.Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
tracks: (state.core.tracks ? state.core.tracks : {}),
|
||||
queue_history: (state.mopidy.queue_history ? state.mopidy.queue_history : []),
|
||||
});
|
||||
|
||||
@ -21,6 +21,7 @@ import * as lastfmActions from '../services/lastfm/actions';
|
||||
import * as spotifyActions from '../services/spotify/actions';
|
||||
import { isHosted } from '../util/helpers';
|
||||
import { i18n, I18n, languagesAvailable } from '../locale';
|
||||
import Button from '../components/Button';
|
||||
|
||||
class Settings extends React.Component {
|
||||
constructor(props) {
|
||||
@ -127,13 +128,13 @@ class Settings extends React.Component {
|
||||
const loading = processes.local_scan && processes.local_scan.status === 'running';
|
||||
|
||||
return (
|
||||
<button
|
||||
className={`button button--default ${loading ? 'button--working' : ''}`}
|
||||
<Button
|
||||
working={loading}
|
||||
onClick={this.doLocalScan}
|
||||
type="button"
|
||||
tracking={{ category: 'System', action: 'LocalScan' }}
|
||||
>
|
||||
<I18n path="settings.advanced.start_local_scan" />
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@ -159,24 +160,26 @@ class Settings extends React.Component {
|
||||
|
||||
const options = (
|
||||
<span>
|
||||
<Link
|
||||
className="button button--discrete button--no-hover"
|
||||
<Button
|
||||
discrete
|
||||
noHover
|
||||
to="/settings/debug"
|
||||
>
|
||||
<I18n path="debug.title">
|
||||
<Icon name="code" />
|
||||
</I18n>
|
||||
</Link>
|
||||
<a
|
||||
className="button button--discrete button--no-hover"
|
||||
</Button>
|
||||
<Button
|
||||
href="https://github.com/jaedb/Iris/wiki"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
discrete
|
||||
noHover
|
||||
>
|
||||
<I18n path="settings.help">
|
||||
<Icon name="help" />
|
||||
</I18n>
|
||||
</a>
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -403,9 +406,9 @@ class Settings extends React.Component {
|
||||
runCommand={(id, notify) => runCommand(id, notify)}
|
||||
onChange={(commands) => setCommands(commands)}
|
||||
/>
|
||||
<Link to="/edit-command" className="button button--default">
|
||||
<Button to="/edit-command">
|
||||
<I18n path="actions.add" />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -504,43 +507,40 @@ class Settings extends React.Component {
|
||||
|
||||
<div className="field">
|
||||
{this.renderLocalScanButton()}
|
||||
<Link
|
||||
className="button button--default"
|
||||
to="/share-configuration"
|
||||
>
|
||||
<Button to="/share-configuration">
|
||||
<I18n path="settings.advanced.share_configuration" />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
{pusher.version.upgrade_available && (
|
||||
<button
|
||||
className="button button--secondary"
|
||||
<Button
|
||||
type="secondary"
|
||||
onClick={this.doUpgrade}
|
||||
type="button"
|
||||
tracking={{ category: 'System', action: 'Upgrade', label: pusher.version.latest }}
|
||||
>
|
||||
<I18n path="settings.advanced.version.upgrade" version={pusher.version.latest} />
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
<button
|
||||
className={`button button--destructive${mopidy.restarting ? ' button--working' : ''}`}
|
||||
<Button
|
||||
type="destructive"
|
||||
working={mopidy.restarting}
|
||||
onClick={this.doRestart}
|
||||
type="button"
|
||||
tracking={{ category: 'System', action: 'Restart' }}
|
||||
>
|
||||
<I18n path="settings.advanced.restart" />
|
||||
</button>
|
||||
</Button>
|
||||
<ConfirmationButton
|
||||
className="button--destructive"
|
||||
content={i18n('settings.advanced.reset')}
|
||||
onConfirm={this.resetAllSettings}
|
||||
/>
|
||||
<button
|
||||
className="button button--destructive"
|
||||
<Button
|
||||
type="destructive"
|
||||
onClick={this.resetServiceWorkerAndCache}
|
||||
type="button"
|
||||
tracking={{ category: 'System', action: 'ResetCache' }}
|
||||
>
|
||||
<I18n path="settings.advanced.reset_cache" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<h4 className="underline">
|
||||
@ -563,18 +563,26 @@ class Settings extends React.Component {
|
||||
<br />
|
||||
<br />
|
||||
<div>
|
||||
<a className="button button--default" href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=james%40barnsley%2enz&lc=NZ&item_name=James%20Barnsley¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted" target="_blank">
|
||||
<Button
|
||||
href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=james%40barnsley%2enz&lc=NZ&item_name=James%20Barnsley¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted"
|
||||
target="_blank"
|
||||
tracking={{ category: 'About', action: 'Paypal' }}
|
||||
>
|
||||
<I18n path="settings.about.donate">
|
||||
<Icon type="fontawesome" name="paypal" />
|
||||
{' '}
|
||||
</I18n>
|
||||
</a>
|
||||
<a className="button button--default" href="https://github.com/jaedb/Iris" target="_blank">
|
||||
</Button>
|
||||
<Button
|
||||
href="https://github.com/jaedb/Iris"
|
||||
target="_blank"
|
||||
tracking={{ category: 'About', action: 'GitHub' }}
|
||||
>
|
||||
<I18n path="settings.about.github">
|
||||
<Icon type="fontawesome" name="github" />
|
||||
{' '}
|
||||
</I18n>
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
@ -27,6 +27,7 @@ import {
|
||||
uriType,
|
||||
} from '../util/helpers';
|
||||
import { i18n, I18n } from '../locale';
|
||||
import Button from '../components/Button';
|
||||
|
||||
class Track extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -52,14 +53,12 @@ class Track extends React.Component {
|
||||
componentDidUpdate = ({
|
||||
uri: prevUri,
|
||||
track: prevTrack,
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
}) => {
|
||||
const {
|
||||
uri,
|
||||
track,
|
||||
genius_authorized,
|
||||
lastfm_authorized,
|
||||
mopidy_connected,
|
||||
coreActions: {
|
||||
loadTrack,
|
||||
},
|
||||
@ -70,14 +69,13 @@ class Track extends React.Component {
|
||||
getTrack,
|
||||
},
|
||||
} = this.props;
|
||||
// if our URI has changed, fetch new track
|
||||
|
||||
if (prevUri !== uri) {
|
||||
loadTrack(uri);
|
||||
if (genius_authorized && track.artists) findTrackLyrics(track);
|
||||
|
||||
// if mopidy has just connected AND we're not a Spotify track, go get
|
||||
} else if (!prev_mopidy_connected && mopidy_connected) {
|
||||
if (uriSource(uri) !== 'spotify') loadTrack(uri);
|
||||
if (genius_authorized && track.artists) {
|
||||
findTrackLyrics(track);
|
||||
}
|
||||
}
|
||||
|
||||
// We have just received our full track or our track artists
|
||||
@ -299,9 +297,13 @@ class Track extends React.Component {
|
||||
</div>
|
||||
|
||||
<div className="actions">
|
||||
<button className="button button--primary" onClick={this.play} type="button">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.play}
|
||||
tracking={{ category: 'Track', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play" />
|
||||
</button>
|
||||
</Button>
|
||||
<LastfmLoveButton
|
||||
uri={uri}
|
||||
artist={(track.artists ? track.artists[0].name : null)}
|
||||
@ -370,7 +372,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
lastfm_authorized: state.lastfm.authorization,
|
||||
spotify_authorized: state.spotify.authorization,
|
||||
genius_authorized: state.genius.authorization,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
import { isLoading } from '../../util/helpers';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class DiscoverFeatured extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -89,10 +90,14 @@ class DiscoverFeatured extends React.Component {
|
||||
}
|
||||
|
||||
const options = (
|
||||
<a className="button button--no-hover" onClick={this.onRefresh}>
|
||||
<Button
|
||||
noHover
|
||||
onClick={this.onRefresh}
|
||||
tracking={{ category: 'DiscoverFeatured', action: 'Refresh' }}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
<I18n path="actions.refresh" />
|
||||
</a>
|
||||
</Button>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -13,6 +13,7 @@ import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
import { isLoading } from '../../util/helpers';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class DiscoverNewReleases extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -119,10 +120,14 @@ class DiscoverNewReleases extends React.Component {
|
||||
}
|
||||
|
||||
const options = (
|
||||
<a className="button button--no-hover" onClick={this.refresh}>
|
||||
<Button
|
||||
noHover
|
||||
onClick={this.refresh}
|
||||
tracking={{ category: 'DiscoverFeatured', action: 'Refresh' }}
|
||||
>
|
||||
<Icon name="refresh" />
|
||||
<I18n path="actions.refresh" />
|
||||
</a>
|
||||
</Button>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -24,6 +24,7 @@ import {
|
||||
} from '../../util/helpers';
|
||||
import { arrayOf, indexToArray } from '../../util/arrays';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class Discover extends React.Component {
|
||||
constructor(props) {
|
||||
@ -526,9 +527,13 @@ class Discover extends React.Component {
|
||||
<I18n path="discover.recommendations.tracks" />
|
||||
<div className="pull-right">
|
||||
<ContextMenuTrigger onTrigger={this.handleContextMenu} />
|
||||
<button className="button button--primary" onClick={this.playTracks} type="button">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={this.playTracks}
|
||||
tracking={{ category: 'DiscoverRecommendations', action: 'Play' }}
|
||||
>
|
||||
<I18n path="actions.play_all" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</h4>
|
||||
<TrackList className="discover-track-list" uri={this.uri()} tracks={tracks} />
|
||||
@ -608,15 +613,19 @@ class Discover extends React.Component {
|
||||
handleChange={this.toggleTunability}
|
||||
/>
|
||||
<div className="intro__actions__separator" />
|
||||
<span
|
||||
className={`submit button button--primary button--large${is_loading ? ' button--working' : ''}`}
|
||||
<Button
|
||||
className="submit"
|
||||
type="primary"
|
||||
size="large"
|
||||
working={is_loading}
|
||||
onClick={this.getRecommendations}
|
||||
tracking={{ category: 'DiscoverRecommendations', action: 'Submit' }}
|
||||
>
|
||||
<Icon name="explore" />
|
||||
<I18n path="discover.recommendations.find_recommendations" afterContent>
|
||||
{' '}
|
||||
</I18n>
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -40,16 +40,6 @@ class LibraryAlbums extends React.Component {
|
||||
uiActions: {
|
||||
setWindowTitle,
|
||||
},
|
||||
mopidy_connected,
|
||||
mopidy_library_albums_status,
|
||||
source,
|
||||
mopidyActions,
|
||||
spotifyActions,
|
||||
googleActions,
|
||||
google_available,
|
||||
google_library_albums_status,
|
||||
spotify_available,
|
||||
spotify_library_albums_status,
|
||||
} = this.props;
|
||||
|
||||
// Restore any limit defined in our location state
|
||||
@ -60,59 +50,71 @@ class LibraryAlbums extends React.Component {
|
||||
}
|
||||
|
||||
setWindowTitle(i18n('library.albums.title'));
|
||||
this.getMopidyLibrary();
|
||||
this.getGoogleLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
|
||||
if (mopidy_connected && mopidy_library_albums_status !== 'finished' && mopidy_library_albums_status !== 'started' && (source === 'all' || source === 'local')) {
|
||||
mopidyActions.getLibraryAlbums();
|
||||
}
|
||||
componentDidUpdate = ({ source: prevSource }) => {
|
||||
const { source } = this.props;
|
||||
|
||||
if (google_available && google_library_albums_status !== 'finished' && google_library_albums_status !== 'started' && (source === 'all' || source === 'google')) {
|
||||
googleActions.getLibraryAlbums();
|
||||
}
|
||||
|
||||
if (spotify_available && spotify_library_albums_status !== 'finished' && spotify_library_albums_status !== 'started' && (source == 'all' || source === 'spotify')) {
|
||||
spotifyActions.getLibraryAlbums();
|
||||
if (source !== prevSource) {
|
||||
this.getMopidyLibrary();
|
||||
this.getGoogleLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate = ({
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
}) => {
|
||||
getMopidyLibrary = () => {
|
||||
const {
|
||||
mopidy_connected,
|
||||
google_available,
|
||||
spotify_available,
|
||||
source,
|
||||
mopidyActions,
|
||||
googleActions,
|
||||
spotifyActions,
|
||||
mopidy_library_albums_status,
|
||||
google_library_albums_status,
|
||||
spotify_library_albums_status,
|
||||
mopidy_library_playlists,
|
||||
mopidyActions: {
|
||||
getLibraryAlbums,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (mopidy_connected && (source === 'all' || source === 'local')) {
|
||||
if (!prev_mopidy_connected) mopidyActions.getLibraryAlbums();
|
||||
if (source !== 'local' && source !== 'all') return;
|
||||
if (mopidy_library_playlists) return;
|
||||
|
||||
// Filter changed, but we haven't got this provider's library yet
|
||||
if (source !== 'all' && source !== 'local' && mopidy_library_albums_status !== 'finished' && mopidy_library_albums_status !== 'started') {
|
||||
mopidyActions.getLibraryAlbums();
|
||||
}
|
||||
}
|
||||
getLibraryAlbums();
|
||||
};
|
||||
|
||||
if (google_available && (source === 'all' || source === 'google')) {
|
||||
// Filter changed, but we haven't got this provider's library yet
|
||||
if (source !== 'all' && source !== 'google' && google_library_albums_status !== 'finished' && google_library_albums_status !== 'started') {
|
||||
googleActions.getLibraryAlbums();
|
||||
}
|
||||
}
|
||||
getGoogleLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
google_available,
|
||||
google_library_albums_status,
|
||||
googleActions: {
|
||||
getLibraryAlbums,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (spotify_available && (source === 'all' || source === 'spotify')) {
|
||||
// Filter changed, but we haven't got this provider's library yet
|
||||
if (spotify_library_albums_status !== 'finished' && spotify_library_albums_status !== 'started') {
|
||||
spotifyActions.getLibraryAlbums();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!google_available) return;
|
||||
if (source !== 'google' && source !== 'all') return;
|
||||
if (google_library_albums_status === 'finished') return;
|
||||
if (google_library_albums_status === 'started') return;
|
||||
|
||||
getLibraryAlbums();
|
||||
};
|
||||
|
||||
getSpotifyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
spotify_available,
|
||||
spotify_library_albums_status,
|
||||
spotifyActions: {
|
||||
getLibraryAlbums,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (!spotify_available) return;
|
||||
if (source !== 'spotify' && source !== 'all') return;
|
||||
if (spotify_library_albums_status === 'finished') return;
|
||||
if (spotify_library_albums_status === 'started') return;
|
||||
|
||||
getLibraryAlbums();
|
||||
};
|
||||
|
||||
handleContextMenu = (e, item) => {
|
||||
const {
|
||||
@ -398,7 +400,6 @@ class LibraryAlbums extends React.Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
load_queue: state.ui.load_queue,
|
||||
artists: state.core.artists,
|
||||
|
||||
@ -31,6 +31,12 @@ class LibraryArtists extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
uiActions: {
|
||||
setWindowTitle,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
// Restore any limit defined in our location state
|
||||
const state = (this.props.location.state ? this.props.location.state : {});
|
||||
if (state.limit) {
|
||||
@ -39,57 +45,72 @@ class LibraryArtists extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
this.props.uiActions.setWindowTitle(i18n('library.artists.title'));
|
||||
setWindowTitle(i18n('library.artists.title'));
|
||||
|
||||
if (!this.props.mopidy_library_artists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')) {
|
||||
this.props.mopidyActions.getLibraryArtists();
|
||||
}
|
||||
this.getMopidyLibrary();
|
||||
this.getGoogleLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
|
||||
if (this.props.google_available && !this.props.google_library_artists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'google')) {
|
||||
this.props.googleActions.getLibraryArtists();
|
||||
}
|
||||
componentDidUpdate = ({ source: prevSource }) => {
|
||||
const { source } = this.props;
|
||||
|
||||
if (this.props.spotify_available && this.props.spotify_library_artists_status != 'finished' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
this.props.spotifyActions.getLibraryArtists();
|
||||
if (source !== prevSource) {
|
||||
this.getMopidyLibrary();
|
||||
this.getGoogleLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate = ({
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
}) => {
|
||||
getMopidyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
mopidy_connected,
|
||||
google_available,
|
||||
spotify_available,
|
||||
mopidyActions,
|
||||
googleActions,
|
||||
spotifyActions,
|
||||
mopidy_library_artists,
|
||||
google_library_artists,
|
||||
spotify_library_artists_status,
|
||||
mopidyActions: {
|
||||
getLibraryArtists,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (mopidy_connected && (source === 'all' || source === 'local')) {
|
||||
if (!prev_mopidy_connected) mopidyActions.getLibraryArtists();
|
||||
if (source !== 'local' && source !== 'all') return;
|
||||
if (mopidy_library_artists) return;
|
||||
|
||||
if (source !== 'all' && source !== 'local' && !mopidy_library_artists) {
|
||||
mopidyActions.getLibraryArtists();
|
||||
}
|
||||
}
|
||||
getLibraryArtists();
|
||||
};
|
||||
|
||||
if (mopidy_connected && google_available && (source === 'all' || source === 'google')) {
|
||||
if (source !== 'all' && source !== 'google' && !google_library_artists) {
|
||||
googleActions.getLibraryArtists();
|
||||
}
|
||||
}
|
||||
getGoogleLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
google_available,
|
||||
google_library_artists,
|
||||
googleActions: {
|
||||
getLibraryArtists,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (spotify_available && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_library_artists_status !== 'finished' && spotify_library_artists_status !== 'started') {
|
||||
spotifyActions.getLibraryArtists();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!google_available) return;
|
||||
if (source !== 'google' && source !== 'all') return;
|
||||
if (google_library_artists) return;
|
||||
|
||||
getLibraryArtists();
|
||||
};
|
||||
|
||||
getSpotifyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
spotify_available,
|
||||
spotify_library_artists_status,
|
||||
spotifyActions: {
|
||||
getLibraryArtists,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (!spotify_available) return;
|
||||
if (source !== 'spotify' && source !== 'all') return;
|
||||
if (spotify_library_artists_status === 'finished') return;
|
||||
if (spotify_library_artists_status === 'started') return;
|
||||
|
||||
getLibraryArtists();
|
||||
};
|
||||
|
||||
handleContextMenu(e, item) {
|
||||
const data = {
|
||||
@ -324,8 +345,7 @@ class LibraryArtists extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
const mapStateToProps = (state) => ({
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
mopidy_library_artists: state.mopidy.library_artists,
|
||||
google_available: (state.mopidy.uri_schemes && state.mopidy.uri_schemes.includes('gmusic:')),
|
||||
|
||||
@ -17,15 +17,14 @@ class LibraryBrowse extends React.Component {
|
||||
this.props.uiActions.setWindowTitle(i18n('library.browse.title'));
|
||||
}
|
||||
|
||||
componentDidUpdate = ({ mopidy_connected: prev_mopidy_connected}) => {
|
||||
const { mopidy_connected } = this.props;
|
||||
if (!prev_mopidy_connected && mopidy_connected) this.loadDirectory();
|
||||
}
|
||||
loadDirectory = () => {
|
||||
const {
|
||||
mopidyActions: {
|
||||
getDirectory,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
loadDirectory(props = this.props) {
|
||||
if (props.mopidy_connected) {
|
||||
this.props.mopidyActions.getDirectory(null);
|
||||
}
|
||||
getDirectory(null);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -64,6 +63,10 @@ class LibraryBrowse extends React.Component {
|
||||
subdirectory.icons = ['/iris/assets/backgrounds/browse-soundcloud.jpg'];
|
||||
break;
|
||||
|
||||
case 'Mixcloud':
|
||||
subdirectory.icons = ['/iris/assets/backgrounds/browse-mixcloud.jpg'];
|
||||
break;
|
||||
|
||||
case 'iTunes Store: Podcasts':
|
||||
subdirectory.icons = ['/iris/assets/backgrounds/browse-itunes.jpg'];
|
||||
break;
|
||||
@ -124,9 +127,8 @@ class LibraryBrowse extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
const mapStateToProps = (state) => ({
|
||||
load_queue: state.ui.load_queue,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
directory: state.mopidy.directory,
|
||||
view: state.ui.library_directory_view,
|
||||
});
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
} from '../../util/helpers';
|
||||
import { arrayOf, sortItems } from '../../util/arrays';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class LibraryBrowseDirectory extends React.Component {
|
||||
constructor(props) {
|
||||
@ -45,27 +46,23 @@ class LibraryBrowseDirectory extends React.Component {
|
||||
this.loadDirectory();
|
||||
}
|
||||
|
||||
componentDidUpdate = ({
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
uri: prevUri,
|
||||
}) => {
|
||||
const {
|
||||
uri,
|
||||
mopidy_connected,
|
||||
} = this.props;
|
||||
componentDidUpdate = ({ uri: prevUri }) => {
|
||||
const { uri } = this.props;
|
||||
|
||||
if (!prev_mopidy_connected && mopidy_connected) this.loadDirectory();
|
||||
if (uri && uri !== prevUri) this.loadDirectory();
|
||||
if (uri && uri !== prevUri) {
|
||||
this.loadDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
loadDirectory(props = this.props) {
|
||||
if (props.mopidy_connected) {
|
||||
let uri = null;
|
||||
if (props.uri !== undefined) {
|
||||
uri = props.uri;
|
||||
}
|
||||
this.props.mopidyActions.getDirectory(uri);
|
||||
}
|
||||
loadDirectory = () => {
|
||||
const {
|
||||
uri,
|
||||
mopidyActions: {
|
||||
getDirectory,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
getDirectory(uri);
|
||||
}
|
||||
|
||||
loadMore = () => {
|
||||
@ -221,15 +218,24 @@ class LibraryBrowseDirectory extends React.Component {
|
||||
handleChange={(value) => { uiActions.set({ library_directory_view: value }); uiActions.hideContextMenu(); }}
|
||||
/>
|
||||
{tracks && (
|
||||
<a className="button button--no-hover" onClick={(e) => { uiActions.hideContextMenu(); this.playAll(e, all_tracks); }}>
|
||||
<Button
|
||||
onClick={(e) => { uiActions.hideContextMenu(); this.playAll(e, all_tracks); }}
|
||||
noHover
|
||||
discrete
|
||||
tracking={{ category: 'Directory', action: 'Play' }}
|
||||
>
|
||||
<Icon name="play_circle_filled" />
|
||||
<I18n path="actions.play_all" />
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
<a className="button button--no-hover" onClick={(e) => { uiActions.hideContextMenu(); this.goBack(e); }}>
|
||||
<Button
|
||||
onClick={(e) => { uiActions.hideContextMenu(); this.goBack(e); }}
|
||||
noHover
|
||||
tracking={{ category: 'Directory', action: 'Back' }}
|
||||
>
|
||||
<Icon name="keyboard_backspace" />
|
||||
<I18n path="actions.back" />
|
||||
</a>
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -283,7 +289,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
uri,
|
||||
load_queue: state.ui.load_queue,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
directory: state.mopidy.directory,
|
||||
view: state.ui.library_directory_view,
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import Link from '../../components/Link';
|
||||
import Button from '../../components/Button';
|
||||
import PlaylistGrid from '../../components/PlaylistGrid';
|
||||
import List from '../../components/List';
|
||||
import DropdownField from '../../components/Fields/DropdownField';
|
||||
@ -39,40 +39,49 @@ class LibraryPlaylists extends React.Component {
|
||||
|
||||
this.props.uiActions.setWindowTitle(i18n('library.playlists.title'));
|
||||
|
||||
if (!this.props.mopidy_library_playlists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')) {
|
||||
this.props.mopidyActions.getLibraryPlaylists();
|
||||
}
|
||||
|
||||
if (this.props.spotify_available && this.props.spotify_library_playlists_status !== 'finished' && (this.props.source == 'all' || this.props.source == 'spotify')) {
|
||||
this.props.spotifyActions.getLibraryPlaylists();
|
||||
}
|
||||
this.getMopidyLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
|
||||
componentDidUpdate = ({
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
}) => {
|
||||
getMopidyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
mopidy_connected,
|
||||
mopidy_library_playlists,
|
||||
spotify_available,
|
||||
spotify_library_playlists_status,
|
||||
mopidyActions,
|
||||
spotifyActions,
|
||||
mopidyActions: {
|
||||
getLibraryPlaylists,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (mopidy_connected && (source == 'all' || source == 'local')) {
|
||||
if (!prev_mopidy_connected) mopidyActions.getLibraryPlaylists();
|
||||
if (source !== 'local' && source !== 'all') return;
|
||||
if (mopidy_library_playlists) return;
|
||||
|
||||
if (source !== 'all' && source !== 'local' && !mopidy_library_playlists) {
|
||||
this.props.mopidyActions.getLibraryPlaylists();
|
||||
}
|
||||
}
|
||||
getLibraryPlaylists();
|
||||
};
|
||||
|
||||
if (spotify_available && (source === 'all' || source === 'spotify')) {
|
||||
if (spotify_library_playlists_status !== 'finished' && spotify_library_playlists_status !== 'started') {
|
||||
spotifyActions.getLibraryPlaylists();
|
||||
}
|
||||
getSpotifyLibrary = () => {
|
||||
const {
|
||||
source,
|
||||
spotify_available,
|
||||
spotify_library_playlists_status,
|
||||
spotifyActions: {
|
||||
getLibraryPlaylists,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (!spotify_available) return;
|
||||
if (source !== 'spotify' && source !== 'all') return;
|
||||
if (spotify_library_playlists_status === 'finished') return;
|
||||
if (spotify_library_playlists_status === 'started') return;
|
||||
|
||||
getLibraryPlaylists();
|
||||
};
|
||||
|
||||
componentDidUpdate = ({ source: prevSource }) => {
|
||||
const { source } = this.props;
|
||||
|
||||
if (source !== prevSource) {
|
||||
this.getMopidyLibrary();
|
||||
this.getSpotifyLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,10 +281,15 @@ class LibraryPlaylists extends React.Component {
|
||||
options={source_options}
|
||||
handleChange={(value) => { this.props.uiActions.set({ library_playlists_source: value }); this.props.uiActions.hideContextMenu(); }}
|
||||
/>
|
||||
<Link className="button button--no-hover" to="/playlist/create">
|
||||
<Button
|
||||
to="/playlist/create"
|
||||
noHover
|
||||
discrete
|
||||
tracking={{ category: 'Playlist', action: 'Create' }}
|
||||
>
|
||||
<Icon name="add_box" />
|
||||
<I18n path="actions.add" />
|
||||
</Link>
|
||||
</Button>
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -291,9 +305,8 @@ class LibraryPlaylists extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
const mapStateToProps = (state) => ({
|
||||
slim_mode: state.ui.slim_mode,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
mopidy_library_playlists: state.mopidy.library_playlists,
|
||||
mopidy_library_playlists_status: (state.ui.processes.MOPIDY_LIBRARY_PLAYLISTS_PROCESSOR !== undefined ? state.ui.processes.MOPIDY_LIBRARY_PLAYLISTS_PROCESSOR.status : null),
|
||||
|
||||
@ -12,6 +12,7 @@ import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
import { isLoading } from '../../util/helpers';
|
||||
import { I18n, i18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class LibraryTracks extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -63,10 +64,17 @@ class LibraryTracks extends React.Component {
|
||||
}
|
||||
|
||||
const options = (
|
||||
<a className="button button--no-hover" onClick={(e) => this.playAll(e)}>
|
||||
<Icon name="play_circle_filled" />
|
||||
<I18n path="actions.play_all" />
|
||||
</a>
|
||||
<div className="header__options__wrapper">
|
||||
<Button
|
||||
onClick={(e) => this.playAll(e)}
|
||||
tracking={{ category: 'LibraryTracks', action: 'Play' }}
|
||||
noHover
|
||||
discrete
|
||||
>
|
||||
<Icon name="play_circle_filled" />
|
||||
<I18n path="actions.play_all" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -19,7 +19,6 @@ class AddToPlaylist extends React.Component {
|
||||
const {
|
||||
spotify_library_playlists_status,
|
||||
mopidy_library_playlists_status,
|
||||
mopidy_connected,
|
||||
spotify_available,
|
||||
spotifyActions,
|
||||
mopidyActions,
|
||||
@ -32,7 +31,7 @@ class AddToPlaylist extends React.Component {
|
||||
spotifyActions.getLibraryPlaylists();
|
||||
}
|
||||
|
||||
if ((!mopidy_library_playlists_status || mopidy_library_playlists_status !== 'finished') && mopidy_connected) {
|
||||
if ((!mopidy_library_playlists_status || mopidy_library_playlists_status !== 'finished')) {
|
||||
mopidyActions.getLibraryPlaylists();
|
||||
}
|
||||
|
||||
@ -114,7 +113,6 @@ class AddToPlaylist extends React.Component {
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
uris: (ownProps.match.params.uris ? decodeURIComponent(ownProps.match.params.uris).split(',') : []),
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
mopidy_uri_schemes: state.mopidy.uri_schemes,
|
||||
mopidy_library_playlists: state.mopidy.library_playlists,
|
||||
mopidy_library_playlists_status: (state.ui.processes.MOPIDY_LIBRARY_PLAYLISTS_PROCESSOR !== undefined ? state.ui.processes.MOPIDY_LIBRARY_PLAYLISTS_PROCESSOR.status : null),
|
||||
|
||||
@ -12,6 +12,7 @@ import { uriType } from '../../util/helpers';
|
||||
import Icon from '../../components/Icon';
|
||||
import TextField from '../../components/Fields/TextField';
|
||||
import LinksSentence from '../../components/LinksSentence';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
const UriListItem = ({
|
||||
uri,
|
||||
@ -44,14 +45,17 @@ const UriListItem = ({
|
||||
</I18n>
|
||||
)}
|
||||
<span className="mid_grey-text">{` (${type})`}</span>
|
||||
<button
|
||||
className="button button--discrete button--destructive button--tiny pull-right"
|
||||
type="button"
|
||||
<Button
|
||||
type="destructive"
|
||||
discrete
|
||||
size="tiny"
|
||||
className="pull-right"
|
||||
onClick={() => remove(uri)}
|
||||
tracking={{ category: 'AddToQueue', action: 'RemoveItem' }}
|
||||
>
|
||||
<Icon name="delete" />
|
||||
<I18n path="actions.remove" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -257,20 +261,23 @@ class AddToQueue extends React.Component {
|
||||
</div>
|
||||
|
||||
<div className="actions centered-text">
|
||||
<button
|
||||
type="button"
|
||||
className="button button--grey button--large"
|
||||
<Button
|
||||
colour="grey"
|
||||
size="large"
|
||||
onClick={this.addRandom}
|
||||
tracking={{ category: 'AddToQueue', action: 'AddRandom' }}
|
||||
>
|
||||
<I18n path="modal.add_to_queue.add_random" />
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="button button--primary button--large"
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
disabled={!uris.length}
|
||||
submit
|
||||
tracking={{ category: 'AddToQueue', action: 'Submit' }}
|
||||
>
|
||||
<I18n path="actions.add" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
@ -279,7 +286,6 @@ class AddToQueue extends React.Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
albums: state.core.albums,
|
||||
tracks: state.core.tracks,
|
||||
view: state.core.view ? state.core.view : {},
|
||||
|
||||
@ -6,6 +6,7 @@ import Modal from './Modal';
|
||||
import * as coreActions from '../../services/core/actions';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class CreatePlaylist extends React.Component {
|
||||
constructor(props) {
|
||||
@ -173,9 +174,14 @@ class CreatePlaylist extends React.Component {
|
||||
{this.renderFields()}
|
||||
|
||||
<div className="actions centered-text">
|
||||
<button type="submit" className="button button--primary button--large">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
submit
|
||||
tracking={{ category: 'CreatePlaylist', action: 'Submit' }}
|
||||
>
|
||||
<I18n path="modal.edit_playlist.create_playlist" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@ -10,6 +10,7 @@ import * as pusherActions from '../../services/pusher/actions';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import { scrollTo, generateGuid } from '../../util/helpers';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class EditCommand extends React.Component {
|
||||
constructor(props) {
|
||||
@ -239,17 +240,23 @@ class EditCommand extends React.Component {
|
||||
|
||||
<div className="actions centered-text">
|
||||
{command && (
|
||||
<button
|
||||
type="button"
|
||||
className="button button--destructive button--large"
|
||||
<Button
|
||||
type="destructive"
|
||||
size="large"
|
||||
onClick={(e) => this.handleDelete(e)}
|
||||
tracking={{ category: 'EditCommand', action: 'Delete' }}
|
||||
>
|
||||
<I18n path="actions.delete" />
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
<button type="submit" className="button button--primary button--large">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
submit
|
||||
tracking={{ category: 'EditCommand', action: 'Submit' }}
|
||||
>
|
||||
<I18n path="actions.save" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@ -9,6 +9,7 @@ import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
import { uriSource } from '../../util/helpers';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class EditPlaylist extends React.Component {
|
||||
constructor(props) {
|
||||
@ -43,27 +44,24 @@ class EditPlaylist extends React.Component {
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this.props.mopidy_connected) {
|
||||
this.props.mopidyActions.getPlaylist(this.props.uri);
|
||||
}
|
||||
this.props.mopidyActions.getPlaylist(this.props.uri);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate = ({
|
||||
mopidy_connected: prev_mopidy_connected,
|
||||
playlist: prevPlaylist,
|
||||
}) => {
|
||||
const {
|
||||
uri,
|
||||
playlist,
|
||||
mopidy_connected,
|
||||
mopidyActions: {
|
||||
getPlaylist,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
if (!prev_mopidy_connected && mopidy_connected && !playlist) {
|
||||
if (playlist !== prevPlaylist) {
|
||||
getPlaylist(uri);
|
||||
}
|
||||
}
|
||||
@ -225,9 +223,14 @@ class EditPlaylist extends React.Component {
|
||||
{this.renderFields()}
|
||||
|
||||
<div className="actions centered-text">
|
||||
<button type="submit" className="button button--primary button--large">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
tracking={{ category: 'EditPlaylist', action: 'Submit' }}
|
||||
submit
|
||||
>
|
||||
<I18n path="actions.save" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
@ -249,7 +252,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
|
||||
return {
|
||||
uri,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
playlist: (state.core.playlists[uri] !== undefined ? state.core.playlists[uri] : null),
|
||||
playlists: state.core.playlists,
|
||||
};
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
} from '../../util/helpers';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import TextField from '../../components/Fields/TextField';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
const SeedListItem = ({ seed, remove }) => (
|
||||
<div className="list__item list__item--no-interaction" key={seed.uri}>
|
||||
@ -28,14 +29,17 @@ const SeedListItem = ({ seed, remove }) => (
|
||||
{` (${uriType(seed.uri)})`}
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="button button--discrete button--destructive button--tiny pull-right"
|
||||
<Button
|
||||
type="destructive"
|
||||
size="tiny"
|
||||
className="pull-right"
|
||||
discrete
|
||||
onClick={() => remove(seed.uri)}
|
||||
tracking={{ category: 'Directory', action: 'Play' }}
|
||||
>
|
||||
<Icon name="delete" />
|
||||
<I18n path="actions.remove" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -277,28 +281,35 @@ class EditRadio extends React.Component {
|
||||
</div>
|
||||
|
||||
<div className="actions centered-text">
|
||||
{this.state.enabled ? (
|
||||
<span className="button button--destructive button--large" onClick={(e) => this.handleStop(e)}>
|
||||
{this.state.enabled && (
|
||||
<Button
|
||||
type="destructive"
|
||||
size="large"
|
||||
onClick={(e) => this.handleStop(e)}
|
||||
tracking={{ category: 'Radio', action: 'Stop' }}
|
||||
>
|
||||
<I18n path="actions.add" />
|
||||
</span>
|
||||
) : null}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{this.state.enabled ? (
|
||||
<button
|
||||
className="button button--primary button--large"
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
onClick={(e) => this.handleUpdate(e)}
|
||||
type="button"
|
||||
tracking={{ category: 'Radio', action: 'Update' }}
|
||||
>
|
||||
<I18n path="actions.save" />
|
||||
</button>
|
||||
</Button>
|
||||
) : (
|
||||
<button
|
||||
className="button button--primary button--large"
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
onClick={(e) => this.handleStart(e)}
|
||||
type="button"
|
||||
tracking={{ category: 'Radio', action: 'Start' }}
|
||||
>
|
||||
<I18n path="actions.start" />
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
@ -308,7 +319,6 @@ class EditRadio extends React.Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
radio: state.core.radio,
|
||||
artists: state.core.artists,
|
||||
tracks: state.core.tracks,
|
||||
|
||||
@ -9,6 +9,7 @@ import * as pusherActions from '../../services/pusher/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import { queryString, isHosted } from '../../util/helpers';
|
||||
import { I18n, i18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class InitialSetup extends React.Component {
|
||||
constructor(props) {
|
||||
@ -163,9 +164,15 @@ class InitialSetup extends React.Component {
|
||||
)}
|
||||
|
||||
<div className="actions centered-text">
|
||||
<button className={`button button--primary button--large${this.state.saving ? ' button--working' : ''}`} onClick={(e) => this.handleSubmit(e)}>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
working={this.state.saving}
|
||||
onClick={(e) => this.handleSubmit(e)}
|
||||
tracking={{ category: 'InitialSetup', action: 'Submit' }}
|
||||
>
|
||||
<I18n path="actions.save" />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@ -6,6 +6,7 @@ import Modal from './Modal';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as pusherActions from '../../services/pusher/actions';
|
||||
import { i18n, I18n } from '../../locale';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class ShareConfiguration extends React.Component {
|
||||
constructor(props) {
|
||||
@ -280,15 +281,15 @@ class ShareConfiguration extends React.Component {
|
||||
</div>
|
||||
|
||||
<div className="actions centered-text">
|
||||
{this.state.recipients.length > 0 ? (
|
||||
<button className="button button--primary button--large" onClick={(e) => this.handleSubmit(e)}>
|
||||
<I18n path="actions.send" />
|
||||
</button>
|
||||
) : (
|
||||
<button className="button button--primary button--large" disabled="disabled" onClick={(e) => this.handleSubmit(e)}>
|
||||
<I18n path="actions.send" />
|
||||
</button>
|
||||
)}
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
disabled={this.state.recipients.length <= 0}
|
||||
onClick={(e) => this.handleSubmit(e)}
|
||||
tracking={{ category: 'ShareConfiguration', action: 'Send' }}
|
||||
>
|
||||
<I18n path="actions.send" />
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user