React/Redux - publish component #323

Merged
bones7242 merged 80 commits from react-upload into master 2018-01-25 22:43:20 +01:00
7 changed files with 186 additions and 55 deletions
Showing only changes of commit 257df15e44 - Show all commits

View file

@ -0,0 +1,97 @@
import React from 'react';
function ChannelSuccess (message) {
return (
<div>
<p>{this.props.message}</p>
</div>
);
}
function ChannelInProgress () {
return (
<div id="channel-publish-in-progress">
<p>Creating your new channel. This may take a few seconds...</p>
<div id="create-channel-progress-bar"></div>
</div>
);
}
class ChannelCreateForm extends React.Component {
constructor (props) {
super(props);
this.state = {
error : null,
channel : null,
password: null,
status : null,
};
this.handleChannelInput = this.handleChannelInput.bind(this);
this.handleInput = this.handleInput.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.props.cleanseInput(value);
this.setState({[name]: value});
this.checkChannelIsAvailable(value);
}
handleInput (event) {
event.preventDefault();
const name = event.target.name;
const value = event.target.value;
this.setState({[name]: value});
}
checkChannelIsAvailable (channel) {
const that = this;
this.props.makeGetRequest(`/api/channel-is-available/${channel}`)
.then(() => {
that.setState({urlError: null});
})
.catch((error) => {
that.setState({error: error.message});
});
}
createChannel (event) {
event.preventDefault();
// publishNewChannel(event)
}
render () {
return (
<form id="publish-channel-form">
<p id="input-error-channel-name" className="info-message-placeholder info-message--failure">{this.state.error}</p>
<div className="row row--wide row--short">
<div className="column column--3 column--sml-10">
<label className="label" htmlFor="new-channel-name">Name:</label>
</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="new-channel-name" id="new-channel-name" className="input-text" placeholder="exampleChannelName" value={this.channel} onChange={this.handleChannelInput} />
<span id="input-success-channel-name" className="info-message--success">{'\u2713'}</span>
</div>
</div>
</div>
<div className="row row--wide row--short">
<div className="column column--3 column--sml-10">
<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="new-channel-password" id="new-channel-password" className="input-text" placeholder="" value={this.password} onChange={this.handleInput} />
</div>
</div>
</div>
<div className="row row--wide">
<button className="button--primary" onClick={this.createChannel}>Create</button>
</div>
</form>
);
}
}
module.exports = ChannelCreateForm;

View file

@ -0,0 +1,55 @@
import React from 'react';
class ChannelLoginForm extends React.Component {
constructor (props) {
super(props);
this.state = {
error : null,
name : null,
password: null,
};
this.handleInput = this.handleInput.bind(this);
this.loginToChannel = this.loginToChannel.bind(this);
}
handleInput (event) {
event.preventDefault();
const name = event.target.name;
const value = event.target.value;
this.setState({[name]: value});
}
loginToChannel (event) {
event.preventDefault();
}
render () {
return (
<form id="channel-login-form">
<p id="login-error-display-element" className="info-message-placeholder info-message--failure">{this.state.error}</p>
<div className="row row--wide row--short">
<div className="column column--3 column--sml-10">
<label className="label" htmlFor="channel-login-name-input">Name:</label>
</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" id="channel-login-name-input" className="input-text" name="name" placeholder="Your Channel Name" value={this.state.channelName} onChange={this.handleInput}/>
</div>
</div>
</div>
<div className="row row--wide row--short">
<div className="column column--3 column--sml-10">
<label className="label" htmlFor="channel-login-password-input" >Password:</label>
</div><div className="column column--6 column--sml-10">
<div className="input-text--primary">
<input type="password" id="channel-login-password-input" name="password" className="input-text" placeholder="" value={this.state.channelPassword} onChange={this.handleInput}/>
</div>
</div>
</div>
<div className="row row--wide">
<button className="button--primary" onClick={this.loginToChannel}>Authenticate</button>
</div>
</form>
);
}
}
module.exports = ChannelLoginForm;

View file

