Files
Iris/src/js/views/modals/AddToQueue.js

302 lines
7.7 KiB
JavaScript
Raw Normal View History

2017-03-08 09:13:24 +13:00
2019-09-05 15:36:11 +12:00
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
2018-07-09 19:09:12 +12:00
import Modal from './Modal';
2019-09-05 15:36:11 +12:00
import * as coreActions from '../../services/core/actions';
import * as uiActions from '../../services/ui/actions';
import * as mopidyActions from '../../services/mopidy/actions';
import * as spotifyActions from '../../services/spotify/actions';
import { I18n, i18n } from '../../locale';
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,
tracks,
2020-08-03 20:42:17 +12:00
random_tracks,
albums,
remove,
}) => {
const type = uriType(uri);
let item = null;
switch (type) {
case 'track':
item = tracks[uri];
break;
case 'album':
item = albums[uri];
break;
default:
break;
}
2020-08-03 20:42:17 +12:00
if (!item) {
item = random_tracks.find((track) => track.uri === uri);
}
return (
<div className="list__item list__item--no-interaction">
{item ? item.name : <span className="mid_grey-text">{uri}</span>}
{item && item.artists && (
<I18n path="common.by" contentAfter>
<LinksSentence nolinks items={item.artists} />
</I18n>
)}
<span className="mid_grey-text">{` (${type})`}</span>
<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>
</div>
);
};
2017-03-08 09:13:24 +13:00
class AddToQueue extends React.Component {
2019-09-05 15:36:11 +12:00
constructor(props) {
super(props);
this.state = {
text: '',
error: '',
2019-09-05 15:36:11 +12:00
next: false,
};
}
2017-03-08 09:13:24 +13:00
2019-09-05 15:36:11 +12:00
componentDidMount() {
const {
uiActions: {
setWindowTitle,
},
} = this.props;
setWindowTitle(i18n('modal.add_to_queue.title'));
2019-09-05 15:36:11 +12:00
}
2017-03-08 09:13:24 +13:00
onSubmit = (e) => {
const {
next,
} = this.state;
const {
mopidyActions: {
enqueueURIs,
},
2020-08-03 20:42:17 +12:00
view: {
uris = [],
},
} = this.props;
2019-09-05 15:36:11 +12:00
e.preventDefault();
enqueueURIs(uris, null, next);
2020-08-03 20:42:17 +12:00
this.reset();
2019-09-05 15:36:11 +12:00
window.history.back();
}
2018-07-13 16:48:41 +12:00
onChange = (text) => {
this.setState({ text });
}
2020-08-03 20:42:17 +12:00
reset = () => {
const {
coreActions: {
viewDataLoaded,
},
} = this.props;
viewDataLoaded({ uris: [], random_tracks: [] });
}
addRandom = () => {
const {
mopidyActions: {
2020-08-03 20:42:17 +12:00
view_getRandomTracks,
},
} = this.props;
2020-08-03 20:42:17 +12:00
view_getRandomTracks(20);
}
addUris = () => {
const {
text,
} = this.state;
const {
2020-08-03 20:42:17 +12:00
view: {
uris: prevUris = [],
},
coreActions: {
loadItem,
2020-08-03 20:42:17 +12:00
viewDataLoaded,
},
} = this.props;
const uris = text.split(',');
const validatedUris = uris.filter((uri) => uriType(uri));
validatedUris.forEach((uri) => {
loadItem(uri);
});
2020-08-03 20:42:17 +12:00
this.setState({ text: '' });
viewDataLoaded({ uris: [...prevUris, ...validatedUris] });
}
removeUri = (uri) => {
const {
2020-08-03 20:42:17 +12:00
view: {
uris = [],
},
coreActions: {
viewDataLoaded,
},
} = this.props;
2020-08-03 20:42:17 +12:00
viewDataLoaded({ uris: uris.filter((item) => item !== uri) });
}
render = () => {
const {
tracks,
albums,
2020-08-03 20:42:17 +12:00
view: {
uris = [],
random_tracks = [],
},
} = this.props;
const {
text,
error,
next,
} = this.state;
2019-09-05 15:36:11 +12:00
return (
<Modal className="modal--add-to-queue">
<h1>
<I18n path="modal.add_to_queue.title" />
</h1>
<h2 className="mid_grey-text">
<I18n path="modal.add_to_queue.subtitle" />
</h2>
2017-03-08 09:13:24 +13:00
<form onSubmit={this.onSubmit}>
<div className="field text">
<div className="name">
<I18n path="fields.uri" />
</div>
<div className="input">
<TextField
onChange={this.onChange}
value={text}
/>
<span className="button discrete add-uri no-hover" onClick={this.addUris}>
<Icon name="add" />
<I18n path="actions.add" />
</span>
{error && <span className="description error">{error}</span>}
</div>
</div>
<div className="field text">
<div className="name">
<I18n path="fields.items_to_add.label" />
</div>
<div className="input">
{uris.length ? (
<div className="list">
{uris.map((uri, index) => (
<UriListItem
uri={uri}
tracks={tracks}
2020-08-03 20:42:17 +12:00
random_tracks={random_tracks}
albums={albums}
remove={this.removeUri}
key={`${uri}_${index}`}
/>
))}
</div>
) : (
<span className="text mid_grey-text">
<I18n path="fields.items_to_add.placeholder" />
</span>
)}
</div>
</div>
2019-09-05 15:36:11 +12:00
<div className="field radio white">
<div className="name">
<I18n path="modal.add_to_queue.position.label" />
2019-09-05 15:36:11 +12:00
</div>
<div className="input">
<label>
<input
type="radio"
name="next"
checked={!next}
onChange={() => this.setState({ next: false })}
2019-09-05 15:36:11 +12:00
/>
<span className="label">
<I18n path="modal.add_to_queue.position.end" />
</span>
2019-09-05 15:36:11 +12:00
</label>
<label>
<input
type="radio"
name="next"
checked={next}
onChange={() => this.setState({ next: true })}
2019-09-05 15:36:11 +12:00
/>
<span className="label">
<I18n path="modal.add_to_queue.position.next" />
</span>
2019-09-05 15:36:11 +12:00
</label>
</div>
</div>
2017-03-08 09:13:24 +13:00
2019-09-05 15:36:11 +12:00
<div className="actions centered-text">
<Button
colour="grey"
size="large"
onClick={this.addRandom}
tracking={{ category: 'AddToQueue', action: 'AddRandom' }}
>
<I18n path="modal.add_to_queue.add_random" />
</Button>
<Button
type="primary"
size="large"
2020-08-03 20:42:17 +12:00
disabled={!uris.length}
submit
tracking={{ category: 'AddToQueue', action: 'Submit' }}
2020-08-03 20:42:17 +12:00
>
<I18n path="actions.add" />
</Button>
2019-09-05 15:36:11 +12:00
</div>
</form>
</Modal>
);
}
2018-07-09 19:09:12 +12:00
}
const mapStateToProps = (state) => ({
albums: state.core.albums,
tracks: state.core.tracks,
2020-08-03 20:42:17 +12:00
view: state.core.view ? state.core.view : {},
2019-09-05 15:36:11 +12:00
});
2018-07-09 19:09:12 +12:00
2019-09-05 15:36:11 +12:00
const mapDispatchToProps = (dispatch) => ({
coreActions: bindActionCreators(coreActions, dispatch),
uiActions: bindActionCreators(uiActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
});
2018-07-09 19:09:12 +12:00
export default connect(mapStateToProps, mapDispatchToProps)(AddToQueue);