529 lines
16 KiB
JavaScript
529 lines
16 KiB
JavaScript
/*
|
|
* app.api.js
|
|
* Ajax api helper module
|
|
*/
|
|
|
|
/*jslint browser : true, continue : true,
|
|
devel : true, indent : 2, maxerr : 50,
|
|
newcap : true, nomen : true, plusplus : true,
|
|
regexp : true, sloppy : true, vars : false,
|
|
white : true
|
|
*/
|
|
/*global $, io, app */
|
|
|
|
app.api = (function () {
|
|
'use strict';
|
|
var
|
|
initModule, getAuthHeaderObject,
|
|
GZAppVersion,
|
|
get, remove, create, update, uploadFile,
|
|
doSync, getListFromStore, putListInStore,
|
|
goToNextList, getActiveList, replaceActiveList, renameActiveList, toggleDeleteActiveList,
|
|
getActiveListIndex, replaceRecordInStore, insertRecordInStore, getRecordFromStore,
|
|
getListItemCoordinates, setActiveListId, getActiveListId, newList
|
|
;
|
|
|
|
|
|
GZAppVersion = "1.4";
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// NOT AUTHORIZED ERROR HANDLER
|
|
|
|
|
|
$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
|
|
//unauthorized? Trigger logout which will trigger login after clearing creds
|
|
if (jqxhr.status == 401) {
|
|
window.location.replace('#!/logout');
|
|
}
|
|
});
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// UTILITY
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Return the auth token header
|
|
//
|
|
//
|
|
getAuthHeaderObject = function () {
|
|
return {
|
|
"Authorization": "Bearer " + app.shell.stateMap.user.token
|
|
};
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Fetch the list from local storage
|
|
//
|
|
//
|
|
getListFromStore = function () {
|
|
return store.get('pecklist.list');
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Replace the list in local store
|
|
//
|
|
//
|
|
putListInStore = function (theList) {
|
|
store.set('pecklist.list', theList);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Get the active list id or first if active not found
|
|
//
|
|
getActiveListId = function (theId) {
|
|
var ret = store.get('pecklist.activeListId');
|
|
|
|
//validate it's ok
|
|
var l = app.api.getListFromStore();
|
|
var firstListId = l[0].id;//get a default in case it's not found
|
|
|
|
var len = l.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (l[i].id == ret) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
//if we're here then it's not a valid id so use the first one instead and set it
|
|
store.set('pecklist.activeListId', firstListId);
|
|
return firstListId;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Set the active list id
|
|
//
|
|
//
|
|
setActiveListId = function (theId) {
|
|
if (theId) {
|
|
store.set('pecklist.activeListId', theId);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// ADVANCE ACTIVE LIST ID TO NEXT LIST
|
|
//
|
|
//
|
|
goToNextList = function () {
|
|
var l = getListFromStore();
|
|
var allLength = l.length;
|
|
//is there more than one list?
|
|
if (allLength < 2) {
|
|
//Nope
|
|
return;
|
|
}
|
|
|
|
//figure out what the next list id should be
|
|
var currentIndex = getActiveListIndex();
|
|
var highestPossibleIndex = allLength - 1;
|
|
|
|
//are we already at the last list?
|
|
if (currentIndex == highestPossibleIndex) {
|
|
//go to first list (wrap)
|
|
setActiveListId(l[0].id);
|
|
return;
|
|
}
|
|
|
|
//advance to the next list
|
|
setActiveListId(l[currentIndex + 1].id);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////
|
|
// GET LIST INDEX
|
|
//
|
|
getActiveListIndex = function () {
|
|
var activeListId = getActiveListId();
|
|
var l = app.api.getListFromStore();
|
|
var len = l.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (l[i].id == activeListId) {
|
|
return i;
|
|
}
|
|
}
|
|
//This should never happen, if it does something is very wrong:
|
|
throw new Error("Error: app.main.js::getActiveListIndex - active list ID not found in list store");
|
|
}
|
|
|
|
///////////////////////////
|
|
// GET ACTIVE LIST
|
|
//
|
|
getActiveList = function () {
|
|
var activeListId = getActiveListId();
|
|
var l = app.api.getListFromStore();
|
|
var len = l.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (l[i].id == activeListId) {
|
|
return l[i];
|
|
}
|
|
}
|
|
//This should never happen, if it does something is very wrong:
|
|
throw new Error("Error: app.main.js::getActiveList - activeListId not found in list store");
|
|
}
|
|
|
|
|
|
///////////////////////////
|
|
// CREATE NEW LIST
|
|
//
|
|
newList = function () {
|
|
|
|
var l = app.api.getListFromStore();
|
|
var newListRecord={
|
|
id:"NEW_"+ _.now(),
|
|
name: "New list "+Date(),
|
|
v:1,
|
|
name_v:1,
|
|
items:[]
|
|
}
|
|
|
|
l.push(newListRecord);
|
|
app.api.putListInStore(l);
|
|
setActiveListId(newListRecord.id);
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////
|
|
// RENAME ACTIVE LIST
|
|
//
|
|
renameActiveList = function (newName) {
|
|
var activeListId = getActiveListId();
|
|
var l = app.api.getListFromStore();
|
|
var len = l.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (l[i].id == activeListId) {
|
|
l[i].name = newName;
|
|
putListInStore(l);
|
|
return;
|
|
}
|
|
}
|
|
//This should never happen, if it does something is very wrong:
|
|
throw new Error("Error: app.main.js::renameActiveList - activeListId not found in list store");
|
|
}
|
|
|
|
|
|
///////////////////////////
|
|
// DELETE ACTIVE LIST
|
|
//
|
|
toggleDeleteActiveList = function () {
|
|
var activeListId = getActiveListId();
|
|
var l = app.api.getListFromStore();
|
|
var len = l.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (l[i].id == activeListId) {
|
|
if (l[i].deleted) {
|
|
delete l[i].deleted;
|
|
} else {
|
|
l[i].deleted = true;//tag it as deleted
|
|
}
|
|
putListInStore(l);
|
|
return;
|
|
}
|
|
}
|
|
//This should never happen, if it does something is very wrong:
|
|
throw new Error("Error: app.main.js::toggleDeleteActiveList - activeListId not found in list store");
|
|
}
|
|
|
|
|
|
///////////////////////////
|
|
// REPLACE ACTIVE LIST
|
|
//
|
|
replaceActiveList = function (replacementList) {
|
|
var activeListId = getActiveListId();
|
|
var l = app.api.getListFromStore();
|
|
var len = l.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (l[i].id == activeListId) {
|
|
l[i] = replacementList;
|
|
putListInStore(l);
|
|
return;
|
|
}
|
|
}
|
|
//This should never happen, if it does something is very wrong:
|
|
throw new Error("Error: app.main.js::replaceActiveList - activeListId not found in list store");
|
|
}
|
|
|
|
|
|
//////////////////////////////
|
|
// GET LIST ITEM CO-ORDINATES
|
|
//
|
|
getListItemCoordinates = function (itemId) {
|
|
var allLists = app.api.getListFromStore();
|
|
var allLength = allLists.length, j = 0;
|
|
for (j; j < allLength; j++) {
|
|
//iterate the list and find it
|
|
var len = allLists[j].items.length, i = 0;
|
|
for (i; i < len; i++) {
|
|
if (allLists[j].items[i].id == itemId) {
|
|
return { listIndex: j, itemIndex: i };
|
|
}
|
|
}
|
|
}
|
|
//This should never happen, if it does something is very wrong:
|
|
throw new Error("Error: app.main.js::getListItemCoordinates - List item ID not found in list store");
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////
|
|
// GET RECORD FROM STORE
|
|
//
|
|
getRecordFromStore = function (itemId) {
|
|
var co = getListItemCoordinates(itemId);
|
|
var allLists = app.api.getListFromStore();
|
|
return allLists[co.listIndex].items[co.itemIndex];
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////
|
|
// REPLACE RECORD IN STORE
|
|
//
|
|
replaceRecordInStore = function (itemId, replacementRecord) {
|
|
var co = getListItemCoordinates(itemId);
|
|
var l = app.api.getListFromStore();
|
|
//Todo: is this the proper way to do it?
|
|
l[co.listIndex].items[co.itemIndex] = replacementRecord;
|
|
app.api.putListInStore(l);
|
|
}
|
|
|
|
|
|
///////////////////////////
|
|
// INSERT RECORD IN STORE
|
|
//
|
|
insertRecordInStore = function (newRecord) {
|
|
var activeListIndex = getActiveListIndex();
|
|
var l = app.api.getListFromStore();
|
|
l[activeListIndex].items.push(newRecord);
|
|
app.api.putListInStore(l);
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// PECKLIST SPECIFIC ROUTES
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// DOSYNC - Synchronize the stored data
|
|
//
|
|
doSync = function (callback) {
|
|
//get the list from the store
|
|
var theList = getListFromStore();
|
|
|
|
$.ajax({
|
|
method: "post",
|
|
dataType: "json",
|
|
url: app.shell.stateMap.apiUrl + 'sync',
|
|
headers: getAuthHeaderObject(),
|
|
contentType: 'application/json; charset=utf-8',
|
|
data: JSON.stringify(theList),
|
|
success: function (ret, textStatus) {
|
|
//Put the new list in the store
|
|
putListInStore(JSON.parse(ret));
|
|
callback({ ok: 1 });
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
callback({
|
|
error: 1,
|
|
msg: textStatus + '\n' + errorThrown,
|
|
error_detail: {}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// STANDARD API CORE ROUTES
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//Create
|
|
//Route app.post('/api/:obj_type/create', function (req, res) {
|
|
//
|
|
create = function (apiRoute, objData, callback) {
|
|
$.ajax({
|
|
method: "post",
|
|
dataType: "json",
|
|
url: app.shell.stateMap.apiUrl + apiRoute,
|
|
headers: getAuthHeaderObject(),
|
|
contentType: 'application/json; charset=utf-8',
|
|
data: JSON.stringify(objData),
|
|
success: function (data, textStatus) {
|
|
callback(data);
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
callback({
|
|
error: 1,
|
|
msg: textStatus + '\n' + errorThrown,
|
|
error_detail: {}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/////////////////
|
|
//Get - get anything, the caller provides the route, this should replace most legacy get
|
|
//
|
|
get = function (apiRoute, callback) {
|
|
$.ajax({
|
|
method: "GET",
|
|
dataType: "json",
|
|
url: app.shell.stateMap.apiUrl + apiRoute,
|
|
headers: getAuthHeaderObject(),
|
|
|
|
success: function (data, textStatus) {
|
|
callback(data);
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
callback({
|
|
error: 1,
|
|
msg: textStatus + '\n' + errorThrown,
|
|
error_detail: {}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
////////////////////
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//Update
|
|
//route: app.post('/api/:obj_type/update/:id', function (req, res) {
|
|
//
|
|
update = function (objType, objData, callback) {
|
|
var theId;
|
|
if (!objData.id) {
|
|
return callback({
|
|
error: 1,
|
|
msg: 'app.api.js::update->Error: missing id field in update document',
|
|
error_detail: objData
|
|
});
|
|
}
|
|
theId = objData.id;
|
|
$.ajax({
|
|
method: "put",
|
|
dataType: "json",
|
|
url: app.shell.stateMap.apiUrl + objType + '/' + theId,
|
|
headers: getAuthHeaderObject(),
|
|
contentType: 'application/json; charset=utf-8',
|
|
data: JSON.stringify(objData),
|
|
success: function (data, textStatus) {
|
|
if (data == null) {
|
|
data = { ok: 1 };
|
|
}
|
|
|
|
callback(data);
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
callback({
|
|
error: 1,
|
|
msg: textStatus + '\n' + errorThrown,
|
|
error_detail: {}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//remove Item
|
|
remove = function (apiRoute, callback) {
|
|
$.ajax({
|
|
method: "DELETE",
|
|
dataType: "json",
|
|
url: app.shell.stateMap.apiUrl + apiRoute,
|
|
headers: getAuthHeaderObject(),
|
|
success: function (data, textStatus) {
|
|
callback(data);
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
callback({
|
|
error: 1,
|
|
msg: textStatus + '\n' + errorThrown,
|
|
error_detail: {}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// uploadFile
|
|
// (ajax route to upload a file)
|
|
//
|
|
uploadFile = function (apiRoute, objData, callback) {
|
|
$.ajax({
|
|
method: "post",
|
|
dataType: "json",
|
|
url: app.shell.stateMap.apiUrl + apiRoute,
|
|
headers: getAuthHeaderObject(),
|
|
contentType: false,
|
|
processData: false,
|
|
data: objData,
|
|
success: function (data, textStatus) {
|
|
callback(data);
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
callback({
|
|
error: 1,
|
|
msg: textStatus + '\n' + errorThrown,
|
|
error_detail: {}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
initModule = function () { };
|
|
|
|
return {
|
|
initModule: initModule,
|
|
getAuthHeaderObject: getAuthHeaderObject,
|
|
GZAppVersion: GZAppVersion,
|
|
get: get,
|
|
remove: remove,
|
|
create: create,
|
|
update: update,
|
|
uploadFile: uploadFile,
|
|
doSync: doSync,
|
|
getListFromStore: getListFromStore,
|
|
putListInStore: putListInStore,
|
|
goToNextList: goToNextList,
|
|
getActiveList: getActiveList,
|
|
replaceActiveList: replaceActiveList,
|
|
getActiveListIndex: getActiveListIndex,
|
|
replaceRecordInStore: replaceRecordInStore,
|
|
insertRecordInStore: insertRecordInStore,
|
|
getRecordFromStore: getRecordFromStore,
|
|
getListItemCoordinates: getListItemCoordinates,
|
|
renameActiveList: renameActiveList,
|
|
toggleDeleteActiveList: toggleDeleteActiveList,
|
|
newList: newList
|
|
|
|
|
|
};
|
|
}()); |