pageflow 12.0.4 → 12.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pageflow might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +158 -374
- data/README.md +24 -3
- data/Rakefile +2 -2
- data/admins/pageflow/accounts.rb +30 -4
- data/admins/pageflow/entry.rb +59 -9
- data/admins/pageflow/membership.rb +57 -6
- data/admins/pageflow/user.rb +25 -4
- data/app/assets/images/pageflow/themes/default/preview.png +0 -0
- data/app/assets/images/pageflow/themes/default/preview_thumbnail.png +0 -0
- data/app/assets/javascripts/pageflow/admin/entries.js +5 -3
- data/app/assets/javascripts/pageflow/admin/users.js +33 -0
- data/app/assets/javascripts/pageflow/admin.js +4 -1
- data/app/assets/javascripts/pageflow/audio_context.js +28 -0
- data/app/assets/javascripts/pageflow/audio_player/get_media_element_method.js +5 -0
- data/app/assets/javascripts/pageflow/audio_player.js +2 -0
- data/app/assets/javascripts/pageflow/base.js +4 -22
- data/app/assets/javascripts/pageflow/dist/react.js +323 -242
- data/app/assets/javascripts/pageflow/editor/api/widget_type.js +23 -0
- data/app/assets/javascripts/pageflow/editor/api/widget_types.js +53 -0
- data/app/assets/javascripts/pageflow/editor/api.js +9 -1
- data/app/assets/javascripts/pageflow/editor/base.js +0 -1
- data/app/assets/javascripts/pageflow/editor/collections/pages_collection.js +1 -0
- data/app/assets/javascripts/pageflow/editor/collections/subset_collection.js +21 -1
- data/app/assets/javascripts/pageflow/editor/collections/themes_collection.js +13 -0
- data/app/assets/javascripts/pageflow/editor/collections/widgets_collection.js +23 -8
- data/app/assets/javascripts/pageflow/editor/controllers/sidebar_controller.js +7 -1
- data/app/assets/javascripts/pageflow/editor/initializers/setup_collections.js +10 -3
- data/app/assets/javascripts/pageflow/editor/initializers/setup_widget_types.js +5 -1
- data/app/assets/javascripts/pageflow/editor/initializers/stylesheet_reloading.js +8 -3
- data/app/assets/javascripts/pageflow/editor/models/edit_lock_container.js +1 -1
- data/app/assets/javascripts/pageflow/editor/models/entry.js +7 -4
- data/app/assets/javascripts/pageflow/editor/models/entry_configuration.js +1 -1
- data/app/assets/javascripts/pageflow/editor/models/file_stage.js +1 -0
- data/app/assets/javascripts/pageflow/editor/models/page.js +3 -1
- data/app/assets/javascripts/pageflow/editor/models/preview_entry_data.js +2 -2
- data/app/assets/javascripts/pageflow/editor/models/theme.js +25 -0
- data/app/assets/javascripts/pageflow/editor/models/theming.js +1 -19
- data/app/assets/javascripts/pageflow/editor/models/widget.js +22 -1
- data/app/assets/javascripts/pageflow/editor/models/widget_configuration.js +5 -0
- data/app/assets/javascripts/pageflow/editor/routers/sidebar_router.js +1 -0
- data/app/assets/javascripts/pageflow/editor/templates/change_theme_dialog.jst.ejs +23 -0
- data/app/assets/javascripts/pageflow/editor/templates/edit_widget.jst.ejs +1 -2
- data/app/assets/javascripts/pageflow/editor/templates/inputs/reference.jst.ejs +2 -2
- data/app/assets/javascripts/pageflow/editor/templates/static_thumbnail.jst.ejs +1 -0
- data/app/assets/javascripts/pageflow/editor/templates/theme_item.jst.ejs +5 -0
- data/app/assets/javascripts/pageflow/editor/templates/widget_item.jst.ejs +3 -0
- data/app/assets/javascripts/pageflow/editor/utils/stylesheet.js +23 -0
- data/app/assets/javascripts/pageflow/editor/views/change_theme_dialog_view.js +76 -0
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/options.js +4 -2
- data/app/assets/javascripts/pageflow/editor/views/edit_meta_data_view.js +17 -4
- data/app/assets/javascripts/pageflow/editor/views/edit_widget_view.js +11 -21
- data/app/assets/javascripts/pageflow/editor/views/edit_widgets_view.js +1 -3
- data/app/assets/javascripts/pageflow/editor/views/file_meta_data_item_value_view.js +10 -1
- data/app/assets/javascripts/pageflow/editor/views/inputs/reference_input_view.js +36 -4
- data/app/assets/javascripts/pageflow/editor/views/inputs/theme_input_view.js +26 -0
- data/app/assets/javascripts/pageflow/editor/views/model_thumbnail_view.js +28 -14
- data/app/assets/javascripts/pageflow/editor/views/static_thumbnail_view.js +20 -0
- data/app/assets/javascripts/pageflow/editor/views/theme_item_view.js +41 -0
- data/app/assets/javascripts/pageflow/editor/views/widget_item_view.js +49 -0
- data/app/assets/javascripts/pageflow/history.js +7 -1
- data/app/assets/javascripts/pageflow/media_player/volume_fading/interval.js +65 -0
- data/app/assets/javascripts/pageflow/media_player/volume_fading/noop.js +5 -0
- data/app/assets/javascripts/pageflow/media_player/volume_fading/web_audio.js +109 -0
- data/app/assets/javascripts/pageflow/media_player/volume_fading.js +14 -65
- data/app/assets/javascripts/pageflow/slideshow/dom_order_scroll_navigator.js +5 -2
- data/app/assets/javascripts/pageflow/slideshow.js +19 -8
- data/app/assets/javascripts/pageflow/ui/views/configuration_editor_view.js +4 -0
- data/app/assets/javascripts/pageflow/ui/views/inputs/text_area_input_view.js +10 -5
- data/app/assets/javascripts/pageflow/ui/views/inputs/text_input_view.js +4 -48
- data/app/assets/javascripts/pageflow/ui/views/mixins/input_with_placeholder_text.js +58 -0
- data/app/assets/javascripts/pageflow/vendor.js +16 -0
- data/app/assets/javascripts/pageflow/video_player/get_media_element_method.js +6 -0
- data/app/assets/javascripts/pageflow/video_player.js +2 -0
- data/app/assets/stylesheets/pageflow/admin/entries.scss +1 -1
- data/app/assets/stylesheets/pageflow/admin/quotas.scss +1 -1
- data/app/assets/stylesheets/pageflow/admin.scss +2 -0
- data/app/assets/stylesheets/pageflow/base.scss +0 -1
- data/app/assets/stylesheets/pageflow/editor/base.scss +2 -0
- data/app/assets/stylesheets/pageflow/editor/change_theme.scss +114 -0
- data/app/assets/stylesheets/pageflow/editor/static_thumbnails.scss +4 -0
- data/app/assets/stylesheets/pageflow/editor/widgets.scss +26 -2
- data/app/assets/stylesheets/pageflow/page.scss +1 -14
- data/app/assets/stylesheets/pageflow/themes/default/indicators.scss +12 -0
- data/app/assets/stylesheets/pageflow/themes/default/loading_spinner.scss +11 -0
- data/app/assets/stylesheets/pageflow/themes/default/logo/alignment.scss +27 -0
- data/app/assets/stylesheets/pageflow/themes/default/logo/variant/background_image.scss +20 -2
- data/app/assets/stylesheets/pageflow/themes/default/logo/variant/watermark.scss +4 -1
- data/app/assets/stylesheets/pageflow/themes/default/page/line_lengths.scss +113 -0
- data/app/assets/stylesheets/pageflow/themes/default/page.scss +1 -0
- data/app/controllers/pageflow/editor/widgets_controller.rb +15 -1
- data/app/controllers/pageflow/entries_controller.rb +1 -1
- data/app/helpers/pageflow/admin/entries_helper.rb +0 -9
- data/app/helpers/pageflow/admin/memberships_helper.rb +43 -123
- data/app/helpers/pageflow/admin/users_helper.rb +15 -0
- data/app/helpers/pageflow/entries_helper.rb +3 -1
- data/app/helpers/pageflow/entry_json_seed_helper.rb +9 -3
- data/app/helpers/pageflow/public_i18n_helper.rb +2 -2
- data/app/helpers/pageflow/quota_helper.rb +2 -2
- data/app/helpers/pageflow/social_share_helper.rb +3 -2
- data/app/helpers/pageflow/themes_helper.rb +11 -3
- data/app/helpers/pageflow/widgets_helper.rb +10 -2
- data/app/jobs/pageflow/prune_auto_snapshots_job.rb +9 -0
- data/app/mailers/pageflow/user_mailer.rb +11 -1
- data/app/models/concerns/pageflow/feature_target.rb +1 -1
- data/app/models/concerns/pageflow/hosted_file.rb +9 -0
- data/app/models/concerns/pageflow/output_source.rb +2 -1
- data/app/models/concerns/pageflow/serialization_blacklist.rb +19 -0
- data/app/models/concerns/pageflow/serialized_configuration.rb +17 -0
- data/app/models/concerns/pageflow/theme_referencer.rb +23 -0
- data/app/models/pageflow/account.rb +6 -1
- data/app/models/pageflow/account_member_query.rb +6 -12
- data/app/models/pageflow/account_role_query.rb +68 -0
- data/app/models/pageflow/application_query.rb +13 -0
- data/app/models/pageflow/application_record.rb +5 -0
- data/app/models/pageflow/audio_file.rb +1 -1
- data/app/models/pageflow/auto_snapshot_pruning.rb +26 -0
- data/app/models/pageflow/chapter.rb +4 -8
- data/app/models/pageflow/draft_entry.rb +2 -1
- data/app/models/pageflow/edit_lock.rb +11 -5
- data/app/models/pageflow/encoding_confirmation.rb +2 -1
- data/app/models/pageflow/entry.rb +13 -2
- data/app/models/pageflow/entry_publication.rb +2 -0
- data/app/models/pageflow/entry_role_query.rb +24 -9
- data/app/models/pageflow/entry_title_or_account_name_query.rb +33 -0
- data/app/models/pageflow/file_usage.rb +3 -7
- data/app/models/pageflow/folder.rb +1 -1
- data/app/models/pageflow/home_button.rb +1 -1
- data/app/models/pageflow/image_file.rb +22 -4
- data/app/models/pageflow/invitation_form.rb +10 -4
- data/app/models/pageflow/managed_user_query.rb +44 -0
- data/app/models/pageflow/membership.rb +1 -1
- data/app/models/pageflow/overview_button.rb +3 -4
- data/app/models/pageflow/page.rb +3 -7
- data/app/models/pageflow/potential_memberships.rb +112 -0
- data/app/models/pageflow/published_entry.rb +2 -1
- data/app/models/pageflow/revision.rb +13 -4
- data/app/models/pageflow/storyline.rb +3 -4
- data/app/models/pageflow/text_track_file.rb +1 -1
- data/app/models/pageflow/theming.rb +15 -10
- data/app/models/pageflow/url_template.rb +8 -2
- data/app/models/pageflow/user_name_query.rb +30 -0
- data/app/models/pageflow/video_file.rb +5 -1
- data/app/models/pageflow/widget.rb +3 -1
- data/app/models/pageflow/zencoder_attachment.rb +16 -5
- data/app/policies/pageflow/account_policy.rb +31 -61
- data/app/policies/pageflow/application_policy.rb +6 -0
- data/app/policies/pageflow/entry_policy.rb +11 -3
- data/app/policies/pageflow/membership_policy.rb +1 -2
- data/app/policies/pageflow/user_policy.rb +20 -1
- data/app/views/admin/accounts/_form.html.erb +4 -4
- data/app/views/admin/accounts/_theming_defaults_inline_help.html.erb +5 -0
- data/app/views/admin/memberships/_form.html.erb +9 -14
- data/app/views/admin/memberships/_role_hint.html.arb +1 -1
- data/app/views/admin/users/invitation.html.erb +18 -9
- data/app/views/admin/users/me.html.erb +2 -2
- data/app/views/admin/users/quota_state.html.erb +1 -0
- data/app/views/components/pageflow/admin/add_membership_button.rb +81 -0
- data/app/views/components/pageflow/admin/members_tab.rb +6 -4
- data/app/views/components/pageflow/admin/revisions_tab.rb +16 -4
- data/app/views/components/pageflow/admin/user_accounts_tab.rb +8 -2
- data/app/views/components/pageflow/admin/user_entries_tab.rb +6 -2
- data/app/views/components/pageflow/admin/users_tab.rb +9 -5
- data/app/views/layouts/pageflow/application.html.erb +2 -1
- data/app/views/pageflow/admin/users/_quota_exhausted.html.erb +1 -0
- data/app/views/pageflow/admin/users/_quota_state.html.erb +7 -0
- data/app/views/pageflow/config/_editor_seeds.json.jbuilder +2 -0
- data/app/views/pageflow/editor/entries/_entry.json.jbuilder +1 -0
- data/app/views/pageflow/editor/entries/seed.json.erb +3 -1
- data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +1 -1
- data/app/views/pageflow/editor/themings/_theming.json.jbuilder +0 -7
- data/app/views/pageflow/editor/widgets/_widget.json.jbuilder +1 -1
- data/app/views/pageflow/entries/_entry.html.erb +5 -5
- data/app/views/pageflow/entries/edit.html.erb +1 -1
- data/app/views/pageflow/entries/show.html.erb +1 -1
- data/app/views/pageflow/entry_json_seed/_entry.json.jbuilder +1 -0
- data/app/views/pageflow/themes/_theme.json.jbuilder +13 -0
- data/config/initializers/admin_resource_tabs.rb +19 -6
- data/config/initializers/features.rb +1 -0
- data/config/locales/de.yml +26 -3
- data/config/locales/en.yml +26 -3
- data/db/migrate/20170201074328_add_configuration_to_widgets.rb +5 -0
- data/db/migrate/20170222124848_update_video_file_output_presences.rb +1 -1
- data/db/migrate/20170315130000_add_theme_name_to_revisions.rb +12 -0
- data/db/migrate/20170912165050_reset_copied_snapshot_type.rb +24 -0
- data/lib/generators/pageflow/routes/routes_generator.rb +11 -1
- data/lib/generators/pageflow/seeds/seeds_generator.rb +5 -0
- data/lib/generators/pageflow/seeds/templates/seeds.rb +5 -3
- data/lib/generators/pageflow/theme/templates/preview.png +0 -0
- data/lib/generators/pageflow/theme/templates/preview_thumbnail.png +0 -0
- data/lib/generators/pageflow/theme/theme_generator.rb +3 -0
- data/lib/pageflow/ability_mixin.rb +27 -6
- data/lib/pageflow/active_admin_can_can_fix.rb +34 -0
- data/lib/pageflow/configuration/permissions.rb +27 -0
- data/lib/pageflow/configuration.rb +28 -0
- data/lib/pageflow/engine.rb +25 -19
- data/lib/pageflow/images/palette.png +0 -0
- data/lib/pageflow/seeds.rb +1 -1
- data/lib/pageflow/theme.rb +8 -0
- data/lib/pageflow/version.rb +1 -1
- data/lib/pageflow/widget_type.rb +13 -0
- data/lib/pageflow/zencoder_video_output_definition.rb +16 -16
- data/lib/tasks/pageflow_tasks.rake +14 -0
- data/spec/factories/entries.rb +4 -0
- data/spec/factories/revisions.rb +10 -0
- data/spec/factories/users.rb +6 -0
- data/spec/factories/video_files.rb +4 -0
- data/vendor/assets/javascripts/audio5.min.js +3 -0
- metadata +78 -15
- data/app/assets/javascripts/pageflow/editor/models/mixins/widget_subject.js +0 -37
- data/app/assets/javascripts/pageflow/editor/utils/reload_stylesheet.js +0 -9
- data/app/assets/stylesheets/pageflow/text_variants.scss +0 -24
- data/app/views/admin/accounts/_widgets_inline_help.html.erb +0 -5
- data/app/views/admin/memberships/_entity_account_input.html.erb +0 -5
- data/app/views/admin/memberships/_entity_entry_input.html.erb +0 -5
- data/app/views/admin/users/_quota_exhausted.html.erb +0 -1
- data/app/views/components/pageflow/admin/add_membership_button_if_needed.rb +0 -62
@@ -3,7 +3,17 @@ module Pageflow
|
|
3
3
|
include Resque::Mailer
|
4
4
|
|
5
5
|
def invitation(options)
|
6
|
-
|
6
|
+
# Different versions of resque_mailer either pass:
|
7
|
+
#
|
8
|
+
# - Hash with string keys (<= 2.4.0)
|
9
|
+
# - Hash with symbol keys (2.4.1)
|
10
|
+
# - Hash with both string and symbol keys (2.4.2)
|
11
|
+
# - HashWithIndifferentAccess (2.4.3)
|
12
|
+
#
|
13
|
+
# Symbolize keys to support 2.4.1, but do not use bang version
|
14
|
+
# (i.e. `smbolize_keys!`) since that is not supported by
|
15
|
+
# HashWithIndifferentAccess.
|
16
|
+
options = options.symbolize_keys
|
7
17
|
|
8
18
|
@user = User.find(options[:user_id])
|
9
19
|
@password_token = options[:password_token]
|
@@ -71,6 +71,15 @@ module Pageflow
|
|
71
71
|
url
|
72
72
|
end
|
73
73
|
|
74
|
+
def cache_key
|
75
|
+
# Ensure the cache key changes when the state changes. There are
|
76
|
+
# cases during processing where the state is updated multiple
|
77
|
+
# times in a single second. Since `cache_key` relies on
|
78
|
+
# `updated_at`, which only is acurate to the second, we need to
|
79
|
+
# prevent caching outdated information.
|
80
|
+
"#{super}-#{state}"
|
81
|
+
end
|
82
|
+
|
74
83
|
# @deprecated Write a migration instead
|
75
84
|
def self.columns(t)
|
76
85
|
t.belongs_to(:entry, index: true)
|
@@ -40,7 +40,8 @@ module Pageflow
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def output_presences
|
43
|
-
|
43
|
+
output_presences = self[:output_presences] || {}
|
44
|
+
output_presences.merge(externally_generated_output_presences)
|
44
45
|
end
|
45
46
|
|
46
47
|
def externally_generated_outputs
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Pageflow
|
2
|
+
# @api private
|
3
|
+
module SerializationBlacklist
|
4
|
+
def serializable_hash(options = nil)
|
5
|
+
options ||= {}
|
6
|
+
|
7
|
+
options[:except] = Array(options[:except])
|
8
|
+
options[:except].concat(blacklist_for_serialization)
|
9
|
+
|
10
|
+
super(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def blacklist_for_serialization
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Pageflow
|
2
|
+
# Add a +configuration+ attribute.
|
3
|
+
# This is a hash serialized as JSON.
|
4
|
+
# It contains everything related to the object, which includes its text
|
5
|
+
# content such as title and body.
|
6
|
+
module SerializedConfiguration
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
serialize :configuration, JSON
|
11
|
+
end
|
12
|
+
|
13
|
+
def configuration
|
14
|
+
self[:configuration] || {}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pageflow
|
2
|
+
module ThemeReferencer
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
validates_inclusion_of(:theme_name, in: :available_theme_names)
|
7
|
+
end
|
8
|
+
|
9
|
+
def theme
|
10
|
+
available_themes.get(theme_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def available_theme_names
|
16
|
+
available_themes.names
|
17
|
+
end
|
18
|
+
|
19
|
+
def available_themes
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class Account <
|
2
|
+
class Account < ApplicationRecord
|
3
3
|
include FeatureTarget
|
4
|
+
include SerializationBlacklist
|
4
5
|
|
5
6
|
has_many :entries, dependent: :restrict_with_exception
|
6
7
|
has_many :folders, dependent: :destroy
|
@@ -22,5 +23,9 @@ module Pageflow
|
|
22
23
|
theming.account = self
|
23
24
|
end
|
24
25
|
end
|
26
|
+
|
27
|
+
def blacklist_for_serialization
|
28
|
+
[:features_configuration]
|
29
|
+
end
|
25
30
|
end
|
26
31
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module Pageflow
|
2
|
-
|
3
|
-
|
2
|
+
# Query accounts for members, e.g. based on role
|
3
|
+
class AccountMemberQuery < ApplicationQuery
|
4
|
+
class Scope < ApplicationQuery::Scope
|
4
5
|
# Account whose members we scope
|
5
|
-
# @return
|
6
|
+
# @return [Pageflow::Account]
|
6
7
|
attr_reader :account
|
7
8
|
|
8
9
|
# Base scope which is further scoped according to account role
|
@@ -12,7 +13,7 @@ module Pageflow
|
|
12
13
|
# Create scope that can limit base scope to account members at
|
13
14
|
# or above a given role
|
14
15
|
#
|
15
|
-
# @param
|
16
|
+
# @param [Pageflow::Account] account
|
16
17
|
# Required. Membership account to check.
|
17
18
|
# @param [ActiveRecord::Relation<User>] scope
|
18
19
|
# Optional. Membership entity to check.
|
@@ -24,7 +25,7 @@ module Pageflow
|
|
24
25
|
# Scope to those members from scope on account who have at least
|
25
26
|
# role
|
26
27
|
#
|
27
|
-
# @param
|
28
|
+
# @param [String] role
|
28
29
|
# Required. Minimum role that we compare against.
|
29
30
|
# @return [ActiveRecord::Relation<User>]
|
30
31
|
def with_role_at_least(role)
|
@@ -34,7 +35,6 @@ module Pageflow
|
|
34
35
|
|
35
36
|
private
|
36
37
|
|
37
|
-
# @api private
|
38
38
|
def memberships_for_account_with_at_least_role(role)
|
39
39
|
options = {roles: Roles.at_least(role), account_id: account.id}
|
40
40
|
|
@@ -48,15 +48,9 @@ module Pageflow
|
|
48
48
|
SQL
|
49
49
|
end
|
50
50
|
|
51
|
-
# @api private
|
52
51
|
def membership_is_present
|
53
52
|
'pageflow_account_memberships.entity_id IS NOT NULL'
|
54
53
|
end
|
55
|
-
|
56
|
-
# @api private
|
57
|
-
def sanitize_sql(sql, interpolations)
|
58
|
-
ActiveRecord::Base.send(:sanitize_sql_array, [sql, interpolations])
|
59
|
-
end
|
60
54
|
end
|
61
55
|
end
|
62
56
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Pageflow
|
2
|
+
# Query users for their role on accounts based on role
|
3
|
+
class AccountRoleQuery < ApplicationQuery
|
4
|
+
# Query for accounts where a user has a given role.
|
5
|
+
class Scope < Scope
|
6
|
+
# Create query scope.
|
7
|
+
#
|
8
|
+
# @param [User] user
|
9
|
+
# User to query roles for.
|
10
|
+
# @param [ActiveRecord::Relation] scope
|
11
|
+
# Scope of all accounts to filter from.
|
12
|
+
def initialize(user, scope)
|
13
|
+
@user = user
|
14
|
+
@scope = scope
|
15
|
+
end
|
16
|
+
|
17
|
+
# Find all accounts where user has at least given role.
|
18
|
+
#
|
19
|
+
# @param [String] role
|
20
|
+
# Name of role.
|
21
|
+
# @return [ActiveRecord::Relation]
|
22
|
+
def with_role_at_least(role)
|
23
|
+
scope.joins(with_membership_for_account(role))
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :user, :scope
|
29
|
+
|
30
|
+
def with_membership_for_account(role)
|
31
|
+
sanitize_sql(<<-SQL, user_id: user.id, roles: Roles.at_least(role))
|
32
|
+
INNER JOIN pageflow_memberships ON
|
33
|
+
pageflow_memberships.user_id = :user_id AND
|
34
|
+
pageflow_memberships.entity_id = pageflow_accounts.id AND
|
35
|
+
pageflow_memberships.entity_type = "Pageflow::Account" AND
|
36
|
+
pageflow_memberships.role IN (:roles)
|
37
|
+
SQL
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create query that can be used for role comparisons
|
42
|
+
#
|
43
|
+
# @param [User] user
|
44
|
+
# Required. Membership user to check.
|
45
|
+
# @param [Pageflow::Account] account
|
46
|
+
# Required. Membership entity to check.
|
47
|
+
def initialize(user, account)
|
48
|
+
@user = user
|
49
|
+
@account = account
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return true if there is a membership with at least role for
|
53
|
+
# user/account
|
54
|
+
#
|
55
|
+
# @param [String] role
|
56
|
+
# Required. Minimum role that we compare against.
|
57
|
+
# @return [Boolean]
|
58
|
+
def has_at_least_role?(role)
|
59
|
+
@user
|
60
|
+
.memberships
|
61
|
+
.where(role: Roles.at_least(role))
|
62
|
+
.where('(entity_id = :account_id AND '\
|
63
|
+
"entity_type = 'Pageflow::Account')",
|
64
|
+
account_id: @account.id)
|
65
|
+
.any?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Pageflow
|
2
|
+
# Abstraction layer for Pageflow's query interface
|
3
|
+
class ApplicationQuery
|
4
|
+
class Scope
|
5
|
+
protected
|
6
|
+
|
7
|
+
# @api private
|
8
|
+
def sanitize_sql(sql, interpolations)
|
9
|
+
ActiveRecord::Base.send(:sanitize_sql_array, [sql, interpolations])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Pageflow
|
2
|
+
# @api private
|
3
|
+
module AutoSnapshotPruning
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def dirty_entry_ids(options)
|
7
|
+
Revision
|
8
|
+
.auto_snapshots
|
9
|
+
.where('created_at < ?', options.fetch(:created_before))
|
10
|
+
.select('COUNT(*) as revisions_count, entry_id')
|
11
|
+
.group('entry_id')
|
12
|
+
.having('revisions_count > ?', options.fetch(:keep_count))
|
13
|
+
.map(&:entry_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def prune(entry, options)
|
17
|
+
entry
|
18
|
+
.revisions
|
19
|
+
.auto_snapshots
|
20
|
+
.where('created_at < ?', options[:created_before])
|
21
|
+
.order('created_at DESC')
|
22
|
+
.offset(options[:keep_count])
|
23
|
+
.each(&:destroy)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,16 +1,12 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class Chapter <
|
2
|
+
class Chapter < ApplicationRecord
|
3
|
+
include SerializedConfiguration
|
4
|
+
|
3
5
|
belongs_to :storyline, touch: true
|
4
|
-
has_many :pages, -> { order('position ASC') }
|
6
|
+
has_many :pages, -> { order('position ASC') }, dependent: :destroy
|
5
7
|
|
6
8
|
delegate :entry, to: :storyline
|
7
9
|
|
8
|
-
serialize :configuration, JSON
|
9
|
-
|
10
|
-
def configuration
|
11
|
-
super || {}
|
12
|
-
end
|
13
|
-
|
14
10
|
def copy_to(storyline)
|
15
11
|
chapter = dup
|
16
12
|
storyline.chapters << chapter
|
@@ -22,6 +22,7 @@ module Pageflow
|
|
22
22
|
:image_files, :video_files, :audio_files,
|
23
23
|
:locale,
|
24
24
|
:author, :publisher, :keywords,
|
25
|
+
:theme,
|
25
26
|
:to => :draft)
|
26
27
|
|
27
28
|
def initialize(entry, draft = nil)
|
@@ -99,7 +100,7 @@ module Pageflow
|
|
99
100
|
end
|
100
101
|
|
101
102
|
def overview_button
|
102
|
-
OverviewButton.new(draft
|
103
|
+
OverviewButton.new(draft)
|
103
104
|
end
|
104
105
|
|
105
106
|
def resolve_widgets(options = {})
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class EditLock <
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
class EditLock < ApplicationRecord
|
3
|
+
scope :active, (lambda do
|
4
|
+
time = Time.now - EditLock.time_to_live
|
5
|
+
where('pageflow_edit_locks.updated_at >= ?', time)
|
6
|
+
end)
|
6
7
|
|
7
8
|
class Error < RuntimeError
|
8
9
|
def code
|
@@ -24,6 +25,11 @@ module Pageflow
|
|
24
25
|
belongs_to :user
|
25
26
|
belongs_to :entry, :inverse_of => :edit_lock
|
26
27
|
|
28
|
+
def self.time_to_live
|
29
|
+
timer_tolerance = 2.3
|
30
|
+
Pageflow.config.edit_lock_polling_interval * timer_tolerance
|
31
|
+
end
|
32
|
+
|
27
33
|
def held_by?(user)
|
28
34
|
self.user == user
|
29
35
|
end
|
@@ -33,7 +39,7 @@ module Pageflow
|
|
33
39
|
end
|
34
40
|
|
35
41
|
def timed_out?
|
36
|
-
Time.now >
|
42
|
+
Time.now > updated_at + EditLock.time_to_live
|
37
43
|
end
|
38
44
|
|
39
45
|
def acquire(current_user, options = {})
|
@@ -3,13 +3,14 @@ module Pageflow
|
|
3
3
|
class QuotaExceededError < RuntimeError
|
4
4
|
end
|
5
5
|
|
6
|
-
attr_reader :entry, :attributes, :encoding_quota, :user
|
6
|
+
attr_reader :entry, :attributes, :encoding_quota, :user, :account
|
7
7
|
|
8
8
|
def initialize(entry, attributes, encoding_quota, user)
|
9
9
|
@entry = entry
|
10
10
|
@attributes = attributes
|
11
11
|
@encoding_quota = encoding_quota
|
12
12
|
@user = user
|
13
|
+
@account = entry.account
|
13
14
|
end
|
14
15
|
|
15
16
|
def exceeding?
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class Entry <
|
2
|
+
class Entry < ApplicationRecord
|
3
3
|
class PasswordMissingError < StandardError
|
4
4
|
end
|
5
5
|
|
6
6
|
include FeatureTarget
|
7
7
|
include EntryPublicationStates
|
8
|
+
include SerializationBlacklist
|
8
9
|
|
9
10
|
extend FriendlyId
|
10
11
|
friendly_id :slug_candidates, :use => [:finders, :slugged]
|
@@ -38,10 +39,15 @@ module Pageflow
|
|
38
39
|
|
39
40
|
scope :editing, -> { joins(:edit_lock).merge(Pageflow::EditLock.active) }
|
40
41
|
|
42
|
+
scope(:include_account_name,
|
43
|
+
lambda do
|
44
|
+
joins(:account).select('pageflow_entries.*, pageflow_accounts.name AS account_name')
|
45
|
+
end)
|
46
|
+
|
41
47
|
attr_accessor :skip_draft_creation
|
42
48
|
|
43
49
|
after_create unless: :skip_draft_creation do
|
44
|
-
create_draft!
|
50
|
+
create_draft!
|
45
51
|
draft.storylines.create!(configuration: {main: true})
|
46
52
|
theming.copy_defaults_to(draft)
|
47
53
|
end
|
@@ -87,6 +93,7 @@ module Pageflow
|
|
87
93
|
restored_revision.copy do |revision|
|
88
94
|
revision.restored_from = restored_revision
|
89
95
|
revision.frozen_at = nil
|
96
|
+
revision.snapshot_type = nil
|
90
97
|
revision.published_at = nil
|
91
98
|
revision.published_until = nil
|
92
99
|
revision.password_protected = nil
|
@@ -109,6 +116,10 @@ module Pageflow
|
|
109
116
|
[:with_publication_state, :published]
|
110
117
|
end
|
111
118
|
|
119
|
+
def blacklist_for_serialization
|
120
|
+
[:password_digest, :features_configuration]
|
121
|
+
end
|
122
|
+
|
112
123
|
private
|
113
124
|
|
114
125
|
def folder_belongs_to_same_account
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class EntryRoleQuery
|
3
|
-
class Scope
|
2
|
+
class EntryRoleQuery < ApplicationQuery
|
3
|
+
class Scope < Scope
|
4
4
|
attr_reader :user, :scope
|
5
5
|
|
6
|
-
def initialize(user, scope)
|
6
|
+
def initialize(user, scope, table_alias_prefix: nil)
|
7
7
|
@user = user
|
8
8
|
@scope = scope
|
9
|
+
@table_alias_prefix = table_alias_prefix
|
9
10
|
end
|
10
11
|
|
11
12
|
def with_role_at_least(role)
|
@@ -15,10 +16,16 @@ module Pageflow
|
|
15
16
|
.where(either_membership_is_present)
|
16
17
|
end
|
17
18
|
|
19
|
+
def with_account_role_at_least(role)
|
20
|
+
scope
|
21
|
+
.joins(memberships_for_account_of_entries_with_at_least_role(role))
|
22
|
+
.where(entry_account_membership_is_present)
|
23
|
+
end
|
24
|
+
|
18
25
|
private
|
19
26
|
|
20
27
|
def memberships_for_entries_with_at_least_role(role)
|
21
|
-
join_memberships(table_alias: '
|
28
|
+
join_memberships(table_alias: table_alias_for('entry'),
|
22
29
|
user_id: user.id,
|
23
30
|
roles: Roles.at_least(role),
|
24
31
|
entity_id_column: 'pageflow_entries.id',
|
@@ -26,7 +33,7 @@ module Pageflow
|
|
26
33
|
end
|
27
34
|
|
28
35
|
def memberships_for_account_of_entries_with_at_least_role(role)
|
29
|
-
join_memberships(table_alias: '
|
36
|
+
join_memberships(table_alias: table_alias_for('entry_account'),
|
30
37
|
user_id: user.id,
|
31
38
|
roles: Roles.at_least(role),
|
32
39
|
entity_id_column: 'pageflow_entries.account_id',
|
@@ -47,12 +54,20 @@ module Pageflow
|
|
47
54
|
end
|
48
55
|
|
49
56
|
def either_membership_is_present
|
50
|
-
|
51
|
-
|
57
|
+
[entry_membership_is_present,
|
58
|
+
entry_account_membership_is_present].join(' OR ')
|
59
|
+
end
|
60
|
+
|
61
|
+
def entry_membership_is_present
|
62
|
+
"#{table_alias_for(:entry)}.entity_id IS NOT NULL"
|
63
|
+
end
|
64
|
+
|
65
|
+
def entry_account_membership_is_present
|
66
|
+
"#{table_alias_for(:entry_account)}.entity_id IS NOT NULL"
|
52
67
|
end
|
53
68
|
|
54
|
-
def
|
55
|
-
|
69
|
+
def table_alias_for(type)
|
70
|
+
[@table_alias_prefix, 'pageflow', type, 'memberships'].compact.join('_')
|
56
71
|
end
|
57
72
|
end
|
58
73
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Pageflow
|
2
|
+
# @api private
|
3
|
+
class EntryTitleOrAccountNameQuery < ApplicationQuery
|
4
|
+
class Scope < Scope
|
5
|
+
def initialize(term, scope)
|
6
|
+
@term = term
|
7
|
+
@scope = scope
|
8
|
+
end
|
9
|
+
|
10
|
+
def resolve
|
11
|
+
scope
|
12
|
+
.joins(:account)
|
13
|
+
.references(:pageflow_accounts)
|
14
|
+
.where(word_conditions(term))
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :term, :scope
|
20
|
+
|
21
|
+
def word_conditions(term)
|
22
|
+
term.split(' ').map { |word|
|
23
|
+
word_condition(word)
|
24
|
+
}.join(' AND ')
|
25
|
+
end
|
26
|
+
|
27
|
+
def word_condition(word)
|
28
|
+
sanitize_sql('(pageflow_entries.title LIKE :word OR pageflow_accounts.name LIKE :word)',
|
29
|
+
word: "%#{word}%")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,14 +1,10 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class FileUsage <
|
2
|
+
class FileUsage < ApplicationRecord
|
3
|
+
include SerializedConfiguration
|
4
|
+
|
3
5
|
belongs_to :revision
|
4
6
|
belongs_to :file, polymorphic: true
|
5
7
|
|
6
|
-
serialize :configuration, JSON
|
7
|
-
|
8
|
-
def configuration
|
9
|
-
super || {}
|
10
|
-
end
|
11
|
-
|
12
8
|
def copy_to(revision)
|
13
9
|
revision.file_usages << dup
|
14
10
|
end
|
@@ -1,27 +1,38 @@
|
|
1
1
|
module Pageflow
|
2
|
-
class ImageFile <
|
2
|
+
class ImageFile < ApplicationRecord
|
3
3
|
include ImageFileStateMachine
|
4
4
|
include UploadedFile
|
5
5
|
|
6
6
|
STYLES = lambda do |attachment|
|
7
7
|
panorama_format = File.extname(attachment.original_filename) == '.png' ? :PNG : :JPG
|
8
8
|
|
9
|
-
Pageflow
|
9
|
+
Pageflow
|
10
|
+
.config.thumbnail_styles
|
10
11
|
.merge(print: ['300x300>', :JPG],
|
11
12
|
medium: ['1024x1024>', :JPG],
|
12
13
|
large: ['1920x1920>', :JPG],
|
13
14
|
ultra: ['3840x3840>', :JPG],
|
14
15
|
panorama_medium: ['1024x1024^', panorama_format],
|
15
|
-
panorama_large: ['1920x1080^', panorama_format]
|
16
|
+
panorama_large: ['1920x1080^', panorama_format],
|
17
|
+
panorama_mask: ['1920x1080^', panorama_format])
|
16
18
|
end
|
17
19
|
|
20
|
+
SOURCE_FILE_OPTIONS = {
|
21
|
+
# Prevent anti aliasing. Otherwise, when processing color map
|
22
|
+
# images, borders between areas are blurred.
|
23
|
+
panorama_mask: '-filter point'
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
palette_path = File.expand_path('../../../../lib/pageflow/images/palette.png', __FILE__)
|
27
|
+
|
18
28
|
CONVERT_OPTIONS = {
|
19
29
|
print: '-quality 10 -interlace Plane',
|
20
30
|
medium: '-quality 70 -interlace Plane',
|
21
31
|
large: '-quality 70 -interlace Plane',
|
22
32
|
ultra: '-quality 90 -interlace Plane',
|
23
33
|
panorama_medium: '-quality 70 -interlace Plane',
|
24
|
-
panorama_large: '-quality 70 -interlace Plane'
|
34
|
+
panorama_large: '-quality 70 -interlace Plane',
|
35
|
+
panorama_mask: "-quality 70 -interlace Plane -dither None -colors 64 -remap #{palette_path}"
|
25
36
|
}.freeze
|
26
37
|
|
27
38
|
has_attached_file(:unprocessed_attachment,
|
@@ -31,6 +42,7 @@ module Pageflow
|
|
31
42
|
Pageflow.config.paperclip_s3_default_options
|
32
43
|
.merge(default_url: ':pageflow_placeholder',
|
33
44
|
styles: STYLES,
|
45
|
+
source_file_options: SOURCE_FILE_OPTIONS,
|
34
46
|
convert_options: CONVERT_OPTIONS))
|
35
47
|
|
36
48
|
do_not_validate_attachment_file_type(:unprocessed_attachment)
|
@@ -72,6 +84,12 @@ module Pageflow
|
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
87
|
+
def panorama_mask_url
|
88
|
+
if processed_attachment.present?
|
89
|
+
attachment.url(:panorama_mask)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
75
93
|
private
|
76
94
|
|
77
95
|
def save_image_dimensions
|