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
})
.then(result => {
setUserCookies(result.channelName, result.channelClaimId, result.shortChannelId);
setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
showChannelCreateDoneDisplay();
window.location = '/';
})

View file

@ -131,7 +131,7 @@ function clearCookie(name) {
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_claim_id', channelClaimId);
setCookie('short_channel_id', shortChannelId);

View file

@ -8,7 +8,7 @@ function loginToChannel (event) {
return sendAuthRequest(userName, password, '/login')
})
.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
window.location = '/';
})

View file

@ -17,20 +17,16 @@ class AnonymousOrChannelSelect extends React.Component {
}
render () {
return (
<div className="row row--padded row--short row--wide">
<div className="column column--10">
<form>
<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}/>
<label className="label label--pointer" htmlFor="anonymous-radio">Anonymous</label>
</div>
<div className="column column--7 column--med-10">
<input type="radio" name="anonymous-or-channel" id="channel-radio" className="input-radio" value="in a channel" checked={this.props.publishInChannel} onChange={this.toggleAnonymousPublish}/>
<label className="label label--pointer" htmlFor="channel-radio">In a channel</label>
</div>
</form>
<form>
<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}/>
<label className="label label--pointer" htmlFor="anonymous-radio">Anonymous</label>
</div>
</div>
<div className="column column--7 column--med-10">
<input type="radio" name="anonymous-or-channel" id="channel-radio" className="input-radio" value="in a channel" checked={this.props.publishInChannel} onChange={this.toggleAnonymousPublish}/>
<label className="label label--pointer" htmlFor="channel-radio">In a channel</label>
</div>
</form>
);
}
}

View file

