Add flexible placement of actions in attachment points, with options.

Review Request #14675 — Created Nov. 6, 2025 and updated

Information

Review Board
release-7.1.x

Reviewers

This is the last piece of the core actions rewrite to enable multiple
views for the same actions.

Instead of assigning a single attachment point and parent ID to an
action, zero or more placements can now be assigned. A placement is an
ActionPlacement instance that sets:

  1. The attachment point to render into
  2. An optional parent action ID
  3. An optional default renderer
  4. An optional DOM element ID

This enables an action to (for example) be parented to a menu or another
group in one attachment point, and then a button or some other render in
another group.

Actions no longer fail to register when a placement fails. That is, if
an action is too deeply nested in one placement, it will still register,
since it can still be used in another (even if registered later via a
future extension hook).

At this point, we have 4 core concepts comprising the action system:

  1. Actions, which contains the core metadata and client-side
    activation logic.

  2. Action renderers, which render the HTML and JavaScript for an action
    in a given attachment point.

  3. Attachment Points, which are a location in which actions can be
    placed, providing default renderers.

  4. Placements, which define the Attachment Point configuration in which
    an Action would be rendered, and options governing that rendering.

Unit tests pass.

Tested that all actions worked as expected, including with in-progress
changes to consolidate the actions used for Quick Access.

Summary ID
Add flexible placement of actions in attachment points, with options.
This is the last piece of the core actions rewrite to enable multiple views for the same actions. Instead of assigning a single attachment point and parent ID to an action, zero or more placements can now be assigned. A placement is an `ActionPlacement` instance that sets: 1. The attachment point to render into 2. An optional parent action ID 3. An optional default renderer 4. An optional DOM element ID This enables an action to (for example) be parented to a menu or another group in one attachment point, and then a button or some other render in another group. Actions no longer fail to register when a placement fails. That is, if an action is too deeply nested in one placement, it will still register, since it can still be used in another (even if registered later via a future extension hook). At this point, we have 4 core concepts comprising the action system: 1. Actions, which contains the core metadata and client-side activation logic. 2. Action renderers, which render the HTML and JavaScript for an action in a given attachment point. 3. Attachment Points, which are a location in which actions can be placed, providing default renderers. 4. Placements, which define the Attachment Point configuration in which an Action would be rendered, and options governing that rendering.
8e4203858cddfef3bde0c1a1a60691fe2de0fddd
Description From Last Updated

These need to be added to "Args"

daviddavid

This is a developer-facing error message that doesn't need localization.

daviddavid

Can you mark the class as deprecated?

daviddavid

Leftover debug output.

daviddavid

'django.utils.translation.gettext as _' imported but unused Column: 1 Error code: F401

reviewbotreviewbot

local variable 'action_id' is assigned to but never used Column: 9 Error code: F841

reviewbotreviewbot
david
  1. 
      
  2. reviewboard/actions/base.py (Diff revision 1)
     
     
     
    Show all issues

    These need to be added to "Args"

  3. reviewboard/actions/base.py (Diff revision 1)
     
     
     
     
     
     
    Show all issues

    This is a developer-facing error message that doesn't need localization.

  4. 
      
david
  1. 
      
  2. reviewboard/actions/errors.py (Diff revision 1)
     
     
     
     
    Show all issues

    Can you mark the class as deprecated?

  3. Show all issues

    Leftover debug output.

  4. 
      
chipx86
Review request changed
Change Summary:
  • Updated code affected by parent changes.
  • Removed leftover debug output.
  • Added missing docs.
  • Removed localization for developer-facing strings.
  • Marked DepthLimitExceededError as deprecated at runtime.
