cms icon indicating copy to clipboard operation
cms copied to clipboard

Data is lost when re-ordering a Replicator block

Open dniccum opened this issue 2 years ago • 16 comments

Bug description

We are currently experiencing an issue where content/settings are being lost when blocks within the Replicator fieldtype are changed. When the re-order is performed and the save/published executed, but the author does not leave the page, the content appears to be fine. However if you leave the page and/or refresh, selections within Select, Image, and Toggle fieldtypes are getting removed.

This has been replicated on various environments (production, staging, local) with various levels of caching.

How to reproduce

  1. Create a new field set called background that has the following items: i. Background color Select with the following keys: bg-white, bg-black ii. Background image - Assets iii. Background Animation - Assets iv. Background Animation - Assets
  2. Create another field set that links to the previous fieldset and also includes the following inputs: i. Section Image - Assets ii. Content - Bard
  3. Create a collection with a blueprint that includes a replicator field and references the aforementioned fieldset
  4. Create and save a page and add multiple entries of the same replicator field type. Ensure that all of the content is populated.
  5. Re-edit the page and simply just re-order the content. Some of the assets should be missing and/or swapped and some content might be missing.

Also see the provided video below on how to reproduce. I do want to mention that while the video does mention the use of "Revealer" fields, this is not true. These are toggles that simply shows and hides the inputs:

https://www.loom.com/share/d684d8c1c0ab4ebfbdc63b58788cb247

Logs

No response

Versions

Statamic 3.3.16 Pro
Laravel 9.19.0
PHP 8.0.12
aerni/font-awesome 1.2.0
aryehraber/statamic-logbook 2.1.0
doublethreedigital/duplicator 2.3.1
joetannenbaum/antlers-stack-tags 0.1.0
octoper/statamic-blade-components 2.0.0
rias/statamic-redirect 2.3.6
ritson/placid-statamic 3.1.0
webographen/statamic-admin-log 1.0.6

Installation

Starter Kit using via CLI

Antlers Parser

regex (default)

Additional details

The site is also using Full Static Page caching and S3 assets.

dniccum avatar Jun 29 '22 15:06 dniccum

After further discovery, this appears to be happening to Replicator blocks that are of the same type.

dniccum avatar Jun 29 '22 16:06 dniccum

Hey @dniccum, was just starting to look into this. Did you close because it's no longer an issue? Or if it is still an issue, maybe you could also provide me with a blueprint file to test with?

jesseleite avatar Jun 29 '22 16:06 jesseleite

Sorry @jesseleite, I must have fat-fingered something. See the requested assets below:

Page blueprint

