React/Redux - publish component #323

Merged
bones7242 merged 80 commits from react-upload into master 2018-01-25 22:43:20 +01:00
12 changed files with 121 additions and 113 deletions
Showing only changes of commit 325cb03661 - Show all commits

View file

@ -33,7 +33,7 @@ function publishNewChannel (event) {
return sendAuthRequest(userName, password, '/signup') // post the request return sendAuthRequest(userName, password, '/signup') // post the request
}) })
.then(result => { .then(result => {
setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
showChannelCreateDoneDisplay(); showChannelCreateDoneDisplay();
window.location = '/'; window.location = '/';
}) })

View file

@ -131,7 +131,7 @@ function clearCookie(name) {
document.cookie = `${name}=; expires=Thu, 01-Jan-1970 00:00:01 GMT;`; document.cookie = `${name}=; expires=Thu, 01-Jan-1970 00:00:01 GMT;`;
} }
function setUserCookies(channelName, channelClaimId, shortChannelId) { function setUserCookies(channelName, shortChannelId, channelClaimId) {
setCookie('channel_name', channelName) setCookie('channel_name', channelName)
setCookie('channel_claim_id', channelClaimId); setCookie('channel_claim_id', channelClaimId);
setCookie('short_channel_id', shortChannelId); setCookie('short_channel_id', shortChannelId);

View file

@ -8,7 +8,7 @@ function loginToChannel (event) {
return sendAuthRequest(userName, password, '/login') return sendAuthRequest(userName, password, '/login')
}) })
.then(result => { .then(result => {
setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId); setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
// if user is on the home page, update the needed elements without reloading // if user is on the home page, update the needed elements without reloading
window.location = '/'; window.location = '/';
}) })

View file

@ -17,8 +17,6 @@ class AnonymousOrChannelSelect extends React.Component {
} }
render () { render () {
return ( return (
<div className="row row--padded row--short row--wide">
<div className="column column--10">
<form> <form>
<div className="column column--3 column--med-10"> <div className="column column--3 column--med-10">
<input type="radio" name="anonymous-or-channel" id="anonymous-radio" className="input-radio" value="anonymous" checked={!this.props.publishInChannel} onChange={this.toggleAnonymousPublish}/> <input type="radio" name="anonymous-or-channel" id="anonymous-radio" className="input-radio" value="anonymous" checked={!this.props.publishInChannel} onChange={this.toggleAnonymousPublish}/>
@ -29,8 +27,6 @@ class AnonymousOrChannelSelect extends React.Component {
<label className="label label--pointer" htmlFor="channel-radio">In a channel</label> <label className="label label--pointer" htmlFor="channel-radio">In a channel</label>
</div> </div>
</form> </form>
</div>
</div>
); );
} }
} }

View file

