Files
pecklist/wwwroot/js/app.api.js
2018-06-28 23:08:13 +00:00

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.3";
//////////////////////////////////////////////////////////////////////////////////////
// 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
};
}());