title: Page
sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          input_type: text
          localizable: true
          listable: true
          display: Title
          validate:
            - required
      -
        handle: headline
        field: content_grid.title
        config:
          character_limit: 50
          display: Headline
          instructions: 'Enter a headline that will be shown at the top of the page'
          width: 100
          if:
            template: 'equals home'
          validate:
            - 'required_if:template,home'
      -
        handle: featured_post
        field:
          max_items: 1
          mode: default
          create: false
          collections:
            - blog
          display: 'Featured Post'
          type: entries
          icon: entries
          instructions: 'Choose a Blog Article to be the featured post, putting it large and in charge at the top of the index page.'
          listable: hidden
          instructions_position: above
          if:
            template: 'equals blog/index'
      -
        handle: gateway_bg_image_std
        field:
          mode: list
          container: assets
          folder: images
          restrict: true
          allow_uploads: true
          show_filename: true
          max_files: 1
          display: 'Gateway Standard Background Image'
          type: assets
          icon: assets
          instructions: 'Select an image to use as the background for the user path selection block for non-mobile browsers.'
          listable: hidden
          instructions_position: above
          if:
            template: 'equals home'
      -
        handle: header_bg_img
        field:
          mode: list
          container: assets
          restrict: false
          allow_uploads: true
          show_filename: true
          display: 'Header Background Image'
          type: assets
          icon: assets
          instructions: 'Choose/Upload an image to use for the header background. Leave blank to use a standard utility treatment.'
          width: 50
          listable: hidden
          instructions_position: above
          if:
            template: 'equals default'
      -
        handle: header_text_color
        field:
          options:
            black: Black
            gray-300: Sand
          multiple: false
          clearable: false
          searchable: true
          taggable: false
          push_tags: false
          cast_booleans: false
          display: 'Header Text Color'
          type: select
          icon: select
          instructions: 'Choose a color for the (title) text used in the page header.'
          width: 50
          listable: hidden
          instructions_position: above
          if:
            template: 'equals default'
          default: black
      -
        import: product_page
      -
        import: page_builder
  seo:
    display: SEO
    fields:
      -
        import: seo
  sidebar:
    display: Sidebar
    fields:
      -
        handle: meta
        field:
          type: section
          instructions: 'This entry''s meta data.'
          display: Meta
      -
        handle: slug
        field:
          type: slug
          localizable: true
          generate: true
          listable: hidden
          display: Slug
          validate:
            - required
            - 'unique_entry_value:{collection},{id},{site}'
      -
        handle: custom_url
        field:
          generate: false
          display: 'Custom Url'
          type: slug
          icon: slug
          instructions: 'If you would like to override the page''s default slug, for routing purposes, add it here.'
          listable: hidden
          instructions_position: above
          validate:
            - string
            - nullable
      -
        handle: parent
        field:
          type: entries
          collections:
            - pages
          max_items: 1
          listable: false
          localizable: true
      -
        handle: template
        field:
          options:
            default: 'Basic Content'
            product/index: 'Product Listing'
            product/details: 'Product Details'
            product/details_accessory: 'Product Details (Accessory)'
            product/details_buy: 'Product Details Buy Now'
            product/details_documents: 'Product Details Documents'
            blog/index: 'Blog Listing'
            specify/documents: Documents
            product/details_test: 'Product Details Testing'
            testing/style-guide: 'Style Guide'
            home: 'Home Page'
          multiple: false
          clearable: false
          searchable: true
          taggable: true
          push_tags: true
          cast_booleans: false
          default: default
          display: Template
          type: select
          icon: select
          instructions: 'Select the template type'
          listable: hidden
          instructions_position: above
          validate:
            - required
      -
        handle: product_types
        field:
          type: terms
          taxonomies:
            - product_types
          display: 'Product Types'
          mode: select
          instructions: 'Indicate the type of product that this page describes.'
          instructions_position: above
          listable: hidden
          create: false
          validate:
            - 'required_if:template,product/details'
          if:
            template: 'contains product/details'
      -
        handle: date
        field:
          type: date
          required: true
          validate:
            - required

Background Fieldset

title: Background
fields:
  -
    handle: background_color
    field: background_color.background_color
    config:
      options:
        bg-white: White
        bg-black: Black
        bg-blue-500: Blue
        bg-green-500: Green
        bg-gray-50: Light-Gray
        bg-gray-300: Medium-Gray
        bg-gray-800: Dark-Gray
      width: 33
  -
    handle: background_image
    field:
      mode: list
      container: assets
      restrict: false
      allow_uploads: false
      show_filename: true
      display: 'Background Image'
      type: assets
      icon: assets
      instructions: 'Choose/Upload an image to use for the background if desired. You may set custom background-repeat, background-position, width and height values in the asset manager/editor.'
      width: 33
      listable: hidden
      instructions_position: above
      max_files: 1
      read_only: false
  -
    handle: bg_screen
    field:
      options:
        bg-transparent: None
        full-black: 'Black - Full'
        partial-black: 'Black - Partial'
        'full-white ': 'White - Full'
        'partial-white ': 'White - Partial'
      multiple: false
      clearable: false
      searchable: true
      taggable: false
      push_tags: false
      cast_booleans: false
      default: bg-transparent
      display: 'Background Screen'
      type: select
      icon: select
      width: 33
      listable: hidden
      instructions_position: above
      max_items: 1
      instructions: 'Place a slightly transparent screen between the background and the text/content/cta.'
      read_only: false
  -
    handle: background_animation
    field:
      mode: list
      container: assets
      folder: videos
      restrict: false
      allow_uploads: false
      show_filename: true
      max_files: 1
      display: 'Background Animation'
      type: assets
      icon: assets
      instructions: 'Select/upload an .MP4 file that will be looped in the background of this section.'
      listable: hidden
      instructions_position: above
      width: 50
  -
    handle: background_animation_poster
    field: common.image
    config:
      display: 'Background Animation Poster'
      width: 50
      instructions: 'Select the image as a fallback to replace the animation on mobile devices.'
      if:
        background_animation: 'not empty'

