pageflow 0.8.2 → 0.9.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.
- checksums.yaml +8 -8
- data/CHANGELOG.md +810 -0
- data/README.md +179 -0
- data/admins/pageflow/accounts.rb +46 -3
- data/admins/pageflow/entry.rb +35 -7
- data/app/assets/javascripts/pageflow/audio.js +62 -0
- data/app/assets/javascripts/pageflow/audio/multi_player.js +127 -0
- data/app/assets/javascripts/pageflow/audio/player_pool.js +15 -0
- data/app/assets/javascripts/pageflow/audio_player.js +23 -1
- data/app/assets/javascripts/pageflow/audio_player/null.js +37 -0
- data/app/assets/javascripts/pageflow/audio_player/pause_in_background.js +34 -0
- data/app/assets/javascripts/pageflow/audio_player/rewind_method.js +17 -0
- data/app/assets/javascripts/pageflow/audio_player/seek_with_invalid_state_handling.js +41 -0
- data/app/assets/javascripts/pageflow/base.js +10 -0
- data/app/assets/javascripts/pageflow/browser.js +123 -0
- data/app/assets/javascripts/pageflow/{features → browser}/hashchange_support.js +1 -1
- data/app/assets/javascripts/pageflow/{features → browser}/high_bandwidth.js +1 -1
- data/app/assets/javascripts/pageflow/{features → browser}/ie_platform.js +1 -1
- data/app/assets/javascripts/pageflow/browser/ios_platform.js +6 -0
- data/app/assets/javascripts/pageflow/{features → browser}/mobile_platform.js +1 -1
- data/app/assets/javascripts/pageflow/{features → browser}/phone_platform.js +1 -1
- data/app/assets/javascripts/pageflow/browser/pushstate_support.js +3 -0
- data/app/assets/javascripts/pageflow/{features → browser}/touch_support.js +1 -1
- data/app/assets/javascripts/pageflow/browser/video.js +16 -0
- data/app/assets/javascripts/pageflow/browser/volume_control_support.js +3 -0
- data/app/assets/javascripts/pageflow/chapter_filter.js +56 -0
- data/app/assets/javascripts/pageflow/editor/api.js +29 -0
- data/app/assets/javascripts/pageflow/editor/api/page_type.js +42 -0
- data/app/assets/javascripts/pageflow/editor/api/page_types.js +47 -0
- data/app/assets/javascripts/pageflow/editor/base.js +7 -1
- data/app/assets/javascripts/pageflow/editor/collections/subset_collection.js +5 -1
- data/app/assets/javascripts/pageflow/editor/initializers/boot.js +10 -2
- data/app/assets/javascripts/pageflow/editor/initializers/setup_audio.js +8 -0
- data/app/assets/javascripts/pageflow/editor/initializers/setup_collections.js +7 -0
- data/app/assets/javascripts/pageflow/editor/initializers/setup_features.js +3 -0
- data/app/assets/javascripts/pageflow/editor/initializers/setup_hotkeys.js +20 -0
- data/app/assets/javascripts/pageflow/editor/initializers/setup_page_types.js +1 -6
- data/app/assets/javascripts/pageflow/editor/models/audio_file.js +8 -0
- data/app/assets/javascripts/pageflow/editor/models/chapter.js +23 -4
- data/app/assets/javascripts/pageflow/editor/models/chapter_configuration.js +7 -0
- data/app/assets/javascripts/pageflow/editor/models/configuration.js +5 -3
- data/app/assets/javascripts/pageflow/editor/models/entry.js +6 -4
- data/app/assets/javascripts/pageflow/editor/models/mixins/delayed_destroying.js +1 -1
- data/app/assets/javascripts/pageflow/editor/models/mixins/stage_provider.js +3 -2
- data/app/assets/javascripts/pageflow/editor/models/page.js +11 -4
- data/app/assets/javascripts/pageflow/editor/models/preview_entry_data.js +31 -0
- data/app/assets/javascripts/pageflow/editor/models/theming.js +8 -0
- data/app/assets/javascripts/pageflow/editor/models/uploaded_file.js +8 -0
- data/app/assets/javascripts/pageflow/editor/templates/drop_down_button.jst.ejs +6 -0
- data/app/assets/javascripts/pageflow/editor/templates/drop_down_button_item.jst.ejs +1 -0
- data/app/assets/javascripts/pageflow/editor/templates/files_explorer.jst.ejs +2 -2
- data/app/assets/javascripts/pageflow/editor/templates/inputs/reference.jst.ejs +7 -0
- data/app/assets/javascripts/pageflow/editor/templates/list.jst.ejs +5 -0
- data/app/assets/javascripts/pageflow/editor/templates/list_blank_slate.jst.ejs +1 -0
- data/app/assets/javascripts/pageflow/editor/templates/list_item.jst.ejs +11 -0
- data/app/assets/javascripts/pageflow/editor/templates/loading.jst.ejs +7 -1
- data/app/assets/javascripts/pageflow/editor/templates/other_entries_blank_slate.jst.ejs +1 -1
- data/app/assets/javascripts/pageflow/editor/templates/page_link_item.jst.ejs +7 -0
- data/app/assets/javascripts/pageflow/editor/templates/page_links.jst.ejs +6 -0
- data/app/assets/javascripts/pageflow/editor/templates/page_selection.jst.ejs +12 -0
- data/app/assets/javascripts/pageflow/editor/templates/publish_entry.jst.ejs +44 -8
- data/app/assets/javascripts/pageflow/editor/views/chapter_item_view.js +3 -1
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/audio.js +1 -1
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/options.js +34 -2
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/page_transitions.js +6 -0
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/video.js +6 -1
- data/app/assets/javascripts/pageflow/editor/views/disabled_atmo_indicator_view.js +27 -0
- data/app/assets/javascripts/pageflow/editor/views/drop_down_button_item_view.js +33 -0
- data/app/assets/javascripts/pageflow/editor/views/drop_down_button_view.js +80 -0
- data/app/assets/javascripts/pageflow/editor/views/edit_chapter_view.js +25 -5
- data/app/assets/javascripts/pageflow/editor/views/edit_entry_view.js +9 -1
- data/app/assets/javascripts/pageflow/editor/views/edit_page_view.js +7 -5
- data/app/assets/javascripts/pageflow/editor/views/edit_widget_view.js +1 -1
- data/app/assets/javascripts/pageflow/editor/views/embedded/background_image_embedded_view.js +4 -1
- data/app/assets/javascripts/pageflow/editor/views/embedded/lazy_video_embedded_view.js +41 -0
- data/app/assets/javascripts/pageflow/editor/views/entry_preview_view.js +6 -6
- data/app/assets/javascripts/pageflow/editor/views/inputs/page_link_input_view.js +9 -0
- data/app/assets/javascripts/pageflow/editor/views/inputs/reference_input_view.js +66 -0
- data/app/assets/javascripts/pageflow/editor/views/list_item_view.js +95 -0
- data/app/assets/javascripts/pageflow/editor/views/list_view.js +59 -0
- data/app/assets/javascripts/pageflow/editor/views/loading_view.js +5 -0
- data/app/assets/javascripts/pageflow/editor/views/model_thumbnail_view.js +37 -0
- data/app/assets/javascripts/pageflow/editor/views/navigatable_page_item_view.js +1 -0
- data/app/assets/javascripts/pageflow/editor/views/other_entries_collection_view.js +4 -4
- data/app/assets/javascripts/pageflow/editor/views/other_entry_item_view.js +2 -1
- data/app/assets/javascripts/pageflow/editor/views/page_item_view.js +2 -2
- data/app/assets/javascripts/pageflow/editor/views/page_link_item_view.js +51 -0
- data/app/assets/javascripts/pageflow/editor/views/page_links_view.js +45 -0
- data/app/assets/javascripts/pageflow/editor/views/page_preview_view.js +24 -16
- data/app/assets/javascripts/pageflow/editor/views/page_selection_view.js +46 -0
- data/app/assets/javascripts/pageflow/editor/views/page_thumbnail_view.js +2 -29
- data/app/assets/javascripts/pageflow/editor/views/publish_entry_view.js +95 -10
- data/app/assets/javascripts/pageflow/editor/views/scrolling_view.js +24 -0
- data/app/assets/javascripts/pageflow/entry_data.js +35 -0
- data/app/assets/javascripts/pageflow/features.js +68 -98
- data/app/assets/javascripts/pageflow/fullscreen.js +24 -0
- data/app/assets/javascripts/pageflow/highlighted_page.js +48 -0
- data/app/assets/javascripts/pageflow/history.js +50 -18
- data/app/assets/javascripts/pageflow/history/hash_adapter.js +36 -0
- data/app/assets/javascripts/pageflow/history/push_state_adapter.js +37 -0
- data/app/assets/javascripts/pageflow/history/simulated_adapter.js +44 -0
- data/app/assets/javascripts/pageflow/media_player.js +25 -0
- data/app/assets/javascripts/pageflow/media_player/async_play.js +54 -0
- data/app/assets/javascripts/pageflow/media_player/hooks.js +24 -0
- data/app/assets/javascripts/pageflow/media_player/load_waiting.js +11 -0
- data/app/assets/javascripts/pageflow/media_player/volume_binding.js +72 -0
- data/app/assets/javascripts/pageflow/media_player/volume_fading.js +62 -0
- data/app/assets/javascripts/pageflow/multimedia_alert.js +13 -0
- data/app/assets/javascripts/pageflow/object.js +14 -0
- data/app/assets/javascripts/pageflow/page_transitions.js +27 -0
- data/app/assets/javascripts/pageflow/page_type.js +6 -0
- data/app/assets/javascripts/pageflow/page_types/audio.js +17 -21
- data/app/assets/javascripts/pageflow/page_types/background_video.js +18 -17
- data/app/assets/javascripts/pageflow/page_types/mixins/common_page_css_classes.js +29 -4
- data/app/assets/javascripts/pageflow/page_types/video.js +73 -36
- data/app/assets/javascripts/pageflow/preload.js +9 -6
- data/app/assets/javascripts/pageflow/ready.js +18 -14
- data/app/assets/javascripts/pageflow/seed_entry_data.js +43 -0
- data/app/assets/javascripts/pageflow/settings.js +17 -4
- data/app/assets/javascripts/pageflow/slideshow.js +103 -23
- data/app/assets/javascripts/pageflow/slideshow/adjacent_pages.js +26 -0
- data/app/assets/javascripts/pageflow/slideshow/adjacent_preparer.js +44 -0
- data/app/assets/javascripts/pageflow/slideshow/atmo.js +105 -0
- data/app/assets/javascripts/pageflow/slideshow/dom_order_scroll_navigator.js +29 -0
- data/app/assets/javascripts/pageflow/slideshow/lazy_page_widget.js +49 -0
- data/app/assets/javascripts/pageflow/slideshow/page_widget.js +60 -26
- data/app/assets/javascripts/pageflow/slideshow/progressive_preload.js +16 -7
- data/app/assets/javascripts/pageflow/slideshow/scroll_indicator_widget.js +45 -7
- data/app/assets/javascripts/pageflow/slideshow/scroller_widget.js +42 -5
- data/app/assets/javascripts/pageflow/ui.js +1 -0
- data/app/assets/javascripts/pageflow/ui/object.js +4 -13
- data/app/assets/javascripts/pageflow/ui/utils/i18n_utils.js +23 -0
- data/app/assets/javascripts/pageflow/ui/views/collection_view.js +8 -4
- data/app/assets/javascripts/pageflow/ui/views/configuration_editor_tab_view.js +6 -5
- data/app/assets/javascripts/pageflow/ui/views/configuration_editor_view.js +2 -11
- data/app/assets/javascripts/pageflow/ui/views/inputs/select_input_view.js +6 -1
- data/app/assets/javascripts/pageflow/ui/views/inputs/text_input_view.js +4 -0
- data/app/assets/javascripts/pageflow/ui/views/mixins/input_view.js +149 -6
- data/app/assets/javascripts/pageflow/ui/views/mixins/subview_container.js +4 -0
- data/app/assets/javascripts/pageflow/video_player.js +5 -0
- data/app/assets/javascripts/pageflow/video_player/buffer_underrun_waiting.js +1 -1
- data/app/assets/javascripts/pageflow/video_player/lazy.js +8 -4
- data/app/assets/javascripts/pageflow/video_player/media_events.js +1 -1
- data/app/assets/javascripts/pageflow/video_player/play_button_patch.js +1 -1
- data/app/assets/javascripts/pageflow/video_player/prebuffering.js +1 -1
- data/app/assets/javascripts/pageflow/widgets/fullscreen_button.js +26 -0
- data/app/assets/javascripts/pageflow/widgets/multimedia_alert.js +21 -5
- data/app/assets/javascripts/pageflow/widgets/mute_button.js +42 -0
- data/app/assets/javascripts/pageflow/widgets/navigation.js +5 -78
- data/app/assets/javascripts/pageflow/widgets/navigation_mobile.js +4 -0
- data/app/assets/javascripts/pageflow/widgets/page_navigation_list.js +28 -34
- data/app/assets/javascripts/pageflow/widgets/parent_page_button.js +27 -0
- data/app/assets/javascripts/pageflow/widgets/skip_page_button.js +22 -0
- data/app/assets/javascripts/pageflow/widgets/top_button.js +6 -7
- data/app/assets/javascripts/pageflow/widgets/volume_slider.js +62 -0
- data/app/assets/stylesheets/pageflow/admin/entries.css.scss +10 -0
- data/app/assets/stylesheets/pageflow/animations.css.scss +1 -0
- data/app/assets/stylesheets/pageflow/animations/loading.css.scss +8 -0
- data/app/assets/stylesheets/pageflow/animations/scroll.css.scss +18 -0
- data/app/assets/stylesheets/pageflow/base.css.scss +3 -1
- data/app/assets/stylesheets/pageflow/delayed_text_fade_in.css.scss +49 -0
- data/app/assets/stylesheets/pageflow/editor/base.css.scss +15 -2
- data/app/assets/stylesheets/pageflow/editor/disabled_atmo_indicator.css.scss +13 -0
- data/app/assets/stylesheets/pageflow/editor/drop_down_button.css.scss +54 -0
- data/app/assets/stylesheets/pageflow/editor/files_explorer.css.scss +6 -0
- data/app/assets/stylesheets/pageflow/editor/indicators.css.scss +5 -0
- data/app/assets/stylesheets/pageflow/editor/inputs.css.scss +1 -0
- data/app/assets/stylesheets/pageflow/editor/inputs/reference.css.scss +51 -0
- data/app/assets/stylesheets/pageflow/editor/list.css.scss +108 -0
- data/app/assets/stylesheets/pageflow/editor/loading.css.scss +31 -0
- data/app/assets/stylesheets/pageflow/editor/outline.css.scss +7 -5
- data/app/assets/stylesheets/pageflow/editor/page_links.css.scss +58 -0
- data/app/assets/stylesheets/pageflow/editor/page_selection.css.scss +39 -0
- data/app/assets/stylesheets/pageflow/editor/publish_entry.css.scss +38 -1
- data/app/assets/stylesheets/pageflow/entries.css.scss +17 -9
- data/app/assets/stylesheets/pageflow/navigation_bar.css.scss +4 -0
- data/app/assets/stylesheets/pageflow/page_transitions.css.scss +10 -0
- data/app/assets/stylesheets/pageflow/page_transitions/crossfade.css.scss +29 -0
- data/app/assets/stylesheets/pageflow/page_transitions/cut.css.scss +23 -0
- data/app/assets/stylesheets/pageflow/page_transitions/fade.css.scss +78 -0
- data/app/assets/stylesheets/pageflow/page_transitions/fade_to_black.css.scss +107 -0
- data/app/assets/stylesheets/pageflow/page_transitions/scroll.css.scss +20 -0
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_in.css.scss +66 -0
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_in_right.css.scss +68 -0
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_left.css.scss +20 -0
- data/app/assets/stylesheets/pageflow/page_transitions/scroll_right.css.scss +20 -0
- data/app/assets/stylesheets/pageflow/page_types.css.scss +1 -3
- data/app/assets/stylesheets/pageflow/page_types/video.css.scss +0 -4
- data/app/assets/stylesheets/pageflow/slideshow.css.scss +0 -145
- data/app/assets/stylesheets/pageflow/text_variants.css.scss +0 -4
- data/app/assets/stylesheets/pageflow/themes/default/navigation.css.scss +0 -3
- data/app/controllers/concerns/pageflow/public_https_mode.rb +13 -0
- data/app/controllers/pageflow/application_controller.rb +0 -6
- data/app/controllers/pageflow/chapters_controller.rb +2 -1
- data/app/controllers/pageflow/editor/entries_controller.rb +2 -0
- data/app/controllers/pageflow/editor/entry_publications_controller.rb +3 -1
- data/app/controllers/pageflow/entries_controller.rb +16 -3
- data/app/controllers/pageflow/files_controller.rb +3 -1
- data/app/helpers/pageflow/admin/features_helper.rb +25 -0
- data/app/helpers/pageflow/background_image_helper.rb +40 -9
- data/app/helpers/pageflow/entries_helper.rb +10 -11
- data/app/helpers/pageflow/entry_json_seed_helper.rb +44 -0
- data/app/helpers/pageflow/help_entries_helper.rb +4 -4
- data/app/helpers/pageflow/page_types_helper.rb +4 -2
- data/app/helpers/pageflow/pages_helper.rb +20 -27
- data/app/helpers/pageflow/widgets_helper.rb +4 -4
- data/app/models/concerns/pageflow/feature_target.rb +37 -0
- data/app/models/pageflow/account.rb +2 -0
- data/app/models/pageflow/chapter.rb +6 -0
- data/app/models/pageflow/draft_entry.rb +2 -0
- data/app/models/pageflow/entry.rb +47 -9
- data/app/models/pageflow/entry_duplicate.rb +51 -0
- data/app/models/pageflow/image_file.rb +33 -13
- data/app/models/pageflow/page.rb +2 -2
- data/app/models/pageflow/published_entry.rb +7 -1
- data/app/views/admin/accounts/_form.html.erb +11 -1
- data/app/views/admin/features/_form.html.erb +16 -0
- data/app/views/components/pageflow/admin/features_tab.rb +10 -0
- data/app/views/components/pageflow/admin/revisions_tab.rb +4 -0
- data/app/views/layouts/pageflow/_meta_tags.html.erb +1 -1
- data/app/views/layouts/pageflow/application.html.erb +2 -2
- data/app/views/pageflow/editor/accounts/_account.json.jbuilder +1 -0
- data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
- data/app/views/pageflow/editor/entries/_help_entries_seed.html.erb +2 -2
- data/app/views/pageflow/editor/entries/_indicators_seed.html.erb +3 -0
- data/app/views/pageflow/editor/entries/seed.json.erb +3 -2
- data/app/views/pageflow/editor/entry_publications/check.json.jbuilder +1 -0
- data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +1 -1
- data/app/views/pageflow/editor/themings/_theming.json.jbuilder +4 -0
- data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +1 -0
- data/app/views/pageflow/entries/_entry.html.erb +4 -3
- data/app/views/pageflow/entries/_indicators.html.erb +13 -0
- data/app/views/pageflow/entries/_mobile_navigation.html.erb +3 -15
- data/app/views/pageflow/entries/edit.html.erb +9 -1
- data/app/views/pageflow/entries/navigation/_bar_top.html.erb +3 -15
- data/app/views/pageflow/entries/share_menu/_facebook_link.html.erb +12 -0
- data/app/views/pageflow/entries/share_menu/_google_link.html.erb +12 -0
- data/app/views/pageflow/entries/share_menu/_twitter_link.html.erb +12 -0
- data/app/views/pageflow/entries/show.css.erb +12 -2
- data/app/views/pageflow/entries/show.html.erb +5 -1
- data/app/views/pageflow/page_types/_page_type.json.jbuilder +7 -1
- data/app/views/pageflow/pages/_page.html.erb +2 -2
- data/app/views/pageflow/pages/templates/_audio.html.erb +10 -0
- data/config/initializers/admin_resource_tabs.rb +1 -0
- data/config/initializers/features.rb +9 -0
- data/config/initializers/page_type_helpers.rb +1 -1
- data/config/initializers/paperclip.rb +1 -1
- data/config/initializers/zencoder.rb +1 -1
- data/config/locales/de.yml +132 -71
- data/config/locales/en.yml +118 -191
- data/db/migrate/20141211110226_add_configuration_to_chapters.rb +5 -0
- data/db/migrate/20150115175116_add_features_configuration_to_accounts.rb +5 -0
- data/db/migrate/20150115175207_add_features_configuration_to_entries.rb +5 -0
- data/db/migrate/20150603091823_add_password_attributes_to_revisions.rb +6 -0
- data/db/migrate/20151022080518_add_first_published_at_to_entries.rb +14 -0
- data/lib/generators/pageflow/initializer/templates/pageflow.rb +26 -17
- data/lib/generators/pageflow/theme/theme_generator.rb +2 -1
- data/lib/pageflow.rb +2 -46
- data/lib/pageflow/admin/form_input.rb +18 -0
- data/lib/pageflow/admin/form_inputs.rb +41 -0
- data/lib/pageflow/built_in_page_type.rb +0 -4
- data/lib/pageflow/configuration.rb +74 -18
- data/lib/pageflow/feature.rb +33 -0
- data/lib/pageflow/features.rb +68 -0
- data/lib/pageflow/global_config_api.rb +118 -0
- data/lib/pageflow/page_type_feature.rb +21 -0
- data/lib/pageflow/page_types.rb +29 -0
- data/lib/pageflow/theme.rb +20 -0
- data/lib/pageflow/themes.rb +26 -0
- data/lib/pageflow/version.rb +1 -1
- data/spec/factories/entries.rb +6 -0
- data/spec/factories/feature_targets.rb +4 -0
- data/spec/fixtures/image.gif +0 -0
- data/spec/fixtures/video.mp4 +0 -0
- data/vendor/assets/javascripts/audio5.min.js +12 -8
- data/vendor/assets/javascripts/iscroll.js +1 -1
- metadata +144 -24
- data/app/assets/images/pageflow/internal_links_pictogram.png +0 -0
- data/app/assets/images/pageflow/internal_links_pictogram_small.png +0 -0
- data/app/assets/images/pageflow/internal_links_sprite.png +0 -0
- data/app/assets/images/pageflow/ov-internal_links.png +0 -0
- data/app/assets/images/pageflow/themes/default/internal_links_sprite.png +0 -0
- data/app/assets/javascripts/pageflow/editor/templates/embedded/page_link.jst.ejs +0 -3
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/internal_links.js +0 -24
- data/app/assets/javascripts/pageflow/editor/views/draggable_page_item_view.js +0 -31
- data/app/assets/javascripts/pageflow/editor/views/embedded/page_link_embedded_view.js +0 -176
- data/app/assets/javascripts/pageflow/features/video.js +0 -16
- data/app/assets/javascripts/pageflow/page_types/internal_links.js +0 -55
- data/app/assets/javascripts/pageflow/ui/templates/inputs/page_reference.jst.ejs +0 -6
- data/app/assets/javascripts/pageflow/ui/views/inputs/page_reference_input_view.js +0 -44
- data/app/assets/stylesheets/pageflow/editor/embedded.css.scss +0 -104
- data/app/assets/stylesheets/pageflow/page_types/internal_links.css.scss +0 -222
- data/app/views/pageflow/pages/templates/_internal_links.html.erb +0 -31
data/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Pageflow
|
|
2
|
+
|
|
3
|
+
[](http://badge.fury.io/rb/pageflow)
|
|
4
|
+
[](https://travis-ci.org/codevise/pageflow)
|
|
5
|
+
|
|
6
|
+
Multimedia story telling for the web.
|
|
7
|
+
|
|
8
|
+
For a high level introduction and example Pageflow stories see
|
|
9
|
+
[pageflow.io](http://pageflow.io).
|
|
10
|
+
|
|
11
|
+
In addition to this README, there is also a [Getting Started Wiki page](https://github.com/codevise/pageflow/wiki/Getting-Started)
|
|
12
|
+
to guide you through the steps of setting up a Rails application with Pageflow
|
|
13
|
+
on your development machine.
|
|
14
|
+
|
|
15
|
+
## Updating
|
|
16
|
+
|
|
17
|
+
For instructions on how to update from a prior version of the gem see
|
|
18
|
+
the
|
|
19
|
+
[Updating Pageflow](https://github.com/codevise/pageflow/wiki/Updating-Pageflow)
|
|
20
|
+
wiki page.
|
|
21
|
+
|
|
22
|
+
## Ingredients
|
|
23
|
+
|
|
24
|
+
Pageflow is a Rails engine which roughly consists of the following
|
|
25
|
+
components:
|
|
26
|
+
|
|
27
|
+
* A full MVC stack to manage and display Pageflow stories
|
|
28
|
+
* User and permission management with support for isolated accounts
|
|
29
|
+
and user collaboration
|
|
30
|
+
* A client side application for live preview editing of stories
|
|
31
|
+
* Background jobs to process and encode images, audios and videos
|
|
32
|
+
* Generators to quickly bootstrap a new Rails application
|
|
33
|
+
|
|
34
|
+
Pageflow assumes the following choice of libraries:
|
|
35
|
+
|
|
36
|
+
* [Devise](https://github.com/plataformatec/devise) for authentication
|
|
37
|
+
* [CanCan](https://github.com/ryanb/cancan) for authorization
|
|
38
|
+
* [ActiveAdmin](http://activeadmin.info/) for administration
|
|
39
|
+
* [Resque](https://github.com/resque/resque) for background jobs
|
|
40
|
+
* [FriendlyId](https://github.com/norman/friendly_id) for pretty URLs
|
|
41
|
+
* [Paperclip](https://github.com/thoughtbot/paperclip) for attachment handling
|
|
42
|
+
* [Backbone](http://backbonejs.org/) [Marionette](http://marionettejs.com/) for client side development
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Requirements
|
|
46
|
+
|
|
47
|
+
Pageflow runs in environments with:
|
|
48
|
+
|
|
49
|
+
* Ruby >= 1.9.3 and < 2.2.0 because of [ActiveAdmin](https://github.com/activeadmin/activeadmin/issues/3715)
|
|
50
|
+
* Rails 4.0 or 4.1
|
|
51
|
+
* Redis server (for Resque)
|
|
52
|
+
* A database server supported by Active Record (tested with MySQL)
|
|
53
|
+
* ImageMagick
|
|
54
|
+
|
|
55
|
+
Accounts of the following cloud services have to be registered:
|
|
56
|
+
|
|
57
|
+
* [Amazon Web Services](http://aws.amazon.com) for S3 file storage and
|
|
58
|
+
(optionally) Cloudfront content delivery
|
|
59
|
+
* [Zencoder](http://zencoder.com) for video/audio encoding
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
Generate a new Rails application using the MySQL database adapter:
|
|
64
|
+
|
|
65
|
+
$ rails new my_pageflow --database=mysql
|
|
66
|
+
$ cd my_pageflow
|
|
67
|
+
|
|
68
|
+
Do not name your application `"pageflow"` since it will cause conflicts
|
|
69
|
+
which constant names created by Pageflow itself.
|
|
70
|
+
|
|
71
|
+
### Database Setup
|
|
72
|
+
|
|
73
|
+
Enter valid MySQL credentials inside `config/database.yml` and create
|
|
74
|
+
the database:
|
|
75
|
+
|
|
76
|
+
$ rake db:create
|
|
77
|
+
|
|
78
|
+
### Gem Dependencies
|
|
79
|
+
|
|
80
|
+
Add this line to your application's Gemfile:
|
|
81
|
+
|
|
82
|
+
# Gemfile
|
|
83
|
+
gem 'pageflow'
|
|
84
|
+
|
|
85
|
+
At the moment, Pageflow depends on a frozen version of Active Admin
|
|
86
|
+
since, back when development started, no Rails 4 compatible version of
|
|
87
|
+
Active Admin was available as a gem. You therefore need to bundle the
|
|
88
|
+
`rails4` branch that we have forked into our github organization:
|
|
89
|
+
|
|
90
|
+
# Gemfile
|
|
91
|
+
gem 'activeadmin', git: 'https://github.com/codevise/active_admin.git', branch: 'rails4'
|
|
92
|
+
gem 'ransack'
|
|
93
|
+
gem 'inherited_resources', '1.4.1'
|
|
94
|
+
gem 'formtastic', '2.3.0'
|
|
95
|
+
# Only required for Rails 4.1:
|
|
96
|
+
gem 'state_machine', git: 'https://github.com/codevise/state_machine.git'
|
|
97
|
+
|
|
98
|
+
Run bundler to install dependencies:
|
|
99
|
+
|
|
100
|
+
$ bundle install
|
|
101
|
+
|
|
102
|
+
### Running the Generator
|
|
103
|
+
|
|
104
|
+
Now you can run the generator to setup Pageflow and its dependencies:
|
|
105
|
+
|
|
106
|
+
$ rails generate pageflow:install
|
|
107
|
+
|
|
108
|
+
The generator will invoke Active Admin and Devise generators in turn
|
|
109
|
+
and apply some configuration changes. When asked to overwrite the
|
|
110
|
+
`db/seeds.rb` file, choose yes.
|
|
111
|
+
|
|
112
|
+
To better understand Pageflow's configuration choices, you can run the
|
|
113
|
+
single steps of the `install` generator one by one. See the wiki page
|
|
114
|
+
[The Install Generator in Detail](https://github.com/codevise/pageflow/wiki/The-Install-Generator-in-Detail)
|
|
115
|
+
for more. If you'd rather not look behind the scenes for now, you can
|
|
116
|
+
safely read on.
|
|
117
|
+
|
|
118
|
+
### Database Migration
|
|
119
|
+
|
|
120
|
+
_Devise migration name fix_: In some cases, the Devise generator creates
|
|
121
|
+
a migration file without file extension. This needs to be fixed manually
|
|
122
|
+
at the moment:
|
|
123
|
+
|
|
124
|
+
$ mv db/migrate/*_devise_create_users{,.rb}
|
|
125
|
+
|
|
126
|
+
Now you can migrate the database.
|
|
127
|
+
|
|
128
|
+
$ rake db:migrate
|
|
129
|
+
|
|
130
|
+
Finally, you can populate the database with some example data, so
|
|
131
|
+
things do not look too blank in development mode.
|
|
132
|
+
|
|
133
|
+
$ rake db:seed
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
Pageflow stores files in S3 buckets also in development
|
|
138
|
+
mode. Otherwise there's no way to have Zencoder encode them. See the
|
|
139
|
+
wiki page [Setting up external services](https://github.com/codevise/pageflow/wiki/Setting-up-External-Services).
|
|
140
|
+
|
|
141
|
+
The host application can utilize environment variables to configure the API keys for S3 and Zencoder. The variables can be found in the generated Pageflow initializer.
|
|
142
|
+
|
|
143
|
+
For available configuration options and examples see the inline docs
|
|
144
|
+
in `config/initializers/pageflow.rb` in your generated rails app.
|
|
145
|
+
|
|
146
|
+
Ensure you have defined default url options in your environments
|
|
147
|
+
files. Here is an example of `default_url_options` appropriate for a
|
|
148
|
+
development environment in `config/environments/development.rb`:
|
|
149
|
+
|
|
150
|
+
config.action_mailer.default_url_options = {host: 'localhost:3000'}
|
|
151
|
+
|
|
152
|
+
In production, `:host` should be set to the actual host of your
|
|
153
|
+
application.
|
|
154
|
+
|
|
155
|
+
## Running Pageflow
|
|
156
|
+
|
|
157
|
+
In addition to the Rails server, you need to start two Rake tasks for
|
|
158
|
+
the background job processing. First, start a Resque worker which handles
|
|
159
|
+
jobs from all queues:
|
|
160
|
+
|
|
161
|
+
$ QUEUE=* rake resque:work
|
|
162
|
+
|
|
163
|
+
Image and video processing are examples of jobs that are executes by these workers.
|
|
164
|
+
|
|
165
|
+
Some jobs need to be executed repeatedly. For example, while videos are being
|
|
166
|
+
encoded by Zencoder, there is a job that runs every few seconds to fetch the
|
|
167
|
+
current progress. This delayed invocation of jobs is handled by the Resque
|
|
168
|
+
Scheduler Rake task:
|
|
169
|
+
|
|
170
|
+
$ QUEUE=* rake resque:scheduler
|
|
171
|
+
|
|
172
|
+
Consider using the [foreman gem](https://github.com/ddollar/foreman) to start all of
|
|
173
|
+
these processes (including the Rails server) with a single command in your
|
|
174
|
+
development environment.
|
|
175
|
+
|
|
176
|
+
## Troubleshooting
|
|
177
|
+
|
|
178
|
+
If you run into problems during the installation of Pageflow, please refer to the [Troubleshooting](https://github.com/codevise/pageflow/wiki/Troubleshooting) wiki
|
|
179
|
+
page. If that doesn't help, consider [filing an issue](https://github.com/codevise/pageflow/issues?state=open).
|
data/admins/pageflow/accounts.rb
CHANGED
|
@@ -23,12 +23,13 @@ module Pageflow
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
controller do
|
|
26
|
+
helper Pageflow::Admin::FeaturesHelper
|
|
26
27
|
helper ThemesHelper
|
|
27
28
|
helper WidgetsHelper
|
|
28
29
|
|
|
29
30
|
def new
|
|
30
31
|
@account = Account.new
|
|
31
|
-
@account.
|
|
32
|
+
@account.build_default_theming
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def create
|
|
@@ -39,7 +40,9 @@ module Pageflow
|
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def update
|
|
42
|
-
|
|
43
|
+
update! do |success, failure|
|
|
44
|
+
success.html { redirect_to(admin_account_path(resource, params.slice(:tab))) }
|
|
45
|
+
end
|
|
43
46
|
update_widgets
|
|
44
47
|
end
|
|
45
48
|
|
|
@@ -54,7 +57,47 @@ module Pageflow
|
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
def permitted_params
|
|
57
|
-
params.permit(
|
|
60
|
+
result = params.permit(account: permitted_account_attributes)
|
|
61
|
+
|
|
62
|
+
if result[:account]
|
|
63
|
+
feature_states = params[:account][:feature_states].try(:permit!)
|
|
64
|
+
result[:account].merge!(feature_states: feature_states || {})
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
result
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def permitted_account_attributes
|
|
73
|
+
[
|
|
74
|
+
:name,
|
|
75
|
+
:default_file_rights,
|
|
76
|
+
default_theming_attributes: permitted_theming_attributes
|
|
77
|
+
] +
|
|
78
|
+
permitted_attributes_for(:account)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def permitted_theming_attributes
|
|
82
|
+
[
|
|
83
|
+
:cname,
|
|
84
|
+
:theme_name,
|
|
85
|
+
:imprint_link_url,
|
|
86
|
+
:imprint_link_label,
|
|
87
|
+
:copyright_link_url,
|
|
88
|
+
:copyright_link_label,
|
|
89
|
+
:home_url,
|
|
90
|
+
:home_button_enabled_by_default
|
|
91
|
+
] +
|
|
92
|
+
permitted_attributes_for(:theming)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def permitted_attributes_for(resource_name)
|
|
96
|
+
if params[:id]
|
|
97
|
+
Pageflow.config_for(resource).admin_form_inputs.permitted_attributes_for(resource_name)
|
|
98
|
+
else
|
|
99
|
+
[]
|
|
100
|
+
end
|
|
58
101
|
end
|
|
59
102
|
end
|
|
60
103
|
end
|
data/admins/pageflow/entry.rb
CHANGED
|
@@ -51,6 +51,8 @@ module Pageflow
|
|
|
51
51
|
if authorized?(:manage, Folder)
|
|
52
52
|
f.input :folder, :collection => collection_for_folders(f.object.account), :include_blank => true
|
|
53
53
|
end
|
|
54
|
+
|
|
55
|
+
Pageflow.config_for(f.object).admin_form_inputs.build(:entry, f)
|
|
54
56
|
end
|
|
55
57
|
f.actions
|
|
56
58
|
end
|
|
@@ -60,10 +62,32 @@ module Pageflow
|
|
|
60
62
|
button_to(I18n.t('pageflow.admin.entries.depublish'),
|
|
61
63
|
pageflow.current_entry_revisions_path(entry),
|
|
62
64
|
:method => :delete,
|
|
63
|
-
:data => {
|
|
65
|
+
:data => {
|
|
66
|
+
:rel => 'depublish',
|
|
67
|
+
:confirm => I18n.t('pageflow.admin.entries.confirm_depublish')
|
|
68
|
+
})
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
action_item :only => :show do
|
|
73
|
+
if authorized?(:duplicate, entry)
|
|
74
|
+
button_to(I18n.t('pageflow.admin.entries.duplicate'),
|
|
75
|
+
duplicate_admin_entry_path(entry),
|
|
76
|
+
:method => :post,
|
|
77
|
+
:data => {
|
|
78
|
+
:rel => 'duplicate',
|
|
79
|
+
:confirm => I18n.t('pageflow.admin.entries.confirm_duplicate')
|
|
80
|
+
})
|
|
64
81
|
end
|
|
65
82
|
end
|
|
66
83
|
|
|
84
|
+
member_action :duplicate, :method => :post do
|
|
85
|
+
entry = Entry.find(params[:id])
|
|
86
|
+
authorize!(:duplicate, entry)
|
|
87
|
+
new_entry = entry.duplicate
|
|
88
|
+
redirect_to(edit_admin_entry_path(new_entry))
|
|
89
|
+
end
|
|
90
|
+
|
|
67
91
|
member_action :snapshot, :method => :post do
|
|
68
92
|
entry = Entry.find(params[:id])
|
|
69
93
|
authorize!(:snapshot, entry)
|
|
@@ -104,16 +128,20 @@ module Pageflow
|
|
|
104
128
|
end
|
|
105
129
|
|
|
106
130
|
def permitted_params
|
|
107
|
-
|
|
108
|
-
restrict_attributes(params[:id], result[:entry]) if result[:entry]
|
|
109
|
-
result
|
|
131
|
+
params.permit(entry: permitted_attributes)
|
|
110
132
|
end
|
|
111
133
|
|
|
112
134
|
private
|
|
113
135
|
|
|
114
|
-
def
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
def permitted_attributes
|
|
137
|
+
result = [:title]
|
|
138
|
+
|
|
139
|
+
target = params[:id] ? resource : current_user.account
|
|
140
|
+
result += Pageflow.config_for(target).admin_form_inputs.permitted_attributes_for(:entry)
|
|
141
|
+
|
|
142
|
+
result += [:account_id, :theming_id] if authorized?(:read, Account)
|
|
143
|
+
result << :folder_id if authorized?(:manage, Folder)
|
|
144
|
+
result
|
|
117
145
|
end
|
|
118
146
|
end
|
|
119
147
|
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//= require_self
|
|
2
|
+
//= require ./audio/player_pool
|
|
3
|
+
//= require ./audio/multi_player
|
|
4
|
+
|
|
5
|
+
pageflow.Audio = function(options) {
|
|
6
|
+
this.getSources = options.getSources || function(audioFileId) {
|
|
7
|
+
return options.audioFiles[audioFileId] || '';
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a player for the given audio file.
|
|
12
|
+
*
|
|
13
|
+
* @param [String|Numberic] audioFileId Id of the audio file to play possibly with a suffix.
|
|
14
|
+
* @param [Object] options Options to pass on player creation
|
|
15
|
+
*
|
|
16
|
+
* The audio file id can be of the form `"5.suffix"` to distinguish
|
|
17
|
+
* multiple occurences of the same audio file for example inside a
|
|
18
|
+
* pageflow.Audio.PlayerPool;
|
|
19
|
+
*/
|
|
20
|
+
this.createPlayer = function(audioFileId, options) {
|
|
21
|
+
var sources = this.getSources(removeSuffix(audioFileId));
|
|
22
|
+
|
|
23
|
+
if (sources) {
|
|
24
|
+
return new pageflow.AudioPlayer(sources, _.extend({
|
|
25
|
+
volumeFading: true
|
|
26
|
+
}, options || {}));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return new pageflow.AudioPlayer.Null();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @option options [Numeric] fadeDuration Time in milliseconds to fade
|
|
35
|
+
* audios in and out.
|
|
36
|
+
* @option options [Boolean] playFromBeginning Always restart audio
|
|
37
|
+
* files from the beginning. Defaults to false.
|
|
38
|
+
* @option options [Boolean] rewindOnChange Play from beginning when
|
|
39
|
+
* changing audio files. Defaults to false.
|
|
40
|
+
*
|
|
41
|
+
* Furthermore all options supported by pageflow.AudioPlayer can be
|
|
42
|
+
* passed.
|
|
43
|
+
*/
|
|
44
|
+
this.createMultiPlayer = function(options) {
|
|
45
|
+
return new pageflow.Audio.MultiPlayer(
|
|
46
|
+
new pageflow.Audio.PlayerPool(this, options),
|
|
47
|
+
options
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function removeSuffix(id) {
|
|
52
|
+
if (!id) {
|
|
53
|
+
return id;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return parseInt(id.toString().split('.')[0], 10);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
pageflow.Audio.setup = function(options) {
|
|
61
|
+
pageflow.audio = new pageflow.Audio(options);
|
|
62
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
pageflow.Audio.MultiPlayer = function(pool, options) {
|
|
2
|
+
if (options.crossFade && options.playFromBeginning) {
|
|
3
|
+
throw 'pageflow.Audio.MultiPlayer: The options crossFade and playFromBeginning can not be used together at the moment.';
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
var current = new pageflow.AudioPlayer.Null();
|
|
7
|
+
var currentId = null;
|
|
8
|
+
var that = this;
|
|
9
|
+
|
|
10
|
+
this.resume = function() {
|
|
11
|
+
return current.play();
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
this.resumeAndFadeIn = function() {
|
|
15
|
+
return current.playAndFadeIn(options.fadeDuration);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
this.seek = function(position) {
|
|
19
|
+
return current.seek(position);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
this.pause = function() {
|
|
23
|
+
return current.pause();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
this.paused = function() {
|
|
27
|
+
return current.paused();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
this.fadeOutAndPause = function() {
|
|
31
|
+
return current.fadeOutAndPause(options.fadeDuration);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
this.position = function() {
|
|
35
|
+
return current.position;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
this.duration = function() {
|
|
39
|
+
return current.duration;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
this.fadeTo = function(id) {
|
|
43
|
+
return changeCurrent(id, function(player) {
|
|
44
|
+
return player.playAndFadeIn(options.fadeDuration);
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
this.play = function(id) {
|
|
49
|
+
return changeCurrent(id, function(player) {
|
|
50
|
+
return player.play();
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
this.changeVolumeFactor = function(factor) {
|
|
55
|
+
return current.changeVolumeFactor(factor, options.fadeDuration);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
this.formatTime = function(time) {
|
|
59
|
+
return current.formatTime(time);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function changeCurrent(id, callback) {
|
|
63
|
+
if (!options.playFromBeginning && id === currentId && !current.paused()) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var player = pool.get(id);
|
|
68
|
+
currentId = id;
|
|
69
|
+
|
|
70
|
+
var fadeOutPromise = current.fadeOutAndPause(options.fadeDuration);
|
|
71
|
+
|
|
72
|
+
fadeOutPromise.then(function() {
|
|
73
|
+
stopEventPropagation(current);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
handleCrossFade(fadeOutPromise).then(function() {
|
|
77
|
+
current = player;
|
|
78
|
+
startEventPropagation(current, id);
|
|
79
|
+
|
|
80
|
+
handlePlayFromBeginning(player).then(function() {
|
|
81
|
+
callback(player);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function handleCrossFade(fadePomise) {
|
|
87
|
+
if (options.crossFade) {
|
|
88
|
+
return new $.Deferred().resolve().promise();
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return fadePomise;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function handlePlayFromBeginning(player) {
|
|
96
|
+
if (options.playFromBeginning || options.rewindOnChange) {
|
|
97
|
+
return player.rewind();
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return new $.Deferred().resolve().promise();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function startEventPropagation(player, id) {
|
|
105
|
+
that.listenTo(player, 'play', function() {
|
|
106
|
+
that.trigger('play', {audioFileId: id});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
that.listenTo(player, 'pause', function() {
|
|
110
|
+
that.trigger('pause', {audioFileId: id});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
that.listenTo(player, 'timeupdate', function() {
|
|
114
|
+
that.trigger('timeupdate', {audioFileId: id});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
that.listenTo(player, 'ended', function() {
|
|
118
|
+
that.trigger('ended', {audioFileId: id});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function stopEventPropagation(player) {
|
|
123
|
+
that.stopListening(player);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
_.extend(pageflow.Audio.MultiPlayer.prototype, Backbone.Events);
|