From 48a131acc91c0635eefbadd5adcd9283a85828bb Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Mon, 10 Aug 2020 15:13:33 +0200 Subject: [PATCH 1/4] Allow registering entry type specific themes Paged and Scrolled entries will have different themes available and will support different theme options. REDMINE-17775 --- lib/pageflow/entry_type_configuration.rb | 1 + spec/pageflow/global_config_api_spec.rb | 22 +++++++++++++++++++ spec/support/helpers/test_entry_type.rb | 12 +++++++++- .../pageflow/admin/features_tab_spec.rb | 11 +++------- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/lib/pageflow/entry_type_configuration.rb b/lib/pageflow/entry_type_configuration.rb index 96d4f5c6cf..98baf0246a 100644 --- a/lib/pageflow/entry_type_configuration.rb +++ b/lib/pageflow/entry_type_configuration.rb @@ -15,6 +15,7 @@ def initialize(config, entry_type) delegate :help_entries, to: :@config delegate :hooks, to: :@config delegate :revision_components, to: :@config + delegate :themes, to: :@config delegate :widget_types, to: :@config def plugin(plugin) diff --git a/spec/pageflow/global_config_api_spec.rb b/spec/pageflow/global_config_api_spec.rb index 31584ee18a..478f4d210b 100644 --- a/spec/pageflow/global_config_api_spec.rb +++ b/spec/pageflow/global_config_api_spec.rb @@ -650,6 +650,28 @@ def initialize(*) expect(skulled_help_entry_names).not_to include('phaged_entry') end + it 'allows registering themes in for_entry_type block' do + pageflow = PageflowModule.new + phaged_entry_type = TestEntryType.new(name: 'phaged') + skulled_entry_type = TestEntryType.new(name: 'skulled') + pageflow.configure do |config| + config.entry_types.register(phaged_entry_type) + config.entry_types.register(skulled_entry_type) + + config.for_entry_type(phaged_entry_type) do |c| + c.themes.register(:phaged_theme) + end + end + phaged_entry = double('entry', entry_type: phaged_entry_type, enabled_feature_names: []) + skulled_entry = double('entry', entry_type: skulled_entry_type, enabled_feature_names: []) + + phaged_help_entry_names = pageflow.config_for(phaged_entry).themes.map(&:name) + skulled_help_entry_names = pageflow.config_for(skulled_entry).themes.map(&:name) + + expect(phaged_help_entry_names).to include('phaged_theme') + expect(skulled_help_entry_names).not_to include('phaged_theme') + end + it 'allows calling plugin method inside for_entry_type block' do pageflow = PageflowModule.new entry_type = TestEntryType.new(name: 'phaged') diff --git a/spec/support/helpers/test_entry_type.rb b/spec/support/helpers/test_entry_type.rb index 10961bdea1..b233ad0f92 100644 --- a/spec/support/helpers/test_entry_type.rb +++ b/spec/support/helpers/test_entry_type.rb @@ -1,7 +1,17 @@ module Pageflow module TestEntryType def self.register(config, options = {}) - config.entry_types.register(new(options)) + entry_type = new(options) + config.entry_types.register(entry_type) + + config.for_entry_type(entry_type) do |entry_type_config| + # Revisions and entry templates use a theme named "default" by + # default. We need to register such a theme to prevent + # validation errors. + entry_type_config.themes.register(:default) + end + + entry_type end def self.new(options = {}) diff --git a/spec/views/components/pageflow/admin/features_tab_spec.rb b/spec/views/components/pageflow/admin/features_tab_spec.rb index 4f1748039e..c7c37b36a6 100644 --- a/spec/views/components/pageflow/admin/features_tab_spec.rb +++ b/spec/views/components/pageflow/admin/features_tab_spec.rb @@ -33,10 +33,8 @@ module Pageflow end it 'displays fields for features registed for entry type of passed entry' do - some_entry_type = TestEntryType.new(name: 'some') - pageflow_configure do |config| - config.entry_types.register(some_entry_type) + some_entry_type = TestEntryType.register(config, name: 'some') config.for_entry_type(some_entry_type) do |entry_type_config| entry_type_config.features.register('some_feature') @@ -51,12 +49,9 @@ module Pageflow end it 'does not display fields for features registered for other entry type' do - some_entry_type = TestEntryType.new(name: 'some') - other_entry_type = TestEntryType.new(name: 'other') - pageflow_configure do |config| - config.entry_types.register(some_entry_type) - config.entry_types.register(other_entry_type) + TestEntryType.register(config, name: 'some') + other_entry_type = TestEntryType.register(config, name: 'other') config.for_entry_type(other_entry_type) do |entry_type_config| entry_type_config.features.register('some_feature') From b08bb42e7fd8c43ab1696215801638672f77bb25 Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Mon, 10 Aug 2020 15:06:54 +0200 Subject: [PATCH 2/4] Include theme data in scrolled entry seed Copy default theme to host application when installing Pageflow Scrolled. Include theme asset paths and theme options in the seed data. Generating the entry JSON seed now requires Webpacker to be installed. We thefore need to run the Pageflow Scrolled install generator when generating the dummy app which is used to run the storybook seed task. REDMINE-17775 --- .travis.yml | 2 +- .../entry_json_seed_helper.rb | 3 +- .../pageflow_scrolled/themes_helper.rb | 8 +++ .../entry_json_seed/_entry.json.jbuilder | 2 + .../entry_json_seed/_theme.json.jbuilder | 7 +++ entry_types/scrolled/doc/creating_themes.md | 21 +++++++ .../install/install_generator.rb | 8 +++ .../install/templates/theme/logoDesktop.svg | 56 +++++++++++++++++++ .../install/templates/theme/logoMobile.svg | 22 ++++++++ .../entry_json_seed_helper_spec.rb | 31 ++++++++++ .../initializer/templates/pageflow.rb | 23 +++++--- 11 files changed, 173 insertions(+), 10 deletions(-) create mode 100644 entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb create mode 100644 entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder create mode 100644 entry_types/scrolled/doc/creating_themes.md create mode 100644 entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg create mode 100644 entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg diff --git a/.travis.yml b/.travis.yml index c205589e3c..9f4b91df14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -113,7 +113,7 @@ jobs: } fi - yarn install - - (cd entry_types/scrolled; bundle exec rake pageflow_scrolled:dummy) + - (cd entry_types/scrolled; PAGEFLOW_PLUGIN_ENGINE=pageflow_scrolled bundle exec rake pageflow_scrolled:dummy) script: - | export PAGEFLOW_PAPERCLIP_S3_ROOT=$([[ $ON_UPSTREAM == "true" ]] && diff --git a/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb b/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb index 02455288e5..1428a08058 100644 --- a/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +++ b/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb @@ -7,9 +7,10 @@ module EntryJsonSeedHelper include Pageflow::RenderJsonHelper include Pageflow::FilesHelper include Pageflow::EntriesHelper + include Pageflow::MetaTagsHelper include Pageflow::SocialShareLinksHelper include PageflowScrolled::I18nHelper - include Pageflow::MetaTagsHelper + include PageflowScrolled::ThemesHelper def scrolled_entry_json_seed_script_tag(scrolled_entry, options = {}) seed_json = render_json do |json| diff --git a/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb b/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb new file mode 100644 index 0000000000..49848ef2df --- /dev/null +++ b/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb @@ -0,0 +1,8 @@ +module PageflowScrolled + # @api private + module ThemesHelper + def scrolled_theme_asset_path(theme, path) + asset_pack_path("media/pageflow-scrolled/themes/#{theme.name}/#{path}") + end + end +end diff --git a/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder b/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder index 8705d59710..f30c67adac 100644 --- a/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +++ b/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder @@ -28,6 +28,8 @@ json.config do json.url entry_privacy_link_url(entry) end end + + json.partial! 'pageflow_scrolled/entry_json_seed/theme', theme: entry.theme end unless options[:skip_i18n] diff --git a/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder b/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder new file mode 100644 index 0000000000..07a933a233 --- /dev/null +++ b/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder @@ -0,0 +1,7 @@ +json.theme do + json.assets do + json.logo_desktop scrolled_theme_asset_path(theme, 'logoDesktop.svg') + json.logo_mobile scrolled_theme_asset_path(theme, 'logoMobile.svg') + end + json.options(theme.options.deep_transform_keys { |key| key.to_s.camelize(:lower) }) +end diff --git a/entry_types/scrolled/doc/creating_themes.md b/entry_types/scrolled/doc/creating_themes.md new file mode 100644 index 0000000000..480e7d30aa --- /dev/null +++ b/entry_types/scrolled/doc/creating_themes.md @@ -0,0 +1,21 @@ +# Creating Themes + +Copy the default theme directory +`app/javascript/pageflow-scrolled/themes/default` to a new directory +with the name of your theme +(e.g. `app/javascript/pageflow-scrolled/themes/my_custom_theme`) and +replace images as needed. + +Register the theme in the Pageflow initializer: + + # config/initializers/pageflow.rb + Pageflow.configure do |config| + config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config| + # ... + + entry_type_config.themes.register(:my_custom_theme, + logo_alt_text: '...') + end + end + +Copy all options from the default theme and make the desired changes. diff --git a/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb b/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb index a4157904d6..dede0d1b7a 100644 --- a/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +++ b/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb @@ -4,6 +4,8 @@ module Generators class InstallGenerator < Rails::Generators::Base desc 'Installs Pageflow Scrolled entry type.' + source_root File.expand_path('templates', __dir__) + def install_webpacker require 'webpacker' gemfile = File.expand_path('../../../../../../Gemfile', __dir__) @@ -36,6 +38,8 @@ def frontend_pack create_file 'app/javascript/packs/pageflow-scrolled-frontend.js', <<-JS import 'pageflow-scrolled/frontend'; import 'pageflow-scrolled/contentElements-frontend'; + + require.context('../pageflow-scrolled/themes', true); JS end @@ -52,6 +56,10 @@ def theme_pack @import "pageflow-scrolled/contentElements-frontend.css"; JS end + + def default_theme + directory 'theme', 'app/javascript/pageflow-scrolled/themes/default' + end end end end diff --git a/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg b/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg new file mode 100644 index 0000000000..39b6e1c759 --- /dev/null +++ b/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg @@ -0,0 +1,56 @@ + + + + +Element 1 + + + + + + + + + + + + + + + + + + + + diff --git a/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg b/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg new file mode 100644 index 0000000000..2e74fed277 --- /dev/null +++ b/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg @@ -0,0 +1,22 @@ + + + + +Pageflow + + + + + + + + diff --git a/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb b/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb index f75a0efadd..dcfc8a6911 100644 --- a/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb +++ b/entry_types/scrolled/spec/helpers/pageflow_scrolled/entry_json_seed_helper_spec.rb @@ -324,6 +324,37 @@ def render(helper, entry, options = {}) }) end + it 'renders theme assets' do + entry = create(:published_entry) + + result = render(helper, entry) + + expect(result).to include_json(config: { + theme: { + assets: { + logoDesktop: %r{themes/default/logoDesktop.*svg$} + } + } + }) + end + + it 'renders theme camelized options' do + pageflow_configure do |config| + config.themes.register(:default, some_option: 'value') + end + entry = create(:published_entry) + + result = render(helper, entry) + + expect(result).to include_json(config: { + theme: { + options: { + someOption: 'value' + } + } + }) + end + context 'i18n' do include_context 'fake translations' diff --git a/lib/generators/pageflow/initializer/templates/pageflow.rb b/lib/generators/pageflow/initializer/templates/pageflow.rb index 7a3e96ede7..a3d29344e3 100644 --- a/lib/generators/pageflow/initializer/templates/pageflow.rb +++ b/lib/generators/pageflow/initializer/templates/pageflow.rb @@ -8,14 +8,21 @@ config.plugin(Pageflow.built_in_widget_types_plugin) # config.plugin(Pageflow::Rainbow.plugin) - # Add custom themes by invoking the pageflow:theme generator and - # registering the theme here. - # - # $ rails generate pageflow:theme my_custom_theme - # => creates app/assets/stylesheets/pageflow/themes/my_custom_theme.css.scss - # - config.themes.register(:default) - # config.themes.register(:my_custom_theme) + config.for_entry_type(PageflowPaged.entry_type) do |entry_type_config| + # Add custom themes by invoking the pageflow:theme generator and + # registering the theme here. + # + # $ rails generate pageflow:theme my_custom_theme + # => creates app/assets/stylesheets/pageflow/themes/my_custom_theme.css.scss + # + entry_type_config.themes.register(:default) + # config.themes.register(:my_custom_theme) + end + + config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config| + entry_type_config.themes.register(:default, + logo_alt_text: 'Pageflow') + end # String to interpolate into paths of files generated by paperclip # preprocessors. This allows to refresh cdn caches after From 63b8b18b8ca32c20f6ee73fcb3d9c7b8510ad5b8 Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Mon, 10 Aug 2020 15:24:57 +0200 Subject: [PATCH 3/4] Add useTheme entry state hook Reusable hook to access thene asset paths and options from seed config. --- .../package/spec/entryState/theme-spec.js | 23 +++++++++++++++++ .../package/spec/support/normalizeSeed.js | 12 ++++++++- .../scrolled/package/src/entryState/index.js | 1 + .../scrolled/package/src/entryState/theme.js | 25 +++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 entry_types/scrolled/package/spec/entryState/theme-spec.js create mode 100644 entry_types/scrolled/package/src/entryState/theme.js diff --git a/entry_types/scrolled/package/spec/entryState/theme-spec.js b/entry_types/scrolled/package/spec/entryState/theme-spec.js new file mode 100644 index 0000000000..bf38719e40 --- /dev/null +++ b/entry_types/scrolled/package/spec/entryState/theme-spec.js @@ -0,0 +1,23 @@ +import {useTheme} from 'entryState'; + +import {renderHookInEntry} from 'support'; + +describe('useTheme', () => { + it('reads data from seed', () => { + const {result} = renderHookInEntry( + () => useTheme(), { + seed: { + themeOptions: { + some: 'option' + } + } + } + ); + + const theme = result.current; + expect(theme).toMatchObject({ + assets: {}, + options: {some: 'option'} + }); + }); +}); diff --git a/entry_types/scrolled/package/spec/support/normalizeSeed.js b/entry_types/scrolled/package/spec/support/normalizeSeed.js index 5ca16e92a9..4b2512b869 100644 --- a/entry_types/scrolled/package/spec/support/normalizeSeed.js +++ b/entry_types/scrolled/package/spec/support/normalizeSeed.js @@ -8,6 +8,7 @@ * @param {Object} [options.shareUrlTemplates] - Mapping of share provider names to sharing urls. * @param {String} [options.defaultFileRights] - Default file rights of entry's account. * @param {Object} [options.legalInfo] - imprint, copyright and privacy information of entry. + * @param {Object} [options.themeOptions] - Options set via theme registration. * @param {Object} [options.entry] - attributes of entry. * @param {Array} [options.imageFiles] - Array of objects with image file attributes of entry. * @param {Array} [options.videoFiles] - Array of objects with video file attributes of entry. @@ -26,6 +27,7 @@ export function normalizeSeed({ shareUrlTemplates, defaultFileRights, legalInfo, + themeOptions, entry, imageFiles, videoFiles, @@ -67,7 +69,8 @@ export function normalizeSeed({ prettyUrl: prettyUrl, shareUrlTemplates: normalizeShareUrlTemplates(shareUrlTemplates), defaultFileRights: defaultFileRights, - legalInfo: normalizeLegalInfo(legalInfo) + legalInfo: normalizeLegalInfo(legalInfo), + theme: normalizeTheme(themeOptions) }, collections: { entries: normalizedEntries, @@ -163,6 +166,13 @@ function normalizeLegalInfo(legalInfo) { } } +function normalizeTheme(options = {}) { + return { + assets: {}, + options + } +} + function normalizeCollection(collection = [], defaults = {}) { return collection.map((item, index) => ({ id: index + 1, diff --git a/entry_types/scrolled/package/src/entryState/index.js b/entry_types/scrolled/package/src/entryState/index.js index d73770adf8..5c73d82dfa 100644 --- a/entry_types/scrolled/package/src/entryState/index.js +++ b/entry_types/scrolled/package/src/entryState/index.js @@ -5,6 +5,7 @@ export {useFile} from './useFile'; export {useNestedFiles} from './useNestedFiles'; export {useFileRights, useLegalInfo, useCredits} from './legalInfo'; export {useAvailableQualities} from './useAvailableQualities'; +export {useTheme} from './theme'; export {EntryStateProvider, useEntryStateDispatch} from './EntryStateProvider'; diff --git a/entry_types/scrolled/package/src/entryState/theme.js b/entry_types/scrolled/package/src/entryState/theme.js new file mode 100644 index 0000000000..dbe67e3034 --- /dev/null +++ b/entry_types/scrolled/package/src/entryState/theme.js @@ -0,0 +1,25 @@ +import {useEntryState} from "./EntryStateProvider"; + +/** + * Returns an object containing theme asset paths. + * + * @example + * + * const theme = useTheme(); + * theme // => + * { + * assets: { + * logoDesktop: 'path/to/logoDesktop.svg', + * logoMobile: 'path/to/logoMobile.svg' + * }, + * options: { + * // options passed to `themes.register` in `pageflow.rb` initializer + * // with camleized keys. + * } + * } + */ +export function useTheme() { + const entryState = useEntryState(); + + return entryState.config.theme; +} From 9274d0ec369b2baf540139294664f9e5775783ee Mon Sep 17 00:00:00 2001 From: Tim Fischbach Date: Mon, 10 Aug 2020 15:27:51 +0200 Subject: [PATCH 4/4] Use theme logo in navigation Replace hard coded image with file that can be supplied by host application. REDMINE-17775 --- .../images/navigation/wdr_logo_header.svg | 12 ----------- .../src/frontend/navigation/AppHeader.js | 4 ++-- .../frontend/navigation/AppHeader.module.css | 8 ++++---- .../package/src/frontend/navigation/Logo.js | 20 +++++++++++++++++++ 4 files changed, 26 insertions(+), 18 deletions(-) delete mode 100644 entry_types/scrolled/package/src/frontend/assets/images/navigation/wdr_logo_header.svg create mode 100644 entry_types/scrolled/package/src/frontend/navigation/Logo.js diff --git a/entry_types/scrolled/package/src/frontend/assets/images/navigation/wdr_logo_header.svg b/entry_types/scrolled/package/src/frontend/assets/images/navigation/wdr_logo_header.svg deleted file mode 100644 index d831093539..0000000000 --- a/entry_types/scrolled/package/src/frontend/assets/images/navigation/wdr_logo_header.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/entry_types/scrolled/package/src/frontend/navigation/AppHeader.js b/entry_types/scrolled/package/src/frontend/navigation/AppHeader.js index 545e63e912..2256b6c3a9 100644 --- a/entry_types/scrolled/package/src/frontend/navigation/AppHeader.js +++ b/entry_types/scrolled/package/src/frontend/navigation/AppHeader.js @@ -8,9 +8,9 @@ import {HamburgerIcon} from './HamburgerIcon' import {ChapterLink} from "./ChapterLink"; import {LegalInfoMenu} from "./LegalInfoMenu"; import {SharingMenu} from "./SharingMenu"; +import {Logo} from './Logo'; import styles from './AppHeader.module.css'; -import WDRlogo from '../assets/images/navigation/wdr_logo_header.svg'; export function AppHeader(props) { const [navExpanded, setNavExpanded] = useState(true); @@ -89,7 +89,7 @@ export function AppHeader(props) { - +