Problem/Motivation

Sometimes a landing page wants to add a splash widget to force the user looking at it.

If you need the same splash screen across many pages, using a Paragraph is possibly a bad fit and a block could be better.
But if this is a content requirement, it makes sense to put the information into a content paragraph and trigger its splashiness.
If that block is in the library, we could reuse it and bind the effect to only show once in all usages or whatever is needed.

Proposed resolution

Create a splash plugin that triggers a splash screen with the content of a Paragraph.

As i'm out of ideas what tool to use, i would simply start with the Plugin, triggering a jQuery UI Dialog with that content.

Behavior settings are:
- Checkbox: Remove content from page. (So it's not cloned into the splash, but the original is removed.)
And more settings if the splash is always reopened or a cookie (with lifetime X) is used to save that the splash is closed.
Not sure if it's closed by cookie and the setting "remove" is chosen, if we should still remove it from the page. ;-)

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#32 new_plugin_splash_screen-2851461-32.patch18.65 KBCTaPByK
#30 new_plugin_splash_screen-2851461-30.patch17.51 KBCTaPByK
#30 interdiff-27-30.txt7.91 KBCTaPByK
#27 new_plugin_splash_screen-2851461-27.patch17.32 KBCTaPByK
#27 interdiff-25-27.txt527 bytesCTaPByK
#25 new_plugin_splash_screen-2851461-25.patch17.32 KBCTaPByK
#24 new_plugin_splash_screen-2851461-24.patch17.92 KBCTaPByK
#24 interdiff-22-24.txt3.72 KBCTaPByK
#22 new_plugin_splash_screen-2851461-22.patch17.18 KBCTaPByK
#22 interdiff-18-22.txt3.45 KBCTaPByK
#18 new_plugin_splash_screen-2851461-18.patch16.73 KBCTaPByK
#18 interdiff-16-18.txt5.49 KBCTaPByK
#16 new_plugin_splash_screen-2851461-16.patch14.95 KBCTaPByK
#16 interdiff-12-16.txt15.57 KBCTaPByK
#12 new_plugin_splash_screen-2851461-12.patch15.52 KBCTaPByK
#12 interdiff-11-12.txt6.07 KBCTaPByK
#11 new_plugin_splash_screen-2851461-11.patch15.88 KBCTaPByK
#11 interdiff-8-11.txt1.74 KBCTaPByK
#8 new_plugin_splash_screen-2851461-8.patch15.75 KBCTaPByK
#7 new_plugin_splash_screen-2851461-7.patch9.28 KBCTaPByK
#7 interdiff-5-7.txt563 bytesCTaPByK
#5 new_plugin_splash_screen-2851461-5.patch8.73 KBCTaPByK
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

miro_dietiker created an issue. See original summary.

Primsi’s picture

Issue tags: +drupalmountaincamp
miro_dietiker’s picture

Component: Code » Modal
CTaPByK’s picture

Assigned: Unassigned » CTaPByK
CTaPByK’s picture

Status: Active » Needs review
FileSize
8.73 KB

Initial patch.

Status: Needs review » Needs work

The last submitted patch, 5: new_plugin_splash_screen-2851461-5.patch, failed testing.

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
563 bytes
9.28 KB

Schema update.

CTaPByK’s picture

Updated with behavior settings and with basic test coverage.

miro_dietiker’s picture

+++ b/js/splash-screen.js
@@ -0,0 +1,21 @@
+    $.removeCookie('paragraphs_splash');
...
+        $.cookie('paragraphs_splash', 1, {expires: 1});

Mind that it's a single cookie now. Users might want to use multiple independent splash screens on different pages. Just because one splash screen was clicked away doesn't mean other splashes should no more show up. But the code means exactly that.

So a user either needs to configure the cookie postfix in use, or we use the same cookie with multiple values. Value / postfix could be a hash from entity type + id -- or the user can configure it. We first need to define this...

Let's create follow-ups for the things we wanto postpone, and then define the MVP here.

CTaPByK’s picture

CTaPByK’s picture

Use modal behavior for dialog.

CTaPByK’s picture

Rebased and test is updated a bit.

Status: Needs review » Needs work

The last submitted patch, 12: new_plugin_splash_screen-2851461-12.patch, failed testing.

CTaPByK’s picture

Status: Needs work » Needs review
Primsi’s picture

Status: Needs review » Needs work
  1. +++ b/config/install/field.field.paragraph.splash_screen.paragraph_splash_screen.yml
    index 0000000..fe56be2
    --- /dev/null
    
    --- /dev/null
    +++ b/config/install/field.storage.paragraph.paragraph_splash_screen.yml
    
    +++ b/config/install/field.storage.paragraph.paragraph_splash_screen.yml
    +++ b/config/install/field.storage.paragraph.paragraph_splash_screen.yml
    @@ -0,0 +1,22 @@
    

    Not sure if we need another field for this. Could we use container?

  2. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +
    

    Additional new line.

  3. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +          $build['#attributes']['class'][] = 'paragraphs-show-modal';
    

    Maybe we could have more splas-screen oriented class name? Ie paragraphs-splashscreen-enabled or something along those lines?

  4. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +    $build['#attached']['drupalSettings'] = [
    +      'use_cookie' => $paragraph->getBehaviorSetting($this->getPluginId(), 'splash_screen_cookie'),
    +    ];
    

    Similarly to the other issue, we probably don't want to have this directly in drupalSettings.

  5. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    

    We need to implement validateConfigurationForm, otherwise we can enable the plugin without proper configuration: see other plugins.

  6. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +    $field_definitions = $this->entityFieldManager->getFieldDefinitions('paragraph', $paragraphs_type->id());
    +    $fields = array_filter($field_definitions, function ($definition) {
    +      return $definition instanceof FieldConfigInterface;
    +    });
    +    $options = array_map(function ($definition) {
    +      return $definition->getLabel();
    +    }, $fields);
    

    I think we could use $this->getFieldNameOptions() here

  7. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +        '#title' => $this->t('Splash screen field'),
    

    only 'Splash screen'

  8. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +          ':link' => Url::fromRoute("entity.{$paragraphs_type->getEntityType()->getBundleOf()}.field_ui_fields", [$paragraphs_type->getEntityTypeId() => $paragraphs_type->id()])->toString(),
    

    Url::fromRoute('entity.paragraph.field_ui_fields', [
    $paragraphs_type->getEntityTypeId() => $paragraphs_type->id()
    ]);

  9. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +    $form['splash_screen'] = [
    

    Maybe splash_screen_disable?

  10. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +      '#title' => $this->t('Disable splash behaviour'),
    

    We went for the american english variant, so it's behavior.

  11. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +      '#description' => $this->t("If checked splash behaviour will be disabled and paragraph's content will be displayed as part of the page content."),
    

    and it's content will be displayed

  12. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +      '#description' => $this->t('Use cookie to save closed state of the splash screen.'),
    

    This could be a bit less technical.

  13. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    

    I would move this under the configuration form method

  14. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,186 @@
    +      return [$this->t('Splash screen: @splash_screen', ['@splash_screen' => 'disabled'])];
    

    Doesn't this make the summary always appear as disabled?

  15. +++ b/src/Tests/ParagraphsSplashScreenTest.php
    @@ -0,0 +1,68 @@
    +  public static $modules = [
    +    'paragraphs_collection',
    +    'link',
    

    Maybe I missed something, but to we need link here?

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
15.57 KB
14.95 KB

Fixed. For 15. i think link is needed, see https://www.drupal.org/node/2852384

Status: Needs review » Needs work

The last submitted patch, 16: new_plugin_splash_screen-2851461-16.patch, failed testing.

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
5.49 KB
16.73 KB

Fixes and updates.

Status: Needs review » Needs work

The last submitted patch, 18: new_plugin_splash_screen-2851461-18.patch, failed testing.

CTaPByK’s picture

Status: Needs work » Needs review
miro_dietiker’s picture

Status: Needs review » Needs work
  1. +++ b/js/splash-screen.js
    @@ -0,0 +1,22 @@
    +  if (drupalSettings.use_cookie === 0) {
    

    Where is this drupalSettings.use_cookie defined?

  2. +++ b/js/splash-screen.js
    @@ -0,0 +1,22 @@
    +    $.removeCookie('paragraphs_splash');
    ...
    +        $.cookie('paragraphs_splash', 1, {expires: 1});
    

    This still creates ONE global cookie. 5 content items can have 5 completely different splash elements.

    If you store that i closed one of those 5, i still need to see the other 4 splash screens!

    Also just because one splash screen has cookie usage disabled doesn't mean you should delete the state cookie for other splash screens that are cookie based.

It seems we need a test with multiple splash screens to get this right.
I would be even fine with getting this in without any cookie at all and always opening the splash screen. It's cumbersome, but clear in behavior. But if we introduce cookies, it needs to treat each splash screen as a separate instance.

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
3.45 KB
17.18 KB

Updated to use separate cookie for each splash screen.

miro_dietiker’s picture

Status: Needs review » Needs work
  1. +++ b/js/splash-screen.js
    @@ -7,16 +7,21 @@
    +  $.each(splash_screen, function (index, value) {
    

    value is a bad variable name here. I think "setting" would be much better.

  2. +++ b/js/splash-screen.js
    @@ -7,16 +7,21 @@
    +          if (!$.cookie('paragraph_splash_' + value.cookie_key) && value.use_cookie === 1) {
    
    +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -80,19 +81,20 @@ class ParagraphsSplashScreenPlugin extends ParagraphsBehaviorBase {
    +      'cookie_key' => Crypt::hashBase64($paragraph->id()),
    

    We put cookie_key if there is no intended cookie use (line before)?
    You would need to first check value.use_cookie though.

  3. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -80,19 +81,20 @@ class ParagraphsSplashScreenPlugin extends ParagraphsBehaviorBase {
    +        if (!$paragraph->getBehaviorSetting($this->getPluginId(), 'splash_screen_cookie') || !$this->request->cookies->get('paragraph_splash_' . Crypt::hashBase64($paragraph->id()))) {
    +          $build['#attributes']['class'][] = 'paragraphs-splashscreen-enabled-' . Crypt::hashBase64($paragraph->id());
    

    Is this similarly done in other core areas?
    I guess you don't want to expose paragraph ids? The resulting cookie key is very long and this could cause trouble with header limitations.
    Is this worth it?

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
3.72 KB
17.92 KB
CTaPByK’s picture

Primsi’s picture

Status: Needs review » Needs work

Just this one thing more, apart from that looks ok to me.

+++ b/js/splash-screen.js
@@ -0,0 +1,27 @@
+            $.cookie('paragraph_splash_' + setting.cookie_key, 1, {expires: 7});

7 days might be a bit low. I am ok if we hardcode this for now, but let's increase it to 30 days or something similar.

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
527 bytes
17.32 KB

Increased from 7 to 30 days.

miro_dietiker’s picture

IMHO we should also enable cookie usage by default.

I don't understand the label tor the "disable" setting. It should control if the the paragraph is still present in the DOM when the overlay is closed.

Primsi’s picture

Status: Needs review » Needs work
  1. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,192 @@
    +      $form['paragraph_splash_screen'] = [
    

    Maybe we should rename this to something like "splash_screen_content"

  2. +++ b/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,192 @@
    +      '#default_value' => $paragraph->getBehaviorSetting($this->getPluginId(), 'splash_screen_cookie'),
    

    Yes, let's enable this by default

About the label: this actually disables the pop-up behavior. Do we want the setting to control if the content from the modal is also rendered on the page or not?

Let's also add Drupal.announce when opening the modal. See [#2014521]

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
7.91 KB
17.51 KB
Primsi’s picture

Status: Needs review » Needs work

This needs to be moved to the demo module as per #2864303: Move experimental types and plugins to demo

CTaPByK’s picture

Status: Needs work » Needs review
FileSize
18.65 KB

Moved to the demo module.

Status: Needs review » Needs work

The last submitted patch, 32: new_plugin_splash_screen-2851461-32.patch, failed testing.

CTaPByK’s picture

Status: Needs work » Needs review
Primsi’s picture

Status: Needs review » Needs work

Hm, this doesn't seem to work any more for me.

About the "If checked splash screen will be disabled and it's content will be removed from the page content." option: having both disabled splash and content removed doesn't make much sense. IMHO a sensible option would be to offer the possibility to show content on the page even if we have splash screen, so effectively hiding it by default.

Another option which would make sense probably is to have an option where the splash screen is disabled which would result in content showing in the page. If this option would be check the above option should be disabled (this could be a follow up maybe).

Primsi’s picture

@miro_dietiker reminded me that we will have tristate, so we can scratch the last paragraph from #35

CTaPByK’s picture

Assigned: CTaPByK » Unassigned
miro_dietiker’s picture

  1. +++ b/modules/paragraphs_collection_demo/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,193 @@
    +        '#description' => $this->t('Choose a field to be used as the splash screen container.'),
    

    IMHO we should not need to choose a field, but promote the container as a whole to the modal.

  2. +++ b/modules/paragraphs_collection_demo/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,193 @@
    +  public function buildBehaviorForm(ParagraphInterface $paragraph, array &$form, FormStateInterface $form_state) {
    

    Since there's no way to enable the plugin per instance, it will always splash. Thus you need tristate to add it conditionally or you need to create an own splash screen Paragraph type.

  3. +++ b/modules/paragraphs_collection_demo/src/Tests/ParagraphsSplashScreenPluginTest.php
    @@ -0,0 +1,102 @@
    +  public function testSplashScreenPlugin() {
    

    Missing tests is enable cookie and check persistence of closing the splash screen.

    Also testing that the content is still present in DOM after closing (with its setting).

  4. +++ b/modules/paragraphs_collection_demo/src/Tests/ParagraphsSplashScreenPluginTest.php
    @@ -0,0 +1,102 @@
    +    $element = $this->xpath('//div[contains(@class, :splash-class)]', [
    

    Should be tested with a JS test.

  5. +++ b/modules/paragraphs_collection_demo/src/Tests/ParagraphsSplashScreenPluginTest.php
    @@ -0,0 +1,102 @@
    +    $this->assertRaw('class="paragraphs-collapsed-description">Splash screen test, Splash screen: disabled');
    

    We don't want to have a disabled message.

miro_dietiker’s picture

+++ b/modules/paragraphs_collection_demo/js/splash-screen.js
@@ -0,0 +1,32 @@
+      $(this).dialog({

This needs an identifier for custom theming.

miro_dietiker’s picture

Known limitation: Maximum one splash Paragraph per page. Should be validated.

There's modal by Boostrap:
https://getbootstrap.com/docs/4.0/components/modal/

And Bootstrap Paragraphs has it implemented:
https://bp.jimbir.ch/paragraph-types/modal

We could simply support bootstrap modal if present and otherwise fallback to jQuery modal.

The modals seem to support a title. We need to support a separate title field.

  1. +++ b/modules/paragraphs_collection_demo/src/Plugin/paragraphs/Behavior/ParagraphsSplashScreenPlugin.php
    @@ -0,0 +1,193 @@
    +    $build['#attached']['drupalSettings']['paragraphs_collection']['splash_screen'][$paragraph->id()] = [
    

    We need to pass in the modal title here.

  2. +++ b/modules/paragraphs_collection_demo/js/splash-screen.js
    @@ -0,0 +1,32 @@
    +      $(this).dialog({
    

    And consider title here.