diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-02-06 22:27:20 +0200 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-02-12 12:38:31 +0200 |
commit | 1dc9c3a59137b1cb9a38669938ba865154100c64 (patch) | |
tree | 28599445ef4a199ecde352afa495c4a918dd4641 /web/client.js | |
parent | 8857a1753ba94c490211b06531995b6ad88506a6 (diff) | |
download | aconf-1dc9c3a59137b1cb9a38669938ba865154100c64.tar.bz2 aconf-1dc9c3a59137b1cb9a38669938ba865154100c64.tar.xz |
web client: transaction module
Diffstat (limited to 'web/client.js')
-rw-r--r-- | web/client.js | 424 |
1 files changed, 3 insertions, 421 deletions
diff --git a/web/client.js b/web/client.js index 81ef869..d289890 100644 --- a/web/client.js +++ b/web/client.js @@ -21,6 +21,7 @@ require( [ "acf2/path", "acf2/statusbar", + "acf2/transaction", "acf2/type", "jquery", "underscore", @@ -28,7 +29,7 @@ require( "jquery-blockui", "jquery-ui/sortable" ], - function(pth, statusBar, type, $, _) { + function(pth, statusBar, txnMgr, type, $, _) { $("#login").submit(function() { $.ajax("/login", { @@ -38,429 +39,10 @@ require( }) }).done(function(data, status, xhr) { - var txnMgr = (function(token, saveRequired) { - var txn, changed, invalid; - - function reset() { - txn = null; - changed = {}; - invalid = {}; - } - reset(); - - function isValid() { return !(_.size(invalid)); } - - function request(url, options) { - options = options || {}; - options.headers = {"X-ACF-Auth-Token": token}; - if (txn) options.headers["X-ACF-Transaction-ID"] = txn; - if (options.data != undefined) - options.data = JSON.stringify(options.data); - return $.ajax(url, options); - } - - function abort() { - request("/transaction", {type: "DELETE"}); - reset(); - } - - function objRequest(path, options) { - return request("/config" + path, options); - } - - function exclusive(task) { - $.blockUI(); - - var def = $.Deferred(); - function resolve(txnValid) { def.resolve(txnValid); } - function reject() { def.reject(); } - - var tasks = _.filter( - _.pluck(_.values(invalid), 1), function(d) { - return d && d.state() == "pending"; - } - ); - - if (tasks.length) - tasks[0].always(function() { - exclusive(task).done(resolve).fail(reject); - }); - else task().always($.unblockUI).done(resolve).fail(reject); - - return def; - } - - function query(path) { - var def = $.Deferred(); - - objRequest(path).done(function(data) { - if (type.isTreeNode(data.meta) && !_.size(data.data)) - data.data = type.isList(data.meta) ? [] : {}; - - function index(name) { - return _.isArray(data.data) ? name - 1 : name; - } - - data.get = function(name, valid) { - var p = pth.join(path, name); - if (!valid && p in invalid) return invalid[p][0]; - - if (data.meta.type == "set") { - return _.contains( - data.data, name - ) ? name : null; - } - - return data.data[index(name)]; - }; - - data.metaRequest = function(name) { - return request("/meta" + pth.join(path, name)); - }; - - data.match = function(filter) { - if (!filter) return true; - return _.every(_.map(filter, function(values, key) { - return _.contains(values, data.data[key]); - })); - }; - - data.status = function(name) { - var p = name ? pth.join(path, name) : path; - function scan(objs) { - return _.size(_.filter( - _.keys(objs), function(obj) { - return pth.isSubordinate(obj, p); - } - )); - } - - if (scan(invalid)) return "invalid"; - if (scan(changed)) return "changed"; - return null; - }; - - data.validate = function() { - var valid = true; - if (data.meta.required) { - valid = _.size(data.data); - if (valid) delete invalid[path]; - else invalid[path] = [path]; - } - return valid && isValid(); - }; - - data.set = function(name, newValue) { - var def = $.Deferred(); - function reject(xhr) { def.reject(xhr); } - - var mpath = pth.join(path, name); - - var value = data.get(name, true); - if (value == undefined) value = null; - - var tn = _.isObject(newValue); - var npv = tn ? mpath : newValue; - - function ignore(path) { - _.each(_.keys(invalid), function(p) { - if (pth.isSubordinate(p, path)) - delete invalid[p]; - }); - } - - function resolve() { - if (mpath in invalid && - invalid[mpath][1] == def) { - - var del = invalid[mpath][0] == null; - - delete invalid[mpath]; - if (del) ignore(mpath); - } - - def.resolve(isValid()); - } - - function validate() { - var del = newValue == null; - var set = data.meta.type == "set"; - - var options; - if (!del) - options = { - type: set ? "POST" : "PUT", - data: newValue - }; - else if (data.get(name, true) != null) - options = {type: "DELETE"}; - - if (!options) { - if (data.meta.type == "model" && - _.findWhere( - data.meta.fields, {name: name} - ).required) - def.reject("Required value not set"); - else resolve(); - return; - } - - objRequest( - set && !del ? path : mpath, options - ).done(function() { - if (!(mpath in changed)) - changed[mpath] = value; - if (!tn && newValue == changed[mpath]) - delete changed[mpath]; - - if (npv == null) - _.each( - _.keys(changed), - function(p) { - if (pth.isSubordinate(p, mpath, true)) - delete changed[p]; - } - ); - - if (data.meta.type == "list" && del) - data.data.splice(name - 1, 1); - else if (!set) data.data[index(name)] = npv; - else if (del) - data.data.splice( - data.data.indexOf(name), 1 - ); - else data.data.push(name); - - data.validate(); - - if (data.meta.type == "model") - _.each( - data.meta.fields, function(field) { - if (field.condition && - field.condition[name] && - !_.contains( - field.condition[name], - newValue - )) - ignore( - pth.join(path, field.name) - ); - } - ); - - if (tn && !set) - query(mpath).done(function(data) { - - if (mpath in invalid) { - if (data.meta.type == "model") - _.each( - data.meta.fields, - function(field) { - var mmpath = pth.join( - mpath, - field.name - ); - if (field.required && - data.match( - field.condition - ) && - !(mmpath in invalid) && - (type.isCollection( - field - ) || data.get( - field.name - ) == null)) { - invalid[ - mmpath - ] = [ - null - ]; - } - }); - - else if (type.isCollection(data.meta) && - data.meta.required) - invalid[mpath] = [mpath]; - } - - resolve(); - }).fail(reject); - - else resolve(); - - }).fail(reject); - } - - var prevTask; - if (mpath in invalid) prevTask = invalid[mpath][1]; - - invalid[mpath] = [npv, def]; - - if (prevTask) prevTask.always(validate); - else validate(); - - return def; - }; - - data.add = function(name) { - return data.set(name, name); - }; - - function adjustListIndex(oldIndex, newIndex) { - var opath = pth.join(path, oldIndex); - var npath = pth.join(path, newIndex); - _.each( - [changed, invalid], - function(map) { - _.each( - _.keys(map), - function(p) { - if (pth.isSubordinate( - p, opath - )) { - map[npath + - p.substring( - opath.length - )] = map[p]; - delete map[p]; - } - }); - } - ); - } - - function adjustListIndices(start, end) { - var offset = start < end ? 1 : -1; - for (var i = start; i != end; i += offset) - adjustListIndex(i + offset, i); - } - - function _delete(name) { - var def = $.Deferred(); - var length = data.data.length; - - data.set(name, null).done(function(txnValid) { - if (type.isTreeNode(data.meta) && - data.meta.type != "set") { - - delete changed[pth.join(path, name)]; - changed[path] = path; - - if (data.meta.type == "list") - adjustListIndices(name, length); - } - def.resolve(txnValid); - - }).fail(function() { def.reject(); }); - - return def; - } - - data.delete = function(name) { - return exclusive(function() { - return _delete(name); - }); - }; - - data.move = function(oldIndex, newIndex) { - if (oldIndex == newIndex) - return $.Deferred().resolve(isValid()); - - var value = data.get(oldIndex); - var length = data.data.length; - - return exclusive(function() { - var def = $.Deferred(); - function reject() { def.reject(); } - - if (oldIndex > newIndex) oldIndex++; - else newIndex++; - - objRequest(path, {type: "POST", data: { - index: newIndex, - data: type.isTreeNode(data.meta.members) ? - pth.join(path, oldIndex) : value - }}).done(function() { - - data.data.splice(newIndex - 1, 0, value); - - adjustListIndices(length + 1, newIndex); - adjustListIndex(oldIndex, newIndex); - - data.delete(oldIndex) - .done(function(txnValid) { - def.resolve(txnValid); - }) - .fail(reject); - - }).fail(reject); - - return def; - }); - }; - - data.invoke = function(name) { - return objRequest(pth.join(path, name), {type: "POST"}); - }; - - def.resolve(data); - }).fail(function() { def.reject(); }); - - return def; - } - - return { - start: function() { - var def = $.Deferred(); - if (txn && isValid() && !(_.size(changed))) abort(); - - if (txn) - def.resolve(); - - else request("/transaction", {type: "POST"}) - .done(function(data, status, xhr) { - txn = xhr.getResponseHeader( - "X-ACF-Transaction-ID" - ); - def.resolve(); - }) - .fail(function() { def.reject(); }); - - return def; - }, - - commit: function() { - var def = $.Deferred(); - function reject(xhr) { def.reject(xhr); } - request( - "/transaction", {type: "PUT"} - ).done(function() { - reset(); - if (saveRequired) - request( - "/save", {type: "POST"} - ).done(function() { - def.resolve(); - }).fail(reject); - else def.resolve(); - }).fail(reject); - return def; - }, - - abort: abort, - - query: query, - - logout: function() { - return request("/login", {type: "DELETE"}); - } - }; - })( + txnMgr = txnMgr( xhr.getResponseHeader("X-ACF-Auth-Token"), xhr.getResponseHeader("X-ACF-Save-Required") == "1" ); - - function formatError(msg, xhr) { msg += " " + xhr.statusCode().status; |