Separating seeds and tunabilities fields

This commit is contained in:
James Barnsley
2018-01-17 10:17:30 +13:00
parent d54a75fedf
commit 0c1aaeced8
11 changed files with 248 additions and 170 deletions

View File

@ -3216,6 +3216,10 @@ input[type="submit"] {
left: 0; } left: 0; }
.field.checkbox input:checked + .label:before { .field.checkbox input:checked + .label:before {
content: '\F00C'; } content: '\F00C'; }
.field.range .label {
padding-bottom: 4px; }
.field.range .label .has-tooltip {
padding-left: 4px; }
.field.range .input-range__track, .field.range .input-range__track,
.field.range .input-range__slider-container { .field.range .input-range__slider-container {
transition: none; } transition: none; }
@ -5105,6 +5109,8 @@ main header {
color: #32b5f2; } color: #32b5f2; }
.dropdown-field.expanded .options { .dropdown-field.expanded .options {
display: block; } display: block; }
.dropdown-field.no-status-icon .options .option {
padding-left: 12px; }
.dropdown-field .options { .dropdown-field .options {
color: #000000; color: #000000;
position: absolute; position: absolute;
@ -5798,12 +5804,14 @@ main .track-view {
color: #FFFFFF; } color: #FFFFFF; }
.discover-view .intro .liner h2 { .discover-view .intro .liner h2 {
padding-bottom: 8px; } padding-bottom: 8px; }
.discover-view .intro .liner h3 {
padding-bottom: 40px;
opacity: 0.5; }
.discover-view .seeds { .discover-view .seeds,
.discover-view .tunabilities {
padding-top: 40px; } padding-top: 40px; }
.discover-view .seeds h3,
.discover-view .tunabilities h3 {
padding-bottom: 6px; }
.discover-view .seeds .seed { .discover-view .seeds .seed {
display: inline-block; display: inline-block;
background: #32b5f2; background: #32b5f2;
@ -5827,6 +5835,19 @@ main .track-view {
right: 0; right: 0;
cursor: pointer; } cursor: pointer; }
.discover-view .tunabilities::after {
content: '';
clear: both;
display: block; }
.discover-view .tunabilities .tunability {
width: 200px;
float: left;
box-sizing: border-box;
padding-right: 20px; }
.discover-view .tunabilities .tunability .input-range .input-range__label-container {
display: none; }
.discover-view .autocomplete-field { .discover-view .autocomplete-field {
width: 250px; width: 250px;
display: inline-block; display: inline-block;
@ -5846,17 +5867,6 @@ main .track-view {
.discover-view .autocomplete-field .input:after { .discover-view .autocomplete-field .input:after {
background: #32b5f2; } background: #32b5f2; }
.discover-view .tunabilities {
margin: 10px -10px; }
.discover-view .tunabilities .tunability {
width: 25%;
box-sizing: border-box;
padding: 10px; }
.discover-view .tunabilities .tunability label {
text-transform: capitalize; }
.discover-view .tunabilities .tunability .input-range .input-range__label-container {
display: none; }
.discover-view section .grid { .discover-view section .grid {
padding-bottom: 20px; } padding-bottom: 20px; }

View File

@ -1058,6 +1058,16 @@ var getIndexedRecords = exports.getIndexedRecords = function getIndexedRecords(i
return records; return records;
}; };
/**
* Uppercase-ify the first character of a string
*
* @param string = string
* @return string
**/
var titleCase = exports.titleCase = function titleCase(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
};
/***/ }), /***/ }),
/* 3 */ /* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
@ -2615,8 +2625,6 @@ function getRecommendations() {
endpoint += '&seed_genres=' + genres.join(','); endpoint += '&seed_genres=' + genres.join(',');
endpoint += '&limit=' + limit; endpoint += '&limit=' + limit;
console.log(tunabilities);
if (tunabilities) { if (tunabilities) {
for (var key in tunabilities) { for (var key in tunabilities) {
if (tunabilities.hasOwnProperty(key)) { if (tunabilities.hasOwnProperty(key)) {
@ -21973,16 +21981,24 @@ var DropdownField = function (_React$Component) {
value: function render() { value: function render() {
var _this2 = this; var _this2 = this;
if (!this.props.options) return null; if (!this.props.options) {
return null;
var classname = 'dropdown-field'; }
if (this.state.expanded) classname += ' expanded';
var className = 'dropdown-field';
if (this.state.expanded) {
className += ' expanded';
}
if (this.props.no_status_icon) {
className += ' no-status-icon';
}
var current_value = this.props.options[0].value; var current_value = this.props.options[0].value;
if (this.props.value) current_value = this.props.value; if (this.props.value) {
current_value = this.props.value;
}
var icon = _react2.default.createElement(_reactFontawesome2.default, { name: 'check' }); var icon = _react2.default.createElement(_reactFontawesome2.default, { name: 'check' });
if (typeof this.props.reverse !== 'undefined') { if (this.props.reverse !== undefined) {
if (this.props.reverse) { if (this.props.reverse) {
icon = _react2.default.createElement(_reactFontawesome2.default, { className: 'reverse', name: 'caret-down' }); icon = _react2.default.createElement(_reactFontawesome2.default, { className: 'reverse', name: 'caret-down' });
} else { } else {
@ -21992,7 +22008,7 @@ var DropdownField = function (_React$Component) {
return _react2.default.createElement( return _react2.default.createElement(
'div', 'div',
{ className: classname, 'data-key': this.props.name.replace(' ', '_').toLowerCase() }, { className: className, 'data-key': this.props.name.replace(' ', '_').toLowerCase() },
_react2.default.createElement( _react2.default.createElement(
'div', 'div',
{ className: 'label', onClick: function onClick() { { className: 'label', onClick: function onClick() {
@ -22019,7 +22035,7 @@ var DropdownField = function (_React$Component) {
{ className: 'option', key: option.value, onClick: function onClick(e) { { className: 'option', key: option.value, onClick: function onClick(e) {
return _this2.handleChange(option.value); return _this2.handleChange(option.value);
} }, } },
option.value == current_value ? icon : null, !_this2.props.no_status_icon && option.value == current_value ? icon : null,
option.label option.label
); );
}) })
@ -69567,6 +69583,10 @@ var _Parallax = __webpack_require__(44);
var _Parallax2 = _interopRequireDefault(_Parallax); var _Parallax2 = _interopRequireDefault(_Parallax);
var _DropdownField = __webpack_require__(63);
var _DropdownField2 = _interopRequireDefault(_DropdownField);
var _AddSeedField = __webpack_require__(446); var _AddSeedField = __webpack_require__(446);
var _AddSeedField2 = _interopRequireDefault(_AddSeedField); var _AddSeedField2 = _interopRequireDefault(_AddSeedField);
@ -69829,13 +69849,18 @@ var Discover = function (_React$Component) {
if (tunabilities.hasOwnProperty(key) && tunabilities[key].enabled) { if (tunabilities.hasOwnProperty(key) && tunabilities[key].enabled) {
var tunability = tunabilities[key]; var tunability = tunabilities[key];
var max = tunability.value.max;
var min = tunability.value.min;
if (tunability.convert_to_decimal) { if (tunability.convert_to_decimal) {
tunability.value.max = tunability.max / 100; max = max / 100;
tunability.value.min = tunability.min / 100; min = min / 100;
} }
digested_tunabilities[key + "_max"] = tunability.value.max; console.log(key, max, min);
digested_tunabilities[key + "_min"] = tunability.value.min;
digested_tunabilities[key + "_max"] = max.toString();
digested_tunabilities[key + "_min"] = min.toString();
} }
} }
this.props.spotifyActions.getRecommendations(seeds, 50, digested_tunabilities); this.props.spotifyActions.getRecommendations(seeds, 50, digested_tunabilities);
@ -69909,6 +69934,11 @@ var Discover = function (_React$Component) {
return _react2.default.createElement( return _react2.default.createElement(
'div', 'div',
{ className: 'seeds' }, { className: 'seeds' },
_react2.default.createElement(
'h3',
null,
'Seeds'
),
seeds_objects.map(function (seed, index) { seeds_objects.map(function (seed, index) {
var type = helpers.uriType(seed.uri); var type = helpers.uriType(seed.uri);
return _react2.default.createElement( return _react2.default.createElement(
@ -69951,41 +69981,42 @@ var Discover = function (_React$Component) {
value: function renderTunabilities() { value: function renderTunabilities() {
var _this3 = this; var _this3 = this;
var tunabilities = []; var enabled_tunabilities = [];
var addable_tunabilities = [];
for (var key in this.state.tunabilities) { for (var key in this.state.tunabilities) {
if (this.state.tunabilities.hasOwnProperty(key)) { if (this.state.tunabilities.hasOwnProperty(key)) {
var tunability = Object.assign({}, this.state.tunabilities[key], { var tunability = Object.assign({}, this.state.tunabilities[key], {
name: key name: key
}); });
tunabilities.push(tunability);
if (tunability.enabled) {
enabled_tunabilities.push(tunability);
} else {
addable_tunabilities.push({
label: helpers.titleCase(tunability.name),
value: tunability.name
});
}
} }
} }
return _react2.default.createElement( return _react2.default.createElement(
'div', 'div',
{ className: 'tunabilities' }, { className: 'tunabilities' },
tunabilities.map(function (tunability) { _react2.default.createElement(
'h3',
null,
'Musical properties'
),
enabled_tunabilities.map(function (tunability) {
return _react2.default.createElement( return _react2.default.createElement(
'div', 'div',
{ className: 'field tunability', key: tunability.name }, { className: 'field tunability range', key: tunability.name },
_react2.default.createElement(
'div',
{ className: 'field sub-field checkbox' },
_react2.default.createElement(
'label',
null,
_react2.default.createElement('input', {
type: 'checkbox',
name: "tunability_" + tunability.name,
checked: tunability.enabled,
onChange: function onChange(e) {
return _this3.toggleTunability(tunability.name);
} }),
_react2.default.createElement( _react2.default.createElement(
'div', 'div',
{ className: 'label' }, { className: 'label' },
tunability.name helpers.titleCase(tunability.name),
),
_react2.default.createElement( _react2.default.createElement(
'span', 'span',
{ className: 'has-tooltip info' }, { className: 'has-tooltip info' },
@ -69996,14 +70027,10 @@ var Discover = function (_React$Component) {
tunability.description tunability.description
) )
) )
)
), ),
tunability.enabled ? _react2.default.createElement(
'div',
{ className: 'input' },
_react2.default.createElement( _react2.default.createElement(
'div', 'div',
{ className: 'field sub-field range' }, { className: 'input' },
_react2.default.createElement(_reactInputRange2.default, { _react2.default.createElement(_reactInputRange2.default, {
disabled: !tunability.enabled, disabled: !tunability.enabled,
minValue: tunability.min, minValue: tunability.min,
@ -70014,9 +70041,11 @@ var Discover = function (_React$Component) {
} }
}) })
) )
) : null
); );
}) }),
_react2.default.createElement(_DropdownField2.default, { icon: 'plus', name: 'Add', options: addable_tunabilities, no_status_icon: true, handleChange: function handleChange(val) {
_this3.toggleTunability(val);
} })
); );
} }
}, { }, {

File diff suppressed because one or more lines are too long

View File

@ -38,7 +38,7 @@
// Release details // Release details
// These are automatically injected to built HTML // These are automatically injected to built HTML
var build = "1515697971"; var build = "1516129632";
var version = "3.11.0"; var version = "3.11.0";
// Construct the script tag // Construct the script tag

View File

@ -40,16 +40,24 @@ export default class DropdownField extends React.Component{
} }
render(){ render(){
if (!this.props.options) return null if (!this.props.options){
return null;
var classname = 'dropdown-field' }
if (this.state.expanded) classname += ' expanded'
var className = 'dropdown-field';
if (this.state.expanded){
className += ' expanded';
}
if (this.props.no_status_icon){
className += ' no-status-icon';
}
var current_value = this.props.options[0].value var current_value = this.props.options[0].value
if (this.props.value) current_value = this.props.value if (this.props.value){
current_value = this.props.value;
}
var icon = <FontAwesome name="check" /> var icon = <FontAwesome name="check" />
if (typeof(this.props.reverse) !== 'undefined'){ if (this.props.reverse !== undefined){
if (this.props.reverse){ if (this.props.reverse){
icon = <FontAwesome className="reverse" name="caret-down" /> icon = <FontAwesome className="reverse" name="caret-down" />
} else { } else {
@ -58,7 +66,7 @@ export default class DropdownField extends React.Component{
} }
return ( return (
<div className={classname} data-key={this.props.name.replace(' ','_').toLowerCase()}> <div className={className} data-key={this.props.name.replace(' ','_').toLowerCase()}>
<div className="label" onClick={ () => this.handleToggle() }> <div className="label" onClick={ () => this.handleToggle() }>
{this.props.icon ? <span><FontAwesome name={this.props.icon} />&nbsp; </span> : null} {this.props.icon ? <span><FontAwesome name={this.props.icon} />&nbsp; </span> : null}
<span className="text">{ this.props.name }</span> <span className="text">{ this.props.name }</span>
@ -68,7 +76,7 @@ export default class DropdownField extends React.Component{
this.props.options.map(option => { this.props.options.map(option => {
return ( return (
<div className="option" key={ option.value } onClick={ e => this.handleChange(option.value) }> <div className="option" key={ option.value } onClick={ e => this.handleChange(option.value) }>
{option.value == current_value ? icon : null} {!this.props.no_status_icon && (option.value == current_value) ? icon : null}
{option.label} {option.label}
</div> </div>
) )

View File

@ -792,3 +792,14 @@ export let getIndexedRecords = function(index, uris){
return records return records
} }
/**
* Uppercase-ify the first character of a string
*
* @param string = string
* @return string
**/
export let titleCase = function(string){
return string.charAt(0).toUpperCase() + string.slice(1)
}

View File

@ -907,13 +907,11 @@ export function getRecommendations(uris = [], limit = 20, tunabilities = null){
} }
// construct our endpoint URL with all the appropriate arguments // construct our endpoint URL with all the appropriate arguments
var endpoint = 'recommendations' var endpoint = 'recommendations';
endpoint += '?seed_artists='+artists_ids.join(',') endpoint += '?seed_artists='+artists_ids.join(',');
endpoint += '&seed_tracks='+tracks_ids.join(',') endpoint += '&seed_tracks='+tracks_ids.join(',');
endpoint += '&seed_genres='+genres.join(',') endpoint += '&seed_genres='+genres.join(',');
endpoint += '&limit='+limit endpoint += '&limit='+limit;
console.log(tunabilities);
if (tunabilities){ if (tunabilities){
for (var key in tunabilities){ for (var key in tunabilities){

View File

@ -11,6 +11,7 @@ import ArtistGrid from '../../components/ArtistGrid'
import AlbumGrid from '../../components/AlbumGrid' import AlbumGrid from '../../components/AlbumGrid'
import TrackList from '../../components/TrackList' import TrackList from '../../components/TrackList'
import Parallax from '../../components/Parallax' import Parallax from '../../components/Parallax'
import DropdownField from '../../components/DropdownField'
import AddSeedField from '../../components/AddSeedField' import AddSeedField from '../../components/AddSeedField'
import URILink from '../../components/URILink' import URILink from '../../components/URILink'
import ContextMenuTrigger from '../../components/ContextMenuTrigger' import ContextMenuTrigger from '../../components/ContextMenuTrigger'
@ -226,13 +227,18 @@ class Discover extends React.Component{
if (tunabilities.hasOwnProperty(key) && tunabilities[key].enabled){ if (tunabilities.hasOwnProperty(key) && tunabilities[key].enabled){
var tunability = tunabilities[key]; var tunability = tunabilities[key];
var max = tunability.value.max;
var min = tunability.value.min;
if (tunability.convert_to_decimal){ if (tunability.convert_to_decimal){
tunability.value.max = tunability.max / 100; max = max / 100;
tunability.value.min = tunability.min / 100; min = min / 100;
} }
digested_tunabilities[key+"_max"] = tunability.value.max; console.log(key,max,min);
digested_tunabilities[key+"_min"] = tunability.value.min;
digested_tunabilities[key+"_max"] = max.toString();
digested_tunabilities[key+"_min"] = min.toString();
} }
} }
this.props.spotifyActions.getRecommendations(seeds, 50, digested_tunabilities) this.props.spotifyActions.getRecommendations(seeds, 50, digested_tunabilities)
@ -299,6 +305,7 @@ class Discover extends React.Component{
return ( return (
<div className="seeds"> <div className="seeds">
<h3>Seeds</h3>
{ {
seeds_objects.map((seed,index) => { seeds_objects.map((seed,index) => {
var type = helpers.uriType(seed.uri) var type = helpers.uriType(seed.uri)
@ -329,10 +336,11 @@ class Discover extends React.Component{
} }
renderTunabilities(){ renderTunabilities(){
var enabled_tunabilities = [];
var tunabilities = []; var addable_tunabilities = [];
for (var key in this.state.tunabilities){ for (var key in this.state.tunabilities){
if (this.state.tunabilities.hasOwnProperty(key)){ if (this.state.tunabilities.hasOwnProperty(key)){
var tunability = Object.assign( var tunability = Object.assign(
{}, {},
this.state.tunabilities[key], this.state.tunabilities[key],
@ -340,34 +348,33 @@ class Discover extends React.Component{
name: key name: key
} }
); );
tunabilities.push(tunability);
if (tunability.enabled){
enabled_tunabilities.push(tunability);
} else {
addable_tunabilities.push({
label: helpers.titleCase(tunability.name),
value: tunability.name
});
}
} }
} }
return ( return (
<div className="tunabilities"> <div className="tunabilities">
<h3>Musical properties</h3>
{ {
tunabilities.map(tunability => { enabled_tunabilities.map(tunability => {
return ( return (
<div className="field tunability" key={tunability.name}> <div className="field tunability range" key={tunability.name}>
<div className="field sub-field checkbox">
<label>
<input
type="checkbox"
name={"tunability_"+tunability.name}
checked={tunability.enabled}
onChange={e => this.toggleTunability(tunability.name)} />
<div className="label"> <div className="label">
{tunability.name} {helpers.titleCase(tunability.name)}
</div>
<span className="has-tooltip info"> <span className="has-tooltip info">
<FontAwesome name="info-circle" /> <FontAwesome name="info-circle" />
<span className="tooltip">{tunability.description}</span> <span className="tooltip">{tunability.description}</span>
</span> </span>
</label>
</div> </div>
{tunability.enabled ? <div className="input"> <div className="input">
<div className="field sub-field range">
<InputRange <InputRange
disabled={!tunability.enabled} disabled={!tunability.enabled}
minValue={tunability.min} minValue={tunability.min}
@ -376,11 +383,11 @@ class Discover extends React.Component{
onChange={value => this.setTunability(tunability.name, value)} onChange={value => this.setTunability(tunability.name, value)}
/> />
</div> </div>
</div> : null}
</div> </div>
); );
}) })
} }
<DropdownField icon="plus" name="Add" options={addable_tunabilities} no_status_icon handleChange={val => {this.toggleTunability(val)}} />
</div> </div>
); );
} }

View File

@ -25,6 +25,14 @@
} }
} }
&.no-status-icon {
.options {
.option {
padding-left: 12px;
}
}
}
.options { .options {
color: $black; color: $black;
position: absolute; position: absolute;

View File

@ -294,6 +294,14 @@ input[type="submit"] {
} }
&.range { &.range {
.label {
padding-bottom: 4px;
.has-tooltip {
padding-left: 4px;
}
}
.input-range__track, .input-range__track,
.input-range__slider-container { .input-range__slider-container {
transition: none; transition: none;

View File

@ -28,17 +28,19 @@
h2 { h2 {
padding-bottom: 8px; padding-bottom: 8px;
} }
}
}
.seeds,
.tunabilities {
padding-top: 40px;
h3 { h3 {
padding-bottom: 40px; padding-bottom: 6px;
opacity: 0.5;
}
} }
} }
.seeds { .seeds {
padding-top: 40px;
.seed { .seed {
display: inline-block; display: inline-block;
background: $blue; background: $blue;
@ -68,6 +70,23 @@
} }
} }
.tunabilities {
@include clearfix();
.tunability {
width: 200px;
float: left;
box-sizing: border-box;
padding-right: 20px;
.input-range {
.input-range__label-container {
display: none;
}
}
}
}
.autocomplete-field { .autocomplete-field {
width: 250px; width: 250px;
display: inline-block; display: inline-block;
@ -97,26 +116,6 @@
} }
} }
.tunabilities {
margin: 10px -10px;
.tunability {
width: 25%;
box-sizing: border-box;
padding: 10px;
label {
text-transform: capitalize;
}
.input-range {
.input-range__label-container {
display: none;
}
}
}
}
section { section {
.grid { .grid {
padding-bottom: 20px; padding-bottom: 20px;