added whatwg-fetch and fixed publish validation
This commit is contained in:
parent
1f78a50b48
commit
8945707d0f
11 changed files with 93 additions and 68 deletions
|
@ -54,6 +54,7 @@
|
||||||
"sequelize-cli": "^3.0.0-3",
|
"sequelize-cli": "^3.0.0-3",
|
||||||
"sleep": "^5.1.1",
|
"sleep": "^5.1.1",
|
||||||
"universal-analytics": "^0.4.13",
|
"universal-analytics": "^0.4.13",
|
||||||
|
"whatwg-fetch": "^2.0.3",
|
||||||
"winston": "^2.3.1",
|
"winston": "^2.3.1",
|
||||||
"winston-slack-webhook": "billbitt/winston-slack-webhook"
|
"winston-slack-webhook": "billbitt/winston-slack-webhook"
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,9 +21,6 @@ const validationFunctions = {
|
||||||
isChannelNameAvailable: function (name) {
|
isChannelNameAvailable: function (name) {
|
||||||
return this.isNameAvailable(name, '/api/channel-is-available/');
|
return this.isNameAvailable(name, '/api/channel-is-available/');
|
||||||
},
|
},
|
||||||
isClaimNameAvailable: function (name) {
|
|
||||||
return this.isNameAvailable(name, '/api/claim-is-available/')
|
|
||||||
},
|
|
||||||
isNameAvailable: function (name, apiUrl) {
|
isNameAvailable: function (name, apiUrl) {
|
||||||
console.log('isNameAvailable?', name);
|
console.log('isNameAvailable?', name);
|
||||||
const url = apiUrl + name;
|
const url = apiUrl + name;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProgressBar from 'components/ProgressBar';
|
import ProgressBar from 'components/ProgressBar';
|
||||||
import { makeGetRequest, makePostRequest } from 'utils/xhr';
|
import request from 'utils/request';
|
||||||
|
|
||||||
class ChannelCreateForm extends React.Component {
|
class ChannelCreateForm extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
@ -43,7 +43,7 @@ class ChannelCreateForm extends React.Component {
|
||||||
updateIsChannelAvailable (channel) {
|
updateIsChannelAvailable (channel) {
|
||||||
const that = this;
|
const that = this;
|
||||||
const channelWithAtSymbol = `@${channel}`;
|
const channelWithAtSymbol = `@${channel}`;
|
||||||
makeGetRequest(`/api/channel-is-available/${channelWithAtSymbol}`)
|
request(`/api/channel-is-available/${channelWithAtSymbol}`)
|
||||||
.then(isAvailable => {
|
.then(isAvailable => {
|
||||||
if (isAvailable) {
|
if (isAvailable) {
|
||||||
that.setState({'error': null});
|
that.setState({'error': null});
|
||||||
|
@ -58,7 +58,7 @@ class ChannelCreateForm extends React.Component {
|
||||||
checkIsChannelAvailable (channel) {
|
checkIsChannelAvailable (channel) {
|
||||||
const channelWithAtSymbol = `@${channel}`;
|
const channelWithAtSymbol = `@${channel}`;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
makeGetRequest(`/api/channel-is-available/${channelWithAtSymbol}`)
|
request(`/api/channel-is-available/${channelWithAtSymbol}`)
|
||||||
.then(isAvailable => {
|
.then(isAvailable => {
|
||||||
console.log('checkIsChannelAvailable result:', isAvailable);
|
console.log('checkIsChannelAvailable result:', isAvailable);
|
||||||
if (!isAvailable) {
|
if (!isAvailable) {
|
||||||
|
@ -82,10 +82,17 @@ class ChannelCreateForm extends React.Component {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
makePublishChannelRequest (channel, password) {
|
makePublishChannelRequest (username, password) {
|
||||||
const params = `username=${channel}&password=${password}`;
|
const params = {
|
||||||
|
method : 'POST',
|
||||||
|
body : JSON.stringify({username, password}),
|
||||||
|
headers: new Headers({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}),
|
||||||
|
credentials: 'include',
|
||||||
|
};
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
makePostRequest('/signup', params)
|
request('/signup', params)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
console.log('makePublishChannelRequest result:', result);
|
console.log('makePublishChannelRequest result:', result);
|
||||||
return resolve(result);
|
return resolve(result);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { makePostRequest } from 'utils/xhr';
|
import request from 'utils/request';
|
||||||
|
|
||||||
class ChannelLoginForm extends React.Component {
|
class ChannelLoginForm extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
@ -19,15 +19,22 @@ class ChannelLoginForm extends React.Component {
|
||||||
}
|
}
|
||||||
loginToChannel (event) {
|
loginToChannel (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const params = `username=${this.state.name}&password=${this.state.password}`;
|
const params = {
|
||||||
|
method : 'POST',
|
||||||
|
body : JSON.stringify({username: this.state.name, password: this.state.password}),
|
||||||
|
headers: new Headers({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}),
|
||||||
|
credentials: 'include',
|
||||||
|
}
|
||||||
const that = this;
|
const that = this;
|
||||||
makePostRequest('login', params)
|
request('login', params)
|
||||||
.then(result => {
|
.then(({success, channelName, shortChannelId, channelClaimId, message}) => {
|
||||||
console.log('loginToChannel result:', result);
|
console.log('loginToChannel success:', success);
|
||||||
if (result.success) {
|
if (success) {
|
||||||
that.props.onChannelLogin(result.channelName, result.shortChannelId, result.channelClaimId);
|
that.props.onChannelLogin(channelName, shortChannelId, channelClaimId);
|
||||||
} else {
|
} else {
|
||||||
that.setState({'error': result.message});
|
that.setState({'error': message});
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { authenticateUser } from 'utils/auth';
|
import request from 'utils/request';
|
||||||
import Logo from 'components/Logo';
|
import Logo from 'components/Logo';
|
||||||
import NavBarChannelDropdown from 'components/NavBarChannelOptionsDropdown';
|
import NavBarChannelDropdown from 'components/NavBarChannelOptionsDropdown';
|
||||||
|
|
||||||
|
@ -19,7 +19,10 @@ class NavBar extends React.Component {
|
||||||
}
|
}
|
||||||
checkForLoggedInUser () {
|
checkForLoggedInUser () {
|
||||||
// check for whether a channel is already logged in
|
// check for whether a channel is already logged in
|
||||||
authenticateUser()
|
const params = {
|
||||||
|
credentials: 'include',
|
||||||
|
}
|
||||||
|
request('/user', params)
|
||||||
.then(({success, message}) => {
|
.then(({success, message}) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
this.props.onChannelLogin(message.channelName, message.shortChannelId, message.channelClaimId);
|
this.props.onChannelLogin(message.channelName, message.shortChannelId, message.channelClaimId);
|
||||||
|
|
|
@ -16,18 +16,21 @@ class PublishForm extends React.Component {
|
||||||
this.publish = this.publish.bind(this);
|
this.publish = this.publish.bind(this);
|
||||||
}
|
}
|
||||||
validateChannelSelection () {
|
validateChannelSelection () {
|
||||||
|
console.log('validating channel selection');
|
||||||
// make sure all required data is provided
|
// make sure all required data is provided
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// if publishInChannel is true, is a channel selected & logged in?
|
// if publishInChannel is true, is a channel selected & logged in?
|
||||||
if (this.props.publishInChannel && (this.props.selectedChannel !== this.props.loggedInChannel.name)) {
|
if (this.props.publishInChannel && (this.props.selectedChannel !== this.props.loggedInChannel.name)) {
|
||||||
// update state with error
|
// update state with error
|
||||||
this.props.onChannelSelectionError('Select a channel or Anonymous');
|
this.props.onChannelSelectionError('Log in to a channel or select Anonymous"');
|
||||||
// reject this promise
|
// reject this promise
|
||||||
return reject(new Error('Fix the channel'));
|
return reject(new Error('Fix the channel'));
|
||||||
}
|
}
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
validatePublishParams () {
|
validatePublishParams () {
|
||||||
|
console.log('validating publish params');
|
||||||
// make sure all required data is provided
|
// make sure all required data is provided
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// is there a file?
|
// is there a file?
|
||||||
|
@ -41,11 +44,11 @@ class PublishForm extends React.Component {
|
||||||
if (this.props.urlError) {
|
if (this.props.urlError) {
|
||||||
return reject(new Error('Fix the url'));
|
return reject(new Error('Fix the url'));
|
||||||
}
|
}
|
||||||
// is the claim available?
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
makePublishRequest (file, metadata) {
|
makePublishRequest (file, metadata) {
|
||||||
|
console.log('making publish request');
|
||||||
const uri = '/api/claim-publish';
|
const uri = '/api/claim-publish';
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
const fd = this.appendDataToFormData(file, metadata);
|
const fd = this.appendDataToFormData(file, metadata);
|
||||||
|
@ -84,6 +87,7 @@ class PublishForm extends React.Component {
|
||||||
xhr.send(fd);
|
xhr.send(fd);
|
||||||
}
|
}
|
||||||
createMetadata () {
|
createMetadata () {
|
||||||
|
console.log('creating metadata');
|
||||||
let metadata = {
|
let metadata = {
|
||||||
name : this.props.claim,
|
name : this.props.claim,
|
||||||
title : this.props.title,
|
title : this.props.title,
|
||||||
|
@ -103,18 +107,19 @@ class PublishForm extends React.Component {
|
||||||
fd.append('file', file);
|
fd.append('file', file);
|
||||||
for (var key in metadata) {
|
for (var key in metadata) {
|
||||||
if (metadata.hasOwnProperty(key)) {
|
if (metadata.hasOwnProperty(key)) {
|
||||||
console.log(key, metadata[key]);
|
console.log('adding form data', key, metadata[key]);
|
||||||
fd.append(key, metadata[key]);
|
fd.append(key, metadata[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
publish () {
|
publish () {
|
||||||
|
console.log('publishing file');
|
||||||
// publish the asset
|
// publish the asset
|
||||||
const that = this;
|
const that = this;
|
||||||
this.validateChannelSelection()
|
this.validateChannelSelection()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return that.validatePublishRequest();
|
return that.validatePublishParams();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const metadata = that.createMetadata();
|
const metadata = that.createMetadata();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {makeGetRequest} from 'utils/xhr';
|
import request from 'utils/request';
|
||||||
import UrlMiddle from 'components/PublishUrlMiddleDisplay';
|
import UrlMiddle from 'components/PublishUrlMiddleDisplay';
|
||||||
|
|
||||||
class PublishUrlInput extends React.Component {
|
class PublishUrlInput extends React.Component {
|
||||||
|
@ -41,10 +41,10 @@ class PublishUrlInput extends React.Component {
|
||||||
}
|
}
|
||||||
checkClaimIsAvailable (claim) {
|
checkClaimIsAvailable (claim) {
|
||||||
const that = this;
|
const that = this;
|
||||||
makeGetRequest(`/api/claim-is-available/${claim}`)
|
request(`/api/claim-is-available/${claim}`)
|
||||||
.then(response => {
|
.then(isAvailable => {
|
||||||
console.log('makeGetRequest response:', response);
|
// console.log('checkClaimIsAvailable request response:', isAvailable);
|
||||||
if (response) {
|
if (isAvailable) {
|
||||||
that.props.onUrlError(null);
|
that.props.onUrlError(null);
|
||||||
} else {
|
} else {
|
||||||
that.props.onUrlError('That url has already been claimed');
|
that.props.onUrlError('That url has already been claimed');
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import {makeGetRequest} from 'utils/xhr';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
authenticateUser () {
|
|
||||||
// send request to server & receive the user info back
|
|
||||||
return makeGetRequest('/user');
|
|
||||||
},
|
|
||||||
};
|
|
44
react/utils/request.js
Normal file
44
react/utils/request.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Parses the JSON returned by a network request
|
||||||
|
*
|
||||||
|
* @param {object} response A response from a network request
|
||||||
|
*
|
||||||
|
* @return {object} The parsed JSON from the request
|
||||||
|
*/
|
||||||
|
function parseJSON (response) {
|
||||||
|
if (response.status === 204 || response.status === 205) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a network request came back fine, and throws an error if not
|
||||||
|
*
|
||||||
|
* @param {object} response A response from a network request
|
||||||
|
*
|
||||||
|
* @return {object|undefined} Returns either the response, or throws an error
|
||||||
|
*/
|
||||||
|
function checkStatus (response) {
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = new Error(response.statusText);
|
||||||
|
error.response = response;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests a URL, returning a promise
|
||||||
|
*
|
||||||
|
* @param {string} url The URL we want to request
|
||||||
|
* @param {object} [options] The options we want to pass to "fetch"
|
||||||
|
*
|
||||||
|
* @return {object} The response data
|
||||||
|
*/
|
||||||
|
export default function request (url, options) {
|
||||||
|
return fetch(url, options)
|
||||||
|
.then(checkStatus)
|
||||||
|
.then(parseJSON);
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
makeGetRequest (url) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let xhttp = new XMLHttpRequest();
|
|
||||||
xhttp.open('GET', url, true);
|
|
||||||
xhttp.responseType = 'json';
|
|
||||||
xhttp.onreadystatechange = () => {
|
|
||||||
if (xhttp.readyState === 4) {
|
|
||||||
console.log('makeGetRequest response:', xhttp.response);
|
|
||||||
resolve(xhttp.response);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
xhttp.send();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
makePostRequest (url, params) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let xhttp = new XMLHttpRequest();
|
|
||||||
xhttp.open('POST', url, true);
|
|
||||||
xhttp.responseType = 'json';
|
|
||||||
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
|
||||||
xhttp.onreadystatechange = () => {
|
|
||||||
if (xhttp.readyState === 4) {
|
|
||||||
console.log('makePostRequest response:', xhttp.response);
|
|
||||||
resolve(xhttp.response);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
xhttp.send(params);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ const Path = require('path');
|
||||||
const REACT_ROOT = Path.resolve(__dirname, 'react/');
|
const REACT_ROOT = Path.resolve(__dirname, 'react/');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry : './react/app.js',
|
entry : ['whatwg-fetch', './react/app.js'],
|
||||||
output: {
|
output: {
|
||||||
path : Path.join(__dirname, '/public/bundle/'),
|
path : Path.join(__dirname, '/public/bundle/'),
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
|
|
Loading…
Add table
Reference in a new issue