This commit is contained in:
@ -3741,6 +3741,9 @@ input[type="submit"] {
|
||||
position: relative; }
|
||||
.modal .content form .field .label {
|
||||
font-size: 16px; }
|
||||
.modal .content form .field .description {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
.modal .content form .field.text > .label, .modal .content form .field.radio > .label, .modal .content form .field.checkbox > .label {
|
||||
opacity: 0.5;
|
||||
width: 100px;
|
||||
@ -3763,7 +3766,6 @@ input[type="submit"] {
|
||||
.modal .content form .field.text input:focus, .modal .content form .field.text input:active {
|
||||
border-color: #08d58f; }
|
||||
.modal .content form .field.radio, .modal .content form .field.checkbox {
|
||||
padding-left: 100px;
|
||||
padding-top: 8px; }
|
||||
.modal .content form button[type="submit"] {
|
||||
margin-top: 50px; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
4
mopidy_iris/static/app.min.css
vendored
4
mopidy_iris/static/app.min.css
vendored
@ -3741,6 +3741,9 @@ input[type="submit"] {
|
||||
position: relative; }
|
||||
.modal .content form .field .label {
|
||||
font-size: 16px; }
|
||||
.modal .content form .field .description {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
.modal .content form .field.text > .label, .modal .content form .field.radio > .label, .modal .content form .field.checkbox > .label {
|
||||
opacity: 0.5;
|
||||
width: 100px;
|
||||
@ -3763,7 +3766,6 @@ input[type="submit"] {
|
||||
.modal .content form .field.text input:focus, .modal .content form .field.text input:active {
|
||||
border-color: #08d58f; }
|
||||
.modal .content form .field.radio, .modal .content form .field.checkbox {
|
||||
padding-left: 100px;
|
||||
padding-top: 8px; }
|
||||
.modal .content form button[type="submit"] {
|
||||
margin-top: 50px; }
|
||||
|
||||
80
mopidy_iris/static/app.min.js
vendored
80
mopidy_iris/static/app.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -77,7 +77,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1527845439";
|
||||
var build = "1528160456";
|
||||
var version = "3.20.0";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -4,6 +4,7 @@ import ReactDOM from 'react-dom';
|
||||
import { createStore, bindActionCreators } from 'redux'
|
||||
import { hashHistory, Link } from 'react-router'
|
||||
import { connect } from 'react-redux'
|
||||
import ReactGA from 'react-ga'
|
||||
|
||||
import Sidebar from './components/Sidebar'
|
||||
import PlaybackControls from './components/Fields/PlaybackControls'
|
||||
@ -47,6 +48,10 @@ class App extends React.Component{
|
||||
|
||||
componentDidMount(){
|
||||
|
||||
if (this.props.allow_reporting){
|
||||
ReactGA.initialize('UA-64701652-3');
|
||||
}
|
||||
|
||||
// Fire up our services
|
||||
this.props.mopidyActions.connect();
|
||||
this.props.pusherActions.connect();
|
||||
@ -55,11 +60,22 @@ class App extends React.Component{
|
||||
// when we navigate to a new route
|
||||
hashHistory.listen(location => {
|
||||
|
||||
// Log our pageview
|
||||
if (this.props.allow_reporting){
|
||||
ReactGA.set({ page: window.location.hash });
|
||||
ReactGA.pageview(window.location.hash);
|
||||
}
|
||||
|
||||
// Hide our sidebar
|
||||
this.props.uiActions.toggleSidebar(false )
|
||||
|
||||
// Unselect any tracks
|
||||
this.props.uiActions.setSelectedTracks([])
|
||||
this.props.uiActions.setSelectedTracks([]);
|
||||
|
||||
// Close context menu
|
||||
if (this.props.context_menu){
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
});
|
||||
|
||||
// Check our slim_mode
|
||||
@ -76,10 +92,9 @@ class App extends React.Component{
|
||||
}
|
||||
|
||||
// show initial setup if required
|
||||
/*
|
||||
if (this.props.show_initial_setup){
|
||||
if (!this.props.initial_setup_complete){
|
||||
this.props.uiActions.openModal('initial_setup');
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
@ -87,11 +102,6 @@ class App extends React.Component{
|
||||
// We've navigated to a new location
|
||||
if (this.props.location.pathname !== nextProps.location.pathname){
|
||||
|
||||
// Close context menu
|
||||
if (this.props.context_menu){
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}
|
||||
|
||||
// Scroll to bottom, only if we've PUSHed to a new route
|
||||
// We also prevent scroll reset for any sub_view routes (like tabs, services, etc)
|
||||
if (nextProps.location.action == 'PUSH' && nextProps.params.sub_view === undefined){
|
||||
@ -317,8 +327,9 @@ class App extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
allow_reporting: state.ui.allow_reporting,
|
||||
touch_dragging: state.ui.touch_dragging,
|
||||
show_initial_setup: state.ui.show_initial_setup,
|
||||
initial_setup_complete: state.ui.initial_setup_complete,
|
||||
slim_mode: state.ui.slim_mode,
|
||||
broadcasts: (state.ui.broadcasts ? state.ui.broadcasts : []),
|
||||
volume: (state.mopidy.volume ? state.mopidy.volume : false),
|
||||
|
||||
2
src/js/bootstrap.js
vendored
2
src/js/bootstrap.js
vendored
@ -48,7 +48,7 @@ var initialState = {
|
||||
http_streaming_url: "http://"+window.location.hostname+":8000/mopidy"
|
||||
},
|
||||
ui: {
|
||||
show_initial_setup: true,
|
||||
allow_reporting: true,
|
||||
slim_mode: false,
|
||||
selected_tracks: [],
|
||||
notifications: {},
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
|
||||
import Icon from '../Icon'
|
||||
import SpotifyAuthenticationFrame from '../Fields/SpotifyAuthenticationFrame'
|
||||
import LastfmAuthenticationFrame from '../Fields/LastfmAuthenticationFrame'
|
||||
|
||||
import * as helpers from '../../helpers'
|
||||
|
||||
export default class InitialSetupModal extends React.Component{
|
||||
@ -9,27 +12,47 @@ export default class InitialSetupModal extends React.Component{
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
username: 'Anonymous'
|
||||
username: 'Anonymous',
|
||||
allow_reporting: this.props.allow_reporting,
|
||||
host: this.props.host,
|
||||
port: this.props.port,
|
||||
ssl: this.props.ssl
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit(e){
|
||||
// save and falseify show_initial_setup
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
handleCancel(e){
|
||||
// falseify show_initial_setup
|
||||
this.props.pusherActions.setUsername(this.state.username);
|
||||
this.props.uiActions.set({
|
||||
initial_setup_complete: true,
|
||||
allow_reporting: this.state.allow_reporting
|
||||
});
|
||||
this.props.mopidyActions.setConfig({
|
||||
host: this.state.host,
|
||||
port: this.state.port,
|
||||
ssl: this.state.ssl
|
||||
});
|
||||
|
||||
this.setState({saving: true});
|
||||
|
||||
// Wait two seconds to allow our actions to complete
|
||||
// Then reload the interface
|
||||
setTimeout(function(){
|
||||
window.location.reload(true);
|
||||
}, 2000);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
<h1>Welcome to Iris</h1>
|
||||
<h1>Get started</h1>
|
||||
<form onSubmit={(e) => this.handleSubmit(e)}>
|
||||
|
||||
<div className="field">
|
||||
<div className="name">Username</div>
|
||||
<div className="input">
|
||||
<div className="field text">
|
||||
<span className="label">Username</span>
|
||||
<input
|
||||
type="text"
|
||||
onChange={e => this.setState({username: e.target.value.replace(/\W/g, '')})}
|
||||
@ -38,11 +61,66 @@ export default class InitialSetupModal extends React.Component{
|
||||
A non-unique string used to identify this client (no special characters)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<div className="name">Host</div>
|
||||
<div className="input">
|
||||
<input
|
||||
type="text"
|
||||
onChange={ e => this.setState({host: e.target.value})}
|
||||
value={ this.state.host } />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">Port</div>
|
||||
<div className="input">
|
||||
<input
|
||||
type="text"
|
||||
onChange={ e => this.setState({port: e.target.value})}
|
||||
value={ this.state.port } />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field checkbox">
|
||||
<div className="name">Encryption</div>
|
||||
<div className="input">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="ssl"
|
||||
checked={this.state.ssl}
|
||||
onChange={e => this.setState({ssl: !this.state.ssl})} />
|
||||
<span className="label has-tooltip">
|
||||
Enable SSL
|
||||
<span className="tooltip">Requires SSL proxy</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field checkbox">
|
||||
<div className="name">Reporting</div>
|
||||
<div className="input">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="allow_reporting"
|
||||
checked={ this.props.ui.allow_reporting }
|
||||
onChange={ e => this.props.uiActions.set({ allow_reporting: !this.props.ui.allow_reporting })} />
|
||||
<span className="label">
|
||||
Allow reporting of anonymous usage statistics
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<div>Google Analytics is used to collect usage data and errors to help trace issues and provide valuable insight into how we can continue to make improvements. Personal information is anonymized prior to collection.</div>
|
||||
</div>
|
||||
|
||||
<div className="actions centered-text">
|
||||
<button className="large" onClick={e => this.handleCancel(e)}>Skip</button>
|
||||
<button className="primary large" onClick={e => this.handleSubmit(e)}>Save</button>
|
||||
<button className={"primary large"+(this.state.saving ? " working" : "")} onClick={e => this.handleSubmit(e)}>
|
||||
{this.state.saving ? "Saving" : "Save"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@ -123,7 +123,12 @@ class Modal extends React.Component{
|
||||
current_track={this.props.current_track} /> : null }
|
||||
|
||||
{ this.props.modal.name == 'initial_setup' ? <InitialSetupModal
|
||||
host={this.props.mopidy_host}
|
||||
port={this.props.mopidy_port}
|
||||
ssl={this.props.mopidy_ssl}
|
||||
allow_reporting={this.props.allow_reporting}
|
||||
uiActions={this.props.uiActions}
|
||||
mopidyActions={this.props.mopidyActions}
|
||||
pusherActions={this.props.pusherActions} /> : null }
|
||||
|
||||
</div>
|
||||
@ -148,7 +153,11 @@ 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,
|
||||
allow_reporting: state.ui.allow_reporting,
|
||||
mopidy_host: state.mopidy.host,
|
||||
mopidy_port: state.mopidy.port,
|
||||
mopidy_ssl: state.mopidy.ssl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@ import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux'
|
||||
import { createStore } from 'redux'
|
||||
import { Router, Route, Link, IndexRoute, hashHistory } from 'react-router'
|
||||
import ReactGA from 'react-ga'
|
||||
|
||||
import store from './bootstrap.js'
|
||||
require('../scss/app.scss');
|
||||
@ -44,18 +43,11 @@ console.error = function(message, error){
|
||||
originalConsoleError.apply(this, arguments)
|
||||
*/
|
||||
|
||||
// setup our analytics tracking
|
||||
ReactGA.initialize('UA-64701652-3');
|
||||
function handleUpdate(){
|
||||
ReactGA.set({ page: window.location.hash });
|
||||
ReactGA.pageview(window.location.hash);
|
||||
}
|
||||
|
||||
global.baseURL = '/'
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<Router history={hashHistory} onUpdate={handleUpdate}>
|
||||
<Router history={hashHistory}>
|
||||
<Route path={global.baseURL} component={App}>
|
||||
|
||||
<IndexRoute component={Queue} />
|
||||
|
||||
@ -72,62 +72,82 @@ const CoreMiddleware = (function(){
|
||||
);
|
||||
|
||||
// Log with Raven Sentry
|
||||
if (store.getState().ui.allow_reporting){
|
||||
Raven.captureException(
|
||||
new Error(message),
|
||||
{
|
||||
extra: data
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Log with Analytics
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({
|
||||
category: "Error",
|
||||
action: message,
|
||||
label: description,
|
||||
nonInteraction: true
|
||||
});
|
||||
}
|
||||
|
||||
store.dispatch(uiActions.createNotification({content: message, type: 'bad', description: description}));
|
||||
console.error(message, description, data);
|
||||
break;
|
||||
|
||||
case 'PLAY_PLAYLIST':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Play', label: action.uri })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Play', label: action.uri });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'SAVE_PLAYLIST':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Save', label: action.key })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Save', label: action.key });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'CREATE_PLAYLIST':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Create', label: +action.name })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Create', label: +action.name });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'REORDER_PLAYLIST_TRACKS':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Reorder tracks', label: action.key })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Reorder tracks', label: action.key });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'ADD_PLAYLIST_TRACKS':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Add tracks', label: action.playlist_uri })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Add tracks', label: action.playlist_uri });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'REMOVE_PLAYLIST_TRACKS':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Remove tracks', label: action.playlist_uri })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Remove tracks', label: action.playlist_uri });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'DELETE_PLAYLIST':
|
||||
ReactGA.event({ category: 'Playlist', action: 'Delete', label: action.uri })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Delete', label: action.uri });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'SEARCH_STARTED':
|
||||
ReactGA.event({ category: 'Search', action: 'Started', label: action.type+': '+action.query })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Search', action: 'Started', label: action.type+': '+action.query });
|
||||
}
|
||||
next(action)
|
||||
|
||||
var state = store.getState()
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
|
||||
import ReactGA from 'react-ga'
|
||||
|
||||
var helpers = require('./../../helpers')
|
||||
var lastfmActions = require('./actions')
|
||||
var uiActions = require('../ui/actions')
|
||||
|
||||
@ -220,7 +220,9 @@ const MopidyMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'MOPIDY_CONNECTED':
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Mopidy', action: 'Connected', label: window.location.hostname });
|
||||
}
|
||||
next(action);
|
||||
break;
|
||||
|
||||
@ -2155,7 +2157,9 @@ const MopidyMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'MOPIDY_DIRECTORY':
|
||||
if (action.data) ReactGA.event({ category: 'Directory', action: 'Load', label: action.data.uri })
|
||||
if (store.getState().ui.allow_reporting && action.data){
|
||||
ReactGA.event({ category: 'Directory', action: 'Load', label: action.data.uri });
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
|
||||
@ -215,7 +215,9 @@ const PusherMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'PUSHER_CONNECTED':
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Pusher', action: 'Connected', label: action.username});
|
||||
}
|
||||
|
||||
store.dispatch(pusherActions.getConfig());
|
||||
store.dispatch(pusherActions.getVersion());
|
||||
@ -375,7 +377,9 @@ const PusherMiddleware = (function(){
|
||||
|
||||
case 'PUSHER_START_RADIO':
|
||||
case 'PUSHER_UPDATE_RADIO':
|
||||
ReactGA.event({ category: 'Pusher', action: 'Start radio', label: action.uris.join() })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Pusher', action: 'Start radio', label: action.uris.join() });
|
||||
}
|
||||
|
||||
// start our UI process notification
|
||||
if (action.type == 'PUSHER_UPDATE_RADIO'){
|
||||
@ -438,7 +442,10 @@ const PusherMiddleware = (function(){
|
||||
|
||||
case 'PUSHER_STOP_RADIO':
|
||||
store.dispatch(uiActions.createNotification({content: 'Stopping radio'}));
|
||||
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Pusher', action: 'Stop radio' });
|
||||
}
|
||||
|
||||
store.dispatch(pusherActions.deliverBroadcast(
|
||||
'notification',
|
||||
@ -503,7 +510,9 @@ const PusherMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'PUSHER_UPGRADE':
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Pusher', action: 'Upgrade', label: '' });
|
||||
}
|
||||
request(store, 'upgrade')
|
||||
.then(
|
||||
response => {
|
||||
@ -516,7 +525,9 @@ const PusherMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'PUSHER_VERSION':
|
||||
ReactGA.event({ category: 'Pusher', action: 'Version', label: action.version.current })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Pusher', action: 'Version', label: action.version.current });
|
||||
}
|
||||
|
||||
if (action.version.upgrade_available){
|
||||
store.dispatch(uiActions.createNotification({content: 'Version '+action.version.latest+' is available. See settings to upgrade.'}));
|
||||
@ -574,8 +585,10 @@ const PusherMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'PUSHER_ERROR':
|
||||
store.dispatch(uiActions.createNotification(action.message, 'bad'))
|
||||
ReactGA.event({ category: 'Pusher', action: 'Error', label: action.message })
|
||||
store.dispatch(uiActions.createNotification(action.message, 'bad'));
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Pusher', action: 'Error', label: action.message });
|
||||
}
|
||||
break
|
||||
|
||||
|
||||
|
||||
@ -18,7 +18,9 @@ const SpotifyMiddleware = (function(){
|
||||
switch(action.type){
|
||||
|
||||
case 'SPOTIFY_AUTHORIZATION_GRANTED':
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({category: 'Spotify', action: 'Authorization granted'});
|
||||
}
|
||||
|
||||
// Flush out the previous user's library
|
||||
store.dispatch(spotifyActions.flushLibrary());
|
||||
@ -27,13 +29,16 @@ const SpotifyMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'SPOTIFY_AUTHORIZATION_REVOKED':
|
||||
if (store.getState().ui.allow_reporting){
|
||||
var hashed_username = null
|
||||
if (store.getState().spotify.me){
|
||||
hashed_username = md5(store.getState().spotify.me);
|
||||
ReactGA.set({userId: hashed_username});
|
||||
}
|
||||
ReactGA.event({ category: 'Spotify', action: 'Authorization revoked', label: hashed_username})
|
||||
next(action)
|
||||
ReactGA.event({ category: 'Spotify', action: 'Authorization revoked', label: hashed_username});
|
||||
}
|
||||
|
||||
next(action);
|
||||
|
||||
// Now dispatch a getMe to get the backend-provided user
|
||||
store.dispatch(spotifyActions.getMe());
|
||||
@ -44,12 +49,14 @@ const SpotifyMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'SPOTIFY_IMPORT_AUTHORIZATION':
|
||||
if (store.getState().ui.allow_reporting){
|
||||
var hashed_username = null
|
||||
if (store.getState().spotify.me){
|
||||
hashed_username = md5(store.getState().spotify.me);
|
||||
ReactGA.set({userId: hashed_username});
|
||||
}
|
||||
ReactGA.event({category: 'Spotify', action: 'Authorization imported', label: hashed_username});
|
||||
}
|
||||
|
||||
// Flush out the previous user's library
|
||||
store.dispatch(spotifyActions.flushLibrary());
|
||||
@ -58,14 +65,16 @@ const SpotifyMiddleware = (function(){
|
||||
break;
|
||||
|
||||
case 'SPOTIFY_RECOMMENDATIONS_LOADED':
|
||||
if (action.seeds_uris){
|
||||
if (store.getState().ui.allow_reporting && action.seeds_uris){
|
||||
ReactGA.event({ category: 'Spotify', action: 'Recommendations', label: action.seeds_uris.join(',') })
|
||||
}
|
||||
next(action)
|
||||
break;
|
||||
|
||||
case 'SPOTIFY_USER_LOADED':
|
||||
if (action.data) ReactGA.event({ category: 'User', action: 'Load', label: action.data.uri })
|
||||
if (store.getState().ui.allow_reporting && action.data){
|
||||
ReactGA.event({ category: 'User', action: 'Load', label: action.data.uri });
|
||||
}
|
||||
next(action)
|
||||
break;
|
||||
|
||||
@ -414,9 +423,11 @@ const SpotifyMiddleware = (function(){
|
||||
store.dispatch(pusherActions.setUsername(name));
|
||||
}
|
||||
|
||||
if (store.getState().ui.allow_reporting){
|
||||
var hashed_username = md5(action.data.id);
|
||||
ReactGA.set({userId: hashed_username});
|
||||
ReactGA.event({category: 'Spotify', action: 'Authorization verified', label: hashed_username});
|
||||
}
|
||||
|
||||
store.dispatch({
|
||||
type: 'USERS_LOADED',
|
||||
|
||||
@ -28,7 +28,9 @@ const UIMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'OPEN_MODAL':
|
||||
ReactGA.event({ category: 'Modal', action: 'Opened', label: action.modal.name })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Modal', action: 'Opened', label: action.modal.name });
|
||||
}
|
||||
$('body').addClass('modal-open')
|
||||
store.dispatch(uiActions.hideContextMenu())
|
||||
store.dispatch(uiActions.hideTouchContextMenu())
|
||||
@ -36,7 +38,9 @@ const UIMiddleware = (function(){
|
||||
break
|
||||
|
||||
case 'CLOSE_MODAL':
|
||||
ReactGA.event({ category: 'Modal', action: 'Closed', label: null })
|
||||
if (store.getState().ui.allow_reporting){
|
||||
ReactGA.event({ category: 'Modal', action: 'Closed', label: null });
|
||||
}
|
||||
$('body').removeClass('modal-open')
|
||||
next(action)
|
||||
break
|
||||
|
||||
@ -90,13 +90,17 @@ class Playlist extends React.Component{
|
||||
}
|
||||
|
||||
follow(){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Follow', label: this.props.playlist.uri })
|
||||
if (this.props.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Follow', label: this.props.playlist.uri });
|
||||
}
|
||||
this.props.spotifyActions.toggleFollowingPlaylist(this.props.playlist.uri, 'PUT')
|
||||
}
|
||||
|
||||
// TODO: Once unfollowing occurs, remove playlist from global playlists list
|
||||
unfollow(){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Unfollow', label: this.props.playlist.uri })
|
||||
if (this.props.allow_reporting){
|
||||
ReactGA.event({ category: 'Playlist', action: 'Unfollow', label: this.props.playlist.uri });
|
||||
}
|
||||
this.props.spotifyActions.toggleFollowingPlaylist(this.props.playlist.uri, 'DELETE' )
|
||||
}
|
||||
|
||||
@ -239,6 +243,7 @@ class Playlist extends React.Component{
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
var uri = ownProps.params.uri;
|
||||
return {
|
||||
allow_reporting: state.ui.allow_reporting,
|
||||
slim_mode: state.ui.slim_mode,
|
||||
load_queue: state.ui.load_queue,
|
||||
tracks: state.core.tracks,
|
||||
|
||||
@ -3,7 +3,6 @@ import React, { PropTypes } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link, hashHistory } from 'react-router'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import ReactGA from 'react-ga'
|
||||
|
||||
import Header from '../components/Header'
|
||||
import Icon from '../components/Icon'
|
||||
|
||||
@ -239,6 +239,28 @@ class Settings extends React.Component {
|
||||
<h4 className="underline">Services</h4>
|
||||
<Services active={this.props.params.sub_view} />
|
||||
|
||||
<h4 className="underline">Privacy</h4>
|
||||
|
||||
<div className="field checkbox">
|
||||
<div className="name">Reporting</div>
|
||||
<div className="input">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="allow_reporting"
|
||||
checked={ this.props.ui.allow_reporting }
|
||||
onChange={ e => this.props.uiActions.set({ allow_reporting: !this.props.ui.allow_reporting })} />
|
||||
<span className="label">
|
||||
Allow reporting of anonymous usage statistics
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<div>Google Analytics is used to collect usage data and errors to help trace issues and provide valuable insight into how we can continue to make improvements. Personal information is anonymized prior to collection.</div>
|
||||
</div>
|
||||
|
||||
<h4 className="underline">Advanced</h4>
|
||||
|
||||
<div className="field checkbox">
|
||||
@ -301,10 +323,6 @@ class Settings extends React.Component {
|
||||
<div className="field">
|
||||
<div>
|
||||
<em><a href="https://github.com/jaedb/Iris" target="_blank">Iris</a></em> is an open-source project by <a href="https://github.com/jaedb" target="_blank">James Barnsley</a>. It is provided free and with absolutely no warranty. If you paid someone for this software, please let me know.
|
||||
<br />
|
||||
<br />
|
||||
Google Analytics is used to collect usage data and errors to help trace issues and provide valuable insight into how we can continue to make improvements. Personal information is anonymized prior to collection. For more information, see <a href="https://github.com/jaedb/Iris/wiki/Terms-of-use" target="_blank">terms and conditions</a>.
|
||||
<br />
|
||||
</div>
|
||||
<br /><br />
|
||||
<div>
|
||||
|
||||
@ -56,6 +56,11 @@
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.description {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
&.text,
|
||||
&.radio,
|
||||
&.checkbox {
|
||||
@ -93,7 +98,6 @@
|
||||
|
||||
&.radio,
|
||||
&.checkbox {
|
||||
padding-left: 100px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user