Skip to content

Allow blocks to be moved between records #445

@Hels666

Description

@Hels666

Similar to issue #107 but goes a bit further.

It would be nice to be able to move an existing block onto a different page or into or out of an elemental-list. This would allow existing content to be re-arranged during a website update. The current module elemental-virtual only allows a copy of the block so can't be used for a complete re-arrange.

Thank you

Notes

  • Within a given model hierarchy, different distinct classes can allow different blocks, e.g. Page may have the ElementalAreasExtension but only HomePage allows the block. In that case Page should still show in the model type dropdown, and only HomePage records can be selected.
  • Some content authors may not immediately identify that they can duplicate and then move a block. We might want to do one of the following:
    1. Make a "duplicate and move" action
    2. Use the below modal for the "duplicate" action, so "duplicate" effectively becomes "duplicate and move-if-you-want-to"
    3. Add a banner to the top of the "move" modal that highlights the fact they can duplicate an existing block and them move it, if they wanna
  • Don't forget about things like TopPage functionality - we probably want to introduce onBeforeMove and onAfterMove hooks. Or simply onMove.... doesn't really matter what it is, but some hook that gets triggered when all the movement infromation is available but the block hasn't been saved yet.
    • It may be enough to just document how to use existing hooks (e.g. in onBeforeWrite() check if isInDB() is true and ParentID has changed)
Old AC's with inline discussion

Acceptance criteria

  • A new "move" action is added for elemental blocks
  • The action is disabled if there's nowhere we can move the block to (NOTE: If this could have performance implications, the alternative is there's clear feedback after clicking it if there's nowhere we can move it to) - Steve: We shouldn't disable the action as that would require making DB requests to work out the button state, and virtually most of the time people aren't interested in moving a block. Seems like clicking the move action should spawn a modal which then presents you fields to select where to move the block to, which is when you'd make your db requests.
  • The block can only move to records where that block type is allowed and the current user has edit permissions
  • The move action opens a new modal form:
    • If there are multiple model types that have ElementalAreasExtension which can accept this block, a dropdown is shown to select the base model (e.g. Page, MyCustomDataObject). It defaults to the model the block is currently on.
      • The model type dropdown is hidden if there's only one valid model type.
      • If the model type has the Hierarchy extension, a TreeDropdownField is used to select the record to move to
      • If the model type doesn't have the Hierarchy extension, a regular DropdownField is used to select the record to move to Steve: SearchableDropdownField is probably better here
    • After the record has been selected, if there are multiple ElementalArea relations on that record, a DropdownField is used to select which area this block will move to. fieldLabel() is used to get the display name.
      • The relation dropdown isn't displayed if there's only one ElementalArea relation
      • The current record can only be selected if there are multiple ElementalArea relations on this record. The area the block currently lives in is not selectable. Steve: might be better to present this as a disabled option instead so the user knows where the current block resideds
  • Submitting the form moves the block. Steve: Presume you mean submitting the form in the move modal?
    • If the block is published, before it moved it gets unpublished. This allows any on[Before|After]Unpublish hooks to fire e.g. to trigger static caching or search-reindexing of the parent record. Steve: I don't think this is correct, I don't think we unpublish record on publish anywhere else?
  • The block's sort value is reset when it gets moved, to avoid multiple blocks with the same sort value. Steve: Probably best to simply make it +1 the max of the highest Sort value for blocks in the target area for simplicity. That way we won't do anything like modifying existing blocks by updating Sort on multiple blocks on move which would put them all in a modified state.
  • We do NOT do a virtual block based implementation - Based on some discussion and here (both internal) we've decided that we will NOT be doing a virtual block style system, as based the real world usage with custom implementations, virtual blocks are seen as less intuitive than non-linked duplicates, and less risky in terms of performance.

Notes

  • "Move and publish" functionality is out of scope for now, though we may implement it later on.

Acceptance criteria

  • A new move action is added for elemental blocks.
  • The move action cannot be selected for inline-editable blocks with unsaved changes
  • A block can only be moved to records where block type is allowed and the user has edit permissions.
  • A modal form opens to select the destination when the move action is clicked
    • If there are model types that have an elemental area that can accept the block then there is a dropdown to select the parent model, otherwise ithe dropdown does not show
    • If the model type has the Hierarchy extension, a TreeDropdownField is used to select the record to move to, otherwise use SearchableDropdownField
    • After the parent record has been selected, if there are multiple ElementalArea relations on that record, a DropdownField is used to select which area this block will move to. fieldLabel() is used to get the display name.
    • The relation dropdown isn't displayed if there's only one ElementalArea relation
    • The current record cannot be picked as the new parent if there's only one ElementalArea on the parent (e.g. I cannot move from "About Us" to "About Us" on the same ElementalArea)
  • Submitting the form moves the block.
    • If the block being moved as published, then unpublish it first to ensure any onBeforeUnpublish/onAfterUnpublish hook fires i.e. to remove from search index
  • The block's sort value is reset when it gets moved, to avoid multiple blocks with the same sort value - note it might already do this with max() + 1
  • The solution does not use any sort of virtual block / reference implementation

PRs

Kitchen sink CI run

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions