pageflow 15.7.1 → 16.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -243
  3. data/README.md +1 -9
  4. data/Rakefile +4 -1
  5. data/admins/pageflow/accounts.rb +12 -16
  6. data/admins/pageflow/entry.rb +57 -28
  7. data/admins/pageflow/entry_templates.rb +5 -7
  8. data/admins/pageflow/sites.rb +50 -0
  9. data/admins/pageflow/user.rb +7 -0
  10. data/app/assets/javascripts/pageflow/admin/entries.js +53 -4
  11. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +65 -0
  12. data/app/assets/stylesheets/pageflow/admin.scss +1 -0
  13. data/app/assets/stylesheets/pageflow/editor/base.scss +2 -6
  14. data/app/assets/stylesheets/pageflow/editor/dialogs.scss +2 -0
  15. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +9 -0
  16. data/app/assets/stylesheets/pageflow/editor/info_box.scss +13 -3
  17. data/app/assets/stylesheets/pageflow/mixins/buttons.scss +1 -0
  18. data/app/assets/stylesheets/pageflow/page.scss +0 -2
  19. data/app/assets/stylesheets/pageflow/themes/default/page.scss +1 -1
  20. data/app/assets/stylesheets/pageflow/ui/forms.scss +4 -1
  21. data/app/controllers/pageflow/editor/file_import_controller.rb +32 -42
  22. data/app/controllers/pageflow/entries_controller.rb +27 -3
  23. data/app/helpers/pageflow/admin/permalinks_helper.rb +15 -0
  24. data/app/helpers/pageflow/common_entry_seed_helper.rb +1 -1
  25. data/app/helpers/pageflow/embed_code_helper.rb +1 -1
  26. data/app/helpers/pageflow/entries_helper.rb +25 -17
  27. data/app/helpers/pageflow/sites_helper.rb +11 -0
  28. data/app/helpers/pageflow/social_share_helper.rb +2 -2
  29. data/app/inputs/pageflow_permalink_input.rb +47 -0
  30. data/app/models/concerns/pageflow/permalinkable.rb +12 -0
  31. data/app/models/concerns/pageflow/reusable_file.rb +5 -0
  32. data/app/models/concerns/pageflow/uploadable_file.rb +4 -0
  33. data/app/models/pageflow/account.rb +7 -33
  34. data/app/models/pageflow/{cname_theming_request_scope.rb → cname_site_request_scope.rb} +3 -3
  35. data/app/models/pageflow/customized_theme.rb +5 -3
  36. data/app/models/pageflow/entry.rb +8 -4
  37. data/app/models/pageflow/entry_at_revision.rb +4 -3
  38. data/app/models/pageflow/entry_duplicate.rb +8 -1
  39. data/app/models/pageflow/entry_template.rb +4 -4
  40. data/app/models/pageflow/home_button.rb +7 -7
  41. data/app/models/pageflow/image_file_url_templates.rb +2 -2
  42. data/app/models/pageflow/permalink.rb +39 -0
  43. data/app/models/pageflow/permalink_directory.rb +10 -0
  44. data/app/models/pageflow/published_entry.rb +19 -2
  45. data/app/models/pageflow/revision.rb +1 -1
  46. data/app/models/pageflow/site.rb +59 -0
  47. data/app/models/pageflow/theme_customization.rb +1 -1
  48. data/app/models/pageflow/theme_customization_file.rb +6 -1
  49. data/app/policies/pageflow/account_policy.rb +2 -2
  50. data/app/policies/pageflow/entry_policy.rb +2 -2
  51. data/app/policies/pageflow/entry_template_policy.rb +1 -1
  52. data/app/policies/pageflow/{theming_policy.rb → site_policy.rb} +13 -11
  53. data/app/views/admin/accounts/_entry_template_details.html.arb +1 -1
  54. data/app/views/admin/accounts/_form.html.erb +4 -22
  55. data/app/views/admin/accounts/_site_defaults_inline_help.html.erb +5 -0
  56. data/app/views/admin/entries/_form.html.erb +11 -12
  57. data/app/views/admin/entries/_permalink_inputs.html.erb +6 -0
  58. data/app/views/admin/entries/_site_input.html.erb +15 -0
  59. data/app/views/admin/entries/{entry_type_name_input.html.erb → entry_site_and_type_name_input.html.erb} +3 -0
  60. data/app/views/admin/entries/permalink_inputs.html.erb +7 -0
  61. data/app/views/admin/entry_templates/_form.html.erb +5 -5
  62. data/app/views/admin/sites/_attributes_table.html.arb +9 -0
  63. data/app/views/admin/sites/_fields.html.erb +17 -0
  64. data/app/views/admin/sites/_form.html.erb +5 -0
  65. data/app/views/components/pageflow/admin/entries_tab.rb +1 -2
  66. data/app/views/components/pageflow/admin/entry_templates_tab.rb +10 -11
  67. data/app/views/components/pageflow/admin/features_tab.rb +1 -1
  68. data/app/views/components/pageflow/admin/sites_tab.rb +32 -0
  69. data/app/views/components/pageflow/admin/users_tab.rb +1 -2
  70. data/app/views/pageflow/editor/entries/seed.json.erb +1 -1
  71. data/app/views/pageflow/editor/file_import/start_import_job.json.jbuilder +10 -0
  72. data/app/views/pageflow/editor/sites/_site.json.jbuilder +1 -0
  73. data/app/views/pageflow/entries/{_theming.css.erb → _site.css.erb} +0 -0
  74. data/app/views/pageflow/entries/stylesheet.css.erb +1 -1
  75. data/app/views/pageflow/files/_file.json.jbuilder +1 -0
  76. data/app/views/pageflow/social_share/_entry_meta_tags.html.erb +1 -1
  77. data/app/views/pageflow/social_share/_page_meta_tags.html.erb +1 -1
  78. data/config/initializers/admin_resource_tabs.rb +29 -12
  79. data/config/initializers/mime_types.rb +1 -0
  80. data/config/locales/de.yml +19 -17
  81. data/config/locales/en.yml +19 -17
  82. data/config/routes.rb +8 -5
  83. data/db/migrate/20221024100724_create_pageflow_permalink_directories.rb +10 -0
  84. data/db/migrate/20221025074049_add_permalink_attributes_to_entries.rb +5 -0
  85. data/db/migrate/20221027065022_create_pageflow_permalinks.rb +12 -0
  86. data/db/migrate/20221215101134_rename_theming_to_site.rb +9 -0
  87. data/db/migrate/20221215120856_associate_entry_templates_with_sites.rb +34 -0
  88. data/db/migrate/20221219203023_add_name_to_sites.rb +5 -0
  89. data/db/migrate/20230103155934_associate_theme_customizations_with_sites.rb +27 -0
  90. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +176 -179
  91. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +49 -7
  92. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +5 -5
  93. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +1 -1
  94. data/entry_types/paged/config/initializers/features.rb +2 -0
  95. data/entry_types/paged/config/locales/{new/help.de.yml → de.yml} +74 -65
  96. data/entry_types/paged/config/locales/{new/help.en.yml → en.yml} +66 -56
  97. data/entry_types/scrolled/app/helpers/pageflow_scrolled/favicon_helper.rb +39 -13
  98. data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +55 -0
  99. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +6 -2
  100. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +2 -0
  101. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/_manifest.json.jbuilder +16 -0
  102. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +9 -3
  103. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +5 -5
  104. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +16 -10
  105. data/entry_types/scrolled/config/locales/de.yml +265 -76
  106. data/entry_types/scrolled/config/locales/en.yml +266 -77
  107. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +3 -3
  108. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +14 -0
  109. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +1 -1
  110. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +1 -1
  111. data/entry_types/scrolled/lib/pageflow_scrolled/web_app_manifest.rb +11 -0
  112. data/entry_types/scrolled/lib/pageflow_scrolled.rb +39 -1
  113. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +3 -2
  114. data/entry_types/scrolled/package/contentElements-editor.js +124 -38
  115. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  116. data/entry_types/scrolled/package/contentElements-frontend.js +321 -27
  117. data/entry_types/scrolled/package/editor.js +1345 -739
  118. data/entry_types/scrolled/package/frontend/EditableInlineText.module-14c7b097.js +5314 -0
  119. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-9fb97827.js → PhonePlatformContext-f6093cc6.js} +87 -223
  120. data/entry_types/scrolled/package/frontend/{Viewer-e2290ea0.js → Viewer-b6becc57.js} +6 -40
  121. data/entry_types/scrolled/package/frontend/arrowRight-78a7cee4.js +42 -0
  122. data/entry_types/scrolled/package/frontend/{components-6ab26015.js → components-b3160dd7.js} +546 -361
  123. data/entry_types/scrolled/package/frontend/index.css +1 -1
  124. data/entry_types/scrolled/package/frontend/index.js +398 -3692
  125. data/entry_types/scrolled/package/package.json +3 -2
  126. data/entry_types/scrolled/package/testHelpers.js +12 -2
  127. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  128. data/entry_types/scrolled/package/widgets/defaultNavigation.js +50 -40
  129. data/entry_types/scrolled/spec/fixtures/image.ico +0 -0
  130. data/lib/pageflow/ability_mixin.rb +16 -8
  131. data/lib/pageflow/admin/attributes_table_rows.rb +1 -1
  132. data/lib/pageflow/admin/form_inputs.rb +1 -1
  133. data/lib/pageflow/admin/tabs.rb +1 -1
  134. data/lib/pageflow/configuration/permissions.rb +3 -3
  135. data/lib/pageflow/configuration.rb +17 -17
  136. data/lib/pageflow/entry_export_import/entry_serialization.rb +1 -1
  137. data/lib/pageflow/entry_type.rb +6 -2
  138. data/lib/pageflow/primary_domain_entry_redirect.rb +7 -7
  139. data/lib/pageflow/seeds.rb +10 -10
  140. data/lib/pageflow/theme_customizations.rb +10 -10
  141. data/lib/pageflow/version.rb +1 -1
  142. data/package/editor.js +129 -156
  143. data/package/frontend.js +19 -2
  144. data/package/testHelpers.js +39 -6
  145. data/spec/factories/accounts.rb +5 -2
  146. data/spec/factories/draft_entries.rb +2 -2
  147. data/spec/factories/entries.rb +18 -1
  148. data/spec/factories/entry_templates.rb +1 -1
  149. data/spec/factories/permalink_directory.rb +6 -0
  150. data/spec/factories/permalinks.rb +4 -0
  151. data/spec/factories/published_entries.rb +4 -2
  152. data/spec/factories/sites.rb +9 -0
  153. metadata +50 -62
  154. data/app/assets/javascripts/pageflow/dist/editor.js +0 -11890
  155. data/app/assets/javascripts/pageflow/dist/frontend.js +0 -5800
  156. data/app/assets/javascripts/pageflow/dist/react-client.js +0 -22
  157. data/app/assets/javascripts/pageflow/dist/react-server.js +0 -19
  158. data/app/helpers/pageflow/themings_helper.rb +0 -11
  159. data/app/models/pageflow/theming.rb +0 -29
  160. data/app/views/admin/accounts/_theming_defaults_inline_help.html.erb +0 -5
  161. data/app/views/admin/accounts/_theming_details.html.arb +0 -5
  162. data/app/views/pageflow/editor/themings/_theming.json.jbuilder +0 -1
  163. data/entry_types/paged/config/locales/new/video_contain.de.yml +0 -7
  164. data/entry_types/paged/config/locales/new/video_contain.en.yml +0 -7
  165. data/entry_types/scrolled/config/locales/new/before_after_slider.de.yml +0 -8
  166. data/entry_types/scrolled/config/locales/new/before_after_slider.en.yml +0 -8
  167. data/entry_types/scrolled/config/locales/new/center_ragged.de.yml +0 -8
  168. data/entry_types/scrolled/config/locales/new/center_ragged.en.yml +0 -9
  169. data/entry_types/scrolled/config/locales/new/consent.de.yml +0 -25
  170. data/entry_types/scrolled/config/locales/new/consent.en.yml +0 -24
  171. data/entry_types/scrolled/config/locales/new/content_element_categories.de.yml +0 -39
  172. data/entry_types/scrolled/config/locales/new/content_element_categories.en.yml +0 -39
  173. data/entry_types/scrolled/config/locales/new/default_transition.de.yml +0 -14
  174. data/entry_types/scrolled/config/locales/new/default_transition.en.yml +0 -14
  175. data/entry_types/scrolled/config/locales/new/header_line_breaks.de.yml +0 -28
  176. data/entry_types/scrolled/config/locales/new/header_line_breaks.en.yml +0 -27
  177. data/entry_types/scrolled/config/locales/new/header_size.de.yml +0 -17
  178. data/entry_types/scrolled/config/locales/new/header_size.en.yml +0 -17
  179. data/entry_types/scrolled/config/locales/new/iframe_embed.de.yml +0 -39
  180. data/entry_types/scrolled/config/locales/new/iframe_embed.en.yml +0 -39
  181. data/entry_types/scrolled/config/locales/new/inline_loops.de.yml +0 -26
  182. data/entry_types/scrolled/config/locales/new/inline_loops.en.yml +0 -26
  183. data/entry_types/scrolled/config/locales/new/portrait_inline_image.de.yml +0 -9
  184. data/entry_types/scrolled/config/locales/new/portrait_inline_image.en.yml +0 -9
  185. data/entry_types/scrolled/config/locales/new/section_width.de.yml +0 -10
  186. data/entry_types/scrolled/config/locales/new/section_width.en.yml +0 -10
  187. data/entry_types/scrolled/config/locales/new/typography_variants.de.yml +0 -7
  188. data/entry_types/scrolled/config/locales/new/typography_variants.en.yml +0 -7
  189. data/entry_types/scrolled/config/locales/new/video_embed_poster.de.yml +0 -8
  190. data/entry_types/scrolled/config/locales/new/video_embed_poster.en.yml +0 -8
  191. data/entry_types/scrolled/config/locales/new/waveform_styles.de.yml +0 -11
  192. data/entry_types/scrolled/config/locales/new/waveform_styles.en.yml +0 -12
  193. data/entry_types/scrolled/config/locales/new/widgets.de.yml +0 -6
  194. data/entry_types/scrolled/config/locales/new/widgets.en.yml +0 -6
  195. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/browserconfig.xml +0 -9
  196. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/mstile-150x150.png +0 -0
  197. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/safari-pinned-tab.svg +0 -46
  198. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/site.webmanifest +0 -19
  199. data/entry_types/scrolled/package/frontend/EditableInlineText.module-b9923660.js +0 -993
  200. data/entry_types/scrolled/package/frontend/usePhonePlatform-2857c22b.js +0 -34
  201. data/spec/factories/themings.rb +0 -7
@@ -32,8 +32,8 @@ module Pageflow
32
32
 
33
33
  title = ["#{entry.title}:"]
34
34
  title << page.title
35
- title << '-' if entry.theming.cname_domain.present?
36
- title << entry.theming.cname_domain
35
+ title << '-' if entry.site.cname_domain.present?
36
+ title << entry.site.cname_domain
37
37
 
38
38
  title.join(' ')
39
39
  end
@@ -0,0 +1,47 @@
1
+ class PageflowPermalinkInput
2
+ include Formtastic::Inputs::Base
3
+ include Formtastic::Inputs::Base::Stringish
4
+
5
+ def to_html
6
+ input_wrapping do
7
+ label_html << permalink_html
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def permalink_html
14
+ template.content_tag(
15
+ :div,
16
+ base_url_html << permalink_inputs_html,
17
+ class: 'permalink'
18
+ )
19
+ end
20
+
21
+ def base_url_html
22
+ template.content_tag(
23
+ :div,
24
+ options[:base_url].gsub(%r{^https?://}, ''),
25
+ class: 'permalink_base_url'
26
+ )
27
+ end
28
+
29
+ def permalink_inputs_html
30
+ return '' if options[:directory_collection].empty?
31
+
32
+ builder.select(:directory_id, options[:directory_collection]) <<
33
+ builder.text_field(:slug, placeholder: options[:slug_placeholder])
34
+ end
35
+
36
+ def error_keys
37
+ [:directory, :slug]
38
+ end
39
+
40
+ def wrapper_html_options
41
+ if options[:directory_collection].empty?
42
+ super.merge(style: 'display: none')
43
+ else
44
+ super
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ module Pageflow
2
+ # @api private
3
+ module Permalinkable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ belongs_to :permalink, optional: true
8
+
9
+ accepts_nested_attributes_for :permalink, update_only: true
10
+ end
11
+ end
12
+ end
@@ -87,6 +87,11 @@ module Pageflow
87
87
  'unused'
88
88
  end
89
89
 
90
+ # Overwritten with the extension of the file.
91
+ def extension
92
+ 'unused'
93
+ end
94
+
90
95
  # Overwritten in UploadableFile with attachment filename.
91
96
  def file_name
92
97
  'unused'
@@ -80,6 +80,10 @@ module Pageflow
80
80
  File.basename(attachment.original_filename, '.*')
81
81
  end
82
82
 
83
+ def extension
84
+ File.extname(attachment.original_filename).sub(/\A\./, '')
85
+ end
86
+
83
87
  def can_upload?
84
88
  uploading?
85
89
  end
@@ -9,47 +9,21 @@ module Pageflow
9
9
  has_many :users, through: :memberships, source: :user, class_name: '::User'
10
10
  has_many :entry_memberships, through: :entries, source: :memberships
11
11
 
12
- has_many :themings, dependent: :destroy
13
- has_many :entry_templates, dependent: :destroy
14
- belongs_to :default_theming, :class_name => 'Theming'
12
+ has_many :sites, dependent: :destroy
13
+ belongs_to :default_site, :class_name => 'Site'
15
14
 
16
- validates :default_theming, :presence => true
17
- validates_associated :entry_templates
15
+ validates :default_site, :presence => true
18
16
 
19
- accepts_nested_attributes_for :default_theming, :update_only => true
17
+ accepts_nested_attributes_for :default_site, :update_only => true
20
18
 
21
19
  scope :with_landing_page, -> { where.not(:landing_page_name => '') }
22
20
 
23
- def build_default_theming(*args)
24
- super.tap do |theming|
25
- theming.account = self
21
+ def build_default_site(*args)
22
+ super.tap do |site|
23
+ site.account = self
26
24
  end
27
25
  end
28
26
 
29
- def first_paged_entry_template
30
- EntryTemplate.find_or_initialize_by(account: self, entry_type_name: 'paged')
31
- end
32
-
33
- def existing_and_potential_entry_templates
34
- entry_type_names = Pageflow.config_for(self).entry_types.map(&:name)
35
- existing_entry_templates = EntryTemplate.where(account_id: id).load
36
- allowed_existing_entry_templates =
37
- existing_entry_templates.select do |template|
38
- entry_type_names.include?(template.entry_type_name)
39
- end
40
- free_type_names =
41
- entry_type_names - allowed_existing_entry_templates.map(&:entry_type_name)
42
-
43
- potential_entry_templates = free_type_names.map do |type_name|
44
- EntryTemplate.new(
45
- account_id: id,
46
- entry_type_name: type_name
47
- )
48
- end
49
-
50
- allowed_existing_entry_templates + potential_entry_templates
51
- end
52
-
53
27
  def blacklist_for_serialization
54
28
  [:features_configuration]
55
29
  end
@@ -1,7 +1,7 @@
1
1
  module Pageflow
2
- class CnameThemingRequestScope
3
- def call(themings, request)
4
- themings.where(<<-SQL, host: request.host)
2
+ class CnameSiteRequestScope
3
+ def call(sites, request)
4
+ sites.where(<<-SQL, host: request.host)
5
5
  cname = :host OR
6
6
  FIND_IN_SET(
7
7
  :host,
@@ -14,7 +14,7 @@ module Pageflow
14
14
  entry: entry,
15
15
  theme: theme,
16
16
  theme_customization: Pageflow.theme_customizations.get(
17
- account: entry.account,
17
+ site: entry.site,
18
18
  entry_type_name: entry.type_name
19
19
  )
20
20
  )
@@ -26,11 +26,13 @@ module Pageflow
26
26
  new(theme,
27
27
  config.transform_theme_customization_overrides.call(
28
28
  theme_customization.overrides,
29
- entry
29
+ entry: entry,
30
+ theme: theme
30
31
  ),
31
32
  config.transform_theme_customization_files.call(
32
33
  theme_customization.selected_files.transform_values(&:urls),
33
- entry
34
+ entry: entry,
35
+ theme: theme
34
36
  ))
35
37
  end
36
38
  end
@@ -5,6 +5,7 @@ module Pageflow
5
5
 
6
6
  include FeatureTarget
7
7
  include EntryPublicationStates
8
+ include Permalinkable
8
9
  include SerializationBlacklist
9
10
 
10
11
  extend FriendlyId
@@ -12,7 +13,7 @@ module Pageflow
12
13
 
13
14
  belongs_to :account, counter_cache: true
14
15
  belongs_to :folder, optional: true
15
- belongs_to :theming
16
+ belongs_to :site
16
17
 
17
18
  has_many :revisions, -> { order('frozen_at DESC') }
18
19
 
@@ -35,7 +36,7 @@ module Pageflow
35
36
 
36
37
  has_secure_password validations: false
37
38
 
38
- validates :account, :theming, :presence => true
39
+ validates :account, :site, :presence => true
39
40
  validates :title, presence: true
40
41
  validate :entry_type_is_available_for_account
41
42
  validate :folder_belongs_to_same_account
@@ -56,8 +57,7 @@ module Pageflow
56
57
  end
57
58
 
58
59
  def entry_template
59
- @entry_template ||= EntryTemplate.find_or_initialize_by(
60
- account_id: account.id,
60
+ @entry_template ||= site.entry_templates.find_or_initialize_by(
61
61
  entry_type_name: type_name
62
62
  )
63
63
  end
@@ -126,6 +126,10 @@ module Pageflow
126
126
  [:title, [:title, :id]]
127
127
  end
128
128
 
129
+ def default_permalink_slug
130
+ title.to_s.parameterize
131
+ end
132
+
129
133
  def self.ransackable_attributes(_auth_object)
130
134
  %w[title type_name created_at edited_at first_published_at]
131
135
  end
@@ -15,7 +15,8 @@ module Pageflow
15
15
 
16
16
  delegate(:id, :slug,
17
17
  :entry_type,
18
- :account, :theming,
18
+ :account, :site,
19
+ :permalink,
19
20
  :feature_state, :enabled_feature_names,
20
21
  :edit_lock,
21
22
  :password_digest,
@@ -42,11 +43,11 @@ module Pageflow
42
43
  end
43
44
 
44
45
  def theme
45
- @theme ||= CustomizedTheme.find(entry: self, theme: revision.theme)
46
+ @theme ||= CustomizedTheme.find(entry: entry, theme: revision.theme)
46
47
  end
47
48
 
48
49
  def home_button
49
- HomeButton.new(revision, theming)
50
+ HomeButton.new(revision, site)
50
51
  end
51
52
 
52
53
  def overview_button
@@ -3,6 +3,7 @@ module Pageflow
3
3
  def create!
4
4
  create_entry
5
5
 
6
+ copy_permalink
6
7
  copy_draft
7
8
  copy_memberships
8
9
 
@@ -21,6 +22,12 @@ module Pageflow
21
22
  @new_entry = Entry.create!(new_attributes)
22
23
  end
23
24
 
25
+ def copy_permalink
26
+ return if original_entry.permalink.blank?
27
+
28
+ new_entry.create_permalink!(directory: original_entry.permalink.directory)
29
+ end
30
+
24
31
  def copy_draft
25
32
  original_entry.draft.copy do |revision|
26
33
  revision.entry = new_entry
@@ -38,7 +45,7 @@ module Pageflow
38
45
  type_name: original_entry.type_name,
39
46
  title: new_title,
40
47
  account: original_entry.account,
41
- theming: original_entry.theming,
48
+ site: original_entry.site,
42
49
  features_configuration: original_entry.features_configuration,
43
50
 
44
51
  skip_draft_creation: true
@@ -3,15 +3,15 @@ module Pageflow
3
3
  include ThemeReferencer
4
4
  include SerializedConfiguration
5
5
  serialize :default_share_providers, JSON
6
- belongs_to :account
7
- delegate :enabled_feature_names, to: :account
6
+ belongs_to :site
7
+ delegate :enabled_feature_names, to: :site
8
8
  has_many :widgets, as: :subject, dependent: :destroy
9
9
 
10
- validates :account, presence: true
10
+ validates :site, presence: true
11
11
  validates :entry_type_name, presence: true
12
12
  validates :entry_type_name,
13
13
  uniqueness: {
14
- scope: :account
14
+ scope: :site
15
15
  }
16
16
 
17
17
  def entry_type
@@ -1,14 +1,14 @@
1
1
  module Pageflow
2
2
  class HomeButton
3
- attr_reader :revision, :theming
3
+ attr_reader :revision, :site
4
4
 
5
- def initialize(revision, theming)
5
+ def initialize(revision, site)
6
6
  @revision = revision
7
- @theming = theming
7
+ @site = site
8
8
  end
9
9
 
10
10
  def url
11
- revision.configuration['home_url'].presence || theming_home_button_url
11
+ revision.configuration['home_url'].presence || site_home_button_url
12
12
  end
13
13
 
14
14
  def enabled?
@@ -27,9 +27,9 @@ module Pageflow
27
27
 
28
28
  private
29
29
 
30
- def theming_home_button_url
31
- if theming.home_url.present?
32
- options = Pageflow.config.theming_url_options(theming) || {}
30
+ def site_home_button_url
31
+ if site.home_url.present?
32
+ options = Pageflow.config.site_url_options(site) || {}
33
33
  Pageflow::Engine.routes.url_for(options.merge(controller: 'pageflow/entries',
34
34
  action: 'index',
35
35
  only_path: !options[:host]))
@@ -9,11 +9,11 @@ module Pageflow
9
9
  private
10
10
 
11
11
  def styles
12
- example_file.attachment_styles(example_file.attachment).keys
12
+ example_file.attachment_styles(example_file.attachment).keys + [:original]
13
13
  end
14
14
 
15
15
  def example_file
16
- @example_file ||= ImageFile.new(id: 0, file_name: ':basename.jpg')
16
+ @example_file ||= ImageFile.new(id: 0, file_name: ':basename.:extension')
17
17
  end
18
18
  end
19
19
  end
@@ -0,0 +1,39 @@
1
+ module Pageflow
2
+ # @api private
3
+ class Permalink < ApplicationRecord
4
+ extend FriendlyId
5
+ friendly_id :slug_candidates, use: :scoped, scope: :directory
6
+
7
+ before_validation :set_default_slug
8
+
9
+ has_one :entry
10
+
11
+ belongs_to :directory, class_name: 'PermalinkDirectory'
12
+
13
+ validates(:slug,
14
+ format: /\A[0-9a-zA-Z_-]+\z/,
15
+ uniqueness: {scope: :directory})
16
+
17
+ validate :belongs_to_same_site_as_entry
18
+
19
+ private
20
+
21
+ def set_default_slug
22
+ self.slug = entry.default_permalink_slug if slug == ''
23
+ end
24
+
25
+ def slug_candidates
26
+ [entry.title, "#{entry.title}-#{entry.id}"]
27
+ end
28
+
29
+ def should_generate_new_friendly_id?
30
+ slug.nil?
31
+ end
32
+
33
+ def belongs_to_same_site_as_entry
34
+ return if !directory || !entry || entry.site_id == directory.site_id
35
+
36
+ errors.add(:directory, :invalid)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ module Pageflow
2
+ # @api private
3
+ class PermalinkDirectory < ApplicationRecord
4
+ belongs_to :site
5
+
6
+ validates(:path,
7
+ format: %r{\A([0-9a-zA-Z-]+/)*\z},
8
+ uniqueness: {scope: :site_id})
9
+ end
10
+ end
@@ -46,12 +46,21 @@ module Pageflow
46
46
  PublishedEntry.new(scope.published.find(id))
47
47
  end
48
48
 
49
+ def self.find_by_permalink(directory: nil, slug:, scope:)
50
+ wrap(
51
+ scope.published.includes(permalink: :directory).where(
52
+ pageflow_permalink_directories: {path: directory || ''},
53
+ pageflow_permalinks: {slug: slug}
54
+ ).first
55
+ )
56
+ end
57
+
49
58
  def cache_key
50
59
  [
51
60
  self.class.model_name.cache_key,
52
61
  entry.cache_key,
53
62
  revision.cache_key,
54
- theming.cache_key
63
+ site.cache_key
55
64
  ].compact.join('-')
56
65
  end
57
66
 
@@ -59,7 +68,7 @@ module Pageflow
59
68
  [
60
69
  entry.cache_version,
61
70
  revision.cache_version,
62
- theming.cache_version
71
+ site.cache_version
63
72
  ].compact.join('-').presence
64
73
  end
65
74
 
@@ -72,5 +81,13 @@ module Pageflow
72
81
  def share_image_file
73
82
  PositionedFile.wrap(find_file_by_perma_id(ImageFile, share_image_id), share_image_x, share_image_y)
74
83
  end
84
+
85
+ class << self
86
+ private
87
+
88
+ def wrap(entry)
89
+ entry && new(entry)
90
+ end
91
+ end
75
92
  end
76
93
  end
@@ -230,7 +230,7 @@ module Pageflow
230
230
  end
231
231
 
232
232
  def available_themes
233
- Pageflow.config_for(entry).themes
233
+ @available_themes ||= Pageflow.config_for(entry).themes
234
234
  end
235
235
  end
236
236
  end
@@ -0,0 +1,59 @@
1
+ module Pageflow
2
+ class Site < ApplicationRecord
3
+ belongs_to :account
4
+
5
+ has_many :entry_templates, dependent: :destroy
6
+ has_many :entries
7
+ has_many :permalink_directories, -> { order('path ASC') }
8
+
9
+ scope :with_home_url, -> { where.not(home_url: '') }
10
+ scope :for_request, ->(request) { Pageflow.config.site_request_scope.call(all, request) }
11
+
12
+ validates :account, :presence => true
13
+
14
+ delegate :enabled_feature_names, to: :account
15
+
16
+ def display_name
17
+ name.presence || I18n.t('pageflow.admin.sites.default_name')
18
+ end
19
+
20
+ def name_with_account_prefix
21
+ [account.name, name].compact.join(' - ')
22
+ end
23
+
24
+ def host
25
+ Pageflow.config.site_url_options(self)&.dig(:host)
26
+ end
27
+
28
+ def cname_domain
29
+ cname.split('.').pop(2).join('.')
30
+ end
31
+
32
+ def first_paged_entry_template
33
+ entry_templates.find_or_initialize_by(entry_type_name: 'paged')
34
+ end
35
+
36
+ def existing_and_potential_entry_templates
37
+ entry_type_names = Pageflow.config_for(account).entry_types.map(&:name)
38
+
39
+ allowed_existing_entry_templates =
40
+ entry_templates.where(entry_type_name: entry_type_names)
41
+
42
+ free_type_names =
43
+ entry_type_names - allowed_existing_entry_templates.map(&:entry_type_name)
44
+
45
+ potential_entry_templates = free_type_names.map do |type_name|
46
+ entry_templates.build(entry_type_name: type_name)
47
+ end
48
+
49
+ allowed_existing_entry_templates + potential_entry_templates
50
+ end
51
+
52
+ # @deprecated Depending on what you need this for, consider
53
+ # scoping your code to an entry type or look at a specific entry's
54
+ # theme name.
55
+ def theme_name
56
+ first_paged_entry_template.theme_name
57
+ end
58
+ end
59
+ end
@@ -4,7 +4,7 @@ module Pageflow
4
4
  #
5
5
  # @since 15.7
6
6
  class ThemeCustomization < ApplicationRecord
7
- belongs_to :account
7
+ belongs_to :site
8
8
 
9
9
  serialize :overrides, JSON
10
10
  serialize :selected_file_ids, JSON
@@ -39,7 +39,7 @@ module Pageflow
39
39
  # A hash of urls based on the styles that were defined when
40
40
  # registering the entry type.
41
41
  def urls
42
- attachment_styles.map { |style, _|
42
+ styles_from_options.map { |style, _|
43
43
  [style, attachment.url(style)]
44
44
  }.to_h
45
45
  end
@@ -51,6 +51,11 @@ module Pageflow
51
51
 
52
52
  # @api private
53
53
  def attachment_styles
54
+ styles_from_options.except(:original)
55
+ end
56
+
57
+ # @api private
58
+ def styles_from_options
54
59
  styles = options_from_entry_type.fetch(:styles, {})
55
60
  styles.respond_to?(:call) ? styles.call(self) : styles
56
61
  end
@@ -29,7 +29,7 @@ module Pageflow
29
29
  entry_creatable
30
30
  end
31
31
 
32
- def themings_accessible
32
+ def sites_accessible
33
33
  entry_creatable
34
34
  end
35
35
 
@@ -62,7 +62,7 @@ module Pageflow
62
62
  publish?
63
63
  end
64
64
 
65
- def update_theming_on_entry_of?
65
+ def update_site_on_entry_of?
66
66
  publish?
67
67
  end
68
68
 
@@ -127,9 +127,9 @@ module Pageflow
127
127
  publish_on_account_of?
128
128
  end
129
129
 
130
- def update_theming_on?
130
+ def update_site_on?
131
131
  user.admin? ||
132
- (!permissions_config.only_admins_may_update_theming &&
132
+ (!permissions_config.only_admins_may_update_site &&
133
133
  publish_on_account_of?)
134
134
  end
135
135
 
@@ -16,7 +16,7 @@ module Pageflow
16
16
  private
17
17
 
18
18
  def allows?(roles)
19
- @user.memberships.where(role: roles, entity: @entry_template.account).any?
19
+ @user.memberships.where(role: roles, entity: @entry_template.site.account).any?
20
20
  end
21
21
  end
22
22
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- class ThemingPolicy < ApplicationPolicy
2
+ class SitePolicy < ApplicationPolicy
3
3
  class Scope < Scope
4
4
  attr_reader :user, :scope
5
5
 
@@ -8,7 +8,7 @@ module Pageflow
8
8
  @scope = scope
9
9
  end
10
10
 
11
- def themings_allowed_for(accounts)
11
+ def sites_allowed_for(accounts)
12
12
  if user.admin?
13
13
  scope.all
14
14
  else
@@ -23,7 +23,7 @@ module Pageflow
23
23
  def publisher_memberships_for_accounts(user, accounts_ids)
24
24
  sanitize_sql_array(['LEFT OUTER JOIN pageflow_memberships ON ' \
25
25
  'pageflow_memberships.user_id = :user_id AND ' \
26
- 'pageflow_themings.account_id IN (:accounts_ids) AND ' \
26
+ 'pageflow_sites.account_id IN (:accounts_ids) AND ' \
27
27
  'pageflow_memberships.entity_id IN (:accounts_ids) AND ' \
28
28
  'pageflow_memberships.entity_type = \'Pageflow::Account\' AND ' \
29
29
  'pageflow_memberships.role IN (\'publisher\', \'manager\')',
@@ -35,19 +35,21 @@ module Pageflow
35
35
  end
36
36
  end
37
37
 
38
- def initialize(user, theming)
38
+ attr_reader :user
39
+
40
+ def initialize(user, site)
39
41
  @user = user
40
- @theming = theming
42
+ @account_role_query = AccountRoleQuery.new(user, site.account)
41
43
  end
42
44
 
43
- def edit?
44
- allows?(%w(publisher manager))
45
+ def read?
46
+ @user.admin? ||
47
+ (@account_role_query.has_at_least_role?(:manager) &&
48
+ Pageflow.config.allow_multiaccount_users)
45
49
  end
46
50
 
47
- private
48
-
49
- def allows?(roles)
50
- @user.memberships.where(role: roles, entity: @theming.account).any?
51
+ def update?
52
+ read?
51
53
  end
52
54
  end
53
55
  end
@@ -1,7 +1,7 @@
1
1
  h5(entry_template.translated_entry_type_name)
2
2
 
3
3
  extensible_attributes_table_for(entry_template,
4
- Pageflow.config_for(entry_template.account)
4
+ Pageflow.config_for(entry_template.site.account)
5
5
  .admin_attributes_table_rows.for(:entry_template)) do
6
6
  row :theme, class: 'theme' do
7
7
  entry_template.theme_name