src/actions/index.js
/*!
* Codefolio
* Copyright(c) 2016 MSMFSD
* MIT Licensed
*/
import { browserHistory } from 'react-router'
import API from '../utils/api'
import { convertToBase64Async, formatProfileData, formatProjectData } from '../utils/helpers'
import { setStorage, getStorage, clearStorage } from '../utils/storage'
// simulate server loading for dev environment only
const devOnlySimulateDelay = process.env.NODE_ENV !== 'production' ? 0 : 0
/*
* action types
*/
// profile
export const FETCH_PROFILE_REQUEST = 'FETCH_PROFILE_REQUEST'
export const FETCH_PROFILE_RESULT = 'FETCH_PROFILE_RESULT'
export const FETCH_PROFILE_ERROR = 'FETCH_PROFILE_ERROR'
export const EDIT_PROFILE = 'EDIT_PROFILE'
export const EDIT_PROFILE_SUCCESS = 'EDIT_PROFILE_SUCCESS'
export const EDIT_PROFILE_FAIL = 'EDIT_PROFILE_FAIL'
export const EDIT_PROFILE_RESET = 'EDIT_PROFILE_RESET'
export const UPDATE_PROFILE_FIELD = 'UPDATE_PROFILE_FIELD'
export const UPDATE_AVATAR_FIELDS = 'UPDATE_AVATAR_FIELDS'
export const UPDATE_LAYOUT_FIELD = 'UPDATE_LAYOUT_FIELD'
export const ADD_PROFILE_TECHICON = 'ADD_PROFILE_TECHICON'
export const ADD_PROFILE_LINK = 'ADD_PROFILE_LINK'
export const REMOVE_PROFILE_ITEM = 'REMOVE_PROFILE_ITEM'
// projects
export const FETCH_PROJECTS_REQUEST = 'FETCH_PROJECTS_REQUEST'
export const FETCH_PROJECTS_RESULT = 'FETCH_PROJECTS_RESULT'
export const FETCH_PROJECTS_ERROR = 'FETCH_PROJECTS_ERROR'
export const DELETE_PROJECT_REQUEST = 'DELETE_PROJECT_REQUEST'
export const DELETE_PROJECT_RESULT = 'DELETE_PROJECT_RESULT'
export const DELETE_PROJECT_FAIL = 'DELETE_PROJECT_FAIL'
// edit/new project
export const EDIT_PROJECT = 'EDIT_PROJECT'
export const EDIT_PROJECT_SUCCESS = 'EDIT_PROJECT_SUCCESS'
export const EDIT_PROJECT_FAIL = 'EDIT_PROJECT_FAIL'
export const EDIT_PROJECT_RESET = 'EDIT_PROJECT_RESET'
export const EDIT_PROJECT_SET = 'EDIT_PROJECT_SET'
export const EDIT_PROJECT_UPLOADING_FILES = 'EDIT_PROJECT_UPLOADING_FILES'
export const EDIT_PROJECT_UPLOADING_FILES_COMPLETE = 'EDIT_PROJECT_UPLOADING_FILES_COMPLETE'
export const EDIT_PROJECT_UPLOADING_FILES_ERROR = 'EDIT_PROJECT_UPLOADING_FILES_ERROR'
export const EDIT_PROJECT_UPDATE_MEDIA = 'EDIT_PROJECT_UPDATE_MEDIA'
export const EDIT_PROJECT_ON_SPLICE_FIELD_ARRAY = 'EDIT_PROJECT_ON_SPLICE_FIELD_ARRAY'
export const EDIT_PROJECT_ON_PUSH_FIELD_ARRAY = 'EDIT_PROJECT_ON_PUSH_FIELD_ARRAY'
export const EDIT_PROJECT_ADD_LINK = 'EDIT_PROJECT_ADD_LINK'
export const EDIT_PROJECT_REMOVE_LINK = 'EDIT_PROJECT_REMOVE_LINK'
export const EDIT_PROJECT_UPDATE_FIELD = 'EDIT_PROJECT_UPDATE_FIELD'
export const EDIT_PROJECT_REMOVE_MEDIA = 'EDIT_PROJECT_REMOVE_MEDIA'
// auth
export const AUTH = 'AUTH'
export const AUTH_SUCCESS = 'AUTH_SUCCESS'
export const AUTH_FAIL = 'AUTH_FAIL'
export const AUTH_LOGOUT = 'AUTH_LOGOUT'
export const AUTH_LOGOUT_FAIL = 'AUTH_LOGOUT_FAIL'
export const AUTH_LOGOUT_SUCCESS = 'AUTH_LOGOUT_SUCCESS'
export const AUTH_INIT = 'AUTH_INIT'
export const REGISTER = 'REGISTER'
export const REGISTER_SUCCESS = 'REGISTER_SUCCESS'
export const REGISTER_FAIL = 'REGISTER_FAIL'
export const FORGOT = 'FORGOT'
export const FORGOT_SUCCESS = 'FORGOT_SUCCESS'
export const FORGOT_FAIL = 'FORGOT_FAIL'
export const RESET_INIT = 'RESET_INIT'
export const RESET_SUCCESS = 'RESET_SUCCESS'
export const RESET_FAIL = 'RESET_FAIL'
// admin
export const EDIT_ADMIN = 'EDIT_ADMIN'
export const EDIT_ADMIN_SUCCESS = 'EDIT_ADMIN_SUCCESS'
export const EDIT_ADMIN_FAIL = 'EDIT_ADMIN_FAIL'
/*
* private action creators
*/
// PROFILE
const fetchProfileRequest = () => ({
type: FETCH_PROFILE_REQUEST
})
const fetchProfileResult = (data) => ({
type: FETCH_PROFILE_RESULT,
payload: data
})
const fetchProfileError = (err) => ({
type: FETCH_PROFILE_ERROR,
payload: err
})
const editProfile = () => ({
type: EDIT_PROFILE
})
const editProfileSuccess = () => ({
type: EDIT_PROFILE_SUCCESS
})
const editProfileFail = (err) => ({
type: EDIT_PROFILE_FAIL,
payload: err
})
// PROJECTS
const fetchProjectsRequest = () => ({
type: FETCH_PROJECTS_REQUEST
})
const fetchProjectsResult = (data) => ({
type: FETCH_PROJECTS_RESULT,
payload: data
})
const fetchProjectsError = (err) => ({
type: FETCH_PROJECTS_ERROR,
payload: err
})
const deleteProjectRequest = () => ({
type: DELETE_PROJECT_REQUEST
})
const deleteProjectResult = () => ({
type: DELETE_PROJECT_RESULT
})
const deleteProjectFail = (err) => ({
type: DELETE_PROJECT_FAIL,
payload: err
})
// EDIT/NEW PROJECT
const editProject = () => ({
type: EDIT_PROJECT
})
const editProjectUploadingFiles = () => ({
type: EDIT_PROJECT_UPLOADING_FILES
})
const editProjectUploadingFilesComplete = (data) => ({
type: EDIT_PROJECT_UPLOADING_FILES_COMPLETE,
payload: data
})
const editProjectUploadingFilesError = (err) => ({
type: EDIT_PROJECT_UPLOADING_FILES_ERROR,
payload: err
})
const editProjectUpdateMedia = (filenames) => ({
type: EDIT_PROJECT_UPDATE_MEDIA,
filenames
})
const editProjectSuccess = () => ({
type: EDIT_PROJECT_SUCCESS
})
const editProjectFail = (err) => ({
type: EDIT_PROJECT_FAIL,
payload: err
})
// AUTH
const auth = (username) => ({
type: AUTH,
payload: username
})
const authSuccess = (data) => ({
type: AUTH_SUCCESS,
payload: data
})
const authFail = (err) => ({
type: AUTH_FAIL,
payload: err
})
const authLogout = () => ({
type: AUTH_LOGOUT
})
const authLogoutFail = (err) => ({
type: AUTH_LOGOUT_FAIL,
payload: err
})
const authLogoutSuccess = () => ({
type: AUTH_LOGOUT_SUCCESS
})
const register = () => ({
type: REGISTER
})
const registerSuccess = () => ({
type: REGISTER_SUCCESS
})
const registerFail = (err) => ({
type: REGISTER_FAIL,
payload: err
})
const forgot = () => ({
type: FORGOT
})
const forgotSuccess = (data) => ({
type: FORGOT_SUCCESS,
payload: data
})
const forgotFail = (err) => ({
type: FORGOT_FAIL,
payload: err
})
const resetInit = () => ({
type: RESET_INIT
})
const resetSuccess = (data) => ({
type: RESET_SUCCESS,
payload: data
})
const resetFail = (err) => ({
type: RESET_FAIL,
payload: err
})
// ADMIN
const editAdmin = () => ({
type: EDIT_ADMIN
})
const editAdminSuccess = () => ({
type: EDIT_ADMIN_SUCCESS
})
const editAdminFail = (err) => ({
type: EDIT_ADMIN_FAIL,
payload: err
})
/*
* public action methods
*/
// PROFILE
/**
* Update Profile Field
* @param {string} fieldName
* @param {string} fieldValue
*/
export const updateProfileField = (fieldName, fieldValue) => ({
type: UPDATE_PROFILE_FIELD,
fieldName,
fieldValue
})
/**
* Update Avatar Field
* @param {string} use
* @param {string} gravitarEmail
* @param {string} customAvatarFile
*/
export const updateAvatarFields = (use, gravitarEmail, customAvatarFile) => ({
type: UPDATE_AVATAR_FIELDS,
use,
gravitarEmail,
customAvatarFile
})
/**
* Update Layout Field
* @param {string} fieldName
* @param {string} fieldValue
*/
export const updateLayoutField = (fieldName, fieldValue) => ({
type: UPDATE_LAYOUT_FIELD,
fieldName,
fieldValue
})
/**
* add Profile Techicon
* @param {string} linkGroup
* @param {string} linkName
* @param {string} linkIcon
*/
export const addProfileTechicon = (linkGroup, linkName, linkIcon) => ({
type: ADD_PROFILE_TECHICON,
linkGroup,
linkName,
linkIcon
})
/**
* add Profile Link
* @param {string} linkGroup
* @param {string} linkName
* @param {string} linkUrl
*/
export const addProfileLink = (linkGroup, linkName, linkUrl) => ({
type: ADD_PROFILE_LINK,
linkGroup,
linkName,
linkUrl
})
/**
* remove Profile Item
* @param {string} linkGroup
* @param {number} index
*/
export const removeProfileItem = (linkGroup, index) => ({
type: REMOVE_PROFILE_ITEM,
linkGroup,
index
})
/**
* edit Profile Reset
*/
export const editProfileReset = () => ({
type: EDIT_PROFILE_RESET
})
/**
* fetch Profile Async
* @return {object}
*/
export const fetchProfileAsync = () => {
return dispatch => {
dispatch(fetchProfileRequest())
setTimeout(() => {
API.FetchCodefolioProfile()
.then(response => {
if(!response.success) {
dispatch(fetchProfileError(response.message))
} else {
// success!
dispatch(fetchProfileResult(response.data))
}
})
.catch((reason) => dispatch(fetchProfileError(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
// PROJECTS
/**
* fetch Projects Async
* @return {object}
*/
export const fetchProjectsAsync = () => {
return dispatch => {
dispatch(fetchProjectsRequest())
setTimeout(() => {
API.FetchCodefolioProjects()
.then(response => {
if(!response.success) {
dispatch(fetchProjectsError(response.message))
} else {
// success!
dispatch(fetchProjectsResult(response.data))
}
})
.catch((reason) => dispatch(fetchProjectsError(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
/**
* Delete project async
* @param {string} id
* @param {string} token
* @return {object}
*/
export const deleteProjectAsync = (id, token) => {
return dispatch => {
dispatch(deleteProjectRequest())
setTimeout(() => {
API.DeleteProject(id, token)
.then(response => {
if(!response.success) {
dispatch(deleteProjectFail(response.message))
} else {
// success!
dispatch(deleteProjectResult())
// ensure sync state to db
dispatch(fetchProjectsAsync())
}
})
.catch((reason) => dispatch(deleteProjectFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
// EDIT/NEW PROJECT
/**
* edit Project Set
* @param {object} project
*/
export const editProjectSet = (project) => ({
type: EDIT_PROJECT_SET,
project
})
/**
* edit Project Reset
*/
export const editProjectReset = () => ({
type: EDIT_PROJECT_RESET
})
/**
* edit Project Update Field
* @param {string} fieldName
* @param {string} fieldValue
*/
export const editProjectUpdateField = (fieldName, fieldValue) => ({
type: EDIT_PROJECT_UPDATE_FIELD,
fieldName,
fieldValue
})
/**
* edit Project On Push Field Array
* @param {string} fieldName
* @param {string} fieldValue
*/
export const editProjectOnPushFieldArray = (fieldName, fieldValue) => ({
type: EDIT_PROJECT_ON_PUSH_FIELD_ARRAY,
fieldName,
fieldValue
})
/**
* edit Project On Splice Field Array
* @param {string} fieldName
* @param {number} index
*/
export const editProjectOnSpliceFieldArray = (fieldName, index) => ({
type: EDIT_PROJECT_ON_SPLICE_FIELD_ARRAY,
fieldName,
index
})
/**
* edit Project Add Link
* @param {string} linkGroup
* @param {string} linkName
* @param {string} linkUrl
*/
export const editProjectAddLink = (linkGroup, linkName, linkUrl) => ({
type: EDIT_PROJECT_ADD_LINK,
linkGroup,
linkName,
linkUrl
})
/**
* edit Project Remove Link
* @param {string} linkGroup
* @param {number} index
*/
export const editProjectRemoveLink = (linkGroup, index) => ({
type: EDIT_PROJECT_REMOVE_LINK,
linkGroup,
index
})
/**
* edit Project Remove Media
* @param {number} index
*/
export const editProjectRemoveMedia = (index) => ({
type: EDIT_PROJECT_REMOVE_MEDIA,
index
})
/**
* edit Project Upload Files Async
* @param {array} files
* @param {string} token
*/
export const editProjectUploadFilesAsync = (files, token) => {
return dispatch => {
dispatch(editProjectUploadingFiles())
setTimeout(() => {
API.UploadProjectFiles(files, token)
.then(response => {
if(!response.success) {
dispatch(editProjectUploadingFilesError(response.message))
} else {
// success!
dispatch(editProjectUploadingFilesComplete())
dispatch(editProjectUpdateMedia(response.data))
}
})
.catch((reason) => dispatch(editProjectUploadingFilesError(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
/**
* new Project Async
* @param {object} formData
* @param {string} token
*/
export const newProjectAsync = (formData, token) => {
return (dispatch) => {
dispatch(editProject())
setTimeout(() => {
API.NewProject(formatProjectData(formData), token)
.then((response) => {
if(!response.success) {
// duplicate name/slug error?
let message = response.message
if(message.indexOf('duplicate key error') !== -1) {
message = 'Database duplicate key error. Ensure project name is unique'
}
dispatch(editProjectFail(message))
} else {
dispatch(editProjectSuccess())
}
})
.catch((reason) => dispatch(editProjectFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
/**
* edit Project Async
* @param {object} formData
* @param {string} token
* @param {string} projectId
*/
export const editProjectAsync = (formData, token, projectId) => {
return (dispatch) => {
dispatch(editProject())
setTimeout(() => {
API.EditProject(formatProjectData(formData), token, projectId)
.then((response) => {
if(!response.success) {
dispatch(editProjectFail(response.message))
} else {
dispatch(editProjectSuccess())
}
})
.catch((reason) => dispatch(editProjectFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
// AUTH
/**
* auth Init
*/
export const authInit = () => (dispatch) => {
// if storage found and token not expired
const storageResult = getStorage()
if(!storageResult) {
clearStorage()
dispatch(authFail(''))
} else {
dispatch(auth(storageResult.username))
dispatch(authSuccess({ token: storageResult.token, lastLoggedIn: storageResult.lastLoggedIn }))
}
}
/**
* login Async
* @param {object} formData
*/
export const loginAsync = (formData) => {
return (dispatch) => {
dispatch(auth(formData.username))
setTimeout(() => {
API.Login(formData)
.then((response) => {
if(!response.success) {
clearStorage()
dispatch(authFail(response.message))
} else {
dispatch(authSuccess(response))
setStorage(response.token, response.lastLoggedIn, formData.username)
browserHistory.push('/admin')
}
})
.catch((reason) => {
clearStorage()
dispatch(authFail(reason.message + '. API server unreachable.'))
})
}, devOnlySimulateDelay)
}
}
/**
* logout Async
* @param {string} token
*/
export const logoutAsync = (token) => (dispatch) => {
dispatch(authLogout())
setTimeout(() => {
API.Logout(token)
.then((response) => {
if(!response.success) {
dispatch(authLogoutFail(response.message))
} else {
dispatch(authLogoutSuccess())
clearStorage()
browserHistory.push('/login')
}
})
.catch((reason) => dispatch(authLogoutFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
/**
* register Async
* @param {object} formData
*/
export const registerAsync = (formData) => {
return (dispatch) => {
dispatch(register())
setTimeout(() => {
API.Register(formData)
.then((response) => {
if(!response.success) {
dispatch(registerFail(response.message))
} else {
dispatch(registerSuccess())
}
})
.catch((reason) => dispatch(registerFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
/**
* forgot Async
* @param {object} formData
*/
export const forgotAsync = (formData) => {
return (dispatch) => {
dispatch(forgot())
setTimeout(() => {
API.Forgot(formData)
.then((response) => {
if(!response.success) {
dispatch(forgotFail(response.message))
} else {
dispatch(forgotSuccess(response))
}
})
.catch((reason) => dispatch(forgotFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
/**
* reset Async
* @param {object} formData
* @param {string} resetToken
*/
export const resetAsync = (formData, resetToken) => {
return (dispatch) => {
dispatch(resetInit())
setTimeout(() => {
API.Reset(formData, resetToken)
.then((response) => {
if(!response.success) {
dispatch(resetFail(response.message))
} else {
dispatch(resetSuccess(response))
}
})
.catch((reason) => dispatch(resetFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
// ADMIN
/**
* edit Admin Async
* @param {object} formData
* @param {string} token
*/
export const editAdminAsync = (formData, token) => {
return (dispatch) => {
dispatch(editAdmin())
setTimeout(() => {
API.EditAdmin(formData, token)
.then((response) => {
if(!response.success) {
dispatch(editAdminFail(response.message))
} else {
dispatch(editAdminSuccess())
// logout app and reset form
dispatch(authLogoutSuccess())
clearStorage()
browserHistory.push('/login')
}
})
.catch((reason) => dispatch(editAdminFail(reason.message + '. API server unreachable.')))
}, devOnlySimulateDelay)
}
}
/**
* edit Profile Async
* @param {object} formData
* @param {string} token
*/
export const editProfileAsync = (formData, token) => {
return (dispatch) => {
dispatch(editProfile())
setTimeout(() => {
convertToBase64Async(formData)
.then((base64) => {
API.EditProfile(formatProfileData(formData, base64), token)
.then((response) => {
if(!response.success) {
dispatch(editProfileFail(response.message))
} else {
dispatch(editProfileSuccess())
// now update profile store
dispatch(fetchProfileAsync())
}
})
.catch((reason) => dispatch(editProfileFail(reason.message + '. API server unreachable.')))
}).catch((reason) => dispatch(editProfileFail(reason.message)))
}, devOnlySimulateDelay)
}
}