Add basic UI

This includes the login form, registration, and a simple nav bar when
you're logged in. I'm just sort of figuring all this stuff out
This commit is contained in:
Eli Ribble 2016-05-17 16:38:20 -06:00
parent ca2b5cdabb
commit 867df0fc57
17 changed files with 715 additions and 0 deletions

13
lib/actions/root.js Normal file
View file

@ -0,0 +1,13 @@
import { bindActionCreators } from 'redux';
import * as ActionsSession from 'vanth/actions/session';
import * as ActionsURL from 'vanth/actions/url';
import * as ActionsUser from 'vanth/actions/user';
import RootStore from 'vanth/store/root';
module.exports = {
Session : bindActionCreators(ActionsSession, RootStore.dispatch),
URL : bindActionCreators(ActionsURL, RootStore.dispatch),
User : bindActionCreators(ActionsUser, RootStore.dispatch),
}

35
lib/actions/session.js Normal file
View file

@ -0,0 +1,35 @@
import * as ActionTools from 'vanth/actions/tools';
export function createSession(username, password, nextPath=null) {
const payload = {
password: password,
username: username,
};
return ActionTools.fetchAndDispatch(
'/session/',
'SESSION_POST_BEGIN',
'SESSION_POST_COMPLETE',
'SESSION_POST_ERROR',
ActionTools.Methods.POST,
payload,
);
}
export function get() {
return ActionTools.fetchAndDispatch(
'/session/',
'SESSION_GET_BEGIN',
'SESSION_GET_COMPLETE',
'SESSION_GET_ERROR'
);
}
export function logout(uri) {
return ActionTools.fetchAndDispatch(
uri,
'SESSION_DELETE_BEGIN',
'SESSION_DELETE_COMPLETE',
'SESSION_DELETE_ERROR',
ActionTools.Methods.DELETE,
);
}

102
lib/actions/tools.js Normal file
View file

@ -0,0 +1,102 @@
import _ from 'lodash';
import Config from 'vanth/config';
import { ActionType } from 'vanth/constants';
import * as Fetch from 'vanth/fetch';
export const Methods = {
DELETE : 'delete',
GET : 'get',
PATCH : 'patch',
POST : 'post',
PUT : 'put',
}
export function action(type) {
return function(data) {
let action = {
type: ActionType[type],
}
if(data != undefined) {
action.data = data;
}
if(!action.type) {
throw new Error(`An action type is required. Could not find an action type constant for ${type}`);
}
return action;
}
}
export function ensureConstantAction(constant) {
if(typeof constant === "string") {
if(!ActionType[constant]) {
let message = `${constant} is not a valid constant - you'll need to add it to constants.js`;
console.error(message)
throw new Error(message);
}
return action(constant);
}
return constant;
}
export function fetchAndDispatch(url, start, end, failed, method=Methods.GET, payload) {
let actionStart = ensureConstantAction(start);
let actionEnd = ensureConstantAction(end);
let actionFailed = ensureConstantAction(failed);
if(!Fetch[method]) {
throw new Error(`Invalid method for fetcher: ${method}`);
}
if(!payload && (method === Methods.POST || method === Methods.PUT)) {
throw new Error(`A payload is required for a ${method} method`);
}
let actionData = {};
if(method === Methods.PUT || method === Methods.DELETE) {
actionData.uri = url;
} else {
actionData.url = url;
}
return dispatch => {
dispatch(actionStart(actionData));
let fullURL = url.indexOf('://') >= 0 ? url : Config.API + url;
return Fetch[method].call(this, fullURL, payload)
.then(response => {
let result = response.json;
switch(method) {
case Methods.GET:
break;
case Methods.POST:
result = _.assign({}, payload, {
uri: response.headers.get('Location')
}, actionData);
break;
case Methods.PUT:
result = _.assign({}, payload, {
uri: url
});
break;
case Methods.DELETE:
result = actionData;
break;
}
let eventType = {
[Methods.DELETE] : 'RESOURCE_DELETE',
[Methods.GET] : 'RESOURCE_GET',
[Methods.PUT] : 'RESOURCE_PUT',
[Methods.POST] : 'RESOURCE_POST',
}[method];
dispatch(ensureConstantAction(eventType)(result));
dispatch(actionEnd(result));
return result;
})
.catch(data => {
actionData.errors = data.errors ? data.errors : [data];
dispatch(actionFailed(actionData));
throw data;
});
}
}

29
lib/actions/url.js Normal file
View file

@ -0,0 +1,29 @@
import { ActionType } from 'vanth/constants';
export function change(oldURL, newURL) {
return {
type : ActionType.URL_CHANGE,
data : {
oldURL : oldURL,
newURL : newURL,
}
}
}
export function replace(newURL) {
let oldURL = window.location.href;
history.replaceState(null, '', '#' + newURL);
return change(oldURL, window.location.href);
}
export function navigate(newURL, query) {
let oldURL = window.location.href;
let url = '#' + newURL;
if(query) {
url = "?nextPath=" + query + url;
} else {
url = "/" + url;
}
history.pushState(null, '', url);
return change(oldURL, window.location.href);
}

17
lib/actions/user.js Normal file
View file

@ -0,0 +1,17 @@
import * as ActionTools from 'vanth/actions/tools';
export function register(name, username, password) {
const payload = {
name : name,
password: password,
username: username,
}
return ActionTools.fetchAndDispatch(
'/user/',
'USER_REGISTER_BEGIN',
'USER_REGISTER_COMPLETE',
'USER_REGISTER_ERROR',
ActionTools.Methods.POST,
payload
);
}