Commit 4a8a1a6c authored by Djordje's avatar Djordje

Add action handlers

parent f9fc9f48
...@@ -43,5 +43,6 @@ ...@@ -43,5 +43,6 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
} },
"proxy": "http://localhost:3001"
} }
import { fetchRequestManager, fetchRequestTenant } from './network-manager'
import { fetchBuildingsSuccess, genericAction, TENANT_BUILDING_RECEIVED, UNAUTHENTICATED, TENANT_VOTING_RECEIVED } from './index'
export function fetchBuildings() {
return dispatch => {
fetchRequestManager("/buildings", (err, data, dispatch) => {
if (err) {
if (err.status === 401) {
dispatch(genericAction(UNAUTHENTICATED))
}
return;
} else {
dispatch(fetchBuildingsSuccess(data));
}
}
, dispatch, "GET" //,null, false
)
}
}
////////////////////////////////////////
//TODO: handle this, it should not go over reducer
export function postNewBuilding(data) {
fetchRequestManager("/buildings", null, null, "POST", data)
//TODO: !!! Add callback that will ADD_BUILDING, not vice versa as it is now
}
export function fetchTemplate(buildingId) {
fetchRequestManager("/b/" + buildingId + "/templating/engine", null, null, 'POST', 'pojedinacno glasanje.pdf', true)
//TODO: !!! Add callback that will CREATE_DOCUMENTS, not vice versa as it is now
}
export function fetchTemplateMeetingVoting(buildingId) {
fetchRequestManager("/b/" + buildingId + "/templating/meeting-voting", null, null, 'POST', 'grupno glasanje.pdf', true)
//TODO: !!! Add callback that will CREATE_DOCUMENTS, not vice versa as it is now
}
export function fetchTemplateLatestVoting(buildingId) {
fetchRequestManager("/b/" + buildingId + "/templating/latest-voting", null, null, 'POST', 'Izvestaj.pdf', true)
//TODO: !!! Add callback that will CREATE_DOCUMENTS, not vice versa as it is now
}
////////////////////////
export function downloadLatestInvoice(buildingId) {
//TODO: consider pros/cons over reducer actions
return dispatch => {
fetchRequestManager("/b/" + buildingId + "/templating/invoice/print-latest" , null, null, 'GET', 'invoice.pdf', true)
// return downloadRequest('GET', API_ADDRESS + "/finance/invoice/print-latest/" + buildingId, 'invoice.docx')
}
}
export function postObligation(buildingId, name, link, price, accounting, callback) {
return dispatch => {
fetchRequestManager("/finance/obligation",
(err, data, dispatch) => {
if (callback) { callback() }
//TODO: consider this
fetchBuildings()(dispatch);
},
dispatch,
"POST",
{
"buildingId": buildingId,
"name": name,
"price": price,
"link": link,
accounting
}
)
};
}
export function postInvoiceConfirmation(buildingId, periodStart, periodEnd) {
return dispatch => {
fetchRequestManager("/finance/invoice-confirmation/" + periodStart + "/" + periodEnd,
(err, data, dispatch) => {
//TODO: add callback
// if (callback) { callback() }
//TODO: consider this
fetchBuildings()(dispatch);
},
dispatch,
"POST",
{buildingId}
)
};
}
//////////////////////////////
//Thunks
function thunkRequestBase(fetchFN, address, object, callback, method = "POST", getBuildings = true) {
return dispatch => {
fetchFN(
address,
(err, data, dsp) => {
if (callback) { callback(err, data, dsp) };
if (getBuildings) {
fetchBuildings()(dsp);
}
},
dispatch, method, object)
}
}
export function thunkRequestTenant(address, object, callback, method = "POST", getBuildings = false) {
return thunkRequestBase(fetchRequestTenant, address, object, callback, method, getBuildings)
}
export function thunkRequestManager(address, object, callback, method = "POST", getBuildings = true) {
return thunkRequestBase(fetchRequestManager, address, object, callback, method, getBuildings)
}
/////////////////////////////
export function postNewNotification(buildingId, title, description, callback) {
return thunkRequestManager(
'/notifications',
{
buildingId,
title,
description
},
callback)
}
export function putNotification(buildingId, notificationId, title, description, callback) {
return thunkRequestManager(
'/notifications',
{
buildingId,
notificationId,
title,
description
},
callback,
"PUT")
}
export function deleteNotification(buildingId, notificationId) {
return thunkRequestManager('/notifications',
{
buildingId,
notificationId
},
null
, "DELETE"
)
}
export function postNewIsssue(buildingId, title, description, callback) {
return thunkRequestManager(`/b/${buildingId}/issues`,
{
title,
description
}, callback)
}
export function postNewSolution(buildingId, issueIndex, name, description, price, callback) {
return thunkRequestManager(`/b/${buildingId}/issue/solution`,
{
issueIndex,
name,
description,
price
}, callback)
}
export function postNewVoting(buildingId, voting, callback) {
return thunkRequestManager(`/b/${buildingId}/voting`, voting, callback)
}
export function postManualVoting(buildingId, unitId, votedFor, callback) {
return thunkRequestManager(`/b/${buildingId}/voting/manual-submit/${unitId}/${votedFor}`, null, callback)
}
export function postVote(buildingId, vote, callback) {
return thunkRequestTenant(`/${buildingId}/voting/submit`, vote, callback, "POST")
}
export function postVotingKey(publicKey, callback) {
return thunkRequestTenant('/info/public-key', { publicKey }, callback, "POST")
}
export function postNewDocument(buildingId, name, link, callback) {
return thunkRequestManager(`/b/${buildingId}/docs`,
{
"buildingId": buildingId,
"name": name,
"link": link
}, callback)
}
export function deleteDocument(buildingId, doc) {
return thunkRequestManager( `/b/${buildingId}/docs`,
{ buildingId, doc },
null,
"DELETE",
true
)
}
export function postLogin(username, password, isManager, callback) {
//NOTE: jwt is not important for this route, it could be used thunkRequestTenant
return thunkRequestManager(isManager ? '/auth/login-manager' : '/auth/login',
{
username,
password
}, callback, "POST", false)
}
export function getBuilding(buildingId) {
return thunkRequestTenant('/' + buildingId + "/building",
null, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
// console.log(err)
console.error("Can not get tenant building")
return
}
dsp(genericAction(TENANT_BUILDING_RECEIVED, data))
},
"GET", false)
}
//TODO: Consider caching, forcing request
// export function getTenantNotification(buildingId) {
// return getBuilding(buildingId)
// }
// export function getTenantActivities(buildingId) {
// return getBuilding(buildingId)
// }
export function getTenentVoting(buildingId, callback) {
return thunkRequestTenant('/' + buildingId + '/voting', null, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
console.error("Can not get tenant voting")
return
}
dsp(genericAction(TENANT_VOTING_RECEIVED, data))
}, "GET", false)
}
export function getTenantInfo(callback) {
return thunkRequestTenant('/info', null, callback, "GET")
}
export function getAllUsers(callback) {
return thunkRequestTenant('/tenants', null, callback, "GET");
}
// export function getTenentInvoices(buildingId) {
// return getBuilding(buildingId)
// }
// export function getTenantDocs(buildingId) {
// return getBuilding(buildingId)
// }
// export function getTenantBuildingFinance(buildingId) {
// return getBuilding(buildingId)
// }
export function getPreRegisterData(token, callback) {
//TODO: check if thunk is suffecient
//NOTE: jwt is not relevant for this request
thunkRequestManager('/auth/pre-register/' + token,
null, callback
,
"GET", false)(null)
}
export function registerUser(token, data, callback) {
//TODO: check if thunk is needed
thunkRequestManager('/auth/register/' + token,
data, callback
,
"POST", false)(null)
}
export function confirmUserUnit(buildingId, unitId, userId) {
return thunkRequestManager(`/b/${buildingId}/auth/confirm-user-unit/${unitId}/${userId}`, {}, null, "POST", true)
}
export function assignUserUnit(buildingId, unitId, userId, data) {
return thunkRequestManager(`/b/${buildingId}/auth/assign-user-unit/${unitId}/${userId}`, data, null, "POST", true)
}
export function setUnitOwner(buildingId, unitId, data) {
return thunkRequestManager(`/b/${buildingId}/auth/set-unit-owner/${unitId}`, data, null, "POST", true)
}
export function postInflow(buildingId, invoiceId, payer, amount, callback) {
return dispatch => {
fetchRequestManager("/finance/inflow",
(err, data, dispatch) => {
if (callback) { callback() }
//TODO: consider this
fetchBuildings()(dispatch);
},
dispatch,
"POST",
{
"buildingId": buildingId,
"invoiceId": invoiceId,
// "payer": payer,
"amount": amount
}
)
};
}
export function postInflowRevert(buildingId, invoiceId, payer, amount, callback) {
return dispatch => {
fetchRequestManager("/finance/inflow-revert",
(err, data, dispatch) => {
if (callback) { callback() }
//TODO: consider this
fetchBuildings()(dispatch);
},
dispatch,
"POST",
{
"buildingId": buildingId,
"invoiceId": invoiceId,
// "payer": payer,
"amount": amount
}
)
};
}
export function postOutflow(buildingId, payableId, amount, reason, callback) {
return dispatch => {
fetchRequestManager("/finance/outflow",
(err, data, dispatch) => {
if (callback) { callback() }
//TODO: consider this
fetchBuildings()(dispatch);
},
dispatch,
"POST",
{
"buildingId": buildingId,
"reason": reason,
// "payer": payer,
"amount": amount,
"payableId": payableId
}
)
};
}
export function settleUnsettled(buildingId) {
return thunkRequestManager("/finance/settle-unsettled", { buildingId }, null, "POST", true)
}
////////////////////////////////////////
//TODO: consider not using reducer
export function editSolution(buildingId, issueIndex, solutionIndex, data) {
let address = `/b/${buildingId}/issue/solution/${issueIndex}/${solutionIndex}`
return thunkRequestManager(address,
data, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
console.error("Can not get update solution")
return
}
},
"PUT", true)
}
export function deleteSolution(buildingId, data) {
let address = `/b/${buildingId}/issue/solution/`
return thunkRequestManager(address,
data, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
console.error("Can not delete solution")
return
}
},
"PUT", true)
}
export function editIssue(buildingId, issueIndex, data) {
let address = `/b/${buildingId}/issue/${issueIndex}`
return thunkRequestManager(address,
data, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
console.error("Can not get update solution")
return
}
},
"PUT", true)
}
export function deleteIssue(buildingId, issueId) {
let address = `/b/${buildingId}/issue/${issueId}`
return thunkRequestManager(address,
null, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
console.error("Can not get update solution")
return
}
},
"DELETE", true)
}
export function moveUpIssue(buildingId, issueIndex, issueId) {
let address = `/b/${buildingId}/issue-move-up/${issueIndex}/${issueId}`
return thunkRequestManager(address,
null, (err, data, dsp) => {
if (err) {
if (err.status === 401) {
dsp(genericAction(UNAUTHENTICATED))
}
console.error("Can not move issue")
return
}
},
"PUT", true)
}
///////////////////
//TODO: add UI success notification
//TODO: add error handling
//NETWORK - Data Caching... TBD...
export const ADD_BUILDING = "ADD_BUILDING";
export const CHANGE_NEW_BUILDING = "CHANGE_NEW_BUILDING"
export const CHANGE_NEW_UNIT_COUNT = "CHANGE_NEW_UNIT_COUNT"
export const CHANGE_NEW_UNIT = "CHANGE_NEW_UNIT"
export const CHANGE_OWNER = "CHANGE_OWNER"
export const CREATE_DOCUMENTS = "CREATE_DOCUMENTS";
export const CHANGE_SELECTED_BUILDING = "CHANGE_SELECTED_BUILDING"
export const GENERIC_STATE_CHANGE = "GENERIC_STATE_CHANGE"
export const FETCH_ALL_BUILDING_SUCCESS = "FETCH_ALL_BUILDING_SUCCESS"
export const TOKEN_RECEIVED = "TOKEN_RECEIVED"
export const TOKEN_RECEIVED_MANAGER = "TOKEN_RECEIVED_MANAGER"
export const TENANT_BUILDING_RECEIVED = "TENANT_BUILDING_RECEIVED"
export const TENANT_VOTING_RECEIVED = "TENANT_VOTING_RECEIVED"
export const UNAUTHENTICATED = "UNAUTHENTICATED"
//TBD:
// ChangeTenant/Owner
// SubmitIssue
// AddProposal
// Vote
export function genericAction(type, payload){
return {type, payload}
}
// export function tokenReceived(jwt, role){
// return genericAction(TOKEN_RECEIVED, {jwt, role})
// }
// export function
// export function tenantBuildingReceived(building){
// return genericAction(TENANT_BUILDING_RECEIVED, building)
// }
//TODO: this should be called when is already added
export function addBuilding(building) {
return {
type: ADD_BUILDING,
payload: building
}
}
export function changeNewBuilding(updateData) {
return {
type: CHANGE_NEW_BUILDING,
payload: updateData
}
}
export function changeNewUnitCount(count) {
return {
type: CHANGE_NEW_UNIT_COUNT,
payload: count
}
}
export function changeNewUnit(updateData) {
return {
type: CHANGE_NEW_UNIT,
payload: updateData
}
}
export function changeNewUnitOwner(updateData) {
return {
type: CHANGE_OWNER,
payload: updateData
}
}
export const fetchBuildingsSuccess = buildings => ({
type: FETCH_ALL_BUILDING_SUCCESS,
payload: { buildings }
});
//TODO: this should not be called by reducer
export function createDocuments(building) {
// console.log(building)
return {
type: CREATE_DOCUMENTS,
payload: building
}
}
export function changeSelectedBuilding(buildingId, selectedIndex) {
return {
type: CHANGE_SELECTED_BUILDING,
payload: { selectedBuilding: buildingId, selectedBuildingIndex: selectedIndex - 1 }
}
}
export function genericStateChange(key, value) {
return {
type: GENERIC_STATE_CHANGE,
payload: { key, value }
}
}
// console.log("process.env.REACT_APP_USE_DEV")
// console.log(process.env.REACT_APP_USE_DEV)
// let API_ADDRESS
// if (process.env.REACT_APP_USE_DEV) {
// // API_ADDRESS = API_ADDRESS = "http://localhost:3001"
// } else {
// API_ADDRESS = "/api"
// }
const API_ADDRESS = "/api"
export const JWT_TENANT = "jwtt"
export const JWT_MANAGER = "jwtm"
function fetchRequestBase(jwt, api_prefix, address, callback, dispatch, method = "GET", object = undefined, isDownload = false) {
let requestInit = {
method,
headers: {
// 'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': localStorage.getItem(jwt)
}
}
if (!isDownload && object) {
requestInit["body"] = JSON.stringify(object)
}
return fetch(API_ADDRESS + api_prefix + address, requestInit)
.then(res => {
//NOTE: cascade promise is used in order to get both res.body and res status in same processing phase.
let promise;
if (!isDownload) {
promise = res.json()
}
else {
promise = res.blob()
}
promise.then(json => {
//TODO: unify error handling
//TODO: verify status
if (!res.ok) {
if (typeof (json) === "string") {
json = { errorMessage: json }
}
console.log(json)
json.statusText = res.statusText
json.status = res.status
console.error(json)
// if (json.status === "error") {}
if (callback) { callback(json, null, dispatch) }
return
}
if (!isDownload) {
if (callback) { callback(null, json, dispatch) };
}
else {
// 1. Create blob link to download
const url = window.URL.createObjectURL(new Blob([json]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', object);
// 2. Append to html page
document.body.appendChild(link);
// 3. Force download
link.click();
// 4. Clean up and remove the link
link.parentNode.removeChild(link);
if (callback) { callback(null, json, dispatch) };
}
})
.catch(error => {
// dispatch(fetchProductsFailure(error))
// console.error("ERR fetch")
console.error(error)
if (callback) { callback(error, null, dispatch) }
});
})
.catch(error => {
// dispatch(fetchProductsFailure(error))
// console.error("ERR fetch")
console.error(error)
if (callback) { callback(error, null, dispatch) }
});
}
export function fetchRequestManager(address, callback, dispatch, method = "GET", object = undefined, isDownload = false) {
return fetchRequestBase(JWT_MANAGER, "/manager", address, callback, dispatch, method, object, isDownload)
}
export function fetchRequestTenant(...args) { return fetchRequestBase(JWT_TENANT, "/tenant", ...args) }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment