pageflow 16.0.0 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -33
  3. data/README.md +6 -6
  4. data/Rakefile +1 -1
  5. data/admins/pageflow/entry.rb +0 -1
  6. data/admins/pageflow/sites.rb +3 -0
  7. data/app/assets/images/pageflow/admin/icons/published_with_noindex.svg +4 -0
  8. data/app/assets/javascripts/pageflow/dist/ui.js +299 -72
  9. data/app/assets/stylesheets/pageflow/admin/active_admin_patches.scss +1 -1
  10. data/app/assets/stylesheets/pageflow/admin/entries.scss +4 -0
  11. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +10 -0
  12. data/app/assets/stylesheets/pageflow/admin/publication_state_indicator.scss +4 -0
  13. data/app/assets/stylesheets/pageflow/editor/base.scss +0 -1
  14. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +61 -7
  15. data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +12 -1
  16. data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +4 -0
  17. data/app/assets/stylesheets/pageflow/editor/help.scss +3 -3
  18. data/app/assets/stylesheets/pageflow/editor/info_box.scss +7 -0
  19. data/app/assets/stylesheets/pageflow/editor/inputs/file_input.scss +0 -5
  20. data/app/assets/stylesheets/pageflow/ui/forms.scss +4 -4
  21. data/app/assets/stylesheets/pageflow/{editor/wysihtml5.scss → ui/input/text_area_input.scss} +13 -1
  22. data/app/assets/stylesheets/pageflow/ui.scss +1 -0
  23. data/app/controllers/pageflow/chapters_controller.rb +2 -2
  24. data/app/controllers/pageflow/editor/entry_publications_controller.rb +5 -1
  25. data/app/controllers/pageflow/editor/file_import_controller.rb +1 -1
  26. data/app/controllers/pageflow/editor/files_controller.rb +1 -1
  27. data/app/controllers/pageflow/entries_controller.rb +12 -2
  28. data/app/controllers/pageflow/feeds_controller.rb +18 -0
  29. data/app/controllers/pageflow/pages_controller.rb +2 -2
  30. data/app/controllers/pageflow/sitemaps_controller.rb +15 -0
  31. data/app/controllers/pageflow/storylines_controller.rb +2 -2
  32. data/app/helpers/pageflow/entries_helper.rb +4 -1
  33. data/app/helpers/pageflow/feeds_helper.rb +66 -0
  34. data/app/helpers/pageflow/meta_tags_helper.rb +2 -1
  35. data/app/helpers/pageflow/page_types_helper.rb +10 -10
  36. data/app/helpers/pageflow/revision_file_helper.rb +3 -3
  37. data/app/helpers/pageflow/social_share_helper.rb +2 -2
  38. data/app/inputs/pageflow_permalink_input.rb +15 -3
  39. data/app/models/concerns/pageflow/entry_publication_states.rb +9 -0
  40. data/app/models/concerns/pageflow/reusable_file.rb +3 -3
  41. data/app/models/concerns/pageflow/uploadable_file.rb +5 -0
  42. data/app/models/pageflow/account.rb +8 -0
  43. data/app/models/pageflow/audio_file_url_templates.rb +2 -1
  44. data/app/models/pageflow/draft_entry.rb +1 -1
  45. data/app/models/pageflow/entries_feed.rb +32 -0
  46. data/app/models/pageflow/entry.rb +7 -5
  47. data/app/models/pageflow/entry_at_revision.rb +2 -0
  48. data/app/models/pageflow/image_file.rb +34 -8
  49. data/app/models/pageflow/image_file_url_templates.rb +7 -1
  50. data/app/models/pageflow/membership.rb +3 -2
  51. data/app/models/pageflow/other_file.rb +5 -0
  52. data/app/models/pageflow/other_file_url_templates.rb +16 -0
  53. data/app/models/pageflow/published_entry.rb +6 -0
  54. data/app/models/pageflow/revision.rb +6 -0
  55. data/app/models/pageflow/site.rb +8 -0
  56. data/app/models/pageflow/sitemaps.rb +14 -0
  57. data/app/models/pageflow/used_file.rb +10 -2
  58. data/app/models/pageflow/video_file_url_templates.rb +3 -1
  59. data/app/models/pageflow/widget.rb +9 -1
  60. data/app/views/admin/entries/_permalink_inputs.html.erb +1 -2
  61. data/app/views/admin/sites/_attributes_table.html.arb +3 -0
  62. data/app/views/admin/sites/_fields.html.erb +6 -0
  63. data/app/views/components/pageflow/admin/extensible_attributes_table.rb +2 -2
  64. data/app/views/components/pageflow/admin/revisions_tab.rb +8 -0
  65. data/app/views/components/pageflow/admin/sites_tab.rb +3 -0
  66. data/app/views/pageflow/editor/config/_seeds.json.jbuilder +2 -0
  67. data/app/views/pageflow/editor/entries/_entry.json.jbuilder +1 -0
  68. data/app/views/pageflow/editor/entry_publications/check.json.jbuilder +1 -0
  69. data/app/views/pageflow/feeds/index.atom.builder +20 -0
  70. data/app/views/pageflow/image_files/_image_file.json.jbuilder +1 -0
  71. data/app/views/pageflow/meta_tags/_entry.html.erb +1 -0
  72. data/app/views/pageflow/sitemaps/index.xml.builder +9 -0
  73. data/config/initializers/features.rb +3 -0
  74. data/config/initializers/paperclip.rb +8 -0
  75. data/config/locales/de.yml +77 -6
  76. data/config/locales/en.yml +79 -4
  77. data/config/routes.rb +3 -0
  78. data/config/spring.rb +1 -1
  79. data/db/migrate/20230120092923_create_other_files.rb +23 -0
  80. data/db/migrate/20230323115745_add_feeds_enabled_to_sites.rb +5 -0
  81. data/db/migrate/20230323154323_add_sitemap_enabled_to_sites.rb +5 -0
  82. data/db/migrate/20230331103823_add_title_to_sites.rb +5 -0
  83. data/db/migrate/20230405103612_add_custom_feed_url_to_sites.rb +5 -0
  84. data/db/migrate/20231024062501_add_output_presences_to_image_files.rb +5 -0
  85. data/db/migrate/20231128124523_add_noindex_to_revisions.rb +5 -0
  86. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +710 -259
  87. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +34 -5
  88. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +1 -1
  89. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +1 -1
  90. data/entry_types/paged/app/controllers/pageflow_paged/editor/entries_controller.rb +0 -2
  91. data/entry_types/paged/app/controllers/pageflow_paged/entries_controller.rb +2 -1
  92. data/entry_types/paged/app/views/pageflow_paged/entries/show.html.erb +1 -0
  93. data/entry_types/paged/config/initializers/features.rb +0 -1
  94. data/entry_types/paged/lib/pageflow_paged/engine.rb +13 -1
  95. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +2 -2
  96. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +3 -4
  97. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +13 -6
  98. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +11 -3
  99. data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +11 -0
  100. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +42 -0
  101. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +8 -5
  102. data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +17 -12
  103. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +9 -1
  104. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +1 -1
  105. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +23 -0
  106. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -1
  107. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_seed.json.jbuilder +1 -5
  108. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/sections/_section_with_content_elements.json.jbuilder +10 -0
  109. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +44 -41
  110. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_consent_vendors.json.jbuilder +16 -0
  111. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +7 -0
  112. data/entry_types/scrolled/config/initializers/features.rb +5 -0
  113. data/entry_types/scrolled/config/locales/consent_widget.de.yml +4 -0
  114. data/entry_types/scrolled/config/locales/consent_widget.en.yml +4 -0
  115. data/entry_types/scrolled/config/locales/de.yml +225 -8
  116. data/entry_types/scrolled/config/locales/en.yml +239 -2
  117. data/entry_types/scrolled/config/routes.rb +4 -0
  118. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +69 -44
  119. data/entry_types/scrolled/lib/pageflow_scrolled/additional_packs.rb +2 -1
  120. data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +1 -1
  121. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +96 -0
  122. data/entry_types/scrolled/lib/pageflow_scrolled/content_element_consent_vendors.rb +38 -0
  123. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +13 -1
  124. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +30 -0
  125. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +6 -1
  126. data/entry_types/scrolled/lib/pageflow_scrolled/web_app_manifest.rb +1 -1
  127. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/dummy.rake +1 -1
  128. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +1 -2
  129. data/entry_types/scrolled/package/config/webpack.js +26 -0
  130. data/entry_types/scrolled/package/contentElements-editor.js +330 -32
  131. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  132. data/entry_types/scrolled/package/contentElements-frontend.js +920 -145
  133. data/entry_types/scrolled/package/editor.js +819 -239
  134. data/entry_types/scrolled/package/frontend/{EditableInlineText.module-14c7b097.js → EditableInlineText.module-6ee0e024.js} +1975 -1792
  135. data/entry_types/scrolled/package/frontend/PhonePlatformContext-b28d991a.js +32 -0
  136. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-8242f213.js +107 -0
  137. data/entry_types/scrolled/package/frontend/Viewer-32cd1ac1.js +154 -0
  138. data/entry_types/scrolled/package/frontend/{Viewer-b6becc57.js → Viewer-6e4d14ed.js} +32 -161
  139. data/entry_types/scrolled/package/frontend/arrowRight-e42e6011.js +77 -0
  140. data/entry_types/scrolled/package/frontend/{components-b3160dd7.js → components-24363f97.js} +188 -47
  141. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-f6093cc6.js → i18n-71c39823.js} +191 -111
  142. data/entry_types/scrolled/package/frontend/index-fc4b13e6.js +118 -0
  143. data/entry_types/scrolled/package/frontend/index.css +1 -1
  144. data/entry_types/scrolled/package/frontend/index.js +252 -76
  145. data/entry_types/scrolled/package/frontend/useContentElementEditorState-245f1986.js +52 -0
  146. data/entry_types/scrolled/package/package.json +6 -4
  147. data/entry_types/scrolled/package/testHelpers.js +11 -2
  148. data/entry_types/scrolled/package/values/colors.module.css +15 -0
  149. data/entry_types/scrolled/package/widgets/consentBar.css +1 -0
  150. data/entry_types/scrolled/package/widgets/consentBar.js +426 -0
  151. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  152. data/entry_types/scrolled/package/widgets/defaultNavigation.js +39 -4
  153. data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -0
  154. data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +49 -0
  155. data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -0
  156. data/entry_types/scrolled/package/widgets/textInlineFileRights.js +37 -0
  157. data/lib/generators/pageflow/resque/resque_generator.rb +1 -1
  158. data/lib/generators/pageflow/resque/templates/resque.rake +1 -1
  159. data/lib/generators/pageflow/resque/templates/resque.rb +1 -1
  160. data/lib/generators/pageflow/routes/routes_generator.rb +1 -1
  161. data/lib/pageflow/ability_mixin.rb +5 -5
  162. data/lib/pageflow/active_admin_can_can_fix.rb +2 -2
  163. data/lib/pageflow/built_in_file_type.rb +7 -0
  164. data/lib/pageflow/configuration.rb +29 -1
  165. data/lib/pageflow/engine.rb +18 -40
  166. data/lib/pageflow/entry_export_import/revision_serialization.rb +1 -1
  167. data/lib/pageflow/file_type.rb +2 -2
  168. data/lib/pageflow/global_config_api.rb +2 -2
  169. data/lib/pageflow/nested_revision_component.rb +23 -5
  170. data/lib/pageflow/page_type.rb +1 -1
  171. data/lib/pageflow/paperclip_processors/webp.rb +63 -0
  172. data/lib/pageflow/rails_version.rb +19 -0
  173. data/lib/pageflow/seeds.rb +10 -7
  174. data/lib/pageflow/user_mixin.rb +1 -1
  175. data/lib/pageflow/version.rb +1 -1
  176. data/lib/pageflow/widget_types.rb +4 -0
  177. data/package/config/jest/index.js +3 -1
  178. data/package/config/webpack5.js +14 -0
  179. data/package/editor.js +410 -181
  180. data/package/frontend.js +34 -4
  181. data/package/testHelpers.js +1 -1
  182. data/package/ui.js +297 -71
  183. data/spec/factories/entries.rb +34 -3
  184. data/spec/factories/sites.rb +3 -0
  185. data/vendor/assets/javascripts/iscroll.js +4 -7
  186. metadata +118 -80
  187. data/app/helpers/pageflow/admin/permalinks_helper.rb +0 -15
  188. data/entry_types/scrolled/package/frontend/arrowRight-78a7cee4.js +0 -42
