Mercurial > hg > isophonics-drupal-site
diff core/modules/quickedit/js/models/EntityModel.js @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/quickedit/js/models/EntityModel.js Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,319 @@ +/** +* DO NOT EDIT THIS FILE. +* See the following change record for more information, +* https://www.drupal.org/node/2815083 +* @preserve +**/ + +(function (_, $, Backbone, Drupal) { + Drupal.quickedit.EntityModel = Drupal.quickedit.BaseModel.extend({ + defaults: { + el: null, + + entityID: null, + + entityInstanceID: null, + + id: null, + + label: null, + + fields: null, + + isActive: false, + + inTempStore: false, + + isDirty: false, + + isCommitting: false, + + state: 'closed', + + fieldsInTempStore: [], + + reload: false + }, + + initialize: function initialize() { + this.set('fields', new Drupal.quickedit.FieldCollection()); + + this.listenTo(this, 'change:state', this.stateChange); + + this.listenTo(this.get('fields'), 'change:state', this.fieldStateChange); + + Drupal.quickedit.BaseModel.prototype.initialize.call(this); + }, + stateChange: function stateChange(entityModel, state, options) { + var to = state; + switch (to) { + case 'closed': + this.set({ + isActive: false, + inTempStore: false, + isDirty: false + }); + break; + + case 'launching': + break; + + case 'opening': + entityModel.get('fields').each(function (fieldModel) { + fieldModel.set('state', 'candidate', options); + }); + break; + + case 'opened': + this.set('isActive', true); + break; + + case 'committing': + var fields = this.get('fields'); + + fields.chain().filter(function (fieldModel) { + return _.intersection([fieldModel.get('state')], ['active']).length; + }).each(function (fieldModel) { + fieldModel.set('state', 'candidate'); + }); + + fields.chain().filter(function (fieldModel) { + return _.intersection([fieldModel.get('state')], Drupal.quickedit.app.changedFieldStates).length; + }).each(function (fieldModel) { + fieldModel.set('state', 'saving'); + }); + break; + + case 'deactivating': + var changedFields = this.get('fields').filter(function (fieldModel) { + return _.intersection([fieldModel.get('state')], ['changed', 'invalid']).length; + }); + + if ((changedFields.length || this.get('fieldsInTempStore').length) && !options.saved && !options.confirmed) { + this.set('state', 'opened', { confirming: true }); + + _.defer(function () { + Drupal.quickedit.app.confirmEntityDeactivation(entityModel); + }); + } else { + var invalidFields = this.get('fields').filter(function (fieldModel) { + return _.intersection([fieldModel.get('state')], ['invalid']).length; + }); + + entityModel.set('reload', this.get('fieldsInTempStore').length || invalidFields.length); + + entityModel.get('fields').each(function (fieldModel) { + if (_.intersection([fieldModel.get('state')], ['candidate', 'highlighted']).length) { + fieldModel.trigger('change:state', fieldModel, fieldModel.get('state'), options); + } else { + fieldModel.set('state', 'candidate', options); + } + }); + } + break; + + case 'closing': + options.reason = 'stop'; + this.get('fields').each(function (fieldModel) { + fieldModel.set({ + inTempStore: false, + state: 'inactive' + }, options); + }); + break; + } + }, + _updateInTempStoreAttributes: function _updateInTempStoreAttributes(entityModel, fieldModel) { + var current = fieldModel.get('state'); + var previous = fieldModel.previous('state'); + var fieldsInTempStore = entityModel.get('fieldsInTempStore'); + + if (current === 'saved') { + entityModel.set('inTempStore', true); + + fieldModel.set('inTempStore', true); + + fieldsInTempStore.push(fieldModel.get('fieldID')); + fieldsInTempStore = _.uniq(fieldsInTempStore); + entityModel.set('fieldsInTempStore', fieldsInTempStore); + } else if (current === 'candidate' && previous === 'inactive') { + fieldModel.set('inTempStore', _.intersection([fieldModel.get('fieldID')], fieldsInTempStore).length > 0); + } + }, + fieldStateChange: function fieldStateChange(fieldModel, state) { + var entityModel = this; + var fieldState = state; + + switch (this.get('state')) { + case 'closed': + case 'launching': + break; + + case 'opening': + _.defer(function () { + entityModel.set('state', 'opened', { + 'accept-field-states': Drupal.quickedit.app.readyFieldStates + }); + }); + break; + + case 'opened': + if (fieldState === 'changed') { + entityModel.set('isDirty', true); + } else { + this._updateInTempStoreAttributes(entityModel, fieldModel); + } + break; + + case 'committing': + if (fieldState === 'invalid') { + _.defer(function () { + entityModel.set('state', 'opened', { reason: 'invalid' }); + }); + } else { + this._updateInTempStoreAttributes(entityModel, fieldModel); + } + + var options = { + 'accept-field-states': Drupal.quickedit.app.readyFieldStates + }; + if (entityModel.set('isCommitting', true, options)) { + entityModel.save({ + success: function success() { + entityModel.set({ + state: 'deactivating', + isCommitting: false + }, { saved: true }); + }, + error: function error() { + entityModel.set('isCommitting', false); + + entityModel.set('state', 'opened', { reason: 'networkerror' }); + + var message = Drupal.t('Your changes to <q>@entity-title</q> could not be saved, either due to a website problem or a network connection problem.<br>Please try again.', { '@entity-title': entityModel.get('label') }); + Drupal.quickedit.util.networkErrorModal(Drupal.t('Network problem!'), message); + } + }); + } + break; + + case 'deactivating': + _.defer(function () { + entityModel.set('state', 'closing', { + 'accept-field-states': Drupal.quickedit.app.readyFieldStates + }); + }); + break; + + case 'closing': + _.defer(function () { + entityModel.set('state', 'closed', { + 'accept-field-states': ['inactive'] + }); + }); + break; + } + }, + save: function save(options) { + var entityModel = this; + + var entitySaverAjax = Drupal.ajax({ + url: Drupal.url('quickedit/entity/' + entityModel.get('entityID')), + error: function error() { + options.error.call(entityModel); + } + }); + + entitySaverAjax.commands.quickeditEntitySaved = function (ajax, response, status) { + entityModel.get('fields').each(function (fieldModel) { + fieldModel.set('inTempStore', false); + }); + entityModel.set('inTempStore', false); + entityModel.set('fieldsInTempStore', []); + + if (options.success) { + options.success.call(entityModel); + } + }; + + entitySaverAjax.execute(); + }, + validate: function validate(attrs, options) { + var acceptedFieldStates = options['accept-field-states'] || []; + + var currentState = this.get('state'); + var nextState = attrs.state; + if (currentState !== nextState) { + if (_.indexOf(this.constructor.states, nextState) === -1) { + return '"' + nextState + '" is an invalid state'; + } + + if (!this._acceptStateChange(currentState, nextState, options)) { + return 'state change not accepted'; + } else if (!this._fieldsHaveAcceptableStates(acceptedFieldStates)) { + return 'state change not accepted because fields are not in acceptable state'; + } + } + + var currentIsCommitting = this.get('isCommitting'); + var nextIsCommitting = attrs.isCommitting; + if (currentIsCommitting === false && nextIsCommitting === true) { + if (!this._fieldsHaveAcceptableStates(acceptedFieldStates)) { + return 'isCommitting change not accepted because fields are not in acceptable state'; + } + } else if (currentIsCommitting === true && nextIsCommitting === true) { + return 'isCommitting is a mutex, hence only changes are allowed'; + } + }, + _acceptStateChange: function _acceptStateChange(from, to, context) { + var accept = true; + + if (!this.constructor.followsStateSequence(from, to)) { + accept = false; + + if (from === 'closing' && to === 'closed') { + accept = true; + } else if (from === 'committing' && to === 'opened' && context.reason && (context.reason === 'invalid' || context.reason === 'networkerror')) { + accept = true; + } else if (from === 'deactivating' && to === 'opened' && context.confirming) { + accept = true; + } else if (from === 'opened' && to === 'deactivating' && context.confirmed) { + accept = true; + } + } + + return accept; + }, + _fieldsHaveAcceptableStates: function _fieldsHaveAcceptableStates(acceptedFieldStates) { + var accept = true; + + if (acceptedFieldStates.length > 0) { + var fieldStates = this.get('fields').pluck('state') || []; + + if (_.difference(fieldStates, acceptedFieldStates).length) { + accept = false; + } + } + + return accept; + }, + destroy: function destroy(options) { + Drupal.quickedit.BaseModel.prototype.destroy.call(this, options); + + this.stopListening(); + + this.get('fields').reset(); + }, + sync: function sync() {} + }, { + states: ['closed', 'launching', 'opening', 'opened', 'committing', 'deactivating', 'closing'], + + followsStateSequence: function followsStateSequence(from, to) { + return _.indexOf(this.states, from) < _.indexOf(this.states, to); + } + }); + + Drupal.quickedit.EntityCollection = Backbone.Collection.extend({ + model: Drupal.quickedit.EntityModel + }); +})(_, jQuery, Backbone, Drupal); \ No newline at end of file