@ -1,5 +1,9 @@
import React from 'react'; import React from 'react';
import {connect} from 'react-redux';
import {updateLoggedInChannel} from '../actions';
import { makeGetRequest, makePostRequest } from '../utils/xhr.js'; import { makeGetRequest, makePostRequest } from '../utils/xhr.js';
import { setUserCookies } from '../utils/cookies.js';
import { replaceChannelSelectionInNavBar } from '../utils/pageUpdate.js';
class ChannelCreateForm extends React.Component { class ChannelCreateForm extends React.Component {
constructor (props) { constructor (props) {
@ -10,25 +14,24 @@ class ChannelCreateForm extends React.Component {
password: null, password: null,
status : null, status : null,
}; };
this.cleanseChannelInput = this.cleanseChannelInput.bind(this);
this.handleChannelInput = this.handleChannelInput.bind(this); this.handleChannelInput = this.handleChannelInput.bind(this);
this.handleInput = this.handleInput.bind(this); this.handleInput = this.handleInput.bind(this);
this.cleanseInput = this.cleanseInput.bind(this);
this.checkChannelIsAvailable = this.checkChannelIsAvailable.bind(this); this.checkChannelIsAvailable = this.checkChannelIsAvailable.bind(this);
this.createChannel = this.createChannel.bind(this); this.createChannel = this.createChannel.bind(this);
} }
handleChannelInput (event) { cleanseChannelInput (input) {
event.preventDefault();
const name = event.target.name;
let value = event.target.value;
value = this.cleanseInput(value);
this.setState({[name]: value});
this.checkChannelIsAvailable(value);
}
cleanseInput (input) {
input = input.replace(/\s+/g, '-'); // replace spaces with dashes input = input.replace(/\s+/g, '-'); // replace spaces with dashes
input = input.replace(/[^A-Za-z0-9-]/g, ''); // remove all characters that are not A-Z, a-z, 0-9, or '-' input = input.replace(/[^A-Za-z0-9-]/g, ''); // remove all characters that are not A-Z, a-z, 0-9, or '-'
return input; return input;
} }
handleChannelInput (event) {
event.preventDefault();
let value = event.target.value;
value = this.cleanseChannelInput(value);
this.setState({channel: value});
this.checkChannelIsAvailable(value);
}
handleInput (event) { handleInput (event) {
event.preventDefault(); event.preventDefault();
const name = event.target.name; const name = event.target.name;
@ -65,10 +68,9 @@ class ChannelCreateForm extends React.Component {
this.setState({status: 'We are publishing your new channel. Sit tight...'}); this.setState({status: 'We are publishing your new channel. Sit tight...'});
makePostRequest(url, params) makePostRequest(url, params)
.then(result => { .then(result => {
that.props.updateLoggedInChannelOutsideReact(result.channelName, result.channelClaimId, result.shortChannelId); that.props.onChannelLogin(result.channelName, result.shortChannelId, result.channelClaimId);
that.props.updateUploaderState('loggedInChannelName', result.channelName); setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
that.props.updateUploaderState('loggedInChannelShortId', result.shortChannelId); replaceChannelSelectionInNavBar(result.channelName);
that.props.selectOption(result.channelName);
}) })
.catch(error => { .catch(error => {
console.log('create channel failure:', error); console.log('create channel failure:', error);
@ -91,7 +93,7 @@ class ChannelCreateForm extends React.Component {
</div><div className="column column--6 column--sml-10"> </div><div className="column column--6 column--sml-10">
<div className="input-text--primary flex-container--row flex-container--left-bottom"> <div className="input-text--primary flex-container--row flex-container--left-bottom">
<span>@</span> <span>@</span>
<input type="text" name="channel" id="new-channel-name" className="input-text" placeholder="exampleChannelName" value={this.channel} onChange={this.handleChannelInput} /> <input type="text" name="channel" id="new-channel-name" className="input-text" placeholder="exampleChannelName" value={this.state.channel} onChange={this.handleChannelInput} />
<span id="input-success-channel-name" className="info-message--success">{'\u2713'}</span> <span id="input-success-channel-name" className="info-message--success">{'\u2713'}</span>
</div> </div>
</div> </div>
@ -101,13 +103,13 @@ class ChannelCreateForm extends React.Component {
<label className="label" htmlFor="new-channel-password">Password:</label> <label className="label" htmlFor="new-channel-password">Password:</label>
</div><div className="column column--6 column--sml-10"> </div><div className="column column--6 column--sml-10">
<div className="input-text--primary"> <div className="input-text--primary">
<input type="password" name="password" id="new-channel-password" className="input-text" placeholder="" value={this.password} onChange={this.handleInput} /> <input type="password" name="password" id="new-channel-password" className="input-text" placeholder="" value={this.state.password} onChange={this.handleInput} />
</div> </div>
</div> </div>
</div> </div>
<div className="row row--wide"> <div className="row row--wide">
<button className="button--primary" onClick={this.createChannel}>Create</button> <button className="button--primary" onClick={this.createChannel}>Create Channel</button>
</div> </div>
</form> </form>
) : ( ) : (
@ -118,4 +120,12 @@ class ChannelCreateForm extends React.Component {
} }
} }
module.exports = ChannelCreateForm; const mapDispatchToProps = dispatch => {
return {
onChannelLogin: (name, shortId, longId) => {
dispatch(updateLoggedInChannel(name, shortId, longId));
},
};
};
export default connect(null, mapDispatchToProps)(ChannelCreateForm);

View file

@ -1,5 +1,9 @@
import React from 'react'; import React from 'react';
import { makePostRequest } from '../utils/xhr.js'; import { makePostRequest } from '../utils/xhr.js';
import { connect } from 'react-redux';
import { updateLoggedInChannel } from '../actions';
import { setUserCookies } from '../utils/cookies.js';
import { replaceChannelSelectionInNavBar } from '../utils/pageUpdate.js';
class ChannelLoginForm extends React.Component { class ChannelLoginForm extends React.Component {
constructor (props) { constructor (props) {
@ -25,17 +29,16 @@ class ChannelLoginForm extends React.Component {
const that = this; const that = this;
makePostRequest(url, params) makePostRequest(url, params)
.then(result => { .then(result => {
that.props.updateLoggedInChannelOutsideReact(result.channelName, result.channelClaimId, result.shortChannelId); that.props.onChannelLogin(result.channelName, result.shortChannelId, result.channelClaimId);
that.props.updateUploaderState('loggedInChannelName', result.channelName); setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
that.props.updateUploaderState('loggedInChannelShortId', result.shortChannelId); replaceChannelSelectionInNavBar(result.channelName);
that.props.selectOption(result.channelName);
}) })
.catch(error => { .catch(error => {
console.log('login error', error); console.log('login error', error);
if (error.message) { if (error.message) {
that.setState({'error': error.message}); that.setState({'error': error.message});
} else { } else {
that.setState({'error': 'There was an error logging into your channel'}); that.setState({'error': error});
} }
}); });
} }
@ -71,4 +74,12 @@ class ChannelLoginForm extends React.Component {
} }
} }
module.exports = ChannelLoginForm; const mapDispatchToProps = dispatch => {
return {
onChannelLogin: (name, shortId, longId) => {
dispatch(updateLoggedInChannel(name, shortId, longId));
},
};
};
export default connect(null, mapDispatchToProps)(ChannelLoginForm);

View file

@ -2,7 +2,6 @@ import React from 'react';
import ChannelLoginForm from './ChannelLoginForm.jsx'; import ChannelLoginForm from './ChannelLoginForm.jsx';
import ChannelCreateForm from './ChannelCreateForm.jsx'; import ChannelCreateForm from './ChannelCreateForm.jsx';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { setUserCookies } from '../utils/cookies.js';
const LOGIN = 'login'; const LOGIN = 'login';
const CREATE = 'create'; const CREATE = 'create';
@ -15,12 +14,17 @@ class ChannelSelector extends React.Component {
}; };
this.handleSelection = this.handleSelection.bind(this); this.handleSelection = this.handleSelection.bind(this);
this.selectOption = this.selectOption.bind(this); this.selectOption = this.selectOption.bind(this);
this.replaceChannelSelectionInNavBar = this.replaceChannelSelectionInNavBar.bind(this);
this.updateLoggedInChannelOutsideReact = this.updateLoggedInChannelOutsideReact.bind(this);
} }
componentWillMount () { componentWillMount () {
console.log('ChannelSelector will mount.');
if (this.props.loggedInChannelName) { if (this.props.loggedInChannelName) {
this.setState({ optionState: this.props.loggedInChannelName }); this.selectOption(this.props.loggedInChannelName);
}
}
componentWillReceiveProps ({ loggedInChannelName }) {
console.log('ChannelSelector will receive props');
if (loggedInChannelName) {
this.selectOption(loggedInChannelName);
} }
} }
handleSelection (event) { handleSelection (event) {
@ -30,39 +34,12 @@ class ChannelSelector extends React.Component {
selectOption (option) { selectOption (option) {
this.setState({optionState: option}); this.setState({optionState: option});
} }
updateLoggedInChannelOutsideReact (channelName, channelClaimId, shortChannelId) {
// update anywhere on page that needs to be updated outside of this component
setUserCookies(channelName, channelClaimId, shortChannelId);
this.replaceChannelSelectionInNavBar(channelName);
}
replaceChannelSelectionInNavBar (loggedInChannel) {
// remove the old channel option
const oldChannel = document.getElementById('nav-bar-channel-select-channel-option');
if (oldChannel) {
oldChannel.parentNode.removeChild(oldChannel);
}
// create new channel option & select it
const newChannelOption = document.createElement('option');
newChannelOption.setAttribute('value', loggedInChannel);
newChannelOption.setAttribute('id', 'nav-bar-channel-select-channel-option');
newChannelOption.setAttribute('selected', '');
newChannelOption.innerText = loggedInChannel;
// add the new option
const channelSelect = document.getElementById('nav-bar-channel-select');
channelSelect.style.display = 'inline-block';
channelSelect.insertBefore(newChannelOption, channelSelect.firstChild);
// hide login
const navBarLoginLink = document.getElementById('nav-bar-login-link');
navBarLoginLink.style.display = 'none';
}
render () { render () {
return ( return (
<div> <div>
{ this.props.publishInChannel && ( { this.props.publishInChannel && (
<div className="row row--padded row--no-top row--no-bottom row--wide"> <div>
<p id="input-error-channel-select" className="info-message-placeholder info-message--failure">{this.props.channelError}</p> <p id="input-error-channel-select" className="info-message-placeholder info-message--failure">{this.props.channelError}</p>
<div className="column column--3"> <div className="column column--3">
<label className="label" htmlFor="channel-name-select">Channel:</label> <label className="label" htmlFor="channel-name-select">Channel:</label>
</div><div className="column column--7"> </div><div className="column column--7">
@ -73,18 +50,9 @@ class ChannelSelector extends React.Component {
</select> </select>
</div> </div>
{ (this.state.optionState === LOGIN) && { (this.state.optionState === LOGIN) && <ChannelLoginForm /> }
<ChannelLoginForm
updateLoggedInChannelOutsideReact={this.updateLoggedInChannelOutsideReact} { (this.state.optionState === CREATE) && <ChannelCreateForm /> }
updateUploaderState={this.props.updateUploaderState}
selectOption={this.selectOption}
/> }
{ (this.state.optionState === CREATE) &&
<ChannelCreateForm
updateLoggedInChannelOutsideReact={this.updateLoggedInChannelOutsideReact}
updateUploaderState={this.props.updateUploaderState}
selectOption={this.selectOption}
/> }
</div> </div>
)} )}

View file

@ -22,12 +22,12 @@ class PublishForm extends React.Component {
this.publish = this.publish.bind(this); this.publish = this.publish.bind(this);
} }
componentWillMount () { componentWillMount () {
// check for whether a channel is logged in // check for whether a channel is already logged in
// if so, set the loggedInChannel to the channel name
const loggedInChannelName = getCookie('channel_name'); const loggedInChannelName = getCookie('channel_name');
const loggedInChannelShortId = getCookie('short_channel_id'); const loggedInChannelShortId = getCookie('short_channel_id');
const loggedInChannelLongId = getCookie('long_channel_id'); const loggedInChannelLongId = getCookie('long_channel_id');
this.props.onChannelUpdate(loggedInChannelName, loggedInChannelShortId, loggedInChannelLongId); console.log(`channel cookies found: ${loggedInChannelName} ${loggedInChannelShortId} ${loggedInChannelLongId}`);
this.props.onChannelLogin(loggedInChannelName, loggedInChannelShortId, loggedInChannelLongId);
} }
publish () { publish () {
// publish the asset // publish the asset
@ -51,9 +51,17 @@ class PublishForm extends React.Component {
<div className="column column--5 column--sml-10 align-content-top"> <div className="column column--5 column--sml-10 align-content-top">
<div id="publish-active-area" className="row row--padded"> <div id="publish-active-area" className="row row--padded">
<div className="row row--padded row--no-top row--wide">
<PublishUrlInput /> <PublishUrlInput />
</div>
<div className="row row--padded row--no-top row--no-bottom row--wide">
<AnonymousOrChannelSelect /> <AnonymousOrChannelSelect />
</div>
<div className="row row--padded row--no-top row--wide">
<ChannelSelector /> <ChannelSelector />
</div>
<PublishMetadataInputs <PublishMetadataInputs
updateUploaderState={this.props.updateUploaderState} updateUploaderState={this.props.updateUploaderState}
@ -98,7 +106,7 @@ const mapDispatchToProps = dispatch => {
onFileClear: () => { onFileClear: () => {
dispatch(clearFile()); dispatch(clearFile());
}, },
onChannelUpdate: (name, shortId, longId) => { onChannelLogin: (name, shortId, longId) => {
dispatch(updateLoggedInChannel(name, shortId, longId)); dispatch(updateLoggedInChannel(name, shortId, longId));
}, },
}; };

View file

@ -56,10 +56,7 @@ class UrlChooser extends React.Component {
render () { render () {
return ( return (
<div> <div>
<div className="row row--padded row--no-top row--wide">
<p id="input-error-claim-name" className="info-message-placeholder info-message--failure">{this.state.error}</p> <p id="input-error-claim-name" className="info-message-placeholder info-message--failure">{this.state.error}</p>
<div className="column column--3 column--sml-10"> <div className="column column--3 column--sml-10">
<label className="label">URL:</label> <label className="label">URL:</label>
</div><div className="column column--7 column--sml-10 input-text--primary span--relative"> </div><div className="column column--7 column--sml-10 input-text--primary span--relative">
@ -70,9 +67,6 @@ class UrlChooser extends React.Component {
<input type="text" id="claim-name-input" className="input-text" name='claim' placeholder="your-url-here" onChange={this.handleInput} value={this.props.claim}/> <input type="text" id="claim-name-input" className="input-text" name='claim' placeholder="your-url-here" onChange={this.handleInput} value={this.props.claim}/>
{ (this.props.claim && !this.state.error) && <span id="input-success-claim-name" className="info-message--success span--absolute">{'\u2713'}</span> } { (this.props.claim && !this.state.error) && <span id="input-success-claim-name" className="info-message--success span--absolute">{'\u2713'}</span> }
</div>
</div> </div>
</div> </div>
); );

View file

@ -9,8 +9,7 @@ const initialState = {
kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).
kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).
shortId: null, shortId: null,
longId : null, longId : null,
}, },
loggedInChannelShortId: null, publishInChannel: false,
kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).
kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).
publishInChannel : false,
kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).
publishStatus : null, publishStatus : null,
error : null, error : null,
file : null, file : null,

kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).
kauffj commented 2018-01-15 20:27:22 +01:00 (Migrated from github.com)
Review

import * as

`import * as`
kauffj commented 2018-01-15 20:28:40 +01:00 (Migrated from github.com)
Review

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

Some of these should possibly be renamed or refactored into separate files (or possibly can wait until next refactor/revision).

View file

@ -17,7 +17,7 @@ module.exports = {
setCookie (key, value) { setCookie (key, value) {
document.cookie = `${key}=${value}`; document.cookie = `${key}=${value}`;
}, },
setUserCookies (channelName, channelClaimId, shortChannelId) { setUserCookies (channelName, shortChannelId, channelClaimId) {
module.exports.setCookie('channel_name', channelName) module.exports.setCookie('channel_name', channelName)
module.exports.setCookie('channel_claim_id', channelClaimId); module.exports.setCookie('channel_claim_id', channelClaimId);
module.exports.setCookie('short_channel_id', shortChannelId); module.exports.setCookie('short_channel_id', shortChannelId);

22
react/utils/pageUpdate.js Normal file
View file

@ -0,0 +1,22 @@
module.exports = {
replaceChannelSelectionInNavBar (loggedInChannel) {
// remove the old channel option
const oldChannel = document.getElementById('nav-bar-channel-select-channel-option');
if (oldChannel) {
oldChannel.parentNode.removeChild(oldChannel);
}
// create new channel option & select it
const newChannelOption = document.createElement('option');
newChannelOption.setAttribute('value', loggedInChannel);
newChannelOption.setAttribute('id', 'nav-bar-channel-select-channel-option');
newChannelOption.setAttribute('selected', '');
newChannelOption.innerText = loggedInChannel;
// add the new option
const channelSelect = document.getElementById('nav-bar-channel-select');
channelSelect.style.display = 'inline-block';
channelSelect.insertBefore(newChannelOption, channelSelect.firstChild);
// hide login
const navBarLoginLink = document.getElementById('nav-bar-login-link');
navBarLoginLink.style.display = 'none';
},
}