PageRenderTime 54ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/web/core/modules/quickedit/js/models/EntityModel.js

https://gitlab.com/andecode/theme-spark
JavaScript | 319 lines | 274 code | 39 blank | 6 comment | 52 complexity | a129681cfad27992ac1ebf7e978d82fb MD5 | raw file
  1. /**
  2. * DO NOT EDIT THIS FILE.
  3. * See the following change record for more information,
  4. * https://www.drupal.org/node/2815083
  5. * @preserve
  6. **/
  7. (function (_, $, Backbone, Drupal) {
  8. Drupal.quickedit.EntityModel = Drupal.quickedit.BaseModel.extend({
  9. defaults: {
  10. el: null,
  11. entityID: null,
  12. entityInstanceID: null,
  13. id: null,
  14. label: null,
  15. fields: null,
  16. isActive: false,
  17. inTempStore: false,
  18. isDirty: false,
  19. isCommitting: false,
  20. state: 'closed',
  21. fieldsInTempStore: [],
  22. reload: false
  23. },
  24. initialize: function initialize() {
  25. this.set('fields', new Drupal.quickedit.FieldCollection());
  26. this.listenTo(this, 'change:state', this.stateChange);
  27. this.listenTo(this.get('fields'), 'change:state', this.fieldStateChange);
  28. Drupal.quickedit.BaseModel.prototype.initialize.call(this);
  29. },
  30. stateChange: function stateChange(entityModel, state, options) {
  31. var to = state;
  32. switch (to) {
  33. case 'closed':
  34. this.set({
  35. isActive: false,
  36. inTempStore: false,
  37. isDirty: false
  38. });
  39. break;
  40. case 'launching':
  41. break;
  42. case 'opening':
  43. entityModel.get('fields').each(function (fieldModel) {
  44. fieldModel.set('state', 'candidate', options);
  45. });
  46. break;
  47. case 'opened':
  48. this.set('isActive', true);
  49. break;
  50. case 'committing':
  51. {
  52. var fields = this.get('fields');
  53. fields.chain().filter(function (fieldModel) {
  54. return _.intersection([fieldModel.get('state')], ['active']).length;
  55. }).each(function (fieldModel) {
  56. fieldModel.set('state', 'candidate');
  57. });
  58. fields.chain().filter(function (fieldModel) {
  59. return _.intersection([fieldModel.get('state')], Drupal.quickedit.app.changedFieldStates).length;
  60. }).each(function (fieldModel) {
  61. fieldModel.set('state', 'saving');
  62. });
  63. break;
  64. }
  65. case 'deactivating':
  66. {
  67. var changedFields = this.get('fields').filter(function (fieldModel) {
  68. return _.intersection([fieldModel.get('state')], ['changed', 'invalid']).length;
  69. });
  70. if ((changedFields.length || this.get('fieldsInTempStore').length) && !options.saved && !options.confirmed) {
  71. this.set('state', 'opened', {
  72. confirming: true
  73. });
  74. _.defer(function () {
  75. Drupal.quickedit.app.confirmEntityDeactivation(entityModel);
  76. });
  77. } else {
  78. var invalidFields = this.get('fields').filter(function (fieldModel) {
  79. return _.intersection([fieldModel.get('state')], ['invalid']).length;
  80. });
  81. entityModel.set('reload', this.get('fieldsInTempStore').length || invalidFields.length);
  82. entityModel.get('fields').each(function (fieldModel) {
  83. if (_.intersection([fieldModel.get('state')], ['candidate', 'highlighted']).length) {
  84. fieldModel.trigger('change:state', fieldModel, fieldModel.get('state'), options);
  85. } else {
  86. fieldModel.set('state', 'candidate', options);
  87. }
  88. });
  89. }
  90. break;
  91. }
  92. case 'closing':
  93. options.reason = 'stop';
  94. this.get('fields').each(function (fieldModel) {
  95. fieldModel.set({
  96. inTempStore: false,
  97. state: 'inactive'
  98. }, options);
  99. });
  100. break;
  101. }
  102. },
  103. _updateInTempStoreAttributes: function _updateInTempStoreAttributes(entityModel, fieldModel) {
  104. var current = fieldModel.get('state');
  105. var previous = fieldModel.previous('state');
  106. var fieldsInTempStore = entityModel.get('fieldsInTempStore');
  107. if (current === 'saved') {
  108. entityModel.set('inTempStore', true);
  109. fieldModel.set('inTempStore', true);
  110. fieldsInTempStore.push(fieldModel.get('fieldID'));
  111. fieldsInTempStore = _.uniq(fieldsInTempStore);
  112. entityModel.set('fieldsInTempStore', fieldsInTempStore);
  113. } else if (current === 'candidate' && previous === 'inactive') {
  114. fieldModel.set('inTempStore', _.intersection([fieldModel.get('fieldID')], fieldsInTempStore).length > 0);
  115. }
  116. },
  117. fieldStateChange: function fieldStateChange(fieldModel, state) {
  118. var entityModel = this;
  119. var fieldState = state;
  120. switch (this.get('state')) {
  121. case 'closed':
  122. case 'launching':
  123. break;
  124. case 'opening':
  125. _.defer(function () {
  126. entityModel.set('state', 'opened', {
  127. 'accept-field-states': Drupal.quickedit.app.readyFieldStates
  128. });
  129. });
  130. break;
  131. case 'opened':
  132. if (fieldState === 'changed') {
  133. entityModel.set('isDirty', true);
  134. } else {
  135. this._updateInTempStoreAttributes(entityModel, fieldModel);
  136. }
  137. break;
  138. case 'committing':
  139. {
  140. if (fieldState === 'invalid') {
  141. _.defer(function () {
  142. entityModel.set('state', 'opened', {
  143. reason: 'invalid'
  144. });
  145. });
  146. } else {
  147. this._updateInTempStoreAttributes(entityModel, fieldModel);
  148. }
  149. var options = {
  150. 'accept-field-states': Drupal.quickedit.app.readyFieldStates
  151. };
  152. if (entityModel.set('isCommitting', true, options)) {
  153. entityModel.save({
  154. success: function success() {
  155. entityModel.set({
  156. state: 'deactivating',
  157. isCommitting: false
  158. }, {
  159. saved: true
  160. });
  161. },
  162. error: function error() {
  163. entityModel.set('isCommitting', false);
  164. entityModel.set('state', 'opened', {
  165. reason: 'networkerror'
  166. });
  167. 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.', {
  168. '@entity-title': entityModel.get('label')
  169. });
  170. Drupal.quickedit.util.networkErrorModal(Drupal.t('Network problem!'), message);
  171. }
  172. });
  173. }
  174. break;
  175. }
  176. case 'deactivating':
  177. _.defer(function () {
  178. entityModel.set('state', 'closing', {
  179. 'accept-field-states': Drupal.quickedit.app.readyFieldStates
  180. });
  181. });
  182. break;
  183. case 'closing':
  184. _.defer(function () {
  185. entityModel.set('state', 'closed', {
  186. 'accept-field-states': ['inactive']
  187. });
  188. });
  189. break;
  190. }
  191. },
  192. save: function save(options) {
  193. var entityModel = this;
  194. var entitySaverAjax = Drupal.ajax({
  195. url: Drupal.url("quickedit/entity/".concat(entityModel.get('entityID'))),
  196. error: function error() {
  197. options.error.call(entityModel);
  198. }
  199. });
  200. entitySaverAjax.commands.quickeditEntitySaved = function (ajax, response, status) {
  201. entityModel.get('fields').each(function (fieldModel) {
  202. fieldModel.set('inTempStore', false);
  203. });
  204. entityModel.set('inTempStore', false);
  205. entityModel.set('fieldsInTempStore', []);
  206. if (options.success) {
  207. options.success.call(entityModel);
  208. }
  209. };
  210. entitySaverAjax.options.headers = entitySaverAjax.options.headers || {};
  211. entitySaverAjax.options.headers['X-Drupal-Quickedit-CSRF-Token'] = drupalSettings.quickedit.csrf_token;
  212. entitySaverAjax.execute();
  213. },
  214. validate: function validate(attrs, options) {
  215. var acceptedFieldStates = options['accept-field-states'] || [];
  216. var currentState = this.get('state');
  217. var nextState = attrs.state;
  218. if (currentState !== nextState) {
  219. if (_.indexOf(this.constructor.states, nextState) === -1) {
  220. return "\"".concat(nextState, "\" is an invalid state");
  221. }
  222. if (!this._acceptStateChange(currentState, nextState, options)) {
  223. return 'state change not accepted';
  224. }
  225. if (!this._fieldsHaveAcceptableStates(acceptedFieldStates)) {
  226. return 'state change not accepted because fields are not in acceptable state';
  227. }
  228. }
  229. var currentIsCommitting = this.get('isCommitting');
  230. var nextIsCommitting = attrs.isCommitting;
  231. if (currentIsCommitting === false && nextIsCommitting === true) {
  232. if (!this._fieldsHaveAcceptableStates(acceptedFieldStates)) {
  233. return 'isCommitting change not accepted because fields are not in acceptable state';
  234. }
  235. } else if (currentIsCommitting === true && nextIsCommitting === true) {
  236. return 'isCommitting is a mutex, hence only changes are allowed';
  237. }
  238. },
  239. _acceptStateChange: function _acceptStateChange(from, to, context) {
  240. var accept = true;
  241. if (!this.constructor.followsStateSequence(from, to)) {
  242. accept = false;
  243. if (from === 'closing' && to === 'closed') {
  244. accept = true;
  245. } else if (from === 'committing' && to === 'opened' && context.reason && (context.reason === 'invalid' || context.reason === 'networkerror')) {
  246. accept = true;
  247. } else if (from === 'deactivating' && to === 'opened' && context.confirming) {
  248. accept = true;
  249. } else if (from === 'opened' && to === 'deactivating' && context.confirmed) {
  250. accept = true;
  251. }
  252. }
  253. return accept;
  254. },
  255. _fieldsHaveAcceptableStates: function _fieldsHaveAcceptableStates(acceptedFieldStates) {
  256. var accept = true;
  257. if (acceptedFieldStates.length > 0) {
  258. var fieldStates = this.get('fields').pluck('state') || [];
  259. if (_.difference(fieldStates, acceptedFieldStates).length) {
  260. accept = false;
  261. }
  262. }
  263. return accept;
  264. },
  265. destroy: function destroy(options) {
  266. Drupal.quickedit.BaseModel.prototype.destroy.call(this, options);
  267. this.stopListening();
  268. this.get('fields').reset();
  269. },
  270. sync: function sync() {}
  271. }, {
  272. states: ['closed', 'launching', 'opening', 'opened', 'committing', 'deactivating', 'closing'],
  273. followsStateSequence: function followsStateSequence(from, to) {
  274. return _.indexOf(this.states, from) < _.indexOf(this.states, to);
  275. }
  276. });
  277. Drupal.quickedit.EntityCollection = Backbone.Collection.extend({
  278. model: Drupal.quickedit.EntityModel
  279. });
  280. })(_, jQuery, Backbone, Drupal);