data/package/frontend.js CHANGED
@@ -1240,7 +1240,7 @@ var volumeBinding = function volumeBinding(player, settings, options) {
1240
1240
  };
1241
1241
 
1242
1242
  player.targetVolume = function () {
1243
- return settings.get('volume') * volumeFactor;
1243
+ return (options.ignoreVolumeSetting ? 1 : settings.get('volume')) * volumeFactor;
1244
1244
  };
1245
1245
 
1246
1246
  function listenToVolumeSetting() {
@@ -1615,6 +1615,21 @@ mediaPlayer.loadWaiting = loadWaiting;
1615
1615
  mediaPlayer.hooks = hooks;
1616
1616
  mediaPlayer.asyncPlay = asyncPlay;
1617
1617
 
1618
+ // Replacement for Underscore's throttle, because scrolled entries
1619
+ // don't have Underscore anymore
1620
+ function throttle(func, timeFrame) {
1621
+ var lastTime = 0;
1622
+ return function (options) {
1623
+ var now = new Date();
1624
+ func = func.bind(this);
1625
+
1626
+ if (now - lastTime >= timeFrame) {
1627
+ func(options);
1628
+ lastTime = now;
1629
+ }
1630
+ };
1631
+ }
1632
+
1618
1633
  var mediaEvents = function mediaEvents(player, context) {
1619
1634
  function triggerMediaEvent(name) {
1620
1635
  events.trigger('media:' + name, {
@@ -1633,6 +1648,9 @@ var mediaEvents = function mediaEvents(player, context) {
1633
1648
  player.on('timeupdate', function () {
1634
1649
  triggerMediaEvent('timeupdate');
1635
1650
  });
1651
+ player.on('timeupdate', throttle(function () {
1652
+ triggerMediaEvent('timeupdate_throttled');
1653
+ }, 5000));
1636
1654
  player.on('pause', function () {
1637
1655
  triggerMediaEvent('pause');
1638
1656
  });
@@ -2150,6 +2168,9 @@ var mediaEvents$1 = function mediaEvents(player, context) {
2150
2168
  player.on('timeupdate', function () {
2151
2169
  triggerMediaEvent('timeupdate');
2152
2170
  });
2171
+ player.on('timeupdate', throttle(function () {
2172
+ triggerMediaEvent('timeupdate_throttled');
2173
+ }, 5000));
2153
2174
  player.on('pause', function () {
2154
2175
  triggerMediaEvent('pause');
2155
2176
  });
@@ -2291,11 +2312,13 @@ var createMediaPlayer = function createMediaPlayer(options) {
2291
2312
  nativeCaptions: !isAudio && browser.has('iphone platform'),
2292
2313
  // Only used by pageflow-scrolled
2293
2314
  vhs: {
2294
- useBandwidthFromLocalStorage: true
2315
+ useBandwidthFromLocalStorage: true,
2316
+ usePlayerObjectFit: true
2295
2317
  }
2296
2318
  },
2297
2319
  bufferUnderrunWaiting: true,
2298
2320
  fallbackToMutedAutoplay: !isAudio,
2321
+ ignoreVolumeSetting: true,
2299
2322
  volumeFading: true,
2300
2323
  hooks: {},
2301
2324
  mediaEvents: true,
@@ -2524,13 +2547,16 @@ var MediaPool = /*#__PURE__*/function () {
2524
2547
  tagName: type
2525
2548
  });
2526
2549
  mediaEl.setAttribute('src', blankSources[type].src);
2550
+ player.muted(true);
2527
2551
  this.unAllocatedPlayers[type].push(player);
2528
2552
  return player;
2529
2553
  }
2530
2554
  }, {
2531
2555
  key: "initializeMediaPool_",
2532
2556
  value: function initializeMediaPool_(type, mediaElSeed) {
2533
- while (this.allPlayersForType(type).length < this.playerCount) {
2557
+ var playerCount = typeof this.playerCount === 'function' ? this.playerCount(type) : this.playerCount;
2558
+
2559
+ while (this.allPlayersForType(type).length < playerCount) {
2534
2560
  this.createPlayer_(type, mediaElSeed.cloneNode(true));
2535
2561
  }
2536
2562
  }
@@ -2562,7 +2588,11 @@ function clearTextTracks(player) {
2562
2588
  }
2563
2589
 
2564
2590
  var media = {
2565
- playerPool: new MediaPool(),
2591
+ playerPool: new MediaPool({
2592
+ playerCount: function playerCount() {
2593
+ return features.isEnabled('large_player_pool') ? 10 : 4;
2594
+ }
2595
+ }),
2566
2596
  muteState: true,
2567
2597
 
2568
2598
  get muted() {
@@ -174,7 +174,7 @@ var ConfigurationEditorTab = Base.extend({
174
174
  }).get();
175
175
  },
176
176
  visibleInputPropertyNames: function visibleInputPropertyNames() {
177
- return this.$el.find('.input:not(.input-hidden_via_binding)').map(function () {
177
+ return this.$el.find('.input:not(.hidden_via_binding)').map(function () {
178
178
  return $(this).data('inputPropertyName');
179
179
  }).get();
180
180
  },
data/package/ui.js CHANGED
@@ -7,6 +7,7 @@ import ChildViewContainer from 'backbone.babysitter';
7
7
  import IScroll from 'iscroll';
8
8
  import 'jquery.minicolors';
9
9
  import wysihtml5 from 'wysihtml5';
10
+ import 'jquery-ui';
10
11
  import Cocktail from 'cocktail';
11
12
 
12
13
  /*global JST*/
@@ -1064,6 +1065,107 @@ var TooltipView = Marionette.ItemView.extend({
1064
1065
  }
1065
1066
  });
1066
1067
 
1068
+ function _defineProperty(obj, key, value) {
1069
+ if (key in obj) {
1070
+ Object.defineProperty(obj, key, {
1071
+ value: value,
1072
+ enumerable: true,
1073
+ configurable: true,
1074
+ writable: true
1075
+ });
1076
+ } else {
1077
+ obj[key] = value;
1078
+ }
1079
+
1080
+ return obj;
1081
+ }
1082
+
1083
+ function ownKeys(object, enumerableOnly) {
1084
+ var keys = Object.keys(object);
1085
+
1086
+ if (Object.getOwnPropertySymbols) {
1087
+ var symbols = Object.getOwnPropertySymbols(object);
1088
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
1089
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
1090
+ });
1091
+ keys.push.apply(keys, symbols);
1092
+ }
1093
+
1094
+ return keys;
1095
+ }
1096
+
1097
+ function _objectSpread2(target) {
1098
+ for (var i = 1; i < arguments.length; i++) {
1099
+ var source = arguments[i] != null ? arguments[i] : {};
1100
+
1101
+ if (i % 2) {
1102
+ ownKeys(Object(source), true).forEach(function (key) {
1103
+ _defineProperty(target, key, source[key]);
1104
+ });
1105
+ } else if (Object.getOwnPropertyDescriptors) {
1106
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
1107
+ } else {
1108
+ ownKeys(Object(source)).forEach(function (key) {
1109
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
1110
+ });
1111
+ }
1112
+ }
1113
+
1114
+ return target;
1115
+ }
1116
+
1117
+ var attributeBinding = {
1118
+ setupBooleanAttributeBinding: function setupBooleanAttributeBinding(optionName, updateMethod) {
1119
+ this.setupAttributeBinding(optionName, updateMethod, Boolean);
1120
+ },
1121
+ getBooleanAttributBoundOption: function getBooleanAttributBoundOption(optionName) {
1122
+ return this.getAttributeBoundOption(optionName, Boolean);
1123
+ },
1124
+ setupAttributeBinding: function setupAttributeBinding(optionName, updateMethod) {
1125
+ var _this = this;
1126
+
1127
+ var normalize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function (value) {
1128
+ return value;
1129
+ };
1130
+ var binding = this.options["".concat(optionName, "Binding")];
1131
+ var view = this;
1132
+
1133
+ if (binding) {
1134
+ _.flatten([binding]).forEach(function (attribute) {
1135
+ _this.listenTo(_this.model, 'change:' + attribute, update);
1136
+ });
1137
+ }
1138
+
1139
+ update();
1140
+
1141
+ function update() {
1142
+ updateMethod.call(view, view.getAttributeBoundOption(optionName, normalize));
1143
+ }
1144
+ },
1145
+ getAttributeBoundOption: function getAttributeBoundOption(optionName) {
1146
+ var _this2 = this;
1147
+
1148
+ var normalize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (value) {
1149
+ return value;
1150
+ };
1151
+ var binding = this.options["".concat(optionName, "Binding")];
1152
+ var bindingValueOptionName = "".concat(optionName, "BindingValue");
1153
+ var value = Array.isArray(binding) ? binding.map(function (attribute) {
1154
+ return _this2.model.get(attribute);
1155
+ }) : this.model.get(binding);
1156
+
1157
+ if (bindingValueOptionName in this.options) {
1158
+ return value === this.options[bindingValueOptionName];
1159
+ } else if (typeof this.options[optionName] === 'function') {
1160
+ return normalize(this.options[optionName](value));
1161
+ } else if (optionName in this.options) {
1162
+ return normalize(this.options[optionName]);
1163
+ } else if (binding) {
1164
+ return normalize(value);
1165
+ }
1166
+ }
1167
+ };
1168
+
1067
1169
  /**
1068
1170
  * Mixin for input views handling common concerns like labels,
1069
1171
  * inline help, visiblity and disabling.
@@ -1193,7 +1295,7 @@ var TooltipView = Marionette.ItemView.extend({
1193
1295
  * @mixin
1194
1296
  */
1195
1297
 
1196
- var inputView = {
1298
+ var inputView = _objectSpread2(_objectSpread2({}, attributeBinding), {}, {
1197
1299
  ui: {
1198
1300
  label: 'label',
1199
1301
  labelText: 'label .name',
@@ -1237,8 +1339,8 @@ var inputView = {
1237
1339
  this.ui.labelText.text(this.labelText());
1238
1340
  this.updateInlineHelp();
1239
1341
  this.setLabelFor();
1240
- this.setupAttributeBinding('disabled', this.updateDisabled);
1241
- this.setupAttributeBinding('visible', this.updateVisible);
1342
+ this.setupBooleanAttributeBinding('disabled', this.updateDisabled);
1343
+ this.setupBooleanAttributeBinding('visible', this.updateVisible);
1242
1344
  },
1243
1345
 
1244
1346
  /**
@@ -1287,7 +1389,7 @@ var inputView = {
1287
1389
  }
1288
1390
  },
1289
1391
  isDisabled: function isDisabled() {
1290
- return this.getAttributeBoundOption('disabled');
1392
+ return this.getBooleanAttributBoundOption('disabled');
1291
1393
  },
1292
1394
  updateDisabled: function updateDisabled() {
1293
1395
  this.$el.toggleClass('input-disabled', !!this.isDisabled());
@@ -1305,46 +1407,9 @@ var inputView = {
1305
1407
  }
1306
1408
  },
1307
1409
  updateVisible: function updateVisible() {
1308
- this.$el.toggleClass('input-hidden_via_binding', this.getAttributeBoundOption('visible') === false);
1309
- },
1310
- setupAttributeBinding: function setupAttributeBinding(optionName, updateMethod) {
1311
- var _this = this;
1312
-
1313
- var binding = this.options["".concat(optionName, "Binding")];
1314
- var view = this;
1315
-
1316
- if (binding) {
1317
- _.flatten([binding]).forEach(function (attribute) {
1318
- _this.listenTo(_this.model, 'change:' + attribute, update);
1319
- });
1320
- }
1321
-
1322
- update();
1323
-
1324
- function update() {
1325
- updateMethod.call(view, view.getAttributeBoundOption(optionName));
1326
- }
1327
- },
1328
- getAttributeBoundOption: function getAttributeBoundOption(optionName) {
1329
- var _this2 = this;
1330
-
1331
- var binding = this.options["".concat(optionName, "Binding")];
1332
- var bindingValueOptionName = "".concat(optionName, "BindingValue");
1333
- var value = Array.isArray(binding) ? binding.map(function (attribute) {
1334
- return _this2.model.get(attribute);
1335
- }) : this.model.get(binding);
1336
-
1337
- if (bindingValueOptionName in this.options) {
1338
- return value === this.options[bindingValueOptionName];
1339
- } else if (typeof this.options[optionName] === 'function') {
1340
- return !!this.options[optionName](value);
1341
- } else if (optionName in this.options) {
1342
- return !!this.options[optionName];
1343
- } else if (binding) {
1344
- return !!value;
1345
- }
1410
+ this.$el.toggleClass('hidden_via_binding', this.getBooleanAttributBoundOption('visible') === false);
1346
1411
  }
1347
- };
1412
+ });
1348
1413
 
1349
1414
  function template$4(data) {
1350
1415
  var __p = '';
@@ -1463,6 +1528,125 @@ var UrlDisplayView = Marionette.ItemView.extend({
1463
1528
  }
1464
1529
  });
1465
1530
 
1531
+ function _classCallCheck(instance, Constructor) {
1532
+ if (!(instance instanceof Constructor)) {
1533
+ throw new TypeError("Cannot call a class as a function");
1534
+ }
1535
+ }
1536
+
1537
+ function _defineProperties(target, props) {
1538
+ for (var i = 0; i < props.length; i++) {
1539
+ var descriptor = props[i];
1540
+ descriptor.enumerable = descriptor.enumerable || false;
1541
+ descriptor.configurable = true;
1542
+ if ("value" in descriptor) descriptor.writable = true;
1543
+ Object.defineProperty(target, descriptor.key, descriptor);
1544
+ }
1545
+ }
1546
+
1547
+ function _createClass(Constructor, protoProps, staticProps) {
1548
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
1549
+ if (staticProps) _defineProperties(Constructor, staticProps);
1550
+ return Constructor;
1551
+ }
1552
+
1553
+ /**
1554
+ * Input view for a number.
1555
+ *
1556
+ * See {@link inputView} for further options.
1557
+ *
1558
+ * @param {Object} [options]
1559
+ *
1560
+ * @param {string} [options.locale]
1561
+ * Locale used to fomat and parse numbers.
1562
+ *
1563
+ * @class
1564
+ */
1565
+
1566
+ var NumberInputView = Marionette.ItemView.extend({
1567
+ mixins: [inputView],
1568
+ template: function template() {
1569
+ return "\n <label>\n <span class=\"name\"></span>\n <span class=\"inline_help\"></span>\n </label>\n <input type=\"text\" dir=\"auto\" />\n ";
1570
+ },
1571
+ ui: {
1572
+ input: 'input'
1573
+ },
1574
+ events: {
1575
+ 'change': 'onChange'
1576
+ },
1577
+ initialize: function initialize() {
1578
+ this.parser = new NumberParser(this.options.locale);
1579
+ },
1580
+ onRender: function onRender() {
1581
+ this.load();
1582
+ this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
1583
+ },
1584
+ onChange: function onChange() {
1585
+ this.save();
1586
+ this.load();
1587
+ },
1588
+ onClose: function onClose() {
1589
+ this.save();
1590
+ },
1591
+ save: function save() {
1592
+ var inputValue = this.ui.input.val();
1593
+ this.model.set(this.options.propertyName, this.parser.parse(inputValue) || 0);
1594
+ },
1595
+ load: function load() {
1596
+ var input = this.ui.input;
1597
+ var value = this.model.get(this.options.propertyName) || 0;
1598
+ input.val(value.toLocaleString(this.options.locale, {
1599
+ useGrouping: false
1600
+ }));
1601
+ },
1602
+ displayValidationError: function displayValidationError(message) {
1603
+ this.$el.addClass('invalid');
1604
+ this.ui.input.attr('title', message);
1605
+ },
1606
+ resetValidationError: function resetValidationError(message) {
1607
+ this.$el.removeClass('invalid');
1608
+ this.ui.input.attr('title', '');
1609
+ }
1610
+ });
1611
+
1612
+ var NumberParser = /*#__PURE__*/function () {
1613
+ function NumberParser(locale) {
1614
+ _classCallCheck(this, NumberParser);
1615
+
1616
+ var format = new Intl.NumberFormat(locale);
1617
+ var parts = format.formatToParts(12345.6);
1618
+ var numerals = Array.from({
1619
+ length: 10
1620
+ }).map(function (_, i) {
1621
+ return format.format(i);
1622
+ });
1623
+ var index = new Map(numerals.map(function (d, i) {
1624
+ return [d, i];
1625
+ }));
1626
+ this._group = new RegExp("[".concat(parts.find(function (d) {
1627
+ return d.type === "group";
1628
+ }).value, "]"), "g");
1629
+ this._decimal = new RegExp("[".concat(parts.find(function (d) {
1630
+ return d.type === "decimal";
1631
+ }).value, "]"));
1632
+ this._numeral = new RegExp("[".concat(numerals.join(""), "]"), "g");
1633
+
1634
+ this._index = function (d) {
1635
+ return index.get(d);
1636
+ };
1637
+ }
1638
+
1639
+ _createClass(NumberParser, [{
1640
+ key: "parse",
1641
+ value: function parse(string) {
1642
+ string = string.trim().replace(this._group, "").replace(this._decimal, ".").replace(this._numeral, this._index);
1643
+ return string ? +string : NaN;
1644
+ }
1645
+ }]);
1646
+
1647
+ return NumberParser;
1648
+ }();
1649
+
1466
1650
  /**
1467
1651
  * Text based input view that can display a placeholder.
1468
1652
  *
@@ -1673,11 +1857,15 @@ var ColorInputView = Marionette.ItemView.extend({
1673
1857
  this.ui.input.minicolors({
1674
1858
  changeDelay: 200,
1675
1859
  change: _.bind(function (color) {
1860
+ this._saving = true;
1861
+
1676
1862
  if (color === this.defaultValue()) {
1677
1863
  this.model.unset(this.options.propertyName);
1678
1864
  } else {
1679
1865
  this.model.set(this.options.propertyName, color);
1680
1866
  }
1867
+
1868
+ this._saving = false;
1681
1869
  }, this)
1682
1870
  });
1683
1871
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
@@ -1706,7 +1894,10 @@ var ColorInputView = Marionette.ItemView.extend({
1706
1894
  }
1707
1895
  },
1708
1896
  load: function load() {
1709
- this.ui.input.minicolors('value', this.model.get(this.options.propertyName) || this.defaultValue());
1897
+ if (!this._saving) {
1898
+ this.ui.input.minicolors('value', this.model.get(this.options.propertyName) || this.defaultValue());
1899
+ }
1900
+
1710
1901
  this.$el.toggleClass('is_default', !this.model.has(this.options.propertyName));
1711
1902
  },
1712
1903
  refreshPicker: function refreshPicker() {
@@ -2113,6 +2304,7 @@ return __p
2113
2304
  var TextAreaInputView = Marionette.ItemView.extend({
2114
2305
  mixins: [inputView, inputWithPlaceholderText],
2115
2306
  template: template$8,
2307
+ className: 'text_area_input',
2116
2308
  ui: {
2117
2309
  input: 'textarea',
2118
2310
  toolbar: '.toolbar',
@@ -2289,21 +2481,6 @@ var TextAreaInputView = Marionette.ItemView.extend({
2289
2481
  }
2290
2482
  });
2291
2483
 
2292
- function _defineProperty(obj, key, value) {
2293
- if (key in obj) {
2294
- Object.defineProperty(obj, key, {
2295
- value: value,
2296
- enumerable: true,
2297
- configurable: true,
2298
- writable: true
2299
- });
2300
- } else {
2301
- obj[key] = value;
2302
- }
2303
-
2304
- return obj;
2305
- }
2306
-
2307
2484
  function template$9(data) {
2308
2485
  var __p = '';
2309
2486
  __p += '<label>\n <span class="name"></span>\n <span class="inline_help"></span>\n</label>\n<input type="text" />\n<div class="validation"></div>\n';
@@ -2570,6 +2747,25 @@ return __p
2570
2747
  *
2571
2748
  * @param {Object} [options]
2572
2749
  *
2750
+ * @param {number} [options.defaultValue]
2751
+ * Defaults value to display if property is not set.
2752
+ *
2753
+ * @param {number} [options.minValue=0]
2754
+ * Value when dragging slider to the very left.
2755
+ *
2756
+ * @param {number} [options.maxValue=100]
2757
+ * Value when dragging slider to the very right.
2758
+ *
2759
+ * @param {string} [options.unit="%"]
2760
+ * Unit to display after value.
2761
+ *
2762
+ * @param {function} [options.displayText]
2763
+ * Function that receives value and returns custom text to display as value.
2764
+ *
2765
+ * @param {boolean} [options.saveOnSlide]
2766
+ * Already update the model while dragging the handle - not only after
2767
+ * handle has been released.
2768
+ *
2573
2769
  * @class
2574
2770
  */
2575
2771
 
@@ -2582,15 +2778,27 @@ var SliderInputView = Marionette.ItemView.extend({
2582
2778
  value: '.value'
2583
2779
  },
2584
2780
  events: {
2585
- 'slidechange': 'save'
2781
+ 'slidechange': 'save',
2782
+ 'slide': 'handleSlide'
2586
2783
  },
2587
2784
  onRender: function onRender() {
2785
+ var _this = this;
2786
+
2588
2787
  this.ui.widget.slider({
2589
- animate: 'fast',
2590
- min: 'minValue' in this.options ? this.options.minValue : 0,
2591
- max: 'maxValue' in this.options ? this.options.maxValue : 100
2788
+ animate: 'fast'
2789
+ });
2790
+ this.setupAttributeBinding('minValue', function (value) {
2791
+ return _this.updateSliderOption('min', value || 0);
2792
+ });
2793
+ this.setupAttributeBinding('maxValue', function (value) {
2794
+ return _this.updateSliderOption('max', value || 100);
2592
2795
  });
2593
2796
  this.load();
2797
+ this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
2798
+ },
2799
+ updateSliderOption: function updateSliderOption(name, value) {
2800
+ this.ui.widget.slider('option', name, value);
2801
+ this.updateText(this.ui.widget.slider('value'));
2594
2802
  },
2595
2803
  updateDisabled: function updateDisabled(disabled) {
2596
2804
  this.$el.toggleClass('disabled', !!disabled);
@@ -2601,11 +2809,15 @@ var SliderInputView = Marionette.ItemView.extend({
2601
2809
  this.ui.widget.slider('enable');
2602
2810
  }
2603
2811
  },
2604
- save: function save() {
2605
- var value = this.ui.widget.slider('option', 'value');
2606
- var unit = 'unit' in this.options ? this.options.unit : '%';
2607
- this.ui.value.text(value + unit);
2608
- this.model.set(this.options.propertyName, value);
2812
+ handleSlide: function handleSlide(event, ui) {
2813
+ this.updateText(ui.value);
2814
+
2815
+ if (this.options.saveOnSlide) {
2816
+ this.save(event, ui);
2817
+ }
2818
+ },
2819
+ save: function save(event, ui) {
2820
+ this.model.set(this.options.propertyName, ui.value);
2609
2821
  },
2610
2822
  load: function load() {
2611
2823
  var value;
@@ -2616,7 +2828,18 @@ var SliderInputView = Marionette.ItemView.extend({
2616
2828
  value = 'defaultValue' in this.options ? this.options.defaultValue : 0;
2617
2829
  }
2618
2830
 
2619
- this.ui.widget.slider('option', 'value', value);
2831
+ this.ui.widget.slider('option', 'value', this.clampValue(value));
2832
+ this.updateText(value);
2833
+ },
2834
+ clampValue: function clampValue(value) {
2835
+ var min = this.ui.widget.slider('option', 'min');
2836
+ var max = this.ui.widget.slider('option', 'max');
2837
+ return Math.min(max, Math.max(min, value));
2838
+ },
2839
+ updateText: function updateText(value) {
2840
+ var unit = 'unit' in this.options ? this.options.unit : '%';
2841
+ var text = 'displayText' in this.options ? this.options.displayText(value) : value + unit;
2842
+ this.ui.value.text(text);
2620
2843
  }
2621
2844
  });
2622
2845
 
@@ -3010,7 +3233,10 @@ var subviewContainer = {
3010
3233
  return view;
3011
3234
  },
3012
3235
  appendSubview: function appendSubview(view) {
3013
- return this.$el.append(this.subview(view).el);
3236
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
3237
+ to = _ref.to;
3238
+
3239
+ return (to || this.$el).append(this.subview(view).el);
3014
3240
  },
3015
3241
  onClose: function onClose() {
3016
3242
  if (this.subviews) {
@@ -3067,4 +3293,4 @@ var tooltipContainer = {
3067
3293
  }
3068
3294
  };
3069
3295
 
3070
- export { CheckBoxGroupInputView, CheckBoxInputView, CollectionView, ColorInputView, ConfigurationEditorTabView, ConfigurationEditorView, DeleteRowTableCellView, EnumTableCellView, ExtendedSelectInputView, IconTableCellView, JsonInputView, LabelOnlyView, BaseObject as Object, PresenceTableCellView, ProxyUrlInputView, SelectInputView, SeparatorView, SliderInputView, SortableCollectionView, TableCellView, TableHeaderCellView, TableRowView, TableView, TabsView, TextAreaInputView, TextInputView, TextTableCellView, TooltipView, UrlDisplayView, UrlInputView, cssModulesUtils, i18nUtils, inputView, inputWithPlaceholderText, serverSideValidation, subviewContainer, tooltipContainer, viewWithValidationErrorMessages };
3296
+ export { CheckBoxGroupInputView, CheckBoxInputView, CollectionView, ColorInputView, ConfigurationEditorTabView, ConfigurationEditorView, DeleteRowTableCellView, EnumTableCellView, ExtendedSelectInputView, IconTableCellView, JsonInputView, LabelOnlyView, NumberInputView, BaseObject as Object, PresenceTableCellView, ProxyUrlInputView, SelectInputView, SeparatorView, SliderInputView, SortableCollectionView, TableCellView, TableHeaderCellView, TableRowView, TableView, TabsView, TextAreaInputView, TextInputView, TextTableCellView, TooltipView, UrlDisplayView, UrlInputView, attributeBinding, cssModulesUtils, i18nUtils, inputView, inputWithPlaceholderText, serverSideValidation, subviewContainer, tooltipContainer, viewWithValidationErrorMessages };
@@ -70,18 +70,49 @@ module Pageflow
70
70
  end
71
71
 
72
72
  trait :published do
73
+ first_published_at { 1.month.ago }
74
+
73
75
  transient do
74
76
  published_revision_attributes { {} }
75
77
  end
76
78
 
77
79
  after(:create) do |entry, evaluator|
78
- create(:revision, :published, evaluator.published_revision_attributes.merge(entry: entry))
80
+ create(:revision, :published,
81
+ evaluator.published_revision_attributes.merge(entry: entry))
79
82
  end
80
83
  end
81
84
 
82
85
  trait :published_with_password do
83
- after(:create) do |entry, _evaluator|
84
- create(:revision, :published, entry: entry, password_protected: true)
86
+ first_published_at { 1.month.ago }
87
+
88
+ transient do
89
+ published_revision_attributes { {} }
90
+ end
91
+
92
+ after(:create) do |entry, evaluator|
93
+ create(:revision,
94
+ :published,
95
+ evaluator.published_revision_attributes.merge(
96
+ entry: entry,
97
+ password_protected: true
98
+ ))
99
+ end
100
+ end
101
+
102
+ trait :published_with_noindex do
103
+ first_published_at { 1.month.ago }
104
+
105
+ transient do
106
+ published_revision_attributes { {} }
107
+ end
108
+
109
+ after(:create) do |entry, evaluator|
110
+ create(:revision,
111
+ :published,
112
+ evaluator.published_revision_attributes.merge(
113
+ entry: entry,
114
+ noindex: true
115
+ ))
85
116
  end
86
117
  end
87
118
 
@@ -1,6 +1,9 @@
1
1
  module Pageflow
2
2
  FactoryBot.define do
3
3
  factory :site, class: Pageflow::Site do
4
+ feeds_enabled { true }
5
+ sitemap_enabled { true }
6
+
4
7
  after(:build) do |site|
5
8
  site.account ||= build(:account, default_site: site)
6
9
  end
@@ -101,7 +101,6 @@ var utils = (function () {
101
101
  me.extend(me, {
102
102
  hasTransform: _transform !== false,
103
103
  hasPerspective: _prefixStyle('perspective') in _elementStyle,
104
- hasTouch: 'ontouchstart' in window,
105
104
  hasPointer: navigator.msPointerEnabled,
106
105
  hasTransition: _prefixStyle('transition') in _elementStyle
107
106
  });
@@ -862,12 +861,10 @@ IScroll.prototype = {
862
861
  eventType(target, 'MSPointerUp', this);
863
862
  }
864
863
 
865
- if ( utils.hasTouch ) {
866
- eventType(startEventTarget, 'touchstart', this);
867
- eventType(target, 'touchmove', this);
868
- eventType(target, 'touchcancel', this);
869
- eventType(target, 'touchend', this);
870
- }
864
+ eventType(startEventTarget, 'touchstart', this);
865
+ eventType(target, 'touchmove', this);
866
+ eventType(target, 'touchcancel', this);
867
+ eventType(target, 'touchend', this);
871
868
 
872
869
  eventType(this.scroller, 'transitionend', this);
873
870
  eventType(this.scroller, 'webkitTransitionEnd', this);