Commits:
Summary ID
Add flexible placement of actions in attachment points, with options.
This is the last piece of the core actions rewrite to enable multiple views for the same actions. Instead of assigning a single attachment point and parent ID to an action, zero or more placements can now be assigned. A placement is an `ActionPlacement` instance that sets: 1. The attachment point to render into 2. An optional parent action ID 3. An optional default renderer 4. An optional DOM element ID This enables an action to (for example) be parented to a menu or another group in one attachment point, and then a button or some other render in another group. Actions no longer fail to register when a placement fails. That is, if an action is too deeply nested in one placement, it will still register, since it can still be used in another (even if registered later via a future extension hook). At this point, we have 4 core concepts comprising the action system: 1. Actions, which contains the core metadata and client-side activation logic. 2. Action renderers, which render the HTML and JavaScript for an action in a given attachment point. 3. Attachment Points, which are a location in which actions can be placed, providing default renderers. 4. Placements, which define the Attachment Point configuration in which an Action would be rendered, and options governing that rendering.
1f90054969cc39e180cbdf2dbd6b7c7098bf1522
Add flexible placement of actions in attachment points, with options.
This is the last piece of the core actions rewrite to enable multiple views for the same actions. Instead of assigning a single attachment point and parent ID to an action, zero or more placements can now be assigned. A placement is an `ActionPlacement` instance that sets: 1. The attachment point to render into 2. An optional parent action ID 3. An optional default renderer 4. An optional DOM element ID This enables an action to (for example) be parented to a menu or another group in one attachment point, and then a button or some other render in another group. Actions no longer fail to register when a placement fails. That is, if an action is too deeply nested in one placement, it will still register, since it can still be used in another (even if registered later via a future extension hook). At this point, we have 4 core concepts comprising the action system: 1. Actions, which contains the core metadata and client-side activation logic. 2. Action renderers, which render the HTML and JavaScript for an action in a given attachment point. 3. Attachment Points, which are a location in which actions can be placed, providing default renderers. 4. Placements, which define the Attachment Point configuration in which an Action would be rendered, and options governing that rendering.
e28820232b046503a73a73b173f08f6d5992a66b

Checks run (1 failed, 1 succeeded)

flake8 failed.
JSHint passed.

flake8

chipx86
Review request changed
Change Summary:
  • Removed an unused import.
  • Updated merged code to use an existing variable.
Commits:
Summary ID
Add flexible placement of actions in attachment points, with options.
This is the last piece of the core actions rewrite to enable multiple views for the same actions. Instead of assigning a single attachment point and parent ID to an action, zero or more placements can now be assigned. A placement is an `ActionPlacement` instance that sets: 1. The attachment point to render into 2. An optional parent action ID 3. An optional default renderer 4. An optional DOM element ID This enables an action to (for example) be parented to a menu or another group in one attachment point, and then a button or some other render in another group. Actions no longer fail to register when a placement fails. That is, if an action is too deeply nested in one placement, it will still register, since it can still be used in another (even if registered later via a future extension hook). At this point, we have 4 core concepts comprising the action system: 1. Actions, which contains the core metadata and client-side activation logic. 2. Action renderers, which render the HTML and JavaScript for an action in a given attachment point. 3. Attachment Points, which are a location in which actions can be placed, providing default renderers. 4. Placements, which define the Attachment Point configuration in which an Action would be rendered, and options governing that rendering.
e28820232b046503a73a73b173f08f6d5992a66b
Add flexible placement of actions in attachment points, with options.
This is the last piece of the core actions rewrite to enable multiple views for the same actions. Instead of assigning a single attachment point and parent ID to an action, zero or more placements can now be assigned. A placement is an `ActionPlacement` instance that sets: 1. The attachment point to render into 2. An optional parent action ID 3. An optional default renderer 4. An optional DOM element ID This enables an action to (for example) be parented to a menu or another group in one attachment point, and then a button or some other render in another group. Actions no longer fail to register when a placement fails. That is, if an action is too deeply nested in one placement, it will still register, since it can still be used in another (even if registered later via a future extension hook). At this point, we have 4 core concepts comprising the action system: 1. Actions, which contains the core metadata and client-side activation logic. 2. Action renderers, which render the HTML and JavaScript for an action in a given attachment point. 3. Attachment Points, which are a location in which actions can be placed, providing default renderers. 4. Placements, which define the Attachment Point configuration in which an Action would be rendered, and options governing that rendering.
8e4203858cddfef3bde0c1a1a60691fe2de0fddd

Checks run (2 succeeded)

flake8 passed.
JSHint passed.