diff options
author | Yaco <franco@reevo.org> | 2020-06-04 11:01:00 -0300 |
---|---|---|
committer | Yaco <franco@reevo.org> | 2020-06-04 11:01:00 -0300 |
commit | fc7369835258467bf97eb64f184b93691f9a9fd5 (patch) | |
tree | daabd60089d2dd76d9f5fb416b005fbe159c799d /www/crm/wp-content/plugins/civicrm/civicrm/ang/crmAutosave.js |
first commit
Diffstat (limited to 'www/crm/wp-content/plugins/civicrm/civicrm/ang/crmAutosave.js')
-rw-r--r-- | www/crm/wp-content/plugins/civicrm/civicrm/ang/crmAutosave.js | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ang/crmAutosave.js b/www/crm/wp-content/plugins/civicrm/civicrm/ang/crmAutosave.js new file mode 100644 index 00000000..359ccfeb --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ang/crmAutosave.js @@ -0,0 +1,118 @@ +/// crmAutosave +(function(angular, $, _) { + + angular.module('crmAutosave', CRM.angRequires('crmAutosave')); + + // usage: + // var autosave = new CrmAutosaveCtrl({ + // save: function -- A function to handle saving. Should return a promise. + // If it's not a promise, then we'll assume that it completes successfully. + // saveIf: function -- Only allow autosave when conditional returns true. Default: !form.$invalid + // model: object|function -- (Re)schedule saves based on observed changes to object. We perform deep + // inspection on the model object. This could be a performance issue you + // had many concurrent autosave forms or a particularly large model, but + // it should be fine with typical usage. + // interval: object -- Interval spec. Default: {poll: 250, save: 5000} + // form: object|function -- FormController or its getter + // }); + // autosave.start(); + // $scope.$on('$destroy', autosave.stop); + // Note: if the save operation itself + angular.module('crmAutosave').service('CrmAutosaveCtrl', function($interval, $timeout, $q) { + function CrmAutosaveCtrl(options) { + var intervals = angular.extend({poll: 250, save: 5000}, options.interval); + var jobs = {poll: null, save: null}; // job handles used ot cancel/reschedule timeouts/intervals + var lastSeenModel = null; + var saving = false; + + // Determine if model has changed; (re)schedule the save. + // This is a bit expensive and doesn't need to be continuous, so we use polling instead of watches. + function checkChanges() { + if (saving) { + return; + } + var currentModel = _.isFunction(options.model) ? options.model() : options.model; + if (!angular.equals(currentModel, lastSeenModel)) { + lastSeenModel = angular.copy(currentModel); + if (jobs.save) { + $timeout.cancel(jobs.save); + } + jobs.save = $timeout(doAutosave, intervals.save); + } + } + + function doAutosave() { + jobs.save = null; + if (saving) { + return; + } + + var form = _.isFunction(options.form) ? options.form() : options.form; + + if (options.saveIf) { + if (!options.saveIf()) { + return; + } + } + else if (form && form.$invalid) { + return; + } + + saving = true; + lastSeenModel = angular.copy(_.isFunction(options.model) ? options.model() : options.model); + + // Set to pristine before saving -- not after saving. + // If an eager user continues editing concurrent with the + // save process, then the form should become dirty again. + if (form) { + form.$setPristine(); + } + var res = options.save(); + if (res && res.then) { + res.then( + function() { + saving = false; + }, + function() { + saving = false; + if (form) { + form.$setDirty(); + } + } + ); + } + else { + saving = false; + } + } + + var self = this; + + this.start = function() { + if (!jobs.poll) { + lastSeenModel = angular.copy(_.isFunction(options.model) ? options.model() : options.model); + jobs.poll = $interval(checkChanges, intervals.poll); + } + }; + + this.stop = function() { + if (jobs.poll) { + $interval.cancel(jobs.poll); + jobs.poll = null; + } + if (jobs.save) { + $timeout.cancel(jobs.save); + jobs.save = null; + } + }; + + this.suspend = function(p) { + self.stop(); + return p.finally(self.start); + }; + } + + return CrmAutosaveCtrl; + }); + +})(angular, CRM.$, CRM._); |