Fieldset that we are seeing the issue with

title: 'One Half - One Half'
fields:
  -
    import: background
  -
    handle: image_fill
    field:
      default: false
      display: 'Image Fill'
      type: toggle
      icon: toggle
      instructions: 'The image provided in this component will fill the entirety of the section that it has been configured to occupy.'
      listable: hidden
      instructions_position: above
      read_only: false
      unless:
        background_image: 'equals empty'
        background_animation: 'equals empty'
  -
    handle: reverse_content_positions
    field:
      default: false
      display: 'Reverse Content Positions'
      type: toggle
      icon: toggle
      instructions: 'By default, the image is on the left - text, title and call-to-action is on the right. Turn this on to reverse those positions.'
      listable: hidden
      instructions_position: above
      read_only: false
  -
    handle: section_image_type
    field:
      options:
        none: None
        image_upload: 'Image Upload'
        spacer: Spacer
      default: image_upload
      display: 'Section Image Type'
      type: button_group
      icon: button_group
      instructions: 'Identify the type of image that you would like to show within this block: <br>**None** – No image should be shown (use with a background) <br>**Image Upload** – Select/upload an image to appear with the text <br>**Spacer** – Use to artificially expand the background image block'
      width: 50
      listable: hidden
      instructions_position: above
      validate:
        - required
  -
    handle: section_image
    field:
      mode: list
      container: assets
      restrict: false
      allow_uploads: false
      show_filename: true
      display: 'Section Image'
      type: assets
      icon: assets
      instructions: 'Pick a pic for this section (.jpg, .png or .svg)'
      width: 50
      listable: hidden
      instructions_position: above
      validate:
        - 'required_if:section_image_type,image_upload'
      read_only: false
      if:
        section_image_type: 'equals image_upload'
  -
    handle: text_alignment
    field: common.text_alignment
    config:
      default: center
  -
    handle: supratitle
    field:
      input_type: text
      antlers: false
      display: Supratitle
      type: text
      icon: text
      instructions: 'Enter text for a subtitle that goes above the main title.'
      listable: hidden
      instructions_position: above
      read_only: false
  -
    handle: half_half_main_title
    field:
      input_type: text
      antlers: false
      display: 'Main Title'
      type: text
      icon: text
      instructions: 'Enter the big title for this section here.'
      listable: hidden
      instructions_position: above
      read_only: false
  -
    handle: half_half_content
    field:
      always_show_set_button: false
      buttons:
        - h2
        - h3
        - bold
        - italic
        - unorderedlist
        - orderedlist
        - removeformat
        - quote
        - anchor
        - image
        - table
        - h4
        - h5
        - h6
        - underline
        - superscript
        - subscript
      save_html: false
      toolbar_mode: fixed
      link_noopener: false
      link_noreferrer: false
      target_blank: false
      reading_time: false
      fullscreen: true
      allow_source: true
      enable_input_rules: true
      enable_paste_rules: true
      antlers: false
      display: Content
      type: bard
      icon: bard
      instructions: 'Enter the content for this section.'
      listable: hidden
      instructions_position: above
      read_only: false
  -
    import: call_to_action

dniccum avatar Jun 29 '22 16:06 dniccum

Also, here is the call to action fieldset:

title: 'Call to Action'
fields:
  -
    handle: cta_text
    field:
      input_type: text
      antlers: false
      display: 'Call to Action Text'
      type: text
      icon: text
      instructions: 'If a call to action link/button is desired, enter its text here.'
      listable: hidden
      instructions_position: above
      read_only: false
  -
    handle: button_style
    field:
      placeholder: 'Blue Field, White Text'
      options:
        primary: 'Blue Field, White Text'
        link: 'Clear Field, Blue Text'
        'link white': 'Clear Field, White Text'
        white: 'White Field, Gray Text'
        danger: 'Red Field, White Text'
        warning: 'Orange Field, White Text'
        success: 'Green Field, White Text'
      multiple: false
      max_items: 1
      clearable: false
      searchable: true
      taggable: false
      push_tags: false
      cast_booleans: false
      default: primary
      display: 'Button Style'
      type: select
      icon: select
      instructions: 'Select an option for the button''s appearance.'
      width: 66
      listable: hidden
      instructions_position: above
      read_only: false
      if:
        cta_text: 'not null'
  -
    handle: button_outline
    field:
      default: false
      display: 'Button Outline'
      type: toggle
      icon: toggle
      instructions: 'Turn on to create an outlined version of the button.'
      width: 33
      listable: hidden
      instructions_position: above
      read_only: false
      if:
        cta_text: 'not null'
  -
    handle: call_to_action_type
    field:
      options:
        link: 'Page / Url / Link (External)'
        button: Button
      default: link
      display: 'Call to Action Type'
      type: button_group
      icon: button_group
      instructions: 'Choose Link to assign a URL. Choose Button to run a predetermined script.'
      listable: hidden
      instructions_position: above
      read_only: false
      if:
        cta_text: 'not null'
  -
    handle: cta_url
    field:
      collections:
        - pages
        - blog
      display: URL
      type: link
      icon: link
      instructions: 'Select a page, enter a web url (http://www.somecompany.com); Email link (mailto:[email protected]); or telephone link (tel:+18005551234).'
      listable: hidden
      instructions_position: above
      validate:
        - 'required_if:call_to_action_type,page'
      width: 66
      read_only: false
      if:
        call_to_action_type: 'equals link'
        cta_text: 'not null'
  -
    handle: new_window
    field:
      default: false
      display: 'New Window'
      type: toggle
      icon: toggle
      instructions: 'Turn on to open a call to action link in new window'
      width: 33
      listable: hidden
      instructions_position: above
      read_only: false
      if:
        call_to_action_type: 'equals link'
        cta_text: 'not null'
  -
    handle: button_action
    field:
      options:
        video-modal-btn: 'Play a Video'
      multiple: false
      max_items: 1
      clearable: false
      searchable: true
      taggable: false
      push_tags: false
      cast_booleans: false
      display: 'Button Action'
      type: select
      icon: select
      instructions: 'Choose an action from this list to assign to the button.'
      width: 50
      listable: hidden
      instructions_position: above
      read_only: false
      if:
        call_to_action_type: 'equals button'
        cta_text: 'not null'
  -
    handle: data_video_id
    field:
      input_type: text
      antlers: false
      display: 'Video ID'
      type: text
      icon: text
      instructions: 'Enter the Video ID used by YouTube or Vimeo here.'
      width: 50
      listable: hidden
      instructions_position: above
      read_only: false
      if:
        button_action: 'equals video-modal-btn'
        call_to_action_type: 'equals button'
        cta_text: 'not null'

dniccum avatar Jun 29 '22 16:06 dniccum

Cool, on it 🙂

jesseleite avatar Jun 29 '22 16:06 jesseleite

You said this:

Also see the provided video below on how to reproduce. I do want to mention that while the video does mention the use of "Revealer" fields, this is not true. These are toggles that simply shows and hides the inputs:

For example, the "Background Editor" field. What fieldtype is that? A toggle or revealer?

CleanShot 2022-06-29 at 13 29 50