@ -1,5 +1,9 @@
import React from 'react';
import {connect} from 'react-redux';
import {updateLoggedInChannel} from '../actions';
import { makeGetRequest, makePostRequest } from '../utils/xhr.js';
import { setUserCookies } from '../utils/cookies.js';
import { replaceChannelSelectionInNavBar } from '../utils/pageUpdate.js';
class ChannelCreateForm extends React.Component {
constructor (props) {
@ -10,25 +14,24 @@ class ChannelCreateForm extends React.Component {
password: null,
status : null,
};
this.cleanseChannelInput = this.cleanseChannelInput.bind(this);
this.handleChannelInput = this.handleChannelInput.bind(this);
this.handleInput = this.handleInput.bind(this);
this.cleanseInput = this.cleanseInput.bind(this);
this.checkChannelIsAvailable = this.checkChannelIsAvailable.bind(this);
this.createChannel = this.createChannel.bind(this);
}
handleChannelInput (event) {
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) {
cleanseChannelInput (input) {
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 '-'
return input;
}
handleChannelInput (event) {
event.preventDefault();
let value = event.target.value;
value = this.cleanseChannelInput(value);
this.setState({channel: value});
this.checkChannelIsAvailable(value);
}
handleInput (event) {
event.preventDefault();
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...'});
makePostRequest(url, params)
.then(result => {
that.props.updateLoggedInChannelOutsideReact(result.channelName, result.channelClaimId, result.shortChannelId);
that.props.updateUploaderState('loggedInChannelName', result.channelName);
that.props.updateUploaderState('loggedInChannelShortId', result.shortChannelId);
that.props.selectOption(result.channelName);
that.props.onChannelLogin(result.channelName, result.shortChannelId, result.channelClaimId);
setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
replaceChannelSelectionInNavBar(result.channelName);
})
.catch(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 className="input-text--primary flex-container--row flex-container--left-bottom">
<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>
</div>
</div>
@ -101,13 +103,13 @@ class ChannelCreateForm extends React.Component {
<label className="label" htmlFor="new-channel-password">Password:</label>
</div><div className="column column--6 column--sml-10">
<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 className="row row--wide">
<button className="button--primary" onClick={this.createChannel}>Create</button>
<button className="button--primary" onClick={this.createChannel}>Create Channel</button>
</div>
</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 { 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 {
constructor (props) {
@ -25,17 +29,16 @@ class ChannelLoginForm extends React.Component {
const that = this;
makePostRequest(url, params)
.then(result => {
that.props.updateLoggedInChannelOutsideReact(result.channelName, result.channelClaimId, result.shortChannelId);
that.props.updateUploaderState('loggedInChannelName', result.channelName);
that.props.updateUploaderState('loggedInChannelShortId', result.shortChannelId);
that.props.selectOption(result.channelName);
that.props.onChannelLogin(result.channelName, result.shortChannelId, result.channelClaimId);
setUserCookies(result.channelName, result.shortChannelId, result.channelClaimId);
replaceChannelSelectionInNavBar(result.channelName);
})
.catch(error => {
console.log('login error', error);
if (error.message) {
that.setState({'error': error.message});
} 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 ChannelCreateForm from './ChannelCreateForm.jsx';
import { connect } from 'react-redux';
import { setUserCookies } from '../utils/cookies.js';
const LOGIN = 'login';
const CREATE = 'create';
@ -15,12 +14,17 @@ class ChannelSelector extends React.Component {
};
this.handleSelection = this.handleSelection.bind(this);
this.selectOption = this.selectOption.bind(this);
this.replaceChannelSelectionInNavBar = this.replaceChannelSelectionInNavBar.bind(this);
this.updateLoggedInChannelOutsideReact = this.updateLoggedInChannelOutsideReact.bind(this);
}
componentWillMount () {
console.log('ChannelSelector will mount.');
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) {
@ -30,39 +34,12 @@ class ChannelSelector extends React.Component {
selectOption (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 () {
return (
<div>
{ 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>
<div className="column column--3">
<label className="label" htmlFor="channel-name-select">Channel:</label>
</div><div className="column column--7">
@ -73,18 +50,9 @@ class ChannelSelector extends React.Component {
</select>
</div>
{ (this.state.optionState === LOGIN) &&
<ChannelLoginForm
updateLoggedInChannelOutsideReact={this.updateLoggedInChannelOutsideReact}
updateUploaderState={this.props.updateUploaderState}
selectOption={this.selectOption}
/> }
{ (this.state.optionState === CREATE) &&
<ChannelCreateForm
updateLoggedInChannelOutsideReact={this.updateLoggedInChannelOutsideReact}
updateUploaderState={this.props.updateUploaderState}
selectOption={this.selectOption}
/> }
{ (this.state.optionState === LOGIN) && <ChannelLoginForm /> }
{ (this.state.optionState === CREATE) && <ChannelCreateForm /> }
</div>
)}

View file

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

View file

@ -56,23 +56,17 @@ class UrlChooser extends React.Component {
render () {
return (
<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>
<div className="column column--3 column--sml-10">
<label className="label">URL:</label>
</div><div className="column column--7 column--sml-10 input-text--primary span--relative">
<p id="input-error-claim-name" className="info-message-placeholder info-message--failure">{this.state.error}</p>
<span className="url-text--secondary">{this.state.host} / </span>
<div className="column column--3 column--sml-10">
<label className="label">URL:</label>
</div><div className="column column--7 column--sml-10 input-text--primary span--relative">
<span className="url-text--secondary">{this.state.host} / </span>
<UrlMiddle publishInChannel={this.props.publishInChannel} loggedInChannelName={this.props.loggedInChannelName} loggedInChannelShortId={this.props.loggedInChannelShortId}/>
<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> }
</div>
<UrlMiddle publishInChannel={this.props.publishInChannel} loggedInChannelName={this.props.loggedInChannelName} loggedInChannelShortId={this.props.loggedInChannelShortId}/>
<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> }
</div>
</div>
);

View file

@ -9,13 +9,12 @@ 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,
longId : null,
},
loggedInChannelShortId: 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).
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,
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).
error : 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).
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).
claim : '',
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).
metadata : {
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,
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).
error : 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).
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).
claim : '',
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).
metadata : {
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).
title : '',
thumbnail : '',
description: '',

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) {
document.cookie = `${key}=${value}`;
},
setUserCookies (channelName, channelClaimId, shortChannelId) {
setUserCookies (channelName, shortChannelId, channelClaimId) {
module.exports.setCookie('channel_name', channelName)
module.exports.setCookie('channel_claim_id', channelClaimId);
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';
},
}