statamic / cms

The core Laravel CMS Composer package
https://statamic.com
Other
4.08k stars 533 forks source link

Data is lost when re-ordering a Replicator block #6266

Closed dniccum closed 2 years ago

dniccum commented 2 years ago

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 commented 2 years ago

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

jesseleite commented 2 years ago

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?

dniccum commented 2 years ago

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 commented 2 years ago

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:someguy@somecompany.com); 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'
jesseleite commented 2 years ago

Cool, on it πŸ™‚

jasonvarga commented 2 years ago

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.

dniccum commented 2 years ago

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.

jasonvarga commented 2 years ago

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

dniccum commented 2 years ago

Yes that is correct.

jasonvarga commented 2 years ago

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 support@statamic.com

dniccum commented 2 years ago

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 support@statamic.com

Invite has been sent to Github repo.

jasonvarga commented 2 years ago

Can you invite my github username instead? support@statamic.com isn't a github account.

dniccum commented 2 years ago

Understood, you have been added. You can contact me via doug.niccum@schierproducts.com if you require any ENV variables.

stuartcusackie commented 2 years ago

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:

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?

jesseleite commented 2 years ago

@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?

stuartcusackie commented 2 years ago

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.

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.

jesseleite commented 2 years ago

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 commented 2 years ago

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

dniccum commented 2 years ago

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