UNPKG

transcend-spotify-react

Version:

A react component to explore Spotify data using Transcend

273 lines (226 loc) 8.3 kB
import React from 'react' import { dateFormatter } from 'transcend-formats'; import { guid } from 'transcend-helpers'; import {SpotifySavedTracksComponent, SpotifyFollowedArtistsComponent, SpotifySavedPlaylistsComponent, SpotifyTopTracksComponent, SpotifyTopArtistsComponent, SpotifyPlayHistoryComponent, SpotifyAllTracksComponent, SpotifyAllArtistsComponent, SpotifyAllFriendsComponent} from 'transcend-spotify-components-react' class User { constructor(userObj, parent){ this.alwaysThisUser = ["allTracks", "allArtists", "allFriends"]; this.data = userObj.data; this.friends = userObj.friends; this.parent = parent; } getFriendData(ind){ return this.friends[ind]; } getDisplayUser(){ if(this.parent.state.displayUser === -1 || this.alwaysThisUser.indexOf(this.parent.state.displayType) > -1) return this.data; else return this.getFriendData(this.parent.state.displayUser); } renderProfile(){ let user = this.getDisplayUser(); return (<div> <div> {user.details.images.length > 0 && <img src={user.details.images[0].url} /> } </div> <div> {user.details.display_name} </div> <div> Num Followers: {user.details.followers.total} </div> </div>); } } /** * Display Spotify Table **/ class SpotifyTable extends React.Component { // Sub components state = { components: [SpotifySavedTracksComponent, SpotifyFollowedArtistsComponent, SpotifySavedPlaylistsComponent, SpotifyTopTracksComponent, SpotifyTopArtistsComponent, SpotifyPlayHistoryComponent, SpotifyAllTracksComponent, SpotifyAllArtistsComponent, SpotifyAllFriendsComponent], instantiatedComponents: {}, display : [], displayParent: [], displayUser : -1, displayType: "allTracks", displayPull: 0, displayState: {}, displayStates : {}, plotOptions: { key : "popularity", plotLocation: "profile", type : "pdf", numBins : 20, standardize : false, allowedTypes : [] } }; constructor(props) { super(props); this.user = new User(this.props.userData, this); // Instantiate components this.state.components.map((Component) => { let instantiatedComponent = new Component({user : this.user, parent : this}); this.state.displayState[instantiatedComponent.state.key] = instantiatedComponent.state.displayState; this.state.displayStates[instantiatedComponent.state.key] = instantiatedComponent.state.displayStates; this.state.instantiatedComponents[instantiatedComponent.state.key] = instantiatedComponent; }) } componentDidMount() { let hash = location.hash.substring(1); if(hash.length > 0) this.setState({ displayType : hash}); else location.hash = "#" + this.state.displayType; } /** * Build the User Profile **/ getCurrentComponent(){ return this.state.instantiatedComponents[this.state.displayType]; } updateAllowedTypes(){ let component = this.getCurrentComponent(); if(component.state.displayStates && component.state.displayStates[this.state.displayType]){ this.state.plotOptions.allowedTypes = component.state.displayStates[this.state.displayType].plot; } } buildProfile(){ this.updateAllowedTypes(); return (<div> { this.user.renderProfile() } { this.state.plotOptions.plotLocation === "profile" && <div className="plotSpace"> {this.getCurrentComponent().plot(this.state.plotOptions) } </div> } </div>); } /** * Build Menus **/ buildHeader(){ let main = <ul key={guid()} className="nav"> { Object.keys(this.state.instantiatedComponents).map((key, ind) => { return <li key={guid()}> <a href={"#" + key} onClick={this.switchDisplayType.bind(this, key)} className={(this.state.displayType === key ? "nav-selected " : "") + "nav-item"}> - {this.state.instantiatedComponents[key].state.displayName } - </a> </li>; })} </ul>; let headers = this.state.instantiatedComponents[this.state.displayType].state.headers; let others = <span key={guid()} > { headers.map((header, ind) => { return this.buildMenu(header); })} </span>; return <div> {main} {others} </div> } buildMenu(menuName){ let user = this.user.getDisplayUser(); switch(menuName){ case "friends": return <ul key={guid()} className="nav"> <li key={guid()} onClick={this.switchToSelf.bind(this)}><a className={(user.userId === this.user.data.userId ? "nav-selected " : "") + "nav-item"}>- Me -</a></li> { this.user.friends.map((friend, ind) => { return <li key={guid()} onClick={this.switchUser.bind(this, ind)}><a className={(user.userId === friend.userId ? "nav-selected " : "") + "nav-item"}>- {friend.details.display_name} -</a></li> })} </ul>; case "pullHistory": let pullLists = user[this.state.displayType]; return <div/>; <ul key={guid()} className="nav"> { user[this.state.displayType].map((pulledList, ind) => { return <div> <li key={guid()} onClick={this.switchPull.bind(this, ind)}><a className="nav-item">- {dateFormatter(new Date(pulledList.timePulled))} -</a></li> </div>; })} </ul> case "collapser": let displayState = this.state.displayState[this.state.displayType]; let displayStates = this.state.displayStates[this.state.displayType]; return <div key={guid()}> { Object.keys(displayState).map((key) => { return <ul key={guid()} className="nav"> <label>{ displayStates[key]['displayName'] }: -</label> {displayStates[key]["plot"].length > 0 && <li key={guid()} onClick={this.switchPlotOption.bind(this, "key", key)}><a className={(this.state.plotOptions.key === key ? "nav-selected " : "") + "nav-item"}>- Plot -</a></li> } <li key={guid()} onClick={this.switchDisplay.bind(this, key, "none")}><a className={(displayState[key].length === 0 ? "nav-selected " : "") + "nav-item"}>- Hide -</a></li> { displayStates[key]['states'].map((state, ind) => { return <li key={guid()} onClick={this.switchDisplay.bind(this, key, state)}><a className={(displayState[key].indexOf(state) > -1 ? "nav-selected " : "") + "nav-item"}>- { state } -</a></li>; })} </ul>; })} </div>; } } /** * Changing State **/ switchPlotOption(key, value){ let plotOptions = this.state.plotOptions; plotOptions[key] = value; this.setState({plotOptions : plotOptions}); } switchUser(id){ this.setState({displayUser :id}); } switchToSelf(){ this.setState({displayUser :-1}); } switchDisplayType(newType){ this.setState({displayType :newType}); } switchPull(id){ this.setState({displayPull :id}); } switchDisplay(stateName, stateValue){ let newState = this.state.displayState; let changeState = newState[this.state.displayType][stateName]; if(stateValue === "none"){ changeState = [] } else{ let index = changeState.indexOf(stateValue); if(index === -1){ changeState.push(stateValue); } else{ changeState.splice(index, 1); } } newState[this.state.displayType][stateName] = changeState; this.setState({displayState : newState}); } /** * Render **/ render() { let header = this.buildHeader(); let profile = this.buildProfile(); return <div className={"row"}> <div className={"col-lg-6"}> {header} </div> <div className={"col-lg-6"}> {profile} </div> { this.state.plotOptions.plotLocation === "fullWidth" && <div className="plotSpace col-lg-12"> {this.getCurrentComponent().plot(this.state.plotOptions) } </div> } { this.state.instantiatedComponents[this.state.displayType].render() } </div>; } } module.exports = { User : User, SpotifyTable : SpotifyTable }