The blueprints/fieldsets you provided don't show these fields.

jasonvarga avatar Jun 29 '22 17:06 jasonvarga

These were toggle fields. These inputs have been removed based on the recommendation of @jesseleite to convert the fields to Revealer field types. We decided to simply remove them in effort to reduce the volatility of our code.

dniccum avatar Jun 29 '22 18:06 dniccum

Are you saying the issue still happens when the fields are always visible?

jasonvarga avatar Jun 29 '22 18:06 jasonvarga

Yes that is correct.

dniccum avatar Jun 29 '22 18:06 dniccum

Could you provide a repo with this behavior? We're having a tough time reproducing this.

If you prefer to not have it public, you can send it to [email protected]

jasonvarga avatar Jun 29 '22 18:06 jasonvarga

Could you provide a repo with this behavior? We're having a tough time reproducing this.

If you prefer to not have it public, you can send it to [email protected]

Invite has been sent to Github repo.

dniccum avatar Jun 29 '22 18:06 dniccum

Can you invite my github username instead? [email protected] isn't a github account.

jasonvarga avatar Jun 29 '22 18:06 jasonvarga

Understood, you have been added. You can contact me via [email protected] if you require any ENV variables.

dniccum avatar Jun 29 '22 18:06 dniccum

I am also seeing values wiped and values not being saved in my replicator. Data that has been there for about a year is now disappearing. Not good. I have told my content editors to stop editing the site.

Some clues:

  • Fields not saving values for new blocks within replicator (renaming the field sometimes fixes it) (conditional fields seem to be the most problematic).
  • Adding a new block affects or wipes the values of other sets.
  • Deleting a block affects or wipes the values of other sets.

Sounds like the indexes of the replicator sets are messed up and the wrong values are being updated.

Another thought, did I notice that Statamic now empties conditional field values from the yaml when they are not shown? This seemed to happen over the last few weeks. As far as I remember, conditional fields that were hidden would maintain their values in the yaml, but recently Statamic seems to wipe them. Could be a connection?

stuartcusackie avatar Jul 12 '22 10:07 stuartcusackie

@stuartcusackie Are your replicator sets collapsed by default? Also are you using revealer field conditions, or just regular conditions? Also what version of Statamic are you on?

jesseleite avatar Jul 13 '22 03:07 jesseleite

Hi @jesseleite. It's 3.3.18, just regular conditions and Yes - sets are collapsed by default.

I've run some quick tests. I simply added a new set to my replicator and dragged it to the top of the list.

  • With collapse: true
    • Values of some conditional fields in other sets get wiped.
    • Some values of the new block were not saved (spatie responsive image field). It takes a second save to fix these.
  • With collapse: false
    • Values of other sets are maintained.
    • Some values of the new block were not saved (spatie responsive image field). It takes a second save to fix these.

So it seems 'collapse: false' improves things but there are other issues. I know spatie's field is outside of the scope but I have a feeling other official Statamic fields will have a problem.

stuartcusackie avatar Jul 13 '22 09:07 stuartcusackie

Hey @stuartcusackie,

  • With collapse: false
    • Values of other sets are maintained.

^ Good to know, this is what we've found here too.

  • Some values of the new block were not saved (spatie responsive image field). It takes a second save to fix these.

So it seems 'collapse: false' improves things but there are other issues. I know spatie's field is outside of the scope but I have a feeling other official Statamic fields will have a problem.

^ If you're still having this issue on the latest version, I believe it's totally unrelated, especially since you mention this happens whether or not sets are collapsed. Feel free to open up a separate issue with a sandbox example and steps to help us reproduce.

jesseleite avatar Oct 17 '22 20:10 jesseleite

@dniccum Can you confirm that https://github.com/statamic/cms/pull/6902 fixes your set re-ordering issue here?

jesseleite avatar Oct 17 '22 20:10 jesseleite

@jesseleite This does appear to fix the issue that we are experiencing. Thanks.

dniccum avatar Oct 18 '22 20:10 dniccum