summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/app')
-rw-r--r--animism-align/frontend/app/actions.js1
-rw-r--r--animism-align/frontend/app/api/crud.fetch.js6
-rw-r--r--animism-align/frontend/app/common/fonts.css2
-rw-r--r--animism-align/frontend/app/common/form.component.js2
-rw-r--r--animism-align/frontend/app/common/form.css3
-rw-r--r--animism-align/frontend/app/session.js6
-rw-r--r--animism-align/frontend/app/store.js4
-rw-r--r--animism-align/frontend/app/types.js7
-rw-r--r--animism-align/frontend/app/views/audio/audio.reducer.js2
-rw-r--r--animism-align/frontend/app/views/auth/auth.actions.js26
-rw-r--r--animism-align/frontend/app/views/auth/auth.css4
-rw-r--r--animism-align/frontend/app/views/auth/auth.gate.js40
-rw-r--r--animism-align/frontend/app/views/auth/auth.login.js16
-rw-r--r--animism-align/frontend/app/views/auth/auth.reducer.js40
14 files changed, 123 insertions, 36 deletions
diff --git a/animism-align/frontend/app/actions.js b/animism-align/frontend/app/actions.js
index 199661d..67cbf85 100644
--- a/animism-align/frontend/app/actions.js
+++ b/animism-align/frontend/app/actions.js
@@ -17,6 +17,7 @@ const crudActions = [
'media',
'episode',
'venue',
+ 'user',
].reduce((a,b) => (a[b] = crud_actions(b)) && a, {})
export default
diff --git a/animism-align/frontend/app/api/crud.fetch.js b/animism-align/frontend/app/api/crud.fetch.js
index c88225e..a8d4a0d 100644
--- a/animism-align/frontend/app/api/crud.fetch.js
+++ b/animism-align/frontend/app/api/crud.fetch.js
@@ -1,4 +1,5 @@
import fetch from 'node-fetch'
+import { session } from 'app/session'
export function crud_fetch(type, tag) {
const uri = '/api/v1/' + type + '/' + (tag || '')
@@ -54,6 +55,7 @@ export function _get_headers() {
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
+ 'Authorization': "JWT " + session.get("access_token"),
},
}
}
@@ -64,6 +66,7 @@ export function post(data) {
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
+ 'Authorization': "JWT " + session.get("access_token"),
'Content-Type': 'application/json'
},
}
@@ -75,6 +78,7 @@ export function postBody(data) {
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
+ 'Authorization': "JWT " + session.get("access_token"),
},
}
}
@@ -85,6 +89,7 @@ export function put(data) {
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
+ 'Authorization': "JWT " + session.get("access_token"),
'Content-Type': 'application/json'
},
}
@@ -96,6 +101,7 @@ export function destroy(data) {
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
+ 'Authorization': "JWT " + session.get("access_token"),
'Content-Type': 'application/json'
},
}
diff --git a/animism-align/frontend/app/common/fonts.css b/animism-align/frontend/app/common/fonts.css
index c782885..7d231d8 100644
--- a/animism-align/frontend/app/common/fonts.css
+++ b/animism-align/frontend/app/common/fonts.css
@@ -36,11 +36,13 @@
font-family: 'Roboto';
src: url('/static/fonts/Roboto-Regular.ttf') format('truetype');
}
+/*
@font-face {
font-family: 'Roboto';
src: url('/static/fonts/Roboto-Italic.ttf') format('truetype');
font-style: italic;
}
+*/
/*
@font-face {
font-family: 'Roboto';
diff --git a/animism-align/frontend/app/common/form.component.js b/animism-align/frontend/app/common/form.component.js
index 37ef9e0..12c56ee 100644
--- a/animism-align/frontend/app/common/form.component.js
+++ b/animism-align/frontend/app/common/form.component.js
@@ -238,6 +238,6 @@ export const SubmitButton = (props) => (
className={props.className ? "submit " + props.className : "submit"}
onClick={props.onClick}
>{props.title}</button>
- {props.after && <span>{props.after}</span>}
+ {props.after && <span className="after">{props.after}</span>}
</label>
)
diff --git a/animism-align/frontend/app/common/form.css b/animism-align/frontend/app/common/form.css
index 1ba81c8..c52b86f 100644
--- a/animism-align/frontend/app/common/form.css
+++ b/animism-align/frontend/app/common/form.css
@@ -37,6 +37,9 @@ form label.textarea {
form input[type="checkbox"] {
margin: -0.0625rem 0.625rem 0 8rem;
}
+form label span.after {
+ margin-left: 1rem;
+}
/* form errors */
diff --git a/animism-align/frontend/app/session.js b/animism-align/frontend/app/session.js
index be93952..0050d69 100644
--- a/animism-align/frontend/app/session.js
+++ b/animism-align/frontend/app/session.js
@@ -12,8 +12,6 @@ export const getDefaultInt = (key, def) => {
export const getDefaultFloat = (key, def) => {
return parseFloat(getDefault(key, def), 10)
}
-
-const username = session.get('username')
-if (!username) {
- session.set('username', 'anonymous')
+export const getDefaultBoolean = (key, def) => {
+ return session.get(key) === String(def)
}
diff --git a/animism-align/frontend/app/store.js b/animism-align/frontend/app/store.js
index d1843f7..df8b835 100644
--- a/animism-align/frontend/app/store.js
+++ b/animism-align/frontend/app/store.js
@@ -3,7 +3,6 @@ import { connectRouter, routerMiddleware } from 'connected-react-router'
import { createBrowserHistory } from 'history'
// import createDebounce from 'redux-debounced'
import thunk from 'redux-thunk'
-// import { login } from 'app/utils'
// cms
import uploadReducer from 'app/views/upload/upload.reducer'
@@ -12,6 +11,7 @@ import siteReducer from 'app/views/site/site.reducer'
import mediaReducer from 'app/views/media/media.reducer'
import episodeReducer from 'app/views/episode/episode.reducer'
import venueReducer from 'app/views/venue/venue.reducer'
+import authReducer from 'app/views/auth/auth.reducer'
// editor
import alignReducer from 'app/views/align/align.reducer'
@@ -23,7 +23,6 @@ import viewerReducer from 'app/views/viewer/viewer.reducer'
const createRootReducer = history => (
combineReducers({
- auth: (state = {}) => state,
router: connectRouter(history),
site: siteReducer,
@@ -32,6 +31,7 @@ const createRootReducer = history => (
media: mediaReducer,
episode: episodeReducer,
venue: venueReducer,
+ auth: authReducer,
align: alignReducer,
paragraph: paragraphReducer,
diff --git a/animism-align/frontend/app/types.js b/animism-align/frontend/app/types.js
index 943527c..d4d701a 100644
--- a/animism-align/frontend/app/types.js
+++ b/animism-align/frontend/app/types.js
@@ -1,8 +1,6 @@
import { with_type, crud_type } from 'app/api/crud.types'
export const api = crud_type('api', [])
-export const auth = crud_type('auth', [])
-
export const upload = crud_type('upload', [])
export const media = crud_type('media', [])
export const peaks = crud_type('peaks', [])
@@ -10,6 +8,7 @@ export const text = crud_type('text', [])
export const annotation = crud_type('annotation', [])
export const episode = crud_type('episode', [])
export const venue = crud_type('venue', [])
+export const user = crud_type('user', [])
export const paragraph = crud_type('paragraph', [
'update_transcript',
])
@@ -37,6 +36,10 @@ export const viewer = with_type('viewer', [
'open_footnote',
])
+export const auth = with_type('auth', [
+ 'logged_in', 'logged_out',
+])
+
export const site = with_type('site', [
])
diff --git a/animism-align/frontend/app/views/audio/audio.reducer.js b/animism-align/frontend/app/views/audio/audio.reducer.js
index bd6bbae..269ad44 100644
--- a/animism-align/frontend/app/views/audio/audio.reducer.js
+++ b/animism-align/frontend/app/views/audio/audio.reducer.js
@@ -10,7 +10,7 @@ const initialState = {
cc: true,
}
-export default function alignReducer(state = initialState, action) {
+export default function authReducer(state = initialState, action) {
// console.log(action.type, action)
switch (action.type) {
case types.audio.play:
diff --git a/animism-align/frontend/app/views/auth/auth.actions.js b/animism-align/frontend/app/views/auth/auth.actions.js
index d7663b7..936e062 100644
--- a/animism-align/frontend/app/views/auth/auth.actions.js
+++ b/animism-align/frontend/app/views/auth/auth.actions.js
@@ -1,12 +1,14 @@
import fetch from 'node-fetch'
+import jsonwebtoken from 'jsonwebtoken'
+import * as types from 'app/types'
import { session } from 'app/session'
const urls = {
login: "/api/v1/auth/login",
}
-export const login = (data) => dispatch => (
+export const login = data => dispatch => (
fetch(urls.login, {
method: 'POST',
body: JSON.stringify(data),
@@ -18,16 +20,26 @@ export const login = (data) => dispatch => (
})
.then(req => req.json())
.then(res => {
- if (res.access_token) {
- session.set('access_token', res.access_token)
+ if (!res.access_token) {
+ throw new Error(res.description)
}
- return res
- })
- .catch(error => {
- console.error(error)
+ session.set('access_token', res.access_token)
+ load_access_token()(dispatch)
})
)
+export const load_access_token = () => dispatch => {
+ const access_token = session.get('access_token') || null
+ if (access_token) {
+ const creds = jsonwebtoken.decode(access_token)
+ const user_id = creds.identity
+ return dispatch({ type: types.auth.logged_in, user_id })
+ } else {
+ return dispatch({ type: types.auth.logged_out })
+ }
+}
+
export const logout = () => dispatch => {
session.set('access_token', '')
+ return dispatch({ type: types.auth.logged_out })
}
diff --git a/animism-align/frontend/app/views/auth/auth.css b/animism-align/frontend/app/views/auth/auth.css
index e9ceb85..2bf5053 100644
--- a/animism-align/frontend/app/views/auth/auth.css
+++ b/animism-align/frontend/app/views/auth/auth.css
@@ -2,13 +2,13 @@
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
- background: linear-gradient(#190051, #1c0406);
+ background: linear-gradient(#190051, #020800);
display: flex;
justify-content: center;
align-items: center;
}
.login {
- background: #333;
+ background: #282828;
padding: 1rem;
box-shadow: 0 5px 10px #000;
}
diff --git a/animism-align/frontend/app/views/auth/auth.gate.js b/animism-align/frontend/app/views/auth/auth.gate.js
index 498d32a..ba69256 100644
--- a/animism-align/frontend/app/views/auth/auth.gate.js
+++ b/animism-align/frontend/app/views/auth/auth.gate.js
@@ -1,4 +1,5 @@
import React, { Component } from 'react'
+import { connect } from 'react-redux'
import './auth.css'
@@ -6,24 +7,49 @@ import actions from 'app/actions'
import AuthLogin from './auth.login'
-export default class AuthGate extends Component {
+class AuthGate extends Component {
constructor(props) {
super(props)
+ actions.auth.load_access_token()
}
- componentDidMount() {
- // actions.site.loadProject()
+ componentDidUpdate(prevProps) {
+ if (this.props.user_id !== prevProps.user_id) {
+ this.load()
+ }
}
- componentDidUpdate() {
-
+ load() {
+ if (!this.props.user_id) return
+ actions.user.show(this.props.user_id)
+ .then(() => {
+ actions.site.loadProject()
+ }).catch(error => {
+ if (error.status_code === 401) {
+ actions.auth.logout()
+ } else {
+ console.error(error)
+ }
+ })
}
render() {
+ if (this.props.user) {
+ return this.props.children
+ }
return (
<div className='auth'>
- <AuthLogin />
+ {this.props.logged_in
+ ? <div className="login">Logging in...</div>
+ : <AuthLogin onAuthenticate={this.load} />
+ }
</div>
)
}
-} \ No newline at end of file
+}
+
+const mapStateToProps = state => ({
+ ...state.auth,
+})
+
+export default connect(mapStateToProps)(AuthGate)
diff --git a/animism-align/frontend/app/views/auth/auth.login.js b/animism-align/frontend/app/views/auth/auth.login.js
index 9ba4c0b..6697901 100644
--- a/animism-align/frontend/app/views/auth/auth.login.js
+++ b/animism-align/frontend/app/views/auth/auth.login.js
@@ -22,7 +22,6 @@ export default class AuthLogin extends Component {
handleChange(e) {
e && e.preventDefault()
- console.log(e.target.name, e.target.value)
this.setState({
data: {
...this.state.data,
@@ -34,14 +33,11 @@ export default class AuthLogin extends Component {
handleSubmit(e) {
e && e.preventDefault()
this.setState({ error: null })
- actions.auth.login(this.state)
- .then(res => {
- console.log(res)
- if (res.error) {
- this.props.onAuthenticate()
- } else {
- this.setState({ error })
- }
+ actions.auth.login(this.state.data)
+ .then(this.props.onAuthenticate)
+ .catch(error => {
+ console.error(error)
+ this.setState({ error: error.description || error.message })
})
}
@@ -49,7 +45,7 @@ export default class AuthLogin extends Component {
return (
<form className='login' onSubmit={this.handleSubmit}>
<h6>
- Welcome to the Animism Editor
+ {'Welcome to Animism '}{'🐍'}
</h6>
<TextInput
title="Username"
diff --git a/animism-align/frontend/app/views/auth/auth.reducer.js b/animism-align/frontend/app/views/auth/auth.reducer.js
new file mode 100644
index 0000000..05741f3
--- /dev/null
+++ b/animism-align/frontend/app/views/auth/auth.reducer.js
@@ -0,0 +1,40 @@
+import * as types from 'app/types'
+import { getDefault } from 'app/session'
+
+const initialState = {
+ logged_in: !!getDefault('access_token', false),
+ user_id: null,
+ user: null,
+}
+
+export default function authReducer(state = initialState, action) {
+ // console.log(action.type, action)
+ switch (action.type) {
+ case types.auth.logged_in:
+ return {
+ ...state,
+ logged_in: true,
+ user_id: action.user_id,
+ user: null,
+ }
+ case types.auth.logged_out:
+ return {
+ ...state,
+ logged_in: false,
+ user_id: null,
+ user: null,
+ }
+ case types.user.show:
+ if (action.data.res.id !== state.user_id) {
+ return state
+ }
+ return {
+ ...state,
+ user: {
+ ...action.data.res,
+ }
+ }
+ default:
+ return state
+ }
+}