added whatwg-fetch and fixed publish validation

This commit is contained in:
bill bittner 2018-01-25 13:37:59 -08:00
parent 1f78a50b48
commit 8945707d0f
11 changed files with 93 additions and 68 deletions

View file

@ -54,6 +54,7 @@
"sequelize-cli": "^3.0.0-3",
"sleep": "^5.1.1",
"universal-analytics": "^0.4.13",
"whatwg-fetch": "^2.0.3",
"winston": "^2.3.1",
"winston-slack-webhook": "billbitt/winston-slack-webhook"
},

View file

@ -21,9 +21,6 @@ const validationFunctions = {
isChannelNameAvailable: function (name) {
return this.isNameAvailable(name, '/api/channel-is-available/');
},
isClaimNameAvailable: function (name) {
return this.isNameAvailable(name, '/api/claim-is-available/')
},
isNameAvailable: function (name, apiUrl) {
console.log('isNameAvailable?', name);
const url = apiUrl + name;

View file

@ -1,6 +1,6 @@
import React from 'react';
import ProgressBar from 'components/ProgressBar';
import { makeGetRequest, makePostRequest } from 'utils/xhr';
import request from 'utils/request';
class ChannelCreateForm extends React.Component {
constructor (props) {
@ -43,7 +43,7 @@ class ChannelCreateForm extends React.Component {
updateIsChannelAvailable (channel) {
const that = this;
const channelWithAtSymbol = `@${channel}`;
makeGetRequest(`/api/channel-is-available/${channelWithAtSymbol}`)
request(`/api/channel-is-available/${channelWithAtSymbol}`)
.then(isAvailable => {
if (isAvailable) {
that.setState({'error': null});
@ -58,7 +58,7 @@ class ChannelCreateForm extends React.Component {
checkIsChannelAvailable (channel) {
const channelWithAtSymbol = `@${channel}`;
return new Promise((resolve, reject) => {
makeGetRequest(`/api/channel-is-available/${channelWithAtSymbol}`)
request(`/api/channel-is-available/${channelWithAtSymbol}`)
.then(isAvailable => {
console.log('checkIsChannelAvailable result:', isAvailable);
if (!isAvailable) {
@ -82,10 +82,17 @@ class ChannelCreateForm extends React.Component {
resolve();
});
}
makePublishChannelRequest (channel, password) {
const params = `username=${channel}&password=${password}`;
makePublishChannelRequest (username, password) {
const params = {
method : 'POST',
body : JSON.stringify({username, password}),
headers: new Headers({
'Content-Type': 'application/json',
}),
credentials: 'include',
};
return new Promise((resolve, reject) => {
makePostRequest('/signup', params)
request('/signup', params)
.then(result => {
console.log('makePublishChannelRequest result:', result);
return resolve(result);

View file

@ -1,5 +1,5 @@
import React from 'react';
import { makePostRequest } from 'utils/xhr';
import request from 'utils/request';
class ChannelLoginForm extends React.Component {
constructor (props) {
@ -19,15 +19,22 @@ class ChannelLoginForm extends React.Component {
}
loginToChannel (event) {
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;
makePostRequest('login', params)
.then(result => {
console.log('loginToChannel result:', result);
if (result.success) {
that.props.onChannelLogin(result.channelName, result.shortChannelId, result.channelClaimId);
request('login', params)
.then(({success, channelName, shortChannelId, channelClaimId, message}) => {
console.log('loginToChannel success:', success);
if (success) {
that.props.onChannelLogin(channelName, shortChannelId, channelClaimId);
} else {
that.setState({'error': result.message});
that.setState({'error': message});
};
})
.catch(error => {

View file

@ -1,5 +1,5 @@
import React from 'react';
import { authenticateUser } from 'utils/auth';
import request from 'utils/request';
import Logo from 'components/Logo';
import NavBarChannelDropdown from 'components/NavBarChannelOptionsDropdown';
@ -19,7 +19,10 @@ class NavBar extends React.Component {
}
checkForLoggedInUser () {
// check for whether a channel is already logged in
authenticateUser()
const params = {
credentials: 'include',
}
request('/user', params)
.then(({success, message}) => {
if (success) {
this.props.onChannelLogin(message.channelName, message.shortChannelId, message.channelClaimId);

View file

@ -16,18 +16,21 @@ class PublishForm extends React.Component {
this.publish = this.publish.bind(this);
}
validateChannelSelection () {
console.log('validating channel selection');
// make sure all required data is provided
return new Promise((resolve, reject) => {
// if publishInChannel is true, is a channel selected & logged in?
if (this.props.publishInChannel && (this.props.selectedChannel !== this.props.loggedInChannel.name)) {
// 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
return reject(new Error('Fix the channel'));
}
resolve();
});
}
validatePublishParams () {
console.log('validating publish params');
// make sure all required data is provided
return new Promise((resolve, reject) => {
// is there a file?
@ -41,11 +44,11 @@ class PublishForm extends React.Component {
if (this.props.urlError) {
return reject(new Error('Fix the url'));
}
// is the claim available?
resolve();
});
}
makePublishRequest (file, metadata) {
console.log('making publish request');
const uri = '/api/claim-publish';
const xhr = new XMLHttpRequest();
const fd = this.appendDataToFormData(file, metadata);
@ -84,6 +87,7 @@ class PublishForm extends React.Component {
xhr.send(fd);
}
createMetadata () {
console.log('creating metadata');
let metadata = {
name : this.props.claim,
title : this.props.title,
@ -103,18 +107,19 @@ class PublishForm extends React.Component {
fd.append('file', file);
for (var key in metadata) {
if (metadata.hasOwnProperty(key)) {
console.log(key, metadata[key]);
console.log('adding form data', key, metadata[key]);
fd.append(key, metadata[key]);
}
}
return fd;
}
publish () {
console.log('publishing file');
// publish the asset
const that = this;
this.validateChannelSelection()
.then(() => {
return that.validatePublishRequest();
return that.validatePublishParams();
})
.then(() => {
const metadata = that.createMetadata();

View file

@ -1,5 +1,5 @@
import React from 'react';
import {makeGetRequest} from 'utils/xhr';
import request from 'utils/request';
import UrlMiddle from 'components/PublishUrlMiddleDisplay';
class PublishUrlInput extends React.Component {
@ -41,10 +41,10 @@ class PublishUrlInput extends React.Component {
}
checkClaimIsAvailable (claim) {
const that = this;
makeGetRequest(`/api/claim-is-available/${claim}`)
.then(response => {
console.log('makeGetRequest response:', response);
if (response) {
request(`/api/claim-is-available/${claim}`)
.then(isAvailable => {
// console.log('checkClaimIsAvailable request response:', isAvailable);
if (isAvailable) {
that.props.onUrlError(null);
} else {
that.props.onUrlError('That url has already been claimed');

View file

@ -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
View 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);
}

View file

@ -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);
});
},
}

View file

@ -3,7 +3,7 @@ const Path = require('path');
const REACT_ROOT = Path.resolve(__dirname, 'react/');
module.exports = {
entry : './react/app.js',
entry : ['whatwg-fetch', './react/app.js'],
output: {
path : Path.join(__dirname, '/public/bundle/'),
filename: 'bundle.js',