@ -1,42 +1,23 @@
import React from 'react'; import React from 'react';
import ChannelLoginForm from './channelLoginForm.jsx';
import ChannelCreateForm from './channelCreateForm.jsx';
const LOGIN = 'login'; const LOGIN = 'login';
const CREATE = 'create'; const CREATE = 'create';
class ChannelLoginForm extends React.Component {
constructor (props) {
super(props);
}
render () {
return (
<div>
<h4>Channel Login Form</h4>
</div>
);
}
}
class ChannelCreateForm extends React.Component {
constructor (props) {
super(props);
}
render () {
return (
<div>
<h4>Create Channel Form</h4>
</div>
);
}
}
class ChannelSelector extends React.Component { class ChannelSelector extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
this.state = { this.state = {
displayCreateOrLogin: null, displayCreateOrLogin: LOGIN,
}; };
this.toggleCreateOrLogin = this.toggleCreateOrLogin.bind(this); this.toggleCreateOrLogin = this.toggleCreateOrLogin.bind(this);
} }
componentWillMount () {
if (this.props.loggedInChannelName) {
this.setState({ displayCreateOrLogin: null });
}
}
toggleCreateOrLogin (event) { toggleCreateOrLogin (event) {
const selectedOption = event.target.selectedOptions[0].value; const selectedOption = event.target.selectedOptions[0].value;
if (selectedOption === 'login') { if (selectedOption === 'login') {
@ -66,7 +47,11 @@ class ChannelSelector extends React.Component {
</div> </div>
{ (this.state.displayCreateOrLogin === LOGIN) && <ChannelLoginForm /> } { (this.state.displayCreateOrLogin === LOGIN) && <ChannelLoginForm /> }
{ (this.state.displayCreateOrLogin === CREATE) && <ChannelCreateForm /> } { (this.state.displayCreateOrLogin === CREATE) &&
<ChannelCreateForm
makeGetRequest={this.props.makeGetRequest}
cleanseInput={this.props.cleanseInput}
/> }
</div> </div>
)} )}

View file

@ -126,7 +126,7 @@ class Dropzone extends React.Component {
setClaimNameFromFileName (fileName) { setClaimNameFromFileName (fileName) {
console.log('setClaimNameFromFileName', fileName); console.log('setClaimNameFromFileName', fileName);
const fileNameWithoutEnding = fileName.substring(0, fileName.lastIndexOf('.')); const fileNameWithoutEnding = fileName.substring(0, fileName.lastIndexOf('.'));
const cleanClaimName = this.props.cleanseClaimName(fileNameWithoutEnding); const cleanClaimName = this.props.cleanseInput(fileNameWithoutEnding);
this.props.updateUploaderState('claim', cleanClaimName); this.props.updateUploaderState('claim', cleanClaimName);
} }
render () { render () {

View file

@ -42,9 +42,6 @@ class AnonymousOrChannelSelect extends React.Component {
class PublishForm extends React.Component { class PublishForm extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
this.state = {
channelError: null,
}
// set defaults // set defaults
this.updateUploaderState = this.updateUploaderState.bind(this); this.updateUploaderState = this.updateUploaderState.bind(this);
this.clearUploaderState = this.clearUploaderState.bind(this); this.clearUploaderState = this.clearUploaderState.bind(this);
@ -73,7 +70,7 @@ class PublishForm extends React.Component {
<PreviewDropzone <PreviewDropzone
file={this.props.file} file={this.props.file}
/> />
{ (this.props.file.type === 'video/mp4') && <ThumbnailInput thumbnail={this.props.thumbnail}/> }
</div> </div>
</div> </div>
<div className="column column--5 column--sml-10 align-content-top"> <div className="column column--5 column--sml-10 align-content-top">
@ -85,26 +82,23 @@ class PublishForm extends React.Component {
publishToChannel={this.props.publishToChannel} publishToChannel={this.props.publishToChannel}
loggedInChannelName={this.props.loggedInChannelName} loggedInChannelName={this.props.loggedInChannelName}
loggedInChannelShortId={this.props.loggedInChannelShortId} loggedInChannelShortId={this.props.loggedInChannelShortId}
cleanseClaimName={this.props.cleanseClaimName} cleanseInput={this.props.cleanseInput}
updateUploaderState={this.updateUploaderState} updateUploaderState={this.updateUploaderState}
makeGetRequest={this.props.makeGetRequest} makeGetRequest={this.props.makeGetRequest}
/> />
<AnonymousOrChannelSelect <AnonymousOrChannelSelect
publishToChannel={this.props.publishToChannel} publishToChannel={this.props.publishToChannel}
updateUploaderState={this.props.updateUploaderState} updateUploaderState={this.props.updateUploaderState}
/> />
<ChannelSelector <ChannelSelector
channel={this.props.channel} channel={this.props.channel}
loggedInChannelName={this.props.loggedInChannelName} loggedInChannelName={this.props.loggedInChannelName}
publishToChannel={this.props.publishToChannel} publishToChannel={this.props.publishToChannel}
cleanseInput={this.props.cleanseInput}
updateUploaderState={this.updateUploaderState} updateUploaderState={this.updateUploaderState}
channelError={this.state.channelError} makeGetRequest={this.props.makeGetRequest}
/> />
{ (this.props.file.type === 'video/mp4') && <ThumbnailInput thumbnail={this.props.thumbnail}/> }
<MetadataInputs /> <MetadataInputs />
<div className="row row--padded row--wide"> <div className="row row--padded row--wide">

View file

@ -17,8 +17,8 @@ class UrlChooser extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
this.state = { this.state = {
urlError : null, error : null,
urlBeginning: 'spee.ch', host : 'spee.ch',
urlMiddle: null, urlMiddle: null,
}; };
this.handleInput = this.handleInput.bind(this); this.handleInput = this.handleInput.bind(this);
@ -28,7 +28,7 @@ class UrlChooser extends React.Component {
event.preventDefault(); event.preventDefault();
let value = event.target.value; let value = event.target.value;
const name = event.target.name; const name = event.target.name;
value = this.props.cleanseClaimName(value); value = this.props.cleanseInput(value);
this.props.updateUploaderState(name, value); this.props.updateUploaderState(name, value);
this.checkClaimIsAvailable(value); this.checkClaimIsAvailable(value);
} }
@ -36,10 +36,10 @@ class UrlChooser extends React.Component {
const that = this; const that = this;
this.props.makeGetRequest(`/api/claim-is-available/${claim}`) this.props.makeGetRequest(`/api/claim-is-available/${claim}`)
.then(() => { .then(() => {
that.setState({urlError: null}); that.setState({'error': null});
}) })
.catch((error) => { .catch((error) => {
that.setState({urlError: error.message}); that.setState({'error': error.message});
}); });
} }
render () { render () {
@ -47,18 +47,18 @@ class UrlChooser extends React.Component {
<div> <div>
<div className="row row--padded row--no-top row--wide"> <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.urlError}</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">
<span className="url-text--secondary">{this.state.urlBeginning} / </span> <span className="url-text--secondary">{this.state.host} / </span>
<UrlMiddle publishToChannel={this.props.publishToChannel} loggedInChannelName={this.props.loggedInChannelName} loggedInChannelShortId={this.props.loggedInChannelShortId}/> <UrlMiddle publishToChannel={this.props.publishToChannel} 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}/> <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.urlError) && ( { (this.props.claim && !this.state.error) && (
<span id="input-success-claim-name" className="info-message--success span--absolute">{'\u2713'}</span> <span id="input-success-claim-name" className="info-message--success span--absolute">{'\u2713'}</span>
)} )}

View file

@ -31,7 +31,7 @@ class Uploader extends React.Component {
this.clearUploaderState = this.clearUploaderState.bind(this); this.clearUploaderState = this.clearUploaderState.bind(this);
this.makeGetRequest = this.makeGetRequest.bind(this); this.makeGetRequest = this.makeGetRequest.bind(this);
this.makePostRequest = this.makePostRequest.bind(this); this.makePostRequest = this.makePostRequest.bind(this);
this.cleanseClaimName = this.cleanseClaimName.bind(this); this.cleanseInput = this.cleanseInput.bind(this);
this.getCookie = this.getCookie.bind(this); this.getCookie = this.getCookie.bind(this);
} }
componentDidMount () { componentDidMount () {
@ -88,10 +88,10 @@ class Uploader extends React.Component {
xhttp.send(params); xhttp.send(params);
}); });
} }
cleanseClaimName (name) { cleanseInput (input) {
name = name.replace(/\s+/g, '-'); // replace spaces with dashes input = input.replace(/\s+/g, '-'); // replace spaces with dashes
name = name.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 name; return input;
} }
getCookie (cname) { getCookie (cname) {
const name = cname + '='; const name = cname + '=';
@ -114,7 +114,7 @@ class Uploader extends React.Component {
{ this.state.showComponent === DROPZONE && { this.state.showComponent === DROPZONE &&
<Dropzone <Dropzone
updateUploaderState={this.updateUploaderState} updateUploaderState={this.updateUploaderState}
cleanseClaimName={this.cleanseClaimName} cleanseInput={this.cleanseInput}
/> />
} }
{ this.state.showComponent === DETAILS && { this.state.showComponent === DETAILS &&
@ -122,7 +122,7 @@ class Uploader extends React.Component {
updateUploaderState={this.updateUploaderState} updateUploaderState={this.updateUploaderState}
clearUploaderState={this.clearUploaderState} clearUploaderState={this.clearUploaderState}
makeGetRequest={this.makeGetRequest} makeGetRequest={this.makeGetRequest}
cleanseClaimName={this.cleanseClaimName} cleanseInput={this.cleanseInput}
loggedInChannelName={this.state.loggedInChannelName} loggedInChannelName={this.state.loggedInChannelName}
loggedInChannelShortId={this.state.loggedInChannelShortId} loggedInChannelShortId={this.state.loggedInChannelShortId}
publishToChannel={this.state.publishToChannel} publishToChannel={this.state.publishToChannel}