fl-builder-save-manager.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. (function($, FLBuilder) {
  2. /**
  3. * Save Manager Object
  4. */
  5. var SaveManager = {
  6. /**
  7. * Indicates whether or not the current layout is clean or has changes that require
  8. * publish actions.
  9. *
  10. * @var bool
  11. */
  12. layoutNeedsPublish: false,
  13. /**
  14. * The message that is displayed whenever `resetStatusMessage()` is called.
  15. *
  16. * @var string
  17. */
  18. defaultIndicatorMessage: "",
  19. /**
  20. * The tooltip that is displayed whenever 'resetStatusMessage()' is called.
  21. *
  22. * @var string
  23. */
  24. defaultTooltipMessage: "",
  25. /**
  26. * Local reference to strings pertaining to saving states.
  27. *
  28. * @var object
  29. */
  30. messages: null,
  31. /**
  32. * Setup the Save Manager object.
  33. *
  34. * @return void
  35. */
  36. init: function() {
  37. this.messages = FLBuilderStrings.savedStatus;
  38. this.$savingIndicator = $('.fl-builder--saving-indicator', window.parent.document);
  39. FLBuilder.addHook('didBeginAJAX', this.onLayoutSaving.bind(this));
  40. FLBuilder.addHook('didCompleteAJAX', this.onLayoutSaved.bind(this));
  41. FLBuilder.addHook('didPublishLayout', this.onLayoutPublished.bind(this));
  42. FLBuilder.addHook('publishAndRemain', this.onPublishAndRemain.bind(this));
  43. // We have to set the layout as needing publish when settings are opened because
  44. // we can't yet reliably set it to needing publish when settings are changed.
  45. FLBuilder.addHook('didShowLightbox', this.setLayoutNeedsPublish.bind(this));
  46. if ( FLBuilderConfig.layoutHasDraftedChanges || ! FLBuilderConfig.builderEnabled ) {
  47. this.setLayoutNeedsPublish();
  48. this.resetStatusMessage();
  49. }
  50. },
  51. /**
  52. * Flag the layout as needing to be published.
  53. *
  54. * @return void
  55. */
  56. setLayoutNeedsPublish: function() {
  57. if ( !this.layoutNeedsPublish ) {
  58. this.layoutNeedsPublish = true;
  59. $('body').add( 'body', window.parent.document ).addClass('fl-builder--layout-has-drafted-changes');
  60. }
  61. },
  62. /**
  63. * Fires when layout begins saving.
  64. *
  65. * @return void
  66. */
  67. onLayoutSaving: function(e, data) {;
  68. if ( this.isPublishingLayout( data.action ) ) {
  69. this.showStatusMessage( this.messages.publishing, this.messages.publishingTooltip );
  70. }
  71. else if ( this.isUpdatingLayout( data.action ) ) {
  72. this.setLayoutNeedsPublish();
  73. this.showStatusMessage( this.messages.saving, this.messages.savingTooltip );
  74. }
  75. },
  76. /**
  77. * Check if the current ajax action is publishing the layout
  78. *
  79. * @var String action
  80. * @return bool
  81. */
  82. isPublishingLayout: function( action ) {
  83. if ( 'save_layout' == action ) {
  84. return true;
  85. }
  86. return false;
  87. },
  88. /**
  89. * Checks if the current ajax action is updating the layout or some other part of the system.
  90. *
  91. * @var String action
  92. * @return bool
  93. */
  94. isUpdatingLayout: function( action ) {
  95. if ( this.isPublishingLayout() ) return false;
  96. if ( action.startsWith('render') ) {
  97. if ( action.startsWith('render_new') ) return true;
  98. return false;
  99. }
  100. if ( action.startsWith('duplicate') ) return false;
  101. if ( action.startsWith('refresh') ) return false; // Like refresh_revision_items
  102. if ( 'save_ui_skin' == action ) return false;
  103. if ( 'save_lightbox_position' == action ) return false;
  104. if ( 'save_pinned_ui_position' == action ) return false;
  105. if ( 'fl_builder_notifications' == action ) return false;
  106. if ( action.indexOf( 'history' ) > -1 ) return false; // HistoryManager
  107. return true;
  108. },
  109. /**
  110. * Fires after layout has been successfully saved.
  111. * Display the "Saved" message, wait a bit and reset to the default message.
  112. *
  113. * @return void
  114. */
  115. onLayoutSaved: function( e, data ) {
  116. if ( this.isUpdatingLayout( data.fl_builder_data.action ) ) {
  117. this.showStatusMessage(this.messages.saved, this.messages.savedTooltip);
  118. var obj = this;
  119. setTimeout(function() {
  120. obj.resetStatusMessage();
  121. }, 2000);
  122. }
  123. },
  124. /**
  125. * Handle layout published
  126. *
  127. * @return void
  128. */
  129. onLayoutPublished: function() {
  130. this.layoutNeedsPublish = false;
  131. $('body').add( 'body', window.parent.document ).removeClass('fl-builder--layout-has-drafted-changes');
  132. this.resetStatusMessage();
  133. },
  134. /**
  135. * Set the status message area to a string of text.
  136. *
  137. * @var string Message to display
  138. * @return void
  139. */
  140. showStatusMessage: function(message, toolTip) {
  141. this.$savingIndicator.html(message);
  142. if (! FLBuilder.isUndefined(toolTip)) {
  143. this.$savingIndicator.attr('title', toolTip);
  144. $('.fl-builder--saving-indicator', window.parent.document).tipTip({
  145. defaultPosition: 'bottom',
  146. edgeOffset: 14
  147. });
  148. }
  149. },
  150. /**
  151. * Set the status message back to it's default state.
  152. *
  153. * @return void
  154. */
  155. resetStatusMessage: function() {
  156. if(this.layoutNeedsPublish) {
  157. this.defaultIndicatorMessage = this.messages.edited + '<i class="fas fa-question-circle"></i>';
  158. this.defaultTooltipMessage = this.messages.editedTooltip;
  159. } else {
  160. this.defaultIndicatorMessage = "";
  161. this.defaultTooltipMessage = "";
  162. }
  163. this.showStatusMessage(this.defaultIndicatorMessage, this.defaultTooltipMessage );
  164. },
  165. /**
  166. * Handle publish key command
  167. *
  168. * @return void
  169. */
  170. onPublishAndRemain: function() {
  171. FLBuilder.MainMenu.hide();
  172. if (this.layoutNeedsPublish || FLBuilderSettingsForms.settingsHaveChanged()) {
  173. FLBuilder._publishLayout(false, true);
  174. } else {
  175. this.showStatusMessage(this.messages.noChanges);
  176. var manager = this;
  177. setTimeout(function() {
  178. manager.resetStatusMessage();
  179. }, 2000);
  180. }
  181. }
  182. };
  183. /**
  184. * Pubic Interface
  185. */
  186. FLBuilder.SaveManager = {
  187. /**
  188. * Check if the current layout has unpublished changes
  189. *
  190. * @return bool
  191. */
  192. layoutNeedsPublish: function() {
  193. return SaveManager.layoutNeedsPublish;
  194. },
  195. /**
  196. * Show a status message
  197. *
  198. * @var String message
  199. * @var String toolTip
  200. * @return void
  201. */
  202. showStatusMessage: function(message, toolTip) {
  203. SaveManager.showStatusMessage(message, toolTip);
  204. },
  205. /**
  206. * Reset status message to contextual default
  207. *
  208. * @return void
  209. */
  210. resetStatusMessage: function() {
  211. SaveManager.resetStatusMessage();
  212. }
  213. }
  214. /**
  215. * Kick off init.
  216. */
  217. $(function() {
  218. SaveManager.init();
  219. });
  220. })(jQuery, FLBuilder);