/**
- * Core Service - egPrint
+ * Core Service - egPrintStore
+ *
+ * Dispatches print and data storage requests to the appropriate handler.
+ *
+ * With each request, if a connection to Hatch is established, the
+ * request is relayed. If a connection has not been attempted, an
+ * attempt is made then the request is handled. If Hatch is known to be
+ * inaccessible, requests are routed to local handlers.
+ *
+ * Printing is handled locally with an egPrintContainer whose contents
+ * are made visible during printing using CSS print media.
+ *
+ * Storage requests are handled by $window.localStorage.
+ *
+ * Note that all requests return promises, since any request may be
+ * subject to aschronous processing by Hatch.
*
*/
-
angular.module('egCoreMod')
-
.factory('egPrintStore',
['$q','$window','$timeout',
function($q , $window , $timeout) {
service.socket = null;
service.hatchAvailable = null;
service.hatchURL = 'wss://localhost:8443/hatch';
+ service.hatchRequired = false;
+ // TODO: would be nice to support local fall-through for specific actions
// write a message to the Hatch websocket
service.sendToHatch = function(msg) {
// it from our tracked requests.
service.resolveRequest = function(msg) {
- var srcMsg = service.messages[msg.msgid];
- if (!srcMsg) {
- console.log(
- "egPrintStore found no source message for response " +
- msg.msgid
- );
- return;
- }
-
- // remove the source message
- delete service.messages[msg.msgid];
+ // for requests sent through Hatch, only the cached
+ // request will have the original promise attached
+ msg.deferred = service.messages[msg.msgid].deferred;
+ delete service.messages[msg.msgid]; // un-cache
// resolve / reject
if (msg.success) {
console.debug("command succeeded : " + msg.success);
- srcMsg.deferred.resolve(msg.success);
+ msg.deferred.resolve(msg.success);
} else {
console.error("command failed : " + msg.error);
- srcMsg.deferred.reject(msg.error);
+ msg.deferred.reject(msg.error);
}
}
service.handleRequestsLocally = function() {
service.socket = null;
service.hatchAvailable = false;
- angular.forEach(service.pending, function(msg) {
+
+ while ( (msg = service.pending.shift()) ) {
+
+ if (service.hatchRequired) {
+ throw new Error(
+ "egPrintStore : attempt to perform '" + msg.action +
+ "' operation failed because no connection to Hatch could be " +
+ "established and egPrintStore.hatchRequired is set to TRUE"
+ );
+ }
+
switch(msg.action) {
case 'print':
- return service.browserPrint(msg);
+ service.browserPrint(msg);
+ break;
case 'keys':
case 'get':
case 'set':
case 'append':
case 'remove':
- return service.handleLocalStorageRequest(msg);
+ service.handleLocalStorageRequest(msg);
+ break;
}
service.resolveRequest(msg);
- });
+ }
}
service.hatchConnect = function() {
}
service.socket.onerror = function() {
+ if (service.hatchAvailable === false) return; // already registered
console.debug(
"unable to connect to Hatch server at " + service.hatchURL);
service.handleRequestsLocally();
}
}
+ // print locally via the browser
service.browserPrint = function(msg) {
// let our local print container handle printing
service.onBrowserPrint(msg.contentType, msg.content);
msg.success = true; // assume browser print succeeded
}
+ // print the provided content
+ // supported values for contentType are 'text/html' and 'text/plain'
service.print = function(contentType, content) {
if (service.hatchAvailable === false) {
service.browserPrint(contentType, content);
});
}
+ // get the value for a stored item
service.getItem = function(key) {
+ return service.dispatchRequest({key : key, action : 'get'});
}
+ // set the value for a stored or new item
service.setItem = function(key, value) {
- if (key === null || value === null) {
- logger.warn("invalid key or value in egPrintStore.setItem()");
- return $q.reject();
- }
- return service.dispatchRequest({
- key : key,
- value : value,
- action : 'set',
- });
+ return service.dispatchRequest(
+ {key : key, value : value, action : 'set'});
+ }
+
+ // appends the value to the existing item stored at key.
+ // If not item is found at key, this behaves just like setItem()
+ service.appendItem = function(key, value) {
+ return service.dispatchRequest(
+ {key : key, value : value, action : 'append'});
}
- service.removeItem = function() {
+ // remove a stored item
+ service.removeItem = function(key) {
+ return service.dispatchRequest({key : key, action : 'remove'});
}
// if set, prefix limits the return set to keys starting with 'prefix'
service.getKeys = function(prefix) {
- return service.dispatchRequest({
- key : prefix,
- action : 'keys',
- });
+ return service.dispatchRequest({key : prefix, action : 'keys'});
}
// get, set, remove, append, keys : via $window.localStorage
service.handleLocalStorageRequest = function(msg) {
+ console.log('service.handleLocalStorageRequest() ' + msg.action);
+ var key = msg.key;
+ var value = msg.value;
switch(msg.action) {
case 'keys':
var keys = [];
var idx = 0;
- while (true) {
- var key = $window.localStorage.keys(idx);
- if (key === null) break;
- keys.push(key);
+ while ( (k = $window.localStorage.key(idx++)) !== null) {
+ // key prefix match test
+ if (key && k.substr(0, key.length) != key) continue;
+ keys.push(k);
}
msg.success = keys;
break;
case 'set':
- $window.localStorage.setItem(msg.key, msg.value);
+ $window.localStorage.setItem(key, value);
msg.success = true;
break;
- // ...
+ case 'get':
+ msg.success = $window.localStorage.getItem(msg.key);
+ break;
+
+ case 'remove':
+ $window.localStorage.removeItem(msg.key);
+ msg.success = true;
+ break;
+
+ case 'append':
+ var item = $window.localStorage.getItem(key);
+ if (item) value = item + value;
+ $window.localStorage.setItem(key, value);
+ msg.success = value;
+ break;
}
}