import React from 'react'; import analytics from './analytics'; import log from './log'; import storage from './storage'; /* Higher Order Component to provide behavior for loading projects by id from * the window's hash (#this part in the url) * @param {React.Component} WrappedComponent component to receive projectData prop * @returns {React.Component} component with project loading behavior */ const ProjectLoaderHOC = function (WrappedComponent) { class ProjectLoaderComponent extends React.Component { constructor (props) { super(props); this.fetchProjectId = this.fetchProjectId.bind(this); this.updateProject = this.updateProject.bind(this); this.state = { projectId: null, projectData: null, fetchingProject: false }; } componentDidMount () { window.addEventListener('hashchange', this.updateProject); this.updateProject(); } componentWillUpdate (nextProps, nextState) { if (this.state.projectId !== nextState.projectId) { this.setState({fetchingProject: true}, () => { storage .load(storage.AssetType.Project, this.state.projectId, storage.DataFormat.JSON) .then(projectAsset => projectAsset && this.setState({ projectData: projectAsset.data.toString(), fetchingProject: false })) .catch(err => log.error(err)); }); } } componentWillUnmount () { window.removeEventListener('hashchange', this.updateProject); } fetchProjectId () { return window.location.hash.substring(1); } updateProject () { let projectId = this.fetchProjectId(); if (projectId !== this.state.projectId) { if (projectId.length < 1) projectId = 0; this.setState({projectId: projectId}); if (projectId !== 0) { analytics.event({ category: 'project', action: 'Load Project', value: projectId, nonInteraction: true }); } } } render () { if (!this.state.projectData) return null; return ( <WrappedComponent fetchingProject={this.state.fetchingProject} projectData={this.state.projectData} {...this.props} /> ); } } return ProjectLoaderComponent; }; export { ProjectLoaderHOC as default };