Add a generic request function with promises
This commit is contained in:
parent
408c2fca75
commit
b819f988f4
48
src/internal/web/render.go
Normal file
48
src/internal/web/render.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/data"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TmplFuncs handles global template functions
|
||||||
|
var tmplFuncs = []template.FuncMap{
|
||||||
|
map[string]interface{}{
|
||||||
|
"safeURL": func(s string) template.URL {
|
||||||
|
return template.URL(s)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTmplFunc adds a template function
|
||||||
|
func AddTmplFunc(name string, f interface{}) error {
|
||||||
|
tmplFuncs = append(tmplFuncs, map[string]interface{}{
|
||||||
|
name: f,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateData represents object passed to template renderer
|
||||||
|
type TemplateData struct {
|
||||||
|
Route string
|
||||||
|
Data map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rends a view
|
||||||
|
func (e *Env) Rends(w http.ResponseWriter, r *http.Request, template string) error {
|
||||||
|
if r.Header.Get("Accept") == "application/json" {
|
||||||
|
return e.Render.JSON(w, http.StatusOK, TemplateData{
|
||||||
|
Route: mux.CurrentRoute(r).GetName(),
|
||||||
|
Data: data.GetAllData(r),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.Render.HTML(w, http.StatusOK, template, TemplateData{
|
||||||
|
Route: mux.CurrentRoute(r).GetName(),
|
||||||
|
Data: data.GetAllData(r),
|
||||||
|
})
|
||||||
|
}
|
@ -1,119 +1,56 @@
|
|||||||
import axios from 'axios'
|
import { configureAxios, request } from '../requests'
|
||||||
|
|
||||||
// Select Movie
|
// Select Movie
|
||||||
export const SELECT_MOVIE = 'SELECT_MOVIE'
|
|
||||||
export function selectMovie(index) {
|
export function selectMovie(index) {
|
||||||
return {
|
return {
|
||||||
type: SELECT_MOVIE,
|
type: 'SELECT_MOVIE',
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IS_USER_LOGGED_IN = 'IS_USER_LOGGED_IN'
|
|
||||||
export function isUserLoggedIn() {
|
export function isUserLoggedIn() {
|
||||||
return {
|
return {
|
||||||
type: IS_USER_LOGGED_IN,
|
type: 'IS_USER_LOGGED_IN',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ADD_ERROR = 'ADD_ERROR'
|
|
||||||
export function addError(message) {
|
export function addError(message) {
|
||||||
return {
|
return {
|
||||||
type: ADD_ERROR,
|
type: 'ADD_ERROR',
|
||||||
payload: {
|
payload: {
|
||||||
message,
|
message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DISMISS_ERROR = 'DISMISS_ERROR'
|
|
||||||
export function dismissError() {
|
export function dismissError() {
|
||||||
return {
|
return {
|
||||||
type: DISMISS_ERROR,
|
type: 'DISMISS_ERROR',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_LOGOUT = 'USER_LOGOUT'
|
|
||||||
export function userLogout() {
|
export function userLogout() {
|
||||||
return {
|
return {
|
||||||
type: USER_LOGOUT,
|
type: 'USER_LOGOUT',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_LOGIN_FULFILLED = 'USER_LOGIN_FULFILLED',
|
|
||||||
USER_LOGIN_PENDING = 'USER_LOGIN_PENDING';
|
|
||||||
export function loginUser(username, password) {
|
export function loginUser(username, password) {
|
||||||
return function(dispatch) {
|
return request(
|
||||||
dispatch({
|
'USER_LOGIN',
|
||||||
type: USER_LOGIN_PENDING,
|
configureAxios().post(
|
||||||
})
|
|
||||||
axios.post(
|
|
||||||
'/users/login',
|
'/users/login',
|
||||||
{
|
{
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
},
|
},
|
||||||
).then(response => {
|
)
|
||||||
if (response.data.status === 'error')
|
)
|
||||||
{
|
|
||||||
dispatch({
|
|
||||||
type: ADD_ERROR,
|
|
||||||
payload: {
|
|
||||||
message: response.data.message,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
dispatch({
|
|
||||||
type: USER_LOGIN_FULFILLED,
|
|
||||||
payload: response.data,
|
|
||||||
})
|
|
||||||
}).catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MOVIE_LIST_FETCH_FULFILLED = 'MOVIE_LIST_FETCH_FULFILLED',
|
|
||||||
MOVIE_LIST_FETCH_PENDING = 'MOVIE_LIST_FETCH_PENDING';
|
|
||||||
export function fetchMovies() {
|
export function fetchMovies() {
|
||||||
const token = localStorage.getItem('token');
|
return request(
|
||||||
const header = 'Bearer ' + token;
|
'MOVIE_LIST_FETCH',
|
||||||
return function(dispatch) {
|
configureAxios().get('/movies/explore/popular')
|
||||||
dispatch({
|
)
|
||||||
type: MOVIE_LIST_FETCH_PENDING,
|
|
||||||
})
|
|
||||||
axios.get('/movies/explore/popular', {
|
|
||||||
headers: { 'Authorization': header },
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.status === 'error')
|
|
||||||
{
|
|
||||||
dispatch({
|
|
||||||
type: ADD_ERROR,
|
|
||||||
payload: {
|
|
||||||
message: response.data.message,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
dispatch({
|
|
||||||
type: MOVIE_LIST_FETCH_FULFILLED,
|
|
||||||
payload: response.data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// Unauthorized
|
|
||||||
if (error.response.status == 401) {
|
|
||||||
dispatch({
|
|
||||||
type: USER_LOGOUT,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
dispatch({
|
|
||||||
type: ADD_ERROR,
|
|
||||||
payload: {
|
|
||||||
message: error.response.data,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { ADD_ERROR, DISMISS_ERROR } from '../actions/actionCreators'
|
|
||||||
|
|
||||||
export default function error(state = {}, action) {
|
export default function error(state = {}, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ADD_ERROR:
|
case 'ADD_ERROR':
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
message: action.payload.message,
|
message: action.payload.message,
|
||||||
})
|
})
|
||||||
case DISMISS_ERROR:
|
case 'DISMISS_ERROR':
|
||||||
return {};
|
return {};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { SELECT_MOVIE, MOVIE_LIST_FETCH_FULFILLED, MOVIE_LIST_FETCH_PENDING } from '../actions/actionCreators'
|
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
movies: [],
|
movies: [],
|
||||||
selectedMovieIndex: 0,
|
selectedMovieIndex: 0,
|
||||||
@ -7,13 +5,13 @@ const defaultState = {
|
|||||||
|
|
||||||
export default function movieStore(state = defaultState, action) {
|
export default function movieStore(state = defaultState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case MOVIE_LIST_FETCH_FULFILLED:
|
case 'MOVIE_LIST_FETCH_FULFILLED':
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
movies: action.payload.data,
|
movies: action.payload.data,
|
||||||
})
|
})
|
||||||
case MOVIE_LIST_FETCH_PENDING:
|
case 'MOVIE_LIST_FETCH_PENDING':
|
||||||
return state
|
return state
|
||||||
case SELECT_MOVIE:
|
case 'SELECT_MOVIE':
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
selectedMovieIndex: action.index,
|
selectedMovieIndex: action.index,
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { IS_USER_LOGGED_IN, USER_LOGIN_PENDING, USER_LOGIN_FULFILLED, USER_LOGOUT } from '../actions/actionCreators'
|
|
||||||
import jwtDecode from 'jwt-decode'
|
import jwtDecode from 'jwt-decode'
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
@ -10,22 +9,22 @@ const defaultState = {
|
|||||||
|
|
||||||
export default function userStore(state = defaultState, action) {
|
export default function userStore(state = defaultState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case USER_LOGIN_PENDING:
|
case 'USER_LOGIN_PENDING':
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
userLoading: true,
|
userLoading: true,
|
||||||
})
|
})
|
||||||
case USER_LOGIN_FULFILLED:
|
case 'USER_LOGIN_FULFILLED':
|
||||||
if (action.payload.status === "error") {
|
if (action.payload.status === "error") {
|
||||||
return logoutUser(state)
|
return logoutUser(state)
|
||||||
}
|
}
|
||||||
return updateFromToken(state, action.payload.data.token)
|
return updateFromToken(state, action.payload.data.token)
|
||||||
case IS_USER_LOGGED_IN:
|
case 'IS_USER_LOGGED_IN':
|
||||||
let localToken = localStorage.getItem('token');
|
let localToken = localStorage.getItem('token');
|
||||||
if (!localToken || localToken === "") {
|
if (!localToken || localToken === "") {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
return updateFromToken(state, localToken)
|
return updateFromToken(state, localToken)
|
||||||
case USER_LOGOUT:
|
case 'USER_LOGOUT':
|
||||||
return logoutUser(state)
|
return logoutUser(state)
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
59
src/public/js/requests.js
Normal file
59
src/public/js/requests.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
// This functions returns an axios instance, the token is added to the
|
||||||
|
// configuration if found in the localStorage
|
||||||
|
export function configureAxios(headers = {}) {
|
||||||
|
// Get the token from the localStorate
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
if (token) {
|
||||||
|
headers = { 'Authorization': `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
return axios.create({
|
||||||
|
headers
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function takes en event prefix to dispatch evens during the life of the
|
||||||
|
// request, it also take a promise (axios request)
|
||||||
|
export function request(eventPrefix, promise) {
|
||||||
|
// Events
|
||||||
|
const pending = `${eventPrefix}_PENDING`;
|
||||||
|
const fulfilled = `${eventPrefix}_FULFILLED`;
|
||||||
|
|
||||||
|
return function(dispatch) {
|
||||||
|
dispatch({
|
||||||
|
type: pending,
|
||||||
|
})
|
||||||
|
promise
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.status === 'error')
|
||||||
|
{
|
||||||
|
dispatch({
|
||||||
|
type: 'ADD_ERROR',
|
||||||
|
payload: {
|
||||||
|
message: response.data.message,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
dispatch({
|
||||||
|
type: fulfilled,
|
||||||
|
payload: response.data,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Unauthorized
|
||||||
|
if (error.response.status == 401) {
|
||||||
|
dispatch({
|
||||||
|
type: 'USER_LOGOUT',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
dispatch({
|
||||||
|
type: 'ADD_ERROR',
|
||||||
|
payload: {
|
||||||
|
message: error